Fri Oct 2 06:49:24 2009 UTC ()
fix grammar: a -> an


(cegger)
diff -r1.47 -r1.48 src/lib/libc/net/getaddrinfo.3
diff -r1.93 -r1.94 src/lib/libc/net/getaddrinfo.c
diff -r1.73 -r1.74 src/lib/libc/net/gethnamaddr.c
diff -r1.22 -r1.23 src/lib/libc/net/resolver.3

cvs diff -r1.47 -r1.48 src/lib/libc/net/getaddrinfo.3 (switch to unified diff)

--- src/lib/libc/net/getaddrinfo.3 2009/10/02 02:45:29 1.47
+++ src/lib/libc/net/getaddrinfo.3 2009/10/02 06:49:23 1.48
@@ -1,468 +1,468 @@ @@ -1,468 +1,468 @@
1.\" $NetBSD: getaddrinfo.3,v 1.47 2009/10/02 02:45:29 tsarna Exp $ 1.\" $NetBSD: getaddrinfo.3,v 1.48 2009/10/02 06:49:23 cegger Exp $
2.\" $KAME: getaddrinfo.3,v 1.36 2005/01/05 03:23:05 itojun Exp $ 2.\" $KAME: getaddrinfo.3,v 1.36 2005/01/05 03:23:05 itojun Exp $
3.\" $OpenBSD: getaddrinfo.3,v 1.35 2004/12/21 03:40:31 jaredy Exp $ 3.\" $OpenBSD: getaddrinfo.3,v 1.35 2004/12/21 03:40:31 jaredy Exp $
4.\" 4.\"
5.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") 5.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
6.\" Copyright (C) 2000, 2001 Internet Software Consortium. 6.\" Copyright (C) 2000, 2001 Internet Software Consortium.
7.\" 7.\"
8.\" Permission to use, copy, modify, and distribute this software for any 8.\" Permission to use, copy, modify, and distribute this software for any
9.\" purpose with or without fee is hereby granted, provided that the above 9.\" purpose with or without fee is hereby granted, provided that the above
10.\" copyright notice and this permission notice appear in all copies. 10.\" copyright notice and this permission notice appear in all copies.
11.\" 11.\"
12.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
13.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
14.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
15.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
17.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18.\" PERFORMANCE OF THIS SOFTWARE. 18.\" PERFORMANCE OF THIS SOFTWARE.
19.\" 19.\"
20.Dd November 24, 2006 20.Dd November 24, 2006
21.Dt GETADDRINFO 3 21.Dt GETADDRINFO 3
22.Os 22.Os
23.Sh NAME 23.Sh NAME
24.Nm getaddrinfo , 24.Nm getaddrinfo ,
25.Nm freeaddrinfo , 25.Nm freeaddrinfo ,
26.Nm allocaddrinfo 26.Nm allocaddrinfo
27.Nd host and service name to socket address structure 27.Nd host and service name to socket address structure
28.Sh SYNOPSIS 28.Sh SYNOPSIS
29.In netdb.h 29.In netdb.h
30.Ft int 30.Ft int
31.Fn getaddrinfo "const char * restrict hostname" \ 31.Fn getaddrinfo "const char * restrict hostname" \
32 "const char * restrict servname" \ 32 "const char * restrict servname" \
33 "const struct addrinfo * restrict hints" "struct addrinfo ** restrict res" 33 "const struct addrinfo * restrict hints" "struct addrinfo ** restrict res"
34.Ft void 34.Ft void
35.Fn freeaddrinfo "struct addrinfo *ai" 35.Fn freeaddrinfo "struct addrinfo *ai"
36.Ft struct addrinfo * 36.Ft struct addrinfo *
37.Fn allocaddrinfo "socklen_t len" 37.Fn allocaddrinfo "socklen_t len"
38.Sh DESCRIPTION 38.Sh DESCRIPTION
39The 39The
40.Fn getaddrinfo 40.Fn getaddrinfo
41function is used to get a list of 41function is used to get a list of
42.Tn IP 42.Tn IP
43addresses and port numbers for host 43addresses and port numbers for host
44.Fa hostname 44.Fa hostname
45and service 45and service
46.Fa servname . 46.Fa servname .
47It is a replacement for and provides more flexibility than the 47It is a replacement for and provides more flexibility than the
48.Xr gethostbyname 3 48.Xr gethostbyname 3
49and 49and
50.Xr getservbyname 3 50.Xr getservbyname 3
51functions. 51functions.
52.Pp 52.Pp
53The 53The
54.Fa hostname 54.Fa hostname
55and 55and
56.Fa servname 56.Fa servname
57arguments are either pointers to NUL-terminated strings or the null pointer. 57arguments are either pointers to NUL-terminated strings or the null pointer.
58An acceptable value for 58An acceptable value for
59.Fa hostname 59.Fa hostname
60is either a valid host name or a numeric host address string consisting 60is either a valid host name or a numeric host address string consisting
61of a dotted decimal IPv4 address or an IPv6 address. 61of a dotted decimal IPv4 address or an IPv6 address.
62The 62The
63.Fa servname 63.Fa servname
64is either a decimal port number or a service name listed in 64is either a decimal port number or a service name listed in
65.Xr services 5 . 65.Xr services 5 .
66At least one of 66At least one of
67.Fa hostname 67.Fa hostname
68and 68and
69.Fa servname 69.Fa servname
70must be non-null. 70must be non-null.
71.Pp 71.Pp
72.Fa hints 72.Fa hints
73is an optional pointer to a 73is an optional pointer to a
74.Li struct addrinfo , 74.Li struct addrinfo ,
75as defined by 75as defined by
76.Aq Pa netdb.h : 76.Aq Pa netdb.h :
77.Bd -literal 77.Bd -literal
78struct addrinfo { 78struct addrinfo {
79 int ai_flags; /* input flags */ 79 int ai_flags; /* input flags */
80 int ai_family; /* protocol family for socket */ 80 int ai_family; /* protocol family for socket */
81 int ai_socktype; /* socket type */ 81 int ai_socktype; /* socket type */
82 int ai_protocol; /* protocol for socket */ 82 int ai_protocol; /* protocol for socket */
83 socklen_t ai_addrlen; /* length of socket-address */ 83 socklen_t ai_addrlen; /* length of socket-address */
84 struct sockaddr *ai_addr; /* socket-address for socket */ 84 struct sockaddr *ai_addr; /* socket-address for socket */
85 char *ai_canonname; /* canonical name for service location */ 85 char *ai_canonname; /* canonical name for service location */
86 struct addrinfo *ai_next; /* pointer to next in list */ 86 struct addrinfo *ai_next; /* pointer to next in list */
87}; 87};
88.Ed 88.Ed
89.Pp 89.Pp
90This structure can be used to provide hints concerning the type of socket 90This structure can be used to provide hints concerning the type of socket
91that the caller supports or wishes to use. 91that the caller supports or wishes to use.
92The caller can supply the following structure elements in 92The caller can supply the following structure elements in
93.Fa hints : 93.Fa hints :
94.Bl -tag -width "ai_socktypeXX" 94.Bl -tag -width "ai_socktypeXX"
95.It Fa ai_family 95.It Fa ai_family
96The protocol family that should be used. 96The protocol family that should be used.
97When 97When
98.Fa ai_family 98.Fa ai_family
99is set to 99is set to
100.Dv PF_UNSPEC , 100.Dv PF_UNSPEC ,
101it means the caller will accept any protocol family supported by the 101it means the caller will accept any protocol family supported by the
102operating system. 102operating system.
103.It Fa ai_socktype 103.It Fa ai_socktype
104Denotes the type of socket that is wanted: 104Denotes the type of socket that is wanted:
105.Dv SOCK_STREAM , 105.Dv SOCK_STREAM ,
106.Dv SOCK_DGRAM , 106.Dv SOCK_DGRAM ,
107or 107or
108.Dv SOCK_RAW . 108.Dv SOCK_RAW .
109When 109When
110.Fa ai_socktype 110.Fa ai_socktype
111is zero the caller will accept any socket type. 111is zero the caller will accept any socket type.
112.It Fa ai_protocol 112.It Fa ai_protocol
113Indicates which transport protocol is desired, 113Indicates which transport protocol is desired,
114.Dv IPPROTO_UDP 114.Dv IPPROTO_UDP
115or 115or
116.Dv IPPROTO_TCP . 116.Dv IPPROTO_TCP .
117If 117If
118.Fa ai_protocol 118.Fa ai_protocol
119is zero the caller will accept any protocol. 119is zero the caller will accept any protocol.
120.It Fa ai_flags 120.It Fa ai_flags
121.Fa ai_flags 121.Fa ai_flags
122is formed by 122is formed by
123.Tn OR Ns 'ing 123.Tn OR Ns 'ing
124the following values: 124the following values:
125.Bl -tag -width "AI_CANONNAMEXX" 125.Bl -tag -width "AI_CANONNAMEXX"
126.It Dv AI_CANONNAME 126.It Dv AI_CANONNAME
127If the 127If the
128.Dv AI_CANONNAME 128.Dv AI_CANONNAME
129bit is set, a successful call to 129bit is set, a successful call to
130.Fn getaddrinfo 130.Fn getaddrinfo
131will return a NUL-terminated string containing the canonical name 131will return a NUL-terminated string containing the canonical name
132of the specified hostname in the 132of the specified hostname in the
133.Fa ai_canonname 133.Fa ai_canonname
134element of the first 134element of the first
135.Li addrinfo 135.Li addrinfo
136structure returned. 136structure returned.
137.It Dv AI_NUMERICHOST 137.It Dv AI_NUMERICHOST
138If the 138If the
139.Dv AI_NUMERICHOST 139.Dv AI_NUMERICHOST
140bit is set, it indicates that 140bit is set, it indicates that
141.Fa hostname 141.Fa hostname
142should be treated as a numeric string defining an IPv4 or IPv6 address 142should be treated as a numeric string defining an IPv4 or IPv6 address
143and no name resolution should be attempted. 143and no name resolution should be attempted.
144.It Dv AI_NUMERICSERV 144.It Dv AI_NUMERICSERV
145If the 145If the
146.Dv AI_NUMERICSERV 146.Dv AI_NUMERICSERV
147bit is set, it indicates that the 147bit is set, it indicates that the
148.Fa servname 148.Fa servname
149string contains a numeric port number. 149string contains a numeric port number.
150This is used to prevent service name resolution. 150This is used to prevent service name resolution.
151.It Dv AI_PASSIVE 151.It Dv AI_PASSIVE
152If the 152If the
153.Dv AI_PASSIVE 153.Dv AI_PASSIVE
154bit is set it indicates that the returned socket address structure 154bit is set it indicates that the returned socket address structure
155is intended for use in a call to 155is intended for use in a call to
156.Xr bind 2 . 156.Xr bind 2 .
157In this case, if the 157In this case, if the
158.Fa hostname 158.Fa hostname
159argument is the null pointer, then the IP address portion of the 159argument is the null pointer, then the IP address portion of the
160socket address structure will be set to 160socket address structure will be set to
161.Dv INADDR_ANY 161.Dv INADDR_ANY
162for an IPv4 address or 162for an IPv4 address or
163.Dv IN6ADDR_ANY_INIT 163.Dv IN6ADDR_ANY_INIT
164for an IPv6 address. 164for an IPv6 address.
165.Pp 165.Pp
166If the 166If the
167.Dv AI_PASSIVE 167.Dv AI_PASSIVE
168bit is not set, the returned socket address structure will be ready 168bit is not set, the returned socket address structure will be ready
169for use in a call to 169for use in a call to
170.Xr connect 2 170.Xr connect 2
171for a connection-oriented protocol or 171for a connection-oriented protocol or
172.Xr connect 2 , 172.Xr connect 2 ,
173.Xr sendto 2 , 173.Xr sendto 2 ,
174or 174or
175.Xr sendmsg 2 175.Xr sendmsg 2
176if a connectionless protocol was chosen. 176if a connectionless protocol was chosen.
177The 177The
178.Tn IP 178.Tn IP
179address portion of the socket address structure will be set to the 179address portion of the socket address structure will be set to the
180loopback address if 180loopback address if
181.Fa hostname 181.Fa hostname
182is the null pointer and 182is the null pointer and
183.Dv AI_PASSIVE 183.Dv AI_PASSIVE
184is not set. 184is not set.
185.El 185.El
186.El 186.El
187.Pp 187.Pp
188All other elements of the 188All other elements of the
189.Li addrinfo 189.Li addrinfo
190structure passed via 190structure passed via
191.Fa hints 191.Fa hints
192must be zero or the null pointer. 192must be zero or the null pointer.
193.Pp 193.Pp
194If 194If
195.Fa hints 195.Fa hints
196is the null pointer, 196is the null pointer,
197.Fn getaddrinfo 197.Fn getaddrinfo
198behaves as if the caller provided a 198behaves as if the caller provided a
199.Li struct addrinfo 199.Li struct addrinfo
200with 200with
201.Fa ai_family 201.Fa ai_family
202set to 202set to
203.Dv PF_UNSPEC 203.Dv PF_UNSPEC
204and all other elements set to zero or 204and all other elements set to zero or
205.Dv NULL . 205.Dv NULL .
206.Pp 206.Pp
207After a successful call to 207After a successful call to
208.Fn getaddrinfo , 208.Fn getaddrinfo ,
209.Fa *res 209.Fa *res
210is a pointer to a linked list of one or more 210is a pointer to a linked list of one or more
211.Li addrinfo 211.Li addrinfo
212structures. 212structures.
213The list can be traversed by following the 213The list can be traversed by following the
214.Fa ai_next 214.Fa ai_next
215pointer in each 215pointer in each
216.Li addrinfo 216.Li addrinfo
217structure until a null pointer is encountered. 217structure until a null pointer is encountered.
218The three members 218The three members
219.Fa ai_family , 219.Fa ai_family ,
220.Fa ai_socktype , 220.Fa ai_socktype ,
221and 221and
222.Fa ai_protocol 222.Fa ai_protocol
223in each returned 223in each returned
224.Li addrinfo 224.Li addrinfo
225structure are suitable for a call to 225structure are suitable for a call to
226.Xr socket 2 . 226.Xr socket 2 .
227For each 227For each
228.Li addrinfo 228.Li addrinfo
229structure in the list, the 229structure in the list, the
230.Fa ai_addr 230.Fa ai_addr
231member points to a filled-in socket address structure of length 231member points to a filled-in socket address structure of length
232.Fa ai_addrlen . 232.Fa ai_addrlen .
233.Pp 233.Pp
234This implementation of 234This implementation of
235.Fn getaddrinfo 235.Fn getaddrinfo
236allows numeric IPv6 address notation with scope identifier, 236allows numeric IPv6 address notation with scope identifier,
237as documented in chapter 11 of draft-ietf-ipv6-scoping-arch-02.txt. 237as documented in chapter 11 of draft-ietf-ipv6-scoping-arch-02.txt.
238By appending the percent character and scope identifier to addresses, 238By appending the percent character and scope identifier to addresses,
239one can fill the 239one can fill the
240.Li sin6_scope_id 240.Li sin6_scope_id
241field for addresses. 241field for addresses.
242This would make management of scoped addresses easier 242This would make management of scoped addresses easier
243and allows cut-and-paste input of scoped addresses. 243and allows cut-and-paste input of scoped addresses.
244.Pp 244.Pp
245At this moment the code supports only link-local addresses with the format. 245At this moment the code supports only link-local addresses with the format.
246The scope identifier is hardcoded to the name of the hardware interface 246The scope identifier is hardcoded to the name of the hardware interface
247associated 247associated
248with the link 248with the link
249.Po 249.Po
250such as 250such as
251.Li ne0 251.Li ne0
252.Pc . 252.Pc .
253An example is 253An example is
254.Dq Li fe80::1%ne0 , 254.Dq Li fe80::1%ne0 ,
255which means 255which means
256.Do 256.Do
257.Li fe80::1 257.Li fe80::1
258on the link associated with the 258on the link associated with the
259.Li ne0 259.Li ne0
260interface 260interface
261.Dc . 261.Dc .
262.Pp 262.Pp
263The current implementation assumes a one-to-one relationship between 263The current implementation assumes an one-to-one relationship between
264the interface and link, which is not necessarily true from the specification. 264the interface and link, which is not necessarily true from the specification.
265.Pp 265.Pp
266All of the information returned by 266All of the information returned by
267.Fn getaddrinfo 267.Fn getaddrinfo
268is dynamically allocated: the 268is dynamically allocated: the
269.Li addrinfo 269.Li addrinfo
270structures themselves as well as the socket address structures and 270structures themselves as well as the socket address structures and
271the canonical host name strings included in the 271the canonical host name strings included in the
272.Li addrinfo 272.Li addrinfo
273structures. 273structures.
274.Pp 274.Pp
275Memory allocated for the dynamically allocated structures created by 275Memory allocated for the dynamically allocated structures created by
276a successful call to 276a successful call to
277.Fn getaddrinfo 277.Fn getaddrinfo
278is released by the 278is released by the
279.Fn freeaddrinfo 279.Fn freeaddrinfo
280function. 280function.
281The 281The
282.Fa ai 282.Fa ai
283pointer should be a 283pointer should be an
284.Li addrinfo 284.Li addrinfo
285structure created by a call to 285structure created by a call to
286.Fn getaddrinfo 286.Fn getaddrinfo
287or 287or
288.Fn allocaddrinfo . 288.Fn allocaddrinfo .
289The 289The
290.Fn allocaddrinfo 290.Fn allocaddrinfo
291function is intended primarily for authors of 291function is intended primarily for authors of
292.Xr nsdispatch 3 292.Xr nsdispatch 3
293plugins implementing 293plugins implementing
294.Fn getaddrinfo 294.Fn getaddrinfo
295backends. 295backends.
296.Fn allocaddrinfo 296.Fn allocaddrinfo
297allocates a 297allocates a
298.Li struct addrinfo 298.Li struct addrinfo
299in a way that is compatible with being returned from 299in a way that is compatible with being returned from
300.Fn getaddrinfo 300.Fn getaddrinfo
301and being ultimately freed by 301and being ultimately freed by
302.Fn freeaddrinfo . 302.Fn freeaddrinfo .
303The returned structure is zeroed, except for the 303The returned structure is zeroed, except for the
304.Fa ai_addr 304.Fa ai_addr
305field, which 305field, which
306will point to 306will point to
307.Fa len 307.Fa len
308bytes of memory for storage of a socket address. 308bytes of memory for storage of a socket address.
309It is safe to allocate memory separately for 309It is safe to allocate memory separately for
310.Fa ai_canonname 310.Fa ai_canonname
311with 311with
312.Xr malloc 3 , 312.Xr malloc 3 ,
313or in any other way that is compatible with deallocation by 313or in any other way that is compatible with deallocation by
314.Xr free 3 . 314.Xr free 3 .
315.Sh RETURN VALUES 315.Sh RETURN VALUES
316.Fn getaddrinfo 316.Fn getaddrinfo
317returns zero on success or one of the error codes listed in 317returns zero on success or one of the error codes listed in
318.Xr gai_strerror 3 318.Xr gai_strerror 3
319if an error occurs. 319if an error occurs.
320.Sh EXAMPLES 320.Sh EXAMPLES
321The following code tries to connect to 321The following code tries to connect to
322.Dq Li www.kame.net 322.Dq Li www.kame.net
323service 323service
324.Dq Li http 324.Dq Li http
325via a stream socket. 325via a stream socket.
326It loops through all the addresses available, regardless of address family. 326It loops through all the addresses available, regardless of address family.
327If the destination resolves to an IPv4 address, it will use an 327If the destination resolves to an IPv4 address, it will use an
328.Dv AF_INET 328.Dv AF_INET
329socket. 329socket.
330Similarly, if it resolves to IPv6, an 330Similarly, if it resolves to IPv6, an
331.Dv AF_INET6 331.Dv AF_INET6
332socket is used. 332socket is used.
333Observe that there is no hardcoded reference to a particular address family. 333Observe that there is no hardcoded reference to a particular address family.
334The code works even if 334The code works even if
335.Fn getaddrinfo 335.Fn getaddrinfo
336returns addresses that are not IPv4/v6. 336returns addresses that are not IPv4/v6.
337.Bd -literal -offset indent 337.Bd -literal -offset indent
338struct addrinfo hints, *res, *res0; 338struct addrinfo hints, *res, *res0;
339int error; 339int error;
340int s; 340int s;
341const char *cause = NULL; 341const char *cause = NULL;
342 342
343memset(\*[Am]hints, 0, sizeof(hints)); 343memset(\*[Am]hints, 0, sizeof(hints));
344hints.ai_family = PF_UNSPEC; 344hints.ai_family = PF_UNSPEC;
345hints.ai_socktype = SOCK_STREAM; 345hints.ai_socktype = SOCK_STREAM;
346error = getaddrinfo("www.kame.net", "http", \*[Am]hints, \*[Am]res0); 346error = getaddrinfo("www.kame.net", "http", \*[Am]hints, \*[Am]res0);
347if (error) { 347if (error) {
348 errx(1, "%s", gai_strerror(error)); 348 errx(1, "%s", gai_strerror(error));
349 /*NOTREACHED*/ 349 /*NOTREACHED*/
350} 350}
351s = -1; 351s = -1;
352for (res = res0; res; res = res-\*[Gt]ai_next) { 352for (res = res0; res; res = res-\*[Gt]ai_next) {
353 s = socket(res-\*[Gt]ai_family, res-\*[Gt]ai_socktype, 353 s = socket(res-\*[Gt]ai_family, res-\*[Gt]ai_socktype,
354 res-\*[Gt]ai_protocol); 354 res-\*[Gt]ai_protocol);
355 if (s \*[Lt] 0) { 355 if (s \*[Lt] 0) {
356 cause = "socket"; 356 cause = "socket";
357 continue; 357 continue;
358 } 358 }
359 359
360 if (connect(s, res-\*[Gt]ai_addr, res-\*[Gt]ai_addrlen) \*[Lt] 0) { 360 if (connect(s, res-\*[Gt]ai_addr, res-\*[Gt]ai_addrlen) \*[Lt] 0) {
361 cause = "connect"; 361 cause = "connect";
362 close(s); 362 close(s);
363 s = -1; 363 s = -1;
364 continue; 364 continue;
365 } 365 }
366 366
367 break; /* okay we got one */ 367 break; /* okay we got one */
368} 368}
369if (s \*[Lt] 0) { 369if (s \*[Lt] 0) {
370 err(1, "%s", cause); 370 err(1, "%s", cause);
371 /*NOTREACHED*/ 371 /*NOTREACHED*/
372} 372}
373freeaddrinfo(res0); 373freeaddrinfo(res0);
374.Ed 374.Ed
375.Pp 375.Pp
376The following example tries to open a wildcard listening socket onto service 376The following example tries to open a wildcard listening socket onto service
377.Dq Li http , 377.Dq Li http ,
378for all the address families available. 378for all the address families available.
379.Bd -literal -offset indent 379.Bd -literal -offset indent
380struct addrinfo hints, *res, *res0; 380struct addrinfo hints, *res, *res0;
381int error; 381int error;
382int s[MAXSOCK]; 382int s[MAXSOCK];
383int nsock; 383int nsock;
384const char *cause = NULL; 384const char *cause = NULL;
385 385
386memset(\*[Am]hints, 0, sizeof(hints)); 386memset(\*[Am]hints, 0, sizeof(hints));
387hints.ai_family = PF_UNSPEC; 387hints.ai_family = PF_UNSPEC;
388hints.ai_socktype = SOCK_STREAM; 388hints.ai_socktype = SOCK_STREAM;
389hints.ai_flags = AI_PASSIVE; 389hints.ai_flags = AI_PASSIVE;
390error = getaddrinfo(NULL, "http", \*[Am]hints, \*[Am]res0); 390error = getaddrinfo(NULL, "http", \*[Am]hints, \*[Am]res0);
391if (error) { 391if (error) {
392 errx(1, "%s", gai_strerror(error)); 392 errx(1, "%s", gai_strerror(error));
393 /*NOTREACHED*/ 393 /*NOTREACHED*/
394} 394}
395nsock = 0; 395nsock = 0;
396for (res = res0; res \*[Am]\*[Am] nsock \*[Lt] MAXSOCK; res = res-\*[Gt]ai_next) { 396for (res = res0; res \*[Am]\*[Am] nsock \*[Lt] MAXSOCK; res = res-\*[Gt]ai_next) {
397 s[nsock] = socket(res-\*[Gt]ai_family, res-\*[Gt]ai_socktype, 397 s[nsock] = socket(res-\*[Gt]ai_family, res-\*[Gt]ai_socktype,
398 res-\*[Gt]ai_protocol); 398 res-\*[Gt]ai_protocol);
399 if (s[nsock] \*[Lt] 0) { 399 if (s[nsock] \*[Lt] 0) {
400 cause = "socket"; 400 cause = "socket";
401 continue; 401 continue;
402 } 402 }
403 403
404 if (bind(s[nsock], res-\*[Gt]ai_addr, res-\*[Gt]ai_addrlen) \*[Lt] 0) { 404 if (bind(s[nsock], res-\*[Gt]ai_addr, res-\*[Gt]ai_addrlen) \*[Lt] 0) {
405 cause = "bind"; 405 cause = "bind";
406 close(s[nsock]); 406 close(s[nsock]);
407 continue; 407 continue;
408 } 408 }
409 (void) listen(s[nsock], 5); 409 (void) listen(s[nsock], 5);
410 410
411 nsock++; 411 nsock++;
412} 412}
413if (nsock == 0) { 413if (nsock == 0) {
414 err(1, "%s", cause); 414 err(1, "%s", cause);
415 /*NOTREACHED*/ 415 /*NOTREACHED*/
416} 416}
417freeaddrinfo(res0); 417freeaddrinfo(res0);
418.Ed 418.Ed
419.Sh SEE ALSO 419.Sh SEE ALSO
420.Xr bind 2 , 420.Xr bind 2 ,
421.Xr connect 2 , 421.Xr connect 2 ,
422.Xr send 2 , 422.Xr send 2 ,
423.Xr socket 2 , 423.Xr socket 2 ,
424.Xr gai_strerror 3 , 424.Xr gai_strerror 3 ,
425.Xr gethostbyname 3 , 425.Xr gethostbyname 3 ,
426.Xr getnameinfo 3 , 426.Xr getnameinfo 3 ,
427.Xr getservbyname 3 , 427.Xr getservbyname 3 ,
428.Xr resolver 3 , 428.Xr resolver 3 ,
429.Xr hosts 5 , 429.Xr hosts 5 ,
430.Xr resolv.conf 5 , 430.Xr resolv.conf 5 ,
431.Xr services 5 , 431.Xr services 5 ,
432.Xr hostname 7 , 432.Xr hostname 7 ,
433.Xr named 8 433.Xr named 8
434.Rs 434.Rs
435.%A R. Gilligan 435.%A R. Gilligan
436.%A S. Thomson 436.%A S. Thomson
437.%A J. Bound 437.%A J. Bound
438.%A J. McCann 438.%A J. McCann
439.%A W. Stevens 439.%A W. Stevens
440.%T Basic Socket Interface Extensions for IPv6 440.%T Basic Socket Interface Extensions for IPv6
441.%R RFC 3493 441.%R RFC 3493
442.%D February 2003 442.%D February 2003
443.Re 443.Re
444.Rs 444.Rs
445.%A S. Deering 445.%A S. Deering
446.%A B. Haberman 446.%A B. Haberman
447.%A T. Jinmei 447.%A T. Jinmei
448.%A E. Nordmark 448.%A E. Nordmark
449.%A B. Zill 449.%A B. Zill
450.%T "IPv6 Scoped Address Architecture" 450.%T "IPv6 Scoped Address Architecture"
451.%R internet draft 451.%R internet draft
452.%N draft-ietf-ipv6-scoping-arch-02.txt 452.%N draft-ietf-ipv6-scoping-arch-02.txt
453.%O work in progress material 453.%O work in progress material
454.Re 454.Re
455.Rs 455.Rs
456.%A Craig Metz 456.%A Craig Metz
457.%T Protocol Independence Using the Sockets API 457.%T Protocol Independence Using the Sockets API
458.%B "Proceedings of the FREENIX track: 2000 USENIX annual technical conference" 458.%B "Proceedings of the FREENIX track: 2000 USENIX annual technical conference"
459.%D June 2000 459.%D June 2000
460.Re 460.Re
461.Sh STANDARDS 461.Sh STANDARDS
462The 462The
463.Fn getaddrinfo 463.Fn getaddrinfo
464function is defined by the 464function is defined by the
465.St -p1003.1g-2000 465.St -p1003.1g-2000
466draft specification and documented in 466draft specification and documented in
467.Dv "RFC 3493" , 467.Dv "RFC 3493" ,
468.Dq Basic Socket Interface Extensions for IPv6 . 468.Dq Basic Socket Interface Extensions for IPv6 .

cvs diff -r1.93 -r1.94 src/lib/libc/net/getaddrinfo.c (switch to unified diff)

--- src/lib/libc/net/getaddrinfo.c 2009/10/02 02:45:29 1.93
+++ src/lib/libc/net/getaddrinfo.c 2009/10/02 06:49:23 1.94
@@ -1,1958 +1,1958 @@ @@ -1,1958 +1,1958 @@
1/* $NetBSD: getaddrinfo.c,v 1.93 2009/10/02 02:45:29 tsarna Exp $ */ 1/* $NetBSD: getaddrinfo.c,v 1.94 2009/10/02 06:49:23 cegger Exp $ */
2/* $KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $ */ 2/* $KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $ */
3 3
4/* 4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors 16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software 17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission. 18 * without specific prior written permission.
19 * 19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE. 30 * SUCH DAMAGE.
31 */ 31 */
32 32
33/* 33/*
34 * Issues to be discussed: 34 * Issues to be discussed:
35 * - Return values. There are nonstandard return values defined and used 35 * - Return values. There are nonstandard return values defined and used
36 * in the source code. This is because RFC2553 is silent about which error 36 * in the source code. This is because RFC2553 is silent about which error
37 * code must be returned for which situation. 37 * code must be returned for which situation.
38 * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 38 * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
39 * says to use inet_aton() to convert IPv4 numeric to binary (alows 39 * says to use inet_aton() to convert IPv4 numeric to binary (alows
40 * classful form as a result). 40 * classful form as a result).
41 * current code - disallow classful form for IPv4 (due to use of inet_pton). 41 * current code - disallow classful form for IPv4 (due to use of inet_pton).
42 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is 42 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
43 * invalid. 43 * invalid.
44 * current code - SEGV on freeaddrinfo(NULL) 44 * current code - SEGV on freeaddrinfo(NULL)
45 * Note: 45 * Note:
46 * - The code filters out AFs that are not supported by the kernel, 46 * - The code filters out AFs that are not supported by the kernel,
47 * when globbing NULL hostname (to loopback, or wildcard). Is it the right 47 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
48 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG 48 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
49 * in ai_flags? 49 * in ai_flags?
50 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. 50 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
51 * (1) what should we do against numeric hostname (2) what should we do 51 * (1) what should we do against numeric hostname (2) what should we do
52 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? 52 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
53 * non-loopback address configured? global address configured? 53 * non-loopback address configured? global address configured?
54 */ 54 */
55 55
56#include <sys/cdefs.h> 56#include <sys/cdefs.h>
57#if defined(LIBC_SCCS) && !defined(lint) 57#if defined(LIBC_SCCS) && !defined(lint)
58__RCSID("$NetBSD: getaddrinfo.c,v 1.93 2009/10/02 02:45:29 tsarna Exp $"); 58__RCSID("$NetBSD: getaddrinfo.c,v 1.94 2009/10/02 06:49:23 cegger Exp $");
59#endif /* LIBC_SCCS and not lint */ 59#endif /* LIBC_SCCS and not lint */
60 60
61#include "namespace.h" 61#include "namespace.h"
62#include <sys/types.h> 62#include <sys/types.h>
63#include <sys/param.h> 63#include <sys/param.h>
64#include <sys/socket.h> 64#include <sys/socket.h>
65#include <net/if.h> 65#include <net/if.h>
66#include <netinet/in.h> 66#include <netinet/in.h>
67#include <arpa/inet.h> 67#include <arpa/inet.h>
68#include <arpa/nameser.h> 68#include <arpa/nameser.h>
69#include <assert.h> 69#include <assert.h>
70#include <ctype.h> 70#include <ctype.h>
71#include <errno.h> 71#include <errno.h>
72#include <netdb.h> 72#include <netdb.h>
73#include <resolv.h> 73#include <resolv.h>
74#include <stddef.h> 74#include <stddef.h>
75#include <stdio.h> 75#include <stdio.h>
76#include <stdlib.h> 76#include <stdlib.h>
77#include <string.h> 77#include <string.h>
78#include <unistd.h> 78#include <unistd.h>
79 79
80#include <syslog.h> 80#include <syslog.h>
81#include <stdarg.h> 81#include <stdarg.h>
82#include <nsswitch.h> 82#include <nsswitch.h>
83 83
84#ifdef YP 84#ifdef YP
85#include <rpc/rpc.h> 85#include <rpc/rpc.h>
86#include <rpcsvc/yp_prot.h> 86#include <rpcsvc/yp_prot.h>
87#include <rpcsvc/ypclnt.h> 87#include <rpcsvc/ypclnt.h>
88#endif 88#endif
89 89
90#include "servent.h" 90#include "servent.h"
91 91
92#ifdef __weak_alias 92#ifdef __weak_alias
93__weak_alias(getaddrinfo,_getaddrinfo) 93__weak_alias(getaddrinfo,_getaddrinfo)
94__weak_alias(freeaddrinfo,_freeaddrinfo) 94__weak_alias(freeaddrinfo,_freeaddrinfo)
95__weak_alias(gai_strerror,_gai_strerror) 95__weak_alias(gai_strerror,_gai_strerror)
96#endif 96#endif
97 97
98#define SUCCESS 0 98#define SUCCESS 0
99#define ANY 0 99#define ANY 0
100#define YES 1 100#define YES 1
101#define NO 0 101#define NO 0
102 102
103static const char in_addrany[] = { 0, 0, 0, 0 }; 103static const char in_addrany[] = { 0, 0, 0, 0 };
104static const char in_loopback[] = { 127, 0, 0, 1 }; 104static const char in_loopback[] = { 127, 0, 0, 1 };
105#ifdef INET6 105#ifdef INET6
106static const char in6_addrany[] = { 106static const char in6_addrany[] = {
107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
108}; 108};
109static const char in6_loopback[] = { 109static const char in6_loopback[] = {
110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
111}; 111};
112#endif 112#endif
113 113
114static const struct afd { 114static const struct afd {
115 int a_af; 115 int a_af;
116 int a_addrlen; 116 int a_addrlen;
117 int a_socklen; 117 int a_socklen;
118 int a_off; 118 int a_off;
119 const char *a_addrany; 119 const char *a_addrany;
120 const char *a_loopback;  120 const char *a_loopback;
121 int a_scoped; 121 int a_scoped;
122} afdl [] = { 122} afdl [] = {
123#ifdef INET6 123#ifdef INET6
124 {PF_INET6, sizeof(struct in6_addr), 124 {PF_INET6, sizeof(struct in6_addr),
125 sizeof(struct sockaddr_in6), 125 sizeof(struct sockaddr_in6),
126 offsetof(struct sockaddr_in6, sin6_addr), 126 offsetof(struct sockaddr_in6, sin6_addr),
127 in6_addrany, in6_loopback, 1}, 127 in6_addrany, in6_loopback, 1},
128#endif 128#endif
129 {PF_INET, sizeof(struct in_addr), 129 {PF_INET, sizeof(struct in_addr),
130 sizeof(struct sockaddr_in), 130 sizeof(struct sockaddr_in),
131 offsetof(struct sockaddr_in, sin_addr), 131 offsetof(struct sockaddr_in, sin_addr),
132 in_addrany, in_loopback, 0}, 132 in_addrany, in_loopback, 0},
133 {0, 0, 0, 0, NULL, NULL, 0}, 133 {0, 0, 0, 0, NULL, NULL, 0},
134}; 134};
135 135
136struct explore { 136struct explore {
137 int e_af; 137 int e_af;
138 int e_socktype; 138 int e_socktype;
139 int e_protocol; 139 int e_protocol;
140 const char *e_protostr; 140 const char *e_protostr;
141 int e_wild; 141 int e_wild;
142#define WILD_AF(ex) ((ex)->e_wild & 0x01) 142#define WILD_AF(ex) ((ex)->e_wild & 0x01)
143#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) 143#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
144#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) 144#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
145}; 145};
146 146
147static const struct explore explore[] = { 147static const struct explore explore[] = {
148#if 0 148#if 0
149 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, 149 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
150#endif 150#endif
151#ifdef INET6 151#ifdef INET6
152 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 152 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
153 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 153 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
154 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, 154 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
155#endif 155#endif
156 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 156 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
157 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 157 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
158 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, 158 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
159 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 159 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
160 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 160 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
161 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 }, 161 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
162 { -1, 0, 0, NULL, 0 }, 162 { -1, 0, 0, NULL, 0 },
163}; 163};
164 164
165#ifdef INET6 165#ifdef INET6
166#define PTON_MAX 16 166#define PTON_MAX 16
167#else 167#else
168#define PTON_MAX 4 168#define PTON_MAX 4
169#endif 169#endif
170 170
171static const ns_src default_dns_files[] = { 171static const ns_src default_dns_files[] = {
172 { NSSRC_FILES, NS_SUCCESS }, 172 { NSSRC_FILES, NS_SUCCESS },
173 { NSSRC_DNS, NS_SUCCESS }, 173 { NSSRC_DNS, NS_SUCCESS },
174 { 0, 0 } 174 { 0, 0 }
175}; 175};
176 176
177#define MAXPACKET (64*1024) 177#define MAXPACKET (64*1024)
178 178
179typedef union { 179typedef union {
180 HEADER hdr; 180 HEADER hdr;
181 u_char buf[MAXPACKET]; 181 u_char buf[MAXPACKET];
182} querybuf; 182} querybuf;
183 183
184struct res_target { 184struct res_target {
185 struct res_target *next; 185 struct res_target *next;
186 const char *name; /* domain name */ 186 const char *name; /* domain name */
187 int qclass, qtype; /* class and type of query */ 187 int qclass, qtype; /* class and type of query */
188 u_char *answer; /* buffer to put answer */ 188 u_char *answer; /* buffer to put answer */
189 int anslen; /* size of answer buffer */ 189 int anslen; /* size of answer buffer */
190 int n; /* result length */ 190 int n; /* result length */
191}; 191};
192 192
193static int str2number(const char *); 193static int str2number(const char *);
194static int explore_fqdn(const struct addrinfo *, const char *, 194static int explore_fqdn(const struct addrinfo *, const char *,
195 const char *, struct addrinfo **, struct servent_data *); 195 const char *, struct addrinfo **, struct servent_data *);
196static int explore_null(const struct addrinfo *, 196static int explore_null(const struct addrinfo *,
197 const char *, struct addrinfo **, struct servent_data *); 197 const char *, struct addrinfo **, struct servent_data *);
198static int explore_numeric(const struct addrinfo *, const char *, 198static int explore_numeric(const struct addrinfo *, const char *,
199 const char *, struct addrinfo **, const char *, struct servent_data *); 199 const char *, struct addrinfo **, const char *, struct servent_data *);
200static int explore_numeric_scope(const struct addrinfo *, const char *, 200static int explore_numeric_scope(const struct addrinfo *, const char *,
201 const char *, struct addrinfo **, struct servent_data *); 201 const char *, struct addrinfo **, struct servent_data *);
202static int get_canonname(const struct addrinfo *, 202static int get_canonname(const struct addrinfo *,
203 struct addrinfo *, const char *); 203 struct addrinfo *, const char *);
204static struct addrinfo *get_ai(const struct addrinfo *, 204static struct addrinfo *get_ai(const struct addrinfo *,
205 const struct afd *, const char *); 205 const struct afd *, const char *);
206static int get_portmatch(const struct addrinfo *, const char *, 206static int get_portmatch(const struct addrinfo *, const char *,
207 struct servent_data *); 207 struct servent_data *);
208static int get_port(const struct addrinfo *, const char *, int, 208static int get_port(const struct addrinfo *, const char *, int,
209 struct servent_data *); 209 struct servent_data *);
210static const struct afd *find_afd(int); 210static const struct afd *find_afd(int);
211#ifdef INET6 211#ifdef INET6
212static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *); 212static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
213#endif 213#endif
214 214
215static struct addrinfo *getanswer(const querybuf *, int, const char *, int, 215static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
216 const struct addrinfo *); 216 const struct addrinfo *);
217static void aisort(struct addrinfo *s, res_state res); 217static void aisort(struct addrinfo *s, res_state res);
218static int _dns_getaddrinfo(void *, void *, va_list); 218static int _dns_getaddrinfo(void *, void *, va_list);
219static void _sethtent(FILE **); 219static void _sethtent(FILE **);
220static void _endhtent(FILE **); 220static void _endhtent(FILE **);
221static struct addrinfo *_gethtent(FILE **, const char *, 221static struct addrinfo *_gethtent(FILE **, const char *,
222 const struct addrinfo *); 222 const struct addrinfo *);
223static int _files_getaddrinfo(void *, void *, va_list); 223static int _files_getaddrinfo(void *, void *, va_list);
224#ifdef YP 224#ifdef YP
225static struct addrinfo *_yphostent(char *, const struct addrinfo *); 225static struct addrinfo *_yphostent(char *, const struct addrinfo *);
226static int _yp_getaddrinfo(void *, void *, va_list); 226static int _yp_getaddrinfo(void *, void *, va_list);
227#endif 227#endif
228 228
229static int res_queryN(const char *, struct res_target *, res_state); 229static int res_queryN(const char *, struct res_target *, res_state);
230static int res_searchN(const char *, struct res_target *, res_state); 230static int res_searchN(const char *, struct res_target *, res_state);
231static int res_querydomainN(const char *, const char *, 231static int res_querydomainN(const char *, const char *,
232 struct res_target *, res_state); 232 struct res_target *, res_state);
233 233
234static const char * const ai_errlist[] = { 234static const char * const ai_errlist[] = {
235 "Success", 235 "Success",
236 "Address family for hostname not supported", /* EAI_ADDRFAMILY */ 236 "Address family for hostname not supported", /* EAI_ADDRFAMILY */
237 "Temporary failure in name resolution", /* EAI_AGAIN */ 237 "Temporary failure in name resolution", /* EAI_AGAIN */
238 "Invalid value for ai_flags", /* EAI_BADFLAGS */ 238 "Invalid value for ai_flags", /* EAI_BADFLAGS */
239 "Non-recoverable failure in name resolution", /* EAI_FAIL */ 239 "Non-recoverable failure in name resolution", /* EAI_FAIL */
240 "ai_family not supported", /* EAI_FAMILY */ 240 "ai_family not supported", /* EAI_FAMILY */
241 "Memory allocation failure", /* EAI_MEMORY */ 241 "Memory allocation failure", /* EAI_MEMORY */
242 "No address associated with hostname", /* EAI_NODATA */ 242 "No address associated with hostname", /* EAI_NODATA */
243 "hostname nor servname provided, or not known", /* EAI_NONAME */ 243 "hostname nor servname provided, or not known", /* EAI_NONAME */
244 "servname not supported for ai_socktype", /* EAI_SERVICE */ 244 "servname not supported for ai_socktype", /* EAI_SERVICE */
245 "ai_socktype not supported", /* EAI_SOCKTYPE */ 245 "ai_socktype not supported", /* EAI_SOCKTYPE */
246 "System error returned in errno", /* EAI_SYSTEM */ 246 "System error returned in errno", /* EAI_SYSTEM */
247 "Invalid value for hints", /* EAI_BADHINTS */ 247 "Invalid value for hints", /* EAI_BADHINTS */
248 "Resolved protocol is unknown", /* EAI_PROTOCOL */ 248 "Resolved protocol is unknown", /* EAI_PROTOCOL */
249 "Argument buffer overflow", /* EAI_OVERFLOW */ 249 "Argument buffer overflow", /* EAI_OVERFLOW */
250 "Unknown error", /* EAI_MAX */ 250 "Unknown error", /* EAI_MAX */
251}; 251};
252 252
253/* XXX macros that make external reference is BAD. */ 253/* XXX macros that make external reference is BAD. */
254 254
255#define GET_AI(ai, afd, addr) \ 255#define GET_AI(ai, afd, addr) \
256do { \ 256do { \
257 /* external reference: pai, error, and label free */ \ 257 /* external reference: pai, error, and label free */ \
258 (ai) = get_ai(pai, (afd), (addr)); \ 258 (ai) = get_ai(pai, (afd), (addr)); \
259 if ((ai) == NULL) { \ 259 if ((ai) == NULL) { \
260 error = EAI_MEMORY; \ 260 error = EAI_MEMORY; \
261 goto free; \ 261 goto free; \
262 } \ 262 } \
263} while (/*CONSTCOND*/0) 263} while (/*CONSTCOND*/0)
264 264
265#define GET_PORT(ai, serv, svd) \ 265#define GET_PORT(ai, serv, svd) \
266do { \ 266do { \
267 /* external reference: error and label free */ \ 267 /* external reference: error and label free */ \
268 error = get_port((ai), (serv), 0, (svd)); \ 268 error = get_port((ai), (serv), 0, (svd)); \
269 if (error != 0) \ 269 if (error != 0) \
270 goto free; \ 270 goto free; \
271} while (/*CONSTCOND*/0) 271} while (/*CONSTCOND*/0)
272 272
273#define GET_CANONNAME(ai, str) \ 273#define GET_CANONNAME(ai, str) \
274do { \ 274do { \
275 /* external reference: pai, error and label free */ \ 275 /* external reference: pai, error and label free */ \
276 error = get_canonname(pai, (ai), (str)); \ 276 error = get_canonname(pai, (ai), (str)); \
277 if (error != 0) \ 277 if (error != 0) \
278 goto free; \ 278 goto free; \
279} while (/*CONSTCOND*/0) 279} while (/*CONSTCOND*/0)
280 280
281#define ERR(err) \ 281#define ERR(err) \
282do { \ 282do { \
283 /* external reference: error, and label bad */ \ 283 /* external reference: error, and label bad */ \
284 error = (err); \ 284 error = (err); \
285 goto bad; \ 285 goto bad; \
286 /*NOTREACHED*/ \ 286 /*NOTREACHED*/ \
287} while (/*CONSTCOND*/0) 287} while (/*CONSTCOND*/0)
288 288
289#define MATCH_FAMILY(x, y, w) \ 289#define MATCH_FAMILY(x, y, w) \
290 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || \ 290 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || \
291 (y) == PF_UNSPEC)))  291 (y) == PF_UNSPEC)))
292#define MATCH(x, y, w) \ 292#define MATCH(x, y, w) \
293 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) 293 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
294 294
295const char * 295const char *
296gai_strerror(int ecode) 296gai_strerror(int ecode)
297{ 297{
298 if (ecode < 0 || ecode > EAI_MAX) 298 if (ecode < 0 || ecode > EAI_MAX)
299 ecode = EAI_MAX; 299 ecode = EAI_MAX;
300 return ai_errlist[ecode]; 300 return ai_errlist[ecode];
301} 301}
302 302
303void 303void
304freeaddrinfo(struct addrinfo *ai) 304freeaddrinfo(struct addrinfo *ai)
305{ 305{
306 struct addrinfo *next; 306 struct addrinfo *next;
307 307
308 _DIAGASSERT(ai != NULL); 308 _DIAGASSERT(ai != NULL);
309 309
310 do { 310 do {
311 next = ai->ai_next; 311 next = ai->ai_next;
312 if (ai->ai_canonname) 312 if (ai->ai_canonname)
313 free(ai->ai_canonname); 313 free(ai->ai_canonname);
314 /* no need to free(ai->ai_addr) */ 314 /* no need to free(ai->ai_addr) */
315 free(ai); 315 free(ai);
316 ai = next; 316 ai = next;
317 } while (ai); 317 } while (ai);
318} 318}
319 319
320static int 320static int
321str2number(const char *p) 321str2number(const char *p)
322{ 322{
323 char *ep; 323 char *ep;
324 unsigned long v; 324 unsigned long v;
325 325
326 _DIAGASSERT(p != NULL); 326 _DIAGASSERT(p != NULL);
327 327
328 if (*p == '\0') 328 if (*p == '\0')
329 return -1; 329 return -1;
330 ep = NULL; 330 ep = NULL;
331 errno = 0; 331 errno = 0;
332 v = strtoul(p, &ep, 10); 332 v = strtoul(p, &ep, 10);
333 if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) 333 if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX)
334 return v; 334 return v;
335 else 335 else
336 return -1; 336 return -1;
337} 337}
338 338
339int 339int
340getaddrinfo(const char *hostname, const char *servname, 340getaddrinfo(const char *hostname, const char *servname,
341 const struct addrinfo *hints, struct addrinfo **res) 341 const struct addrinfo *hints, struct addrinfo **res)
342{ 342{
343 struct addrinfo sentinel; 343 struct addrinfo sentinel;
344 struct addrinfo *cur; 344 struct addrinfo *cur;
345 int error = 0; 345 int error = 0;
346 struct addrinfo ai; 346 struct addrinfo ai;
347 struct addrinfo ai0; 347 struct addrinfo ai0;
348 struct addrinfo *pai; 348 struct addrinfo *pai;
349 const struct explore *ex; 349 const struct explore *ex;
350 struct servent_data svd; 350 struct servent_data svd;
351 351
352 /* hostname is allowed to be NULL */ 352 /* hostname is allowed to be NULL */
353 /* servname is allowed to be NULL */ 353 /* servname is allowed to be NULL */
354 /* hints is allowed to be NULL */ 354 /* hints is allowed to be NULL */
355 _DIAGASSERT(res != NULL); 355 _DIAGASSERT(res != NULL);
356 356
357 (void)memset(&svd, 0, sizeof(svd)); 357 (void)memset(&svd, 0, sizeof(svd));
358 memset(&sentinel, 0, sizeof(sentinel)); 358 memset(&sentinel, 0, sizeof(sentinel));
359 cur = &sentinel; 359 cur = &sentinel;
360 memset(&ai, 0, sizeof(ai)); 360 memset(&ai, 0, sizeof(ai));
361 pai = &ai; 361 pai = &ai;
362 pai->ai_flags = 0; 362 pai->ai_flags = 0;
363 pai->ai_family = PF_UNSPEC; 363 pai->ai_family = PF_UNSPEC;
364 pai->ai_socktype = ANY; 364 pai->ai_socktype = ANY;
365 pai->ai_protocol = ANY; 365 pai->ai_protocol = ANY;
366 pai->ai_addrlen = 0; 366 pai->ai_addrlen = 0;
367 pai->ai_canonname = NULL; 367 pai->ai_canonname = NULL;
368 pai->ai_addr = NULL; 368 pai->ai_addr = NULL;
369 pai->ai_next = NULL; 369 pai->ai_next = NULL;
370  370
371 if (hostname == NULL && servname == NULL) 371 if (hostname == NULL && servname == NULL)
372 return EAI_NONAME; 372 return EAI_NONAME;
373 if (hints) { 373 if (hints) {
374 /* error check for hints */ 374 /* error check for hints */
375 if (hints->ai_addrlen || hints->ai_canonname || 375 if (hints->ai_addrlen || hints->ai_canonname ||
376 hints->ai_addr || hints->ai_next) 376 hints->ai_addr || hints->ai_next)
377 ERR(EAI_BADHINTS); /* xxx */ 377 ERR(EAI_BADHINTS); /* xxx */
378 if (hints->ai_flags & ~AI_MASK) 378 if (hints->ai_flags & ~AI_MASK)
379 ERR(EAI_BADFLAGS); 379 ERR(EAI_BADFLAGS);
380 switch (hints->ai_family) { 380 switch (hints->ai_family) {
381 case PF_UNSPEC: 381 case PF_UNSPEC:
382 case PF_INET: 382 case PF_INET:
383#ifdef INET6 383#ifdef INET6
384 case PF_INET6: 384 case PF_INET6:
385#endif 385#endif
386 break; 386 break;
387 default: 387 default:
388 ERR(EAI_FAMILY); 388 ERR(EAI_FAMILY);
389 } 389 }
390 memcpy(pai, hints, sizeof(*pai)); 390 memcpy(pai, hints, sizeof(*pai));
391 391
392 /* 392 /*
393 * if both socktype/protocol are specified, check if they 393 * if both socktype/protocol are specified, check if they
394 * are meaningful combination. 394 * are meaningful combination.
395 */ 395 */
396 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { 396 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
397 for (ex = explore; ex->e_af >= 0; ex++) { 397 for (ex = explore; ex->e_af >= 0; ex++) {
398 if (pai->ai_family != ex->e_af) 398 if (pai->ai_family != ex->e_af)
399 continue; 399 continue;
400 if (ex->e_socktype == ANY) 400 if (ex->e_socktype == ANY)
401 continue; 401 continue;
402 if (ex->e_protocol == ANY) 402 if (ex->e_protocol == ANY)
403 continue; 403 continue;
404 if (pai->ai_socktype == ex->e_socktype 404 if (pai->ai_socktype == ex->e_socktype
405 && pai->ai_protocol != ex->e_protocol) { 405 && pai->ai_protocol != ex->e_protocol) {
406 ERR(EAI_BADHINTS); 406 ERR(EAI_BADHINTS);
407 } 407 }
408 } 408 }
409 } 409 }
410 } 410 }
411 411
412 /* 412 /*
413 * check for special cases. (1) numeric servname is disallowed if 413 * check for special cases. (1) numeric servname is disallowed if
414 * socktype/protocol are left unspecified. (2) servname is disallowed 414 * socktype/protocol are left unspecified. (2) servname is disallowed
415 * for raw and other inet{,6} sockets. 415 * for raw and other inet{,6} sockets.
416 */ 416 */
417 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) 417 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
418#ifdef PF_INET6 418#ifdef PF_INET6
419 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) 419 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
420#endif 420#endif
421 ) { 421 ) {
422 ai0 = *pai; /* backup *pai */ 422 ai0 = *pai; /* backup *pai */
423 423
424 if (pai->ai_family == PF_UNSPEC) { 424 if (pai->ai_family == PF_UNSPEC) {
425#ifdef PF_INET6 425#ifdef PF_INET6
426 pai->ai_family = PF_INET6; 426 pai->ai_family = PF_INET6;
427#else 427#else
428 pai->ai_family = PF_INET; 428 pai->ai_family = PF_INET;
429#endif 429#endif
430 } 430 }
431 error = get_portmatch(pai, servname, &svd); 431 error = get_portmatch(pai, servname, &svd);
432 if (error) 432 if (error)
433 ERR(error); 433 ERR(error);
434 434
435 *pai = ai0; 435 *pai = ai0;
436 } 436 }
437 437
438 ai0 = *pai; 438 ai0 = *pai;
439 439
440 /* NULL hostname, or numeric hostname */ 440 /* NULL hostname, or numeric hostname */
441 for (ex = explore; ex->e_af >= 0; ex++) { 441 for (ex = explore; ex->e_af >= 0; ex++) {
442 *pai = ai0; 442 *pai = ai0;
443 443
444 /* PF_UNSPEC entries are prepared for DNS queries only */ 444 /* PF_UNSPEC entries are prepared for DNS queries only */
445 if (ex->e_af == PF_UNSPEC) 445 if (ex->e_af == PF_UNSPEC)
446 continue; 446 continue;
447 447
448 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) 448 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
449 continue; 449 continue;
450 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) 450 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
451 continue; 451 continue;
452 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) 452 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
453 continue; 453 continue;
454 454
455 if (pai->ai_family == PF_UNSPEC) 455 if (pai->ai_family == PF_UNSPEC)
456 pai->ai_family = ex->e_af; 456 pai->ai_family = ex->e_af;
457 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 457 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
458 pai->ai_socktype = ex->e_socktype; 458 pai->ai_socktype = ex->e_socktype;
459 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 459 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
460 pai->ai_protocol = ex->e_protocol; 460 pai->ai_protocol = ex->e_protocol;
461 461
462 if (hostname == NULL) 462 if (hostname == NULL)
463 error = explore_null(pai, servname, &cur->ai_next, 463 error = explore_null(pai, servname, &cur->ai_next,
464 &svd); 464 &svd);
465 else 465 else
466 error = explore_numeric_scope(pai, hostname, servname, 466 error = explore_numeric_scope(pai, hostname, servname,
467 &cur->ai_next, &svd); 467 &cur->ai_next, &svd);
468 468
469 if (error) 469 if (error)
470 goto free; 470 goto free;
471 471
472 while (cur->ai_next) 472 while (cur->ai_next)
473 cur = cur->ai_next; 473 cur = cur->ai_next;
474 } 474 }
475 475
476 /* 476 /*
477 * XXX 477 * XXX
478 * If numeric representation of AF1 can be interpreted as FQDN 478 * If numeric representation of AF1 can be interpreted as FQDN
479 * representation of AF2, we need to think again about the code below. 479 * representation of AF2, we need to think again about the code below.
480 */ 480 */
481 if (sentinel.ai_next) 481 if (sentinel.ai_next)
482 goto good; 482 goto good;
483 483
484 if (hostname == NULL) 484 if (hostname == NULL)
485 ERR(EAI_NODATA); 485 ERR(EAI_NODATA);
486 if (pai->ai_flags & AI_NUMERICHOST) 486 if (pai->ai_flags & AI_NUMERICHOST)
487 ERR(EAI_NONAME); 487 ERR(EAI_NONAME);
488 488
489 /* 489 /*
490 * hostname as alphabetical name. 490 * hostname as alphabetical name.
491 * we would like to prefer AF_INET6 than AF_INET, so we'll make a 491 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
492 * outer loop by AFs. 492 * outer loop by AFs.
493 */ 493 */
494 for (ex = explore; ex->e_af >= 0; ex++) { 494 for (ex = explore; ex->e_af >= 0; ex++) {
495 *pai = ai0; 495 *pai = ai0;
496 496
497 /* require exact match for family field */ 497 /* require exact match for family field */
498 if (pai->ai_family != ex->e_af) 498 if (pai->ai_family != ex->e_af)
499 continue; 499 continue;
500 500
501 if (!MATCH(pai->ai_socktype, ex->e_socktype, 501 if (!MATCH(pai->ai_socktype, ex->e_socktype,
502 WILD_SOCKTYPE(ex))) { 502 WILD_SOCKTYPE(ex))) {
503 continue; 503 continue;
504 } 504 }
505 if (!MATCH(pai->ai_protocol, ex->e_protocol, 505 if (!MATCH(pai->ai_protocol, ex->e_protocol,
506 WILD_PROTOCOL(ex))) { 506 WILD_PROTOCOL(ex))) {
507 continue; 507 continue;
508 } 508 }
509 509
510 if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 510 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
511 pai->ai_socktype = ex->e_socktype; 511 pai->ai_socktype = ex->e_socktype;
512 if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 512 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
513 pai->ai_protocol = ex->e_protocol; 513 pai->ai_protocol = ex->e_protocol;
514 514
515 error = explore_fqdn(pai, hostname, servname, &cur->ai_next, 515 error = explore_fqdn(pai, hostname, servname, &cur->ai_next,
516 &svd); 516 &svd);
517 517
518 while (cur && cur->ai_next) 518 while (cur && cur->ai_next)
519 cur = cur->ai_next; 519 cur = cur->ai_next;
520 } 520 }
521 521
522 /* XXX */ 522 /* XXX */
523 if (sentinel.ai_next) 523 if (sentinel.ai_next)
524 error = 0; 524 error = 0;
525 525
526 if (error) 526 if (error)
527 goto free; 527 goto free;
528 528
529 if (sentinel.ai_next) { 529 if (sentinel.ai_next) {
530 good: 530 good:
531 endservent_r(&svd); 531 endservent_r(&svd);
532 *res = sentinel.ai_next; 532 *res = sentinel.ai_next;
533 return SUCCESS; 533 return SUCCESS;
534 } else 534 } else
535 error = EAI_FAIL; 535 error = EAI_FAIL;
536 free: 536 free:
537 bad: 537 bad:
538 endservent_r(&svd); 538 endservent_r(&svd);
539 if (sentinel.ai_next) 539 if (sentinel.ai_next)
540 freeaddrinfo(sentinel.ai_next); 540 freeaddrinfo(sentinel.ai_next);
541 *res = NULL; 541 *res = NULL;
542 return error; 542 return error;
543} 543}
544 544
545/* 545/*
546 * FQDN hostname, DNS lookup 546 * FQDN hostname, DNS lookup
547 */ 547 */
548static int 548static int
549explore_fqdn(const struct addrinfo *pai, const char *hostname, 549explore_fqdn(const struct addrinfo *pai, const char *hostname,
550 const char *servname, struct addrinfo **res, struct servent_data *svd) 550 const char *servname, struct addrinfo **res, struct servent_data *svd)
551{ 551{
552 struct addrinfo *result; 552 struct addrinfo *result;
553 struct addrinfo *cur; 553 struct addrinfo *cur;
554 int error = 0; 554 int error = 0;
555 static const ns_dtab dtab[] = { 555 static const ns_dtab dtab[] = {
556 NS_FILES_CB(_files_getaddrinfo, NULL) 556 NS_FILES_CB(_files_getaddrinfo, NULL)
557 { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ 557 { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */
558 NS_NIS_CB(_yp_getaddrinfo, NULL) 558 NS_NIS_CB(_yp_getaddrinfo, NULL)
559 NS_NULL_CB 559 NS_NULL_CB
560 }; 560 };
561 561
562 _DIAGASSERT(pai != NULL); 562 _DIAGASSERT(pai != NULL);
563 /* hostname may be NULL */ 563 /* hostname may be NULL */
564 /* servname may be NULL */ 564 /* servname may be NULL */
565 _DIAGASSERT(res != NULL); 565 _DIAGASSERT(res != NULL);
566 566
567 result = NULL; 567 result = NULL;
568 568
569 /* 569 /*
570 * if the servname does not match socktype/protocol, ignore it. 570 * if the servname does not match socktype/protocol, ignore it.
571 */ 571 */
572 if (get_portmatch(pai, servname, svd) != 0) 572 if (get_portmatch(pai, servname, svd) != 0)
573 return 0; 573 return 0;
574 574
575 switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", 575 switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
576 default_dns_files, hostname, pai)) { 576 default_dns_files, hostname, pai)) {
577 case NS_TRYAGAIN: 577 case NS_TRYAGAIN:
578 error = EAI_AGAIN; 578 error = EAI_AGAIN;
579 goto free; 579 goto free;
580 case NS_UNAVAIL: 580 case NS_UNAVAIL:
581 error = EAI_FAIL; 581 error = EAI_FAIL;
582 goto free; 582 goto free;
583 case NS_NOTFOUND: 583 case NS_NOTFOUND:
584 error = EAI_NODATA; 584 error = EAI_NODATA;
585 goto free; 585 goto free;
586 case NS_SUCCESS: 586 case NS_SUCCESS:
587 error = 0; 587 error = 0;
588 for (cur = result; cur; cur = cur->ai_next) { 588 for (cur = result; cur; cur = cur->ai_next) {
589 GET_PORT(cur, servname, svd); 589 GET_PORT(cur, servname, svd);
590 /* canonname should be filled already */ 590 /* canonname should be filled already */
591 } 591 }
592 break; 592 break;
593 } 593 }
594 594
595 *res = result; 595 *res = result;
596 596
597 return 0; 597 return 0;
598 598
599free: 599free:
600 if (result) 600 if (result)
601 freeaddrinfo(result); 601 freeaddrinfo(result);
602 return error; 602 return error;
603} 603}
604 604
605/* 605/*
606 * hostname == NULL. 606 * hostname == NULL.
607 * passive socket -> anyaddr (0.0.0.0 or ::) 607 * passive socket -> anyaddr (0.0.0.0 or ::)
608 * non-passive socket -> localhost (127.0.0.1 or ::1) 608 * non-passive socket -> localhost (127.0.0.1 or ::1)
609 */ 609 */
610static int 610static int
611explore_null(const struct addrinfo *pai, const char *servname, 611explore_null(const struct addrinfo *pai, const char *servname,
612 struct addrinfo **res, struct servent_data *svd) 612 struct addrinfo **res, struct servent_data *svd)
613{ 613{
614 int s; 614 int s;
615 const struct afd *afd; 615 const struct afd *afd;
616 struct addrinfo *cur; 616 struct addrinfo *cur;
617 struct addrinfo sentinel; 617 struct addrinfo sentinel;
618 int error; 618 int error;
619 619
620 _DIAGASSERT(pai != NULL); 620 _DIAGASSERT(pai != NULL);
621 /* servname may be NULL */ 621 /* servname may be NULL */
622 _DIAGASSERT(res != NULL); 622 _DIAGASSERT(res != NULL);
623 623
624 *res = NULL; 624 *res = NULL;
625 sentinel.ai_next = NULL; 625 sentinel.ai_next = NULL;
626 cur = &sentinel; 626 cur = &sentinel;
627 627
628 /* 628 /*
629 * filter out AFs that are not supported by the kernel 629 * filter out AFs that are not supported by the kernel
630 * XXX errno? 630 * XXX errno?
631 */ 631 */
632 s = socket(pai->ai_family, SOCK_DGRAM, 0); 632 s = socket(pai->ai_family, SOCK_DGRAM, 0);
633 if (s < 0) { 633 if (s < 0) {
634 if (errno != EMFILE) 634 if (errno != EMFILE)
635 return 0; 635 return 0;
636 } else 636 } else
637 close(s); 637 close(s);
638 638
639 /* 639 /*
640 * if the servname does not match socktype/protocol, ignore it. 640 * if the servname does not match socktype/protocol, ignore it.
641 */ 641 */
642 if (get_portmatch(pai, servname, svd) != 0) 642 if (get_portmatch(pai, servname, svd) != 0)
643 return 0; 643 return 0;
644 644
645 afd = find_afd(pai->ai_family); 645 afd = find_afd(pai->ai_family);
646 if (afd == NULL) 646 if (afd == NULL)
647 return 0; 647 return 0;
648 648
649 if (pai->ai_flags & AI_PASSIVE) { 649 if (pai->ai_flags & AI_PASSIVE) {
650 GET_AI(cur->ai_next, afd, afd->a_addrany); 650 GET_AI(cur->ai_next, afd, afd->a_addrany);
651 /* xxx meaningless? 651 /* xxx meaningless?
652 * GET_CANONNAME(cur->ai_next, "anyaddr"); 652 * GET_CANONNAME(cur->ai_next, "anyaddr");
653 */ 653 */
654 GET_PORT(cur->ai_next, servname, svd); 654 GET_PORT(cur->ai_next, servname, svd);
655 } else { 655 } else {
656 GET_AI(cur->ai_next, afd, afd->a_loopback); 656 GET_AI(cur->ai_next, afd, afd->a_loopback);
657 /* xxx meaningless? 657 /* xxx meaningless?
658 * GET_CANONNAME(cur->ai_next, "localhost"); 658 * GET_CANONNAME(cur->ai_next, "localhost");
659 */ 659 */
660 GET_PORT(cur->ai_next, servname, svd); 660 GET_PORT(cur->ai_next, servname, svd);
661 } 661 }
662 cur = cur->ai_next; 662 cur = cur->ai_next;
663 663
664 *res = sentinel.ai_next; 664 *res = sentinel.ai_next;
665 return 0; 665 return 0;
666 666
667free: 667free:
668 if (sentinel.ai_next) 668 if (sentinel.ai_next)
669 freeaddrinfo(sentinel.ai_next); 669 freeaddrinfo(sentinel.ai_next);
670 return error; 670 return error;
671} 671}
672 672
673/* 673/*
674 * numeric hostname 674 * numeric hostname
675 */ 675 */
676static int 676static int
677explore_numeric(const struct addrinfo *pai, const char *hostname, 677explore_numeric(const struct addrinfo *pai, const char *hostname,
678 const char *servname, struct addrinfo **res, const char *canonname, 678 const char *servname, struct addrinfo **res, const char *canonname,
679 struct servent_data *svd) 679 struct servent_data *svd)
680{ 680{
681 const struct afd *afd; 681 const struct afd *afd;
682 struct addrinfo *cur; 682 struct addrinfo *cur;
683 struct addrinfo sentinel; 683 struct addrinfo sentinel;
684 int error; 684 int error;
685 char pton[PTON_MAX]; 685 char pton[PTON_MAX];
686 686
687 _DIAGASSERT(pai != NULL); 687 _DIAGASSERT(pai != NULL);
688 /* hostname may be NULL */ 688 /* hostname may be NULL */
689 /* servname may be NULL */ 689 /* servname may be NULL */
690 _DIAGASSERT(res != NULL); 690 _DIAGASSERT(res != NULL);
691 691
692 *res = NULL; 692 *res = NULL;
693 sentinel.ai_next = NULL; 693 sentinel.ai_next = NULL;
694 cur = &sentinel; 694 cur = &sentinel;
695 695
696 /* 696 /*
697 * if the servname does not match socktype/protocol, ignore it. 697 * if the servname does not match socktype/protocol, ignore it.
698 */ 698 */
699 if (get_portmatch(pai, servname, svd) != 0) 699 if (get_portmatch(pai, servname, svd) != 0)
700 return 0; 700 return 0;
701 701
702 afd = find_afd(pai->ai_family); 702 afd = find_afd(pai->ai_family);
703 if (afd == NULL) 703 if (afd == NULL)
704 return 0; 704 return 0;
705 705
706 switch (afd->a_af) { 706 switch (afd->a_af) {
707#if 0 /*X/Open spec*/ 707#if 0 /*X/Open spec*/
708 case AF_INET: 708 case AF_INET:
709 if (inet_aton(hostname, (struct in_addr *)pton) == 1) { 709 if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
710 if (pai->ai_family == afd->a_af || 710 if (pai->ai_family == afd->a_af ||
711 pai->ai_family == PF_UNSPEC /*?*/) { 711 pai->ai_family == PF_UNSPEC /*?*/) {
712 GET_AI(cur->ai_next, afd, pton); 712 GET_AI(cur->ai_next, afd, pton);
713 GET_PORT(cur->ai_next, servname, svd); 713 GET_PORT(cur->ai_next, servname, svd);
714 if ((pai->ai_flags & AI_CANONNAME)) { 714 if ((pai->ai_flags & AI_CANONNAME)) {
715 /* 715 /*
716 * Set the numeric address itself as 716 * Set the numeric address itself as
717 * the canonical name, based on a 717 * the canonical name, based on a
718 * clarification in rfc2553bis-03. 718 * clarification in rfc2553bis-03.
719 */ 719 */
720 GET_CANONNAME(cur->ai_next, canonname); 720 GET_CANONNAME(cur->ai_next, canonname);
721 } 721 }
722 while (cur && cur->ai_next) 722 while (cur && cur->ai_next)
723 cur = cur->ai_next; 723 cur = cur->ai_next;
724 } else 724 } else
725 ERR(EAI_FAMILY); /*xxx*/ 725 ERR(EAI_FAMILY); /*xxx*/
726 } 726 }
727 break; 727 break;
728#endif 728#endif
729 default: 729 default:
730 if (inet_pton(afd->a_af, hostname, pton) == 1) { 730 if (inet_pton(afd->a_af, hostname, pton) == 1) {
731 if (pai->ai_family == afd->a_af || 731 if (pai->ai_family == afd->a_af ||
732 pai->ai_family == PF_UNSPEC /*?*/) { 732 pai->ai_family == PF_UNSPEC /*?*/) {
733 GET_AI(cur->ai_next, afd, pton); 733 GET_AI(cur->ai_next, afd, pton);
734 GET_PORT(cur->ai_next, servname, svd); 734 GET_PORT(cur->ai_next, servname, svd);
735 if ((pai->ai_flags & AI_CANONNAME)) { 735 if ((pai->ai_flags & AI_CANONNAME)) {
736 /* 736 /*
737 * Set the numeric address itself as 737 * Set the numeric address itself as
738 * the canonical name, based on a 738 * the canonical name, based on a
739 * clarification in rfc2553bis-03. 739 * clarification in rfc2553bis-03.
740 */ 740 */
741 GET_CANONNAME(cur->ai_next, canonname); 741 GET_CANONNAME(cur->ai_next, canonname);
742 } 742 }
743 while (cur->ai_next) 743 while (cur->ai_next)
744 cur = cur->ai_next; 744 cur = cur->ai_next;
745 } else 745 } else
746 ERR(EAI_FAMILY); /*xxx*/ 746 ERR(EAI_FAMILY); /*xxx*/
747 } 747 }
748 break; 748 break;
749 } 749 }
750 750
751 *res = sentinel.ai_next; 751 *res = sentinel.ai_next;
752 return 0; 752 return 0;
753 753
754free: 754free:
755bad: 755bad:
756 if (sentinel.ai_next) 756 if (sentinel.ai_next)
757 freeaddrinfo(sentinel.ai_next); 757 freeaddrinfo(sentinel.ai_next);
758 return error; 758 return error;
759} 759}
760 760
761/* 761/*
762 * numeric hostname with scope 762 * numeric hostname with scope
763 */ 763 */
764static int 764static int
765explore_numeric_scope(const struct addrinfo *pai, const char *hostname, 765explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
766 const char *servname, struct addrinfo **res, struct servent_data *svd) 766 const char *servname, struct addrinfo **res, struct servent_data *svd)
767{ 767{
768#if !defined(SCOPE_DELIMITER) || !defined(INET6) 768#if !defined(SCOPE_DELIMITER) || !defined(INET6)
769 return explore_numeric(pai, hostname, servname, res, hostname, svd); 769 return explore_numeric(pai, hostname, servname, res, hostname, svd);
770#else 770#else
771 const struct afd *afd; 771 const struct afd *afd;
772 struct addrinfo *cur; 772 struct addrinfo *cur;
773 int error; 773 int error;
774 char *cp, *hostname2 = NULL, *scope, *addr; 774 char *cp, *hostname2 = NULL, *scope, *addr;
775 struct sockaddr_in6 *sin6; 775 struct sockaddr_in6 *sin6;
776 776
777 _DIAGASSERT(pai != NULL); 777 _DIAGASSERT(pai != NULL);
778 /* hostname may be NULL */ 778 /* hostname may be NULL */
779 /* servname may be NULL */ 779 /* servname may be NULL */
780 _DIAGASSERT(res != NULL); 780 _DIAGASSERT(res != NULL);
781 781
782 /* 782 /*
783 * if the servname does not match socktype/protocol, ignore it. 783 * if the servname does not match socktype/protocol, ignore it.
784 */ 784 */
785 if (get_portmatch(pai, servname, svd) != 0) 785 if (get_portmatch(pai, servname, svd) != 0)
786 return 0; 786 return 0;
787 787
788 afd = find_afd(pai->ai_family); 788 afd = find_afd(pai->ai_family);
789 if (afd == NULL) 789 if (afd == NULL)
790 return 0; 790 return 0;
791 791
792 if (!afd->a_scoped) 792 if (!afd->a_scoped)
793 return explore_numeric(pai, hostname, servname, res, hostname, 793 return explore_numeric(pai, hostname, servname, res, hostname,
794 svd); 794 svd);
795 795
796 cp = strchr(hostname, SCOPE_DELIMITER); 796 cp = strchr(hostname, SCOPE_DELIMITER);
797 if (cp == NULL) 797 if (cp == NULL)
798 return explore_numeric(pai, hostname, servname, res, hostname, 798 return explore_numeric(pai, hostname, servname, res, hostname,
799 svd); 799 svd);
800 800
801 /* 801 /*
802 * Handle special case of <scoped_address><delimiter><scope id> 802 * Handle special case of <scoped_address><delimiter><scope id>
803 */ 803 */
804 hostname2 = strdup(hostname); 804 hostname2 = strdup(hostname);
805 if (hostname2 == NULL) 805 if (hostname2 == NULL)
806 return EAI_MEMORY; 806 return EAI_MEMORY;
807 /* terminate at the delimiter */ 807 /* terminate at the delimiter */
808 hostname2[cp - hostname] = '\0'; 808 hostname2[cp - hostname] = '\0';
809 addr = hostname2; 809 addr = hostname2;
810 scope = cp + 1; 810 scope = cp + 1;
811 811
812 error = explore_numeric(pai, addr, servname, res, hostname, svd); 812 error = explore_numeric(pai, addr, servname, res, hostname, svd);
813 if (error == 0) { 813 if (error == 0) {
814 u_int32_t scopeid; 814 u_int32_t scopeid;
815 815
816 for (cur = *res; cur; cur = cur->ai_next) { 816 for (cur = *res; cur; cur = cur->ai_next) {
817 if (cur->ai_family != AF_INET6) 817 if (cur->ai_family != AF_INET6)
818 continue; 818 continue;
819 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; 819 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
820 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) { 820 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
821 free(hostname2); 821 free(hostname2);
822 return(EAI_NODATA); /* XXX: is return OK? */ 822 return(EAI_NODATA); /* XXX: is return OK? */
823 } 823 }
824 sin6->sin6_scope_id = scopeid; 824 sin6->sin6_scope_id = scopeid;
825 } 825 }
826 } 826 }
827 827
828 free(hostname2); 828 free(hostname2);
829 829
830 return error; 830 return error;
831#endif 831#endif
832} 832}
833 833
834static int 834static int
835get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str) 835get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
836{ 836{
837 837
838 _DIAGASSERT(pai != NULL); 838 _DIAGASSERT(pai != NULL);
839 _DIAGASSERT(ai != NULL); 839 _DIAGASSERT(ai != NULL);
840 _DIAGASSERT(str != NULL); 840 _DIAGASSERT(str != NULL);
841 841
842 if ((pai->ai_flags & AI_CANONNAME) != 0) { 842 if ((pai->ai_flags & AI_CANONNAME) != 0) {
843 ai->ai_canonname = strdup(str); 843 ai->ai_canonname = strdup(str);
844 if (ai->ai_canonname == NULL) 844 if (ai->ai_canonname == NULL)
845 return EAI_MEMORY; 845 return EAI_MEMORY;
846 } 846 }
847 return 0; 847 return 0;
848} 848}
849 849
850struct addrinfo * 850struct addrinfo *
851allocaddrinfo(socklen_t addrlen) 851allocaddrinfo(socklen_t addrlen)
852{ 852{
853 struct addrinfo *ai; 853 struct addrinfo *ai;
854 854
855 ai = calloc(sizeof(struct addrinfo) + addrlen, 1); 855 ai = calloc(sizeof(struct addrinfo) + addrlen, 1);
856 if (ai) { 856 if (ai) {
857 ai->ai_addr = (void *)(ai+1); 857 ai->ai_addr = (void *)(ai+1);
858 ai->ai_addrlen = ai->ai_addr->sa_len = addrlen; 858 ai->ai_addrlen = ai->ai_addr->sa_len = addrlen;
859 } 859 }
860 860
861 return ai; 861 return ai;
862} 862}
863 863
864static struct addrinfo * 864static struct addrinfo *
865get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) 865get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
866{ 866{
867 char *p; 867 char *p;
868 struct addrinfo *ai; 868 struct addrinfo *ai;
869 struct sockaddr *save; 869 struct sockaddr *save;
870 870
871 _DIAGASSERT(pai != NULL); 871 _DIAGASSERT(pai != NULL);
872 _DIAGASSERT(afd != NULL); 872 _DIAGASSERT(afd != NULL);
873 _DIAGASSERT(addr != NULL); 873 _DIAGASSERT(addr != NULL);
874 874
875 ai = allocaddrinfo((socklen_t)afd->a_socklen); 875 ai = allocaddrinfo((socklen_t)afd->a_socklen);
876 if (ai == NULL) 876 if (ai == NULL)
877 return NULL; 877 return NULL;
878 878
879 save = ai->ai_addr; 879 save = ai->ai_addr;
880 memcpy(ai, pai, sizeof(struct addrinfo)); 880 memcpy(ai, pai, sizeof(struct addrinfo));
881 881
882 /* since we just overwrote all of ai, we have 882 /* since we just overwrote all of ai, we have
883 to restore ai_addr and ai_addrlen */ 883 to restore ai_addr and ai_addrlen */
884 ai->ai_addr = save; 884 ai->ai_addr = save;
885 ai->ai_addrlen = (socklen_t)afd->a_socklen; 885 ai->ai_addrlen = (socklen_t)afd->a_socklen;
886  886
887 ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 887 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
888 p = (char *)(void *)(ai->ai_addr); 888 p = (char *)(void *)(ai->ai_addr);
889 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); 889 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
890 return ai; 890 return ai;
891} 891}
892 892
893static int 893static int
894get_portmatch(const struct addrinfo *ai, const char *servname, 894get_portmatch(const struct addrinfo *ai, const char *servname,
895 struct servent_data *svd) 895 struct servent_data *svd)
896{ 896{
897 897
898 _DIAGASSERT(ai != NULL); 898 _DIAGASSERT(ai != NULL);
899 /* servname may be NULL */ 899 /* servname may be NULL */
900 900
901 return get_port(ai, servname, 1, svd); 901 return get_port(ai, servname, 1, svd);
902} 902}
903 903
904static int 904static int
905get_port(const struct addrinfo *ai, const char *servname, int matchonly, 905get_port(const struct addrinfo *ai, const char *servname, int matchonly,
906 struct servent_data *svd) 906 struct servent_data *svd)
907{ 907{
908 const char *proto; 908 const char *proto;
909 struct servent *sp; 909 struct servent *sp;
910 int port; 910 int port;
911 int allownumeric; 911 int allownumeric;
912 912
913 _DIAGASSERT(ai != NULL); 913 _DIAGASSERT(ai != NULL);
914 /* servname may be NULL */ 914 /* servname may be NULL */
915 915
916 if (servname == NULL) 916 if (servname == NULL)
917 return 0; 917 return 0;
918 switch (ai->ai_family) { 918 switch (ai->ai_family) {
919 case AF_INET: 919 case AF_INET:
920#ifdef AF_INET6 920#ifdef AF_INET6
921 case AF_INET6: 921 case AF_INET6:
922#endif 922#endif
923 break; 923 break;
924 default: 924 default:
925 return 0; 925 return 0;
926 } 926 }
927 927
928 switch (ai->ai_socktype) { 928 switch (ai->ai_socktype) {
929 case SOCK_RAW: 929 case SOCK_RAW:
930 return EAI_SERVICE; 930 return EAI_SERVICE;
931 case SOCK_DGRAM: 931 case SOCK_DGRAM:
932 case SOCK_STREAM: 932 case SOCK_STREAM:
933 allownumeric = 1; 933 allownumeric = 1;
934 break; 934 break;
935 case ANY: 935 case ANY:
936 /* 936 /*
937 * This was 0. It is now 1 so that queries specifying 937 * This was 0. It is now 1 so that queries specifying
938 * a NULL hint, or hint without socktype (but, hopefully, 938 * a NULL hint, or hint without socktype (but, hopefully,
939 * with protocol) and numeric address actually work. 939 * with protocol) and numeric address actually work.
940 */ 940 */
941 allownumeric = 1; 941 allownumeric = 1;
942 break; 942 break;
943 default: 943 default:
944 return EAI_SOCKTYPE; 944 return EAI_SOCKTYPE;
945 } 945 }
946 946
947 port = str2number(servname); 947 port = str2number(servname);
948 if (port >= 0) { 948 if (port >= 0) {
949 if (!allownumeric) 949 if (!allownumeric)
950 return EAI_SERVICE; 950 return EAI_SERVICE;
951 if (port < 0 || port > 65535) 951 if (port < 0 || port > 65535)
952 return EAI_SERVICE; 952 return EAI_SERVICE;
953 port = htons(port); 953 port = htons(port);
954 } else { 954 } else {
955 struct servent sv; 955 struct servent sv;
956 if (ai->ai_flags & AI_NUMERICSERV) 956 if (ai->ai_flags & AI_NUMERICSERV)
957 return EAI_NONAME; 957 return EAI_NONAME;
958 958
959 switch (ai->ai_socktype) { 959 switch (ai->ai_socktype) {
960 case SOCK_DGRAM: 960 case SOCK_DGRAM:
961 proto = "udp"; 961 proto = "udp";
962 break; 962 break;
963 case SOCK_STREAM: 963 case SOCK_STREAM:
964 proto = "tcp"; 964 proto = "tcp";
965 break; 965 break;
966 default: 966 default:
967 proto = NULL; 967 proto = NULL;
968 break; 968 break;
969 } 969 }
970 970
971 sp = getservbyname_r(servname, proto, &sv, svd); 971 sp = getservbyname_r(servname, proto, &sv, svd);
972 if (sp == NULL) 972 if (sp == NULL)
973 return EAI_SERVICE; 973 return EAI_SERVICE;
974 port = sp->s_port; 974 port = sp->s_port;
975 } 975 }
976 976
977 if (!matchonly) { 977 if (!matchonly) {
978 switch (ai->ai_family) { 978 switch (ai->ai_family) {
979 case AF_INET: 979 case AF_INET:
980 ((struct sockaddr_in *)(void *) 980 ((struct sockaddr_in *)(void *)
981 ai->ai_addr)->sin_port = port; 981 ai->ai_addr)->sin_port = port;
982 break; 982 break;
983#ifdef INET6 983#ifdef INET6
984 case AF_INET6: 984 case AF_INET6:
985 ((struct sockaddr_in6 *)(void *) 985 ((struct sockaddr_in6 *)(void *)
986 ai->ai_addr)->sin6_port = port; 986 ai->ai_addr)->sin6_port = port;
987 break; 987 break;
988#endif 988#endif
989 } 989 }
990 } 990 }
991 991
992 return 0; 992 return 0;
993} 993}
994 994
995static const struct afd * 995static const struct afd *
996find_afd(int af) 996find_afd(int af)
997{ 997{
998 const struct afd *afd; 998 const struct afd *afd;
999 999
1000 if (af == PF_UNSPEC) 1000 if (af == PF_UNSPEC)
1001 return NULL; 1001 return NULL;
1002 for (afd = afdl; afd->a_af; afd++) { 1002 for (afd = afdl; afd->a_af; afd++) {
1003 if (afd->a_af == af) 1003 if (afd->a_af == af)
1004 return afd; 1004 return afd;
1005 } 1005 }
1006 return NULL; 1006 return NULL;
1007} 1007}
1008 1008
1009#ifdef INET6 1009#ifdef INET6
1010/* convert a string to a scope identifier. XXX: IPv6 specific */ 1010/* convert a string to a scope identifier. XXX: IPv6 specific */
1011static int 1011static int
1012ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) 1012ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
1013{ 1013{
1014 u_long lscopeid; 1014 u_long lscopeid;
1015 struct in6_addr *a6; 1015 struct in6_addr *a6;
1016 char *ep; 1016 char *ep;
1017 1017
1018 _DIAGASSERT(scope != NULL); 1018 _DIAGASSERT(scope != NULL);
1019 _DIAGASSERT(sin6 != NULL); 1019 _DIAGASSERT(sin6 != NULL);
1020 _DIAGASSERT(scopeid != NULL); 1020 _DIAGASSERT(scopeid != NULL);
1021 1021
1022 a6 = &sin6->sin6_addr; 1022 a6 = &sin6->sin6_addr;
1023 1023
1024 /* empty scopeid portion is invalid */ 1024 /* empty scopeid portion is invalid */
1025 if (*scope == '\0') 1025 if (*scope == '\0')
1026 return -1; 1026 return -1;
1027 1027
1028 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { 1028 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
1029 /* 1029 /*
1030 * We currently assume a one-to-one mapping between links 1030 * We currently assume an one-to-one mapping between links
1031 * and interfaces, so we simply use interface indices for 1031 * and interfaces, so we simply use interface indices for
1032 * like-local scopes. 1032 * like-local scopes.
1033 */ 1033 */
1034 *scopeid = if_nametoindex(scope); 1034 *scopeid = if_nametoindex(scope);
1035 if (*scopeid == 0) 1035 if (*scopeid == 0)
1036 goto trynumeric; 1036 goto trynumeric;
1037 return 0; 1037 return 0;
1038 } 1038 }
1039 1039
1040 /* still unclear about literal, allow numeric only - placeholder */ 1040 /* still unclear about literal, allow numeric only - placeholder */
1041 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) 1041 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
1042 goto trynumeric; 1042 goto trynumeric;
1043 if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) 1043 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
1044 goto trynumeric; 1044 goto trynumeric;
1045 else 1045 else
1046 goto trynumeric; /* global */ 1046 goto trynumeric; /* global */
1047 1047
1048 /* try to convert to a numeric id as a last resort */ 1048 /* try to convert to a numeric id as a last resort */
1049 trynumeric: 1049 trynumeric:
1050 errno = 0; 1050 errno = 0;
1051 lscopeid = strtoul(scope, &ep, 10); 1051 lscopeid = strtoul(scope, &ep, 10);
1052 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL); 1052 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
1053 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid) 1053 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
1054 return 0; 1054 return 0;
1055 else 1055 else
1056 return -1; 1056 return -1;
1057} 1057}
1058#endif 1058#endif
1059 1059
1060/* code duplicate with gethnamaddr.c */ 1060/* code duplicate with gethnamaddr.c */
1061 1061
1062static const char AskedForGot[] = 1062static const char AskedForGot[] =
1063 "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 1063 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1064 1064
1065static struct addrinfo * 1065static struct addrinfo *
1066getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 1066getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
1067 const struct addrinfo *pai) 1067 const struct addrinfo *pai)
1068{ 1068{
1069 struct addrinfo sentinel, *cur; 1069 struct addrinfo sentinel, *cur;
1070 struct addrinfo ai; 1070 struct addrinfo ai;
1071 const struct afd *afd; 1071 const struct afd *afd;
1072 char *canonname; 1072 char *canonname;
1073 const HEADER *hp; 1073 const HEADER *hp;
1074 const u_char *cp; 1074 const u_char *cp;
1075 int n; 1075 int n;
1076 const u_char *eom; 1076 const u_char *eom;
1077 char *bp, *ep; 1077 char *bp, *ep;
1078 int type, class, ancount, qdcount; 1078 int type, class, ancount, qdcount;
1079 int haveanswer, had_error; 1079 int haveanswer, had_error;
1080 char tbuf[MAXDNAME]; 1080 char tbuf[MAXDNAME];
1081 int (*name_ok) (const char *); 1081 int (*name_ok) (const char *);
1082 char hostbuf[8*1024]; 1082 char hostbuf[8*1024];
1083 1083
1084 _DIAGASSERT(answer != NULL); 1084 _DIAGASSERT(answer != NULL);
1085 _DIAGASSERT(qname != NULL); 1085 _DIAGASSERT(qname != NULL);
1086 _DIAGASSERT(pai != NULL); 1086 _DIAGASSERT(pai != NULL);
1087 1087
1088 memset(&sentinel, 0, sizeof(sentinel)); 1088 memset(&sentinel, 0, sizeof(sentinel));
1089 cur = &sentinel; 1089 cur = &sentinel;
1090 1090
1091 canonname = NULL; 1091 canonname = NULL;
1092 eom = answer->buf + anslen; 1092 eom = answer->buf + anslen;
1093 switch (qtype) { 1093 switch (qtype) {
1094 case T_A: 1094 case T_A:
1095 case T_AAAA: 1095 case T_AAAA:
1096 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/ 1096 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
1097 name_ok = res_hnok; 1097 name_ok = res_hnok;
1098 break; 1098 break;
1099 default: 1099 default:
1100 return NULL; /* XXX should be abort(); */ 1100 return NULL; /* XXX should be abort(); */
1101 } 1101 }
1102 /* 1102 /*
1103 * find first satisfactory answer 1103 * find first satisfactory answer
1104 */ 1104 */
1105 hp = &answer->hdr; 1105 hp = &answer->hdr;
1106 ancount = ntohs(hp->ancount); 1106 ancount = ntohs(hp->ancount);
1107 qdcount = ntohs(hp->qdcount); 1107 qdcount = ntohs(hp->qdcount);
1108 bp = hostbuf; 1108 bp = hostbuf;
1109 ep = hostbuf + sizeof hostbuf; 1109 ep = hostbuf + sizeof hostbuf;
1110 cp = answer->buf + HFIXEDSZ; 1110 cp = answer->buf + HFIXEDSZ;
1111 if (qdcount != 1) { 1111 if (qdcount != 1) {
1112 h_errno = NO_RECOVERY; 1112 h_errno = NO_RECOVERY;
1113 return (NULL); 1113 return (NULL);
1114 } 1114 }
1115 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 1115 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1116 if ((n < 0) || !(*name_ok)(bp)) { 1116 if ((n < 0) || !(*name_ok)(bp)) {
1117 h_errno = NO_RECOVERY; 1117 h_errno = NO_RECOVERY;
1118 return (NULL); 1118 return (NULL);
1119 } 1119 }
1120 cp += n + QFIXEDSZ; 1120 cp += n + QFIXEDSZ;
1121 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { 1121 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1122 /* res_send() has already verified that the query name is the 1122 /* res_send() has already verified that the query name is the
1123 * same as the one we sent; this just gets the expanded name 1123 * same as the one we sent; this just gets the expanded name
1124 * (i.e., with the succeeding search-domain tacked on). 1124 * (i.e., with the succeeding search-domain tacked on).
1125 */ 1125 */
1126 n = strlen(bp) + 1; /* for the \0 */ 1126 n = strlen(bp) + 1; /* for the \0 */
1127 if (n >= MAXHOSTNAMELEN) { 1127 if (n >= MAXHOSTNAMELEN) {
1128 h_errno = NO_RECOVERY; 1128 h_errno = NO_RECOVERY;
1129 return (NULL); 1129 return (NULL);
1130 } 1130 }
1131 canonname = bp; 1131 canonname = bp;
1132 bp += n; 1132 bp += n;
1133 /* The qname can be abbreviated, but h_name is now absolute. */ 1133 /* The qname can be abbreviated, but h_name is now absolute. */
1134 qname = canonname; 1134 qname = canonname;
1135 } 1135 }
1136 haveanswer = 0; 1136 haveanswer = 0;
1137 had_error = 0; 1137 had_error = 0;
1138 while (ancount-- > 0 && cp < eom && !had_error) { 1138 while (ancount-- > 0 && cp < eom && !had_error) {
1139 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 1139 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1140 if ((n < 0) || !(*name_ok)(bp)) { 1140 if ((n < 0) || !(*name_ok)(bp)) {
1141 had_error++; 1141 had_error++;
1142 continue; 1142 continue;
1143 } 1143 }
1144 cp += n; /* name */ 1144 cp += n; /* name */
1145 type = _getshort(cp); 1145 type = _getshort(cp);
1146 cp += INT16SZ; /* type */ 1146 cp += INT16SZ; /* type */
1147 class = _getshort(cp); 1147 class = _getshort(cp);
1148 cp += INT16SZ + INT32SZ; /* class, TTL */ 1148 cp += INT16SZ + INT32SZ; /* class, TTL */
1149 n = _getshort(cp); 1149 n = _getshort(cp);
1150 cp += INT16SZ; /* len */ 1150 cp += INT16SZ; /* len */
1151 if (class != C_IN) { 1151 if (class != C_IN) {
1152 /* XXX - debug? syslog? */ 1152 /* XXX - debug? syslog? */
1153 cp += n; 1153 cp += n;
1154 continue; /* XXX - had_error++ ? */ 1154 continue; /* XXX - had_error++ ? */
1155 } 1155 }
1156 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && 1156 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1157 type == T_CNAME) { 1157 type == T_CNAME) {
1158 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 1158 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1159 if ((n < 0) || !(*name_ok)(tbuf)) { 1159 if ((n < 0) || !(*name_ok)(tbuf)) {
1160 had_error++; 1160 had_error++;
1161 continue; 1161 continue;
1162 } 1162 }
1163 cp += n; 1163 cp += n;
1164 /* Get canonical name. */ 1164 /* Get canonical name. */
1165 n = strlen(tbuf) + 1; /* for the \0 */ 1165 n = strlen(tbuf) + 1; /* for the \0 */
1166 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 1166 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1167 had_error++; 1167 had_error++;
1168 continue; 1168 continue;
1169 } 1169 }
1170 strlcpy(bp, tbuf, (size_t)(ep - bp)); 1170 strlcpy(bp, tbuf, (size_t)(ep - bp));
1171 canonname = bp; 1171 canonname = bp;
1172 bp += n; 1172 bp += n;
1173 continue; 1173 continue;
1174 } 1174 }
1175 if (qtype == T_ANY) { 1175 if (qtype == T_ANY) {
1176 if (!(type == T_A || type == T_AAAA)) { 1176 if (!(type == T_A || type == T_AAAA)) {
1177 cp += n; 1177 cp += n;
1178 continue; 1178 continue;
1179 } 1179 }
1180 } else if (type != qtype) { 1180 } else if (type != qtype) {
1181 if (type != T_KEY && type != T_SIG) { 1181 if (type != T_KEY && type != T_SIG) {
1182 struct syslog_data sd = SYSLOG_DATA_INIT; 1182 struct syslog_data sd = SYSLOG_DATA_INIT;
1183 syslog_r(LOG_NOTICE|LOG_AUTH, &sd, 1183 syslog_r(LOG_NOTICE|LOG_AUTH, &sd,
1184 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 1184 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1185 qname, p_class(C_IN), p_type(qtype), 1185 qname, p_class(C_IN), p_type(qtype),
1186 p_type(type)); 1186 p_type(type));
1187 } 1187 }
1188 cp += n; 1188 cp += n;
1189 continue; /* XXX - had_error++ ? */ 1189 continue; /* XXX - had_error++ ? */
1190 } 1190 }
1191 switch (type) { 1191 switch (type) {
1192 case T_A: 1192 case T_A:
1193 case T_AAAA: 1193 case T_AAAA:
1194 if (strcasecmp(canonname, bp) != 0) { 1194 if (strcasecmp(canonname, bp) != 0) {
1195 struct syslog_data sd = SYSLOG_DATA_INIT; 1195 struct syslog_data sd = SYSLOG_DATA_INIT;
1196 syslog_r(LOG_NOTICE|LOG_AUTH, &sd, 1196 syslog_r(LOG_NOTICE|LOG_AUTH, &sd,
1197 AskedForGot, canonname, bp); 1197 AskedForGot, canonname, bp);
1198 cp += n; 1198 cp += n;
1199 continue; /* XXX - had_error++ ? */ 1199 continue; /* XXX - had_error++ ? */
1200 } 1200 }
1201 if (type == T_A && n != INADDRSZ) { 1201 if (type == T_A && n != INADDRSZ) {
1202 cp += n; 1202 cp += n;
1203 continue; 1203 continue;
1204 } 1204 }
1205 if (type == T_AAAA && n != IN6ADDRSZ) { 1205 if (type == T_AAAA && n != IN6ADDRSZ) {
1206 cp += n; 1206 cp += n;
1207 continue; 1207 continue;
1208 } 1208 }
1209 if (type == T_AAAA) { 1209 if (type == T_AAAA) {
1210 struct in6_addr in6; 1210 struct in6_addr in6;
1211 memcpy(&in6, cp, IN6ADDRSZ); 1211 memcpy(&in6, cp, IN6ADDRSZ);
1212 if (IN6_IS_ADDR_V4MAPPED(&in6)) { 1212 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1213 cp += n; 1213 cp += n;
1214 continue; 1214 continue;
1215 } 1215 }
1216 } 1216 }
1217 if (!haveanswer) { 1217 if (!haveanswer) {
1218 int nn; 1218 int nn;
1219 1219
1220 canonname = bp; 1220 canonname = bp;
1221 nn = strlen(bp) + 1; /* for the \0 */ 1221 nn = strlen(bp) + 1; /* for the \0 */
1222 bp += nn; 1222 bp += nn;
1223 } 1223 }
1224 1224
1225 /* don't overwrite pai */ 1225 /* don't overwrite pai */
1226 ai = *pai; 1226 ai = *pai;
1227 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6; 1227 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1228 afd = find_afd(ai.ai_family); 1228 afd = find_afd(ai.ai_family);
1229 if (afd == NULL) { 1229 if (afd == NULL) {
1230 cp += n; 1230 cp += n;
1231 continue; 1231 continue;
1232 } 1232 }
1233 cur->ai_next = get_ai(&ai, afd, (const char *)cp); 1233 cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1234 if (cur->ai_next == NULL) 1234 if (cur->ai_next == NULL)
1235 had_error++; 1235 had_error++;
1236 while (cur && cur->ai_next) 1236 while (cur && cur->ai_next)
1237 cur = cur->ai_next; 1237 cur = cur->ai_next;
1238 cp += n; 1238 cp += n;
1239 break; 1239 break;
1240 default: 1240 default:
1241 abort(); 1241 abort();
1242 } 1242 }
1243 if (!had_error) 1243 if (!had_error)
1244 haveanswer++; 1244 haveanswer++;
1245 } 1245 }
1246 if (haveanswer) { 1246 if (haveanswer) {
1247 if (!canonname) 1247 if (!canonname)
1248 (void)get_canonname(pai, sentinel.ai_next, qname); 1248 (void)get_canonname(pai, sentinel.ai_next, qname);
1249 else 1249 else
1250 (void)get_canonname(pai, sentinel.ai_next, canonname); 1250 (void)get_canonname(pai, sentinel.ai_next, canonname);
1251 h_errno = NETDB_SUCCESS; 1251 h_errno = NETDB_SUCCESS;
1252 return sentinel.ai_next; 1252 return sentinel.ai_next;
1253 } 1253 }
1254 1254
1255 h_errno = NO_RECOVERY; 1255 h_errno = NO_RECOVERY;
1256 return NULL; 1256 return NULL;
1257} 1257}
1258 1258
1259#define SORTEDADDR(p) (((struct sockaddr_in *)(void *)(p->ai_next->ai_addr))->sin_addr.s_addr) 1259#define SORTEDADDR(p) (((struct sockaddr_in *)(void *)(p->ai_next->ai_addr))->sin_addr.s_addr)
1260#define SORTMATCH(p, s) ((SORTEDADDR(p) & (s).mask) == (s).addr.s_addr) 1260#define SORTMATCH(p, s) ((SORTEDADDR(p) & (s).mask) == (s).addr.s_addr)
1261 1261
1262static void 1262static void
1263aisort(struct addrinfo *s, res_state res) 1263aisort(struct addrinfo *s, res_state res)
1264{ 1264{
1265 struct addrinfo head, *t, *p; 1265 struct addrinfo head, *t, *p;
1266 int i; 1266 int i;
1267 1267
1268 head.ai_next = NULL; 1268 head.ai_next = NULL;
1269 t = &head; 1269 t = &head;
1270 1270
1271 for (i = 0; i < res->nsort; i++) { 1271 for (i = 0; i < res->nsort; i++) {
1272 p = s; 1272 p = s;
1273 while (p->ai_next) { 1273 while (p->ai_next) {
1274 if ((p->ai_next->ai_family != AF_INET) 1274 if ((p->ai_next->ai_family != AF_INET)
1275 || SORTMATCH(p, res->sort_list[i])) { 1275 || SORTMATCH(p, res->sort_list[i])) {
1276 t->ai_next = p->ai_next; 1276 t->ai_next = p->ai_next;
1277 t = t->ai_next; 1277 t = t->ai_next;
1278 p->ai_next = p->ai_next->ai_next; 1278 p->ai_next = p->ai_next->ai_next;
1279 } else { 1279 } else {
1280 p = p->ai_next; 1280 p = p->ai_next;
1281 } 1281 }
1282 } 1282 }
1283 } 1283 }
1284 1284
1285 /* add rest of list and reset s to the new list*/ 1285 /* add rest of list and reset s to the new list*/
1286 t->ai_next = s->ai_next; 1286 t->ai_next = s->ai_next;
1287 s->ai_next = head.ai_next; 1287 s->ai_next = head.ai_next;
1288} 1288}
1289 1289
1290/*ARGSUSED*/ 1290/*ARGSUSED*/
1291static int 1291static int
1292_dns_getaddrinfo(void *rv, void *cb_data, va_list ap) 1292_dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
1293{ 1293{
1294 struct addrinfo *ai; 1294 struct addrinfo *ai;
1295 querybuf *buf, *buf2; 1295 querybuf *buf, *buf2;
1296 const char *name; 1296 const char *name;
1297 const struct addrinfo *pai; 1297 const struct addrinfo *pai;
1298 struct addrinfo sentinel, *cur; 1298 struct addrinfo sentinel, *cur;
1299 struct res_target q, q2; 1299 struct res_target q, q2;
1300 res_state res; 1300 res_state res;
1301 1301
1302 name = va_arg(ap, char *); 1302 name = va_arg(ap, char *);
1303 pai = va_arg(ap, const struct addrinfo *); 1303 pai = va_arg(ap, const struct addrinfo *);
1304 1304
1305 memset(&q, 0, sizeof(q)); 1305 memset(&q, 0, sizeof(q));
1306 memset(&q2, 0, sizeof(q2)); 1306 memset(&q2, 0, sizeof(q2));
1307 memset(&sentinel, 0, sizeof(sentinel)); 1307 memset(&sentinel, 0, sizeof(sentinel));
1308 cur = &sentinel; 1308 cur = &sentinel;
1309 1309
1310 buf = malloc(sizeof(*buf)); 1310 buf = malloc(sizeof(*buf));
1311 if (buf == NULL) { 1311 if (buf == NULL) {
1312 h_errno = NETDB_INTERNAL; 1312 h_errno = NETDB_INTERNAL;
1313 return NS_NOTFOUND; 1313 return NS_NOTFOUND;
1314 } 1314 }
1315 buf2 = malloc(sizeof(*buf2)); 1315 buf2 = malloc(sizeof(*buf2));
1316 if (buf2 == NULL) { 1316 if (buf2 == NULL) {
1317 free(buf); 1317 free(buf);
1318 h_errno = NETDB_INTERNAL; 1318 h_errno = NETDB_INTERNAL;
1319 return NS_NOTFOUND; 1319 return NS_NOTFOUND;
1320 } 1320 }
1321 1321
1322 switch (pai->ai_family) { 1322 switch (pai->ai_family) {
1323 case AF_UNSPEC: 1323 case AF_UNSPEC:
1324 /* prefer IPv6 */ 1324 /* prefer IPv6 */
1325 q.name = name; 1325 q.name = name;
1326 q.qclass = C_IN; 1326 q.qclass = C_IN;
1327 q.qtype = T_AAAA; 1327 q.qtype = T_AAAA;
1328 q.answer = buf->buf; 1328 q.answer = buf->buf;
1329 q.anslen = sizeof(buf->buf); 1329 q.anslen = sizeof(buf->buf);
1330 q.next = &q2; 1330 q.next = &q2;
1331 q2.name = name; 1331 q2.name = name;
1332 q2.qclass = C_IN; 1332 q2.qclass = C_IN;
1333 q2.qtype = T_A; 1333 q2.qtype = T_A;
1334 q2.answer = buf2->buf; 1334 q2.answer = buf2->buf;
1335 q2.anslen = sizeof(buf2->buf); 1335 q2.anslen = sizeof(buf2->buf);
1336 break; 1336 break;
1337 case AF_INET: 1337 case AF_INET:
1338 q.name = name; 1338 q.name = name;
1339 q.qclass = C_IN; 1339 q.qclass = C_IN;
1340 q.qtype = T_A; 1340 q.qtype = T_A;
1341 q.answer = buf->buf; 1341 q.answer = buf->buf;
1342 q.anslen = sizeof(buf->buf); 1342 q.anslen = sizeof(buf->buf);
1343 break; 1343 break;
1344 case AF_INET6: 1344 case AF_INET6:
1345 q.name = name; 1345 q.name = name;
1346 q.qclass = C_IN; 1346 q.qclass = C_IN;
1347 q.qtype = T_AAAA; 1347 q.qtype = T_AAAA;
1348 q.answer = buf->buf; 1348 q.answer = buf->buf;
1349 q.anslen = sizeof(buf->buf); 1349 q.anslen = sizeof(buf->buf);
1350 break; 1350 break;
1351 default: 1351 default:
1352 free(buf); 1352 free(buf);
1353 free(buf2); 1353 free(buf2);
1354 return NS_UNAVAIL; 1354 return NS_UNAVAIL;
1355 } 1355 }
1356 1356
1357 res = __res_get_state(); 1357 res = __res_get_state();
1358 if (res == NULL) { 1358 if (res == NULL) {
1359 free(buf); 1359 free(buf);
1360 free(buf2); 1360 free(buf2);
1361 return NS_NOTFOUND; 1361 return NS_NOTFOUND;
1362 } 1362 }
1363 1363
1364 if (res_searchN(name, &q, res) < 0) { 1364 if (res_searchN(name, &q, res) < 0) {
1365 __res_put_state(res); 1365 __res_put_state(res);
1366 free(buf); 1366 free(buf);
1367 free(buf2); 1367 free(buf2);
1368 return NS_NOTFOUND; 1368 return NS_NOTFOUND;
1369 } 1369 }
1370 ai = getanswer(buf, q.n, q.name, q.qtype, pai); 1370 ai = getanswer(buf, q.n, q.name, q.qtype, pai);
1371 if (ai) { 1371 if (ai) {
1372 cur->ai_next = ai; 1372 cur->ai_next = ai;
1373 while (cur && cur->ai_next) 1373 while (cur && cur->ai_next)
1374 cur = cur->ai_next; 1374 cur = cur->ai_next;
1375 } 1375 }
1376 if (q.next) { 1376 if (q.next) {
1377 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai); 1377 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
1378 if (ai) 1378 if (ai)
1379 cur->ai_next = ai; 1379 cur->ai_next = ai;
1380 } 1380 }
1381 free(buf); 1381 free(buf);
1382 free(buf2); 1382 free(buf2);
1383 if (sentinel.ai_next == NULL) { 1383 if (sentinel.ai_next == NULL) {
1384 __res_put_state(res); 1384 __res_put_state(res);
1385 switch (h_errno) { 1385 switch (h_errno) {
1386 case HOST_NOT_FOUND: 1386 case HOST_NOT_FOUND:
1387 return NS_NOTFOUND; 1387 return NS_NOTFOUND;
1388 case TRY_AGAIN: 1388 case TRY_AGAIN:
1389 return NS_TRYAGAIN; 1389 return NS_TRYAGAIN;
1390 default: 1390 default:
1391 return NS_UNAVAIL; 1391 return NS_UNAVAIL;
1392 } 1392 }
1393 } 1393 }
1394 1394
1395 if (res->nsort) 1395 if (res->nsort)
1396 aisort(&sentinel, res); 1396 aisort(&sentinel, res);
1397 1397
1398 __res_put_state(res); 1398 __res_put_state(res);
1399 1399
1400 *((struct addrinfo **)rv) = sentinel.ai_next; 1400 *((struct addrinfo **)rv) = sentinel.ai_next;
1401 return NS_SUCCESS; 1401 return NS_SUCCESS;
1402} 1402}
1403 1403
1404static void 1404static void
1405_sethtent(FILE **hostf) 1405_sethtent(FILE **hostf)
1406{ 1406{
1407 1407
1408 if (!*hostf) 1408 if (!*hostf)
1409 *hostf = fopen(_PATH_HOSTS, "r" ); 1409 *hostf = fopen(_PATH_HOSTS, "r" );
1410 else 1410 else
1411 rewind(*hostf); 1411 rewind(*hostf);
1412} 1412}
1413 1413
1414static void 1414static void
1415_endhtent(FILE **hostf) 1415_endhtent(FILE **hostf)
1416{ 1416{
1417 1417
1418 if (*hostf) { 1418 if (*hostf) {
1419 (void) fclose(*hostf); 1419 (void) fclose(*hostf);
1420 *hostf = NULL; 1420 *hostf = NULL;
1421 } 1421 }
1422} 1422}
1423 1423
1424static struct addrinfo * 1424static struct addrinfo *
1425_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai) 1425_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
1426{ 1426{
1427 char *p; 1427 char *p;
1428 char *cp, *tname, *cname; 1428 char *cp, *tname, *cname;
1429 struct addrinfo hints, *res0, *res; 1429 struct addrinfo hints, *res0, *res;
1430 int error; 1430 int error;
1431 const char *addr; 1431 const char *addr;
1432 char hostbuf[8*1024]; 1432 char hostbuf[8*1024];
1433 1433
1434 _DIAGASSERT(name != NULL); 1434 _DIAGASSERT(name != NULL);
1435 _DIAGASSERT(pai != NULL); 1435 _DIAGASSERT(pai != NULL);
1436 1436
1437 if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r" ))) 1437 if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r" )))
1438 return (NULL); 1438 return (NULL);
1439 again: 1439 again:
1440 if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf))) 1440 if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
1441 return (NULL); 1441 return (NULL);
1442 if (*p == '#') 1442 if (*p == '#')
1443 goto again; 1443 goto again;
1444 if (!(cp = strpbrk(p, "#\n"))) 1444 if (!(cp = strpbrk(p, "#\n")))
1445 goto again; 1445 goto again;
1446 *cp = '\0'; 1446 *cp = '\0';
1447 if (!(cp = strpbrk(p, " \t"))) 1447 if (!(cp = strpbrk(p, " \t")))
1448 goto again; 1448 goto again;
1449 *cp++ = '\0'; 1449 *cp++ = '\0';
1450 addr = p; 1450 addr = p;
1451 /* if this is not something we're looking for, skip it. */ 1451 /* if this is not something we're looking for, skip it. */
1452 cname = NULL; 1452 cname = NULL;
1453 while (cp && *cp) { 1453 while (cp && *cp) {
1454 if (*cp == ' ' || *cp == '\t') { 1454 if (*cp == ' ' || *cp == '\t') {
1455 cp++; 1455 cp++;
1456 continue; 1456 continue;
1457 } 1457 }
1458 if (!cname) 1458 if (!cname)
1459 cname = cp; 1459 cname = cp;
1460 tname = cp; 1460 tname = cp;
1461 if ((cp = strpbrk(cp, " \t")) != NULL) 1461 if ((cp = strpbrk(cp, " \t")) != NULL)
1462 *cp++ = '\0'; 1462 *cp++ = '\0';
1463 if (strcasecmp(name, tname) == 0) 1463 if (strcasecmp(name, tname) == 0)
1464 goto found; 1464 goto found;
1465 } 1465 }
1466 goto again; 1466 goto again;
1467 1467
1468found: 1468found:
1469 hints = *pai; 1469 hints = *pai;
1470 hints.ai_flags = AI_NUMERICHOST; 1470 hints.ai_flags = AI_NUMERICHOST;
1471 error = getaddrinfo(addr, NULL, &hints, &res0); 1471 error = getaddrinfo(addr, NULL, &hints, &res0);
1472 if (error) 1472 if (error)
1473 goto again; 1473 goto again;
1474 for (res = res0; res; res = res->ai_next) { 1474 for (res = res0; res; res = res->ai_next) {
1475 /* cover it up */ 1475 /* cover it up */
1476 res->ai_flags = pai->ai_flags; 1476 res->ai_flags = pai->ai_flags;
1477 1477
1478 if (pai->ai_flags & AI_CANONNAME) { 1478 if (pai->ai_flags & AI_CANONNAME) {
1479 if (get_canonname(pai, res, cname) != 0) { 1479 if (get_canonname(pai, res, cname) != 0) {
1480 freeaddrinfo(res0); 1480 freeaddrinfo(res0);
1481 goto again; 1481 goto again;
1482 } 1482 }
1483 } 1483 }
1484 } 1484 }
1485 return res0; 1485 return res0;
1486} 1486}
1487 1487
1488/*ARGSUSED*/ 1488/*ARGSUSED*/
1489static int 1489static int
1490_files_getaddrinfo(void *rv, void *cb_data, va_list ap) 1490_files_getaddrinfo(void *rv, void *cb_data, va_list ap)
1491{ 1491{
1492 const char *name; 1492 const char *name;
1493 const struct addrinfo *pai; 1493 const struct addrinfo *pai;
1494 struct addrinfo sentinel, *cur; 1494 struct addrinfo sentinel, *cur;
1495 struct addrinfo *p; 1495 struct addrinfo *p;
1496#ifndef _REENTRANT 1496#ifndef _REENTRANT
1497 static 1497 static
1498#endif 1498#endif
1499 FILE *hostf = NULL; 1499 FILE *hostf = NULL;
1500 1500
1501 name = va_arg(ap, char *); 1501 name = va_arg(ap, char *);
1502 pai = va_arg(ap, const struct addrinfo *); 1502 pai = va_arg(ap, const struct addrinfo *);
1503 1503
1504 memset(&sentinel, 0, sizeof(sentinel)); 1504 memset(&sentinel, 0, sizeof(sentinel));
1505 cur = &sentinel; 1505 cur = &sentinel;
1506 1506
1507 _sethtent(&hostf); 1507 _sethtent(&hostf);
1508 while ((p = _gethtent(&hostf, name, pai)) != NULL) { 1508 while ((p = _gethtent(&hostf, name, pai)) != NULL) {
1509 cur->ai_next = p; 1509 cur->ai_next = p;
1510 while (cur && cur->ai_next) 1510 while (cur && cur->ai_next)
1511 cur = cur->ai_next; 1511 cur = cur->ai_next;
1512 } 1512 }
1513 _endhtent(&hostf); 1513 _endhtent(&hostf);
1514 1514
1515 *((struct addrinfo **)rv) = sentinel.ai_next; 1515 *((struct addrinfo **)rv) = sentinel.ai_next;
1516 if (sentinel.ai_next == NULL) 1516 if (sentinel.ai_next == NULL)
1517 return NS_NOTFOUND; 1517 return NS_NOTFOUND;
1518 return NS_SUCCESS; 1518 return NS_SUCCESS;
1519} 1519}
1520 1520
1521#ifdef YP 1521#ifdef YP
1522/*ARGSUSED*/ 1522/*ARGSUSED*/
1523static struct addrinfo * 1523static struct addrinfo *
1524_yphostent(char *line, const struct addrinfo *pai) 1524_yphostent(char *line, const struct addrinfo *pai)
1525{ 1525{
1526 struct addrinfo sentinel, *cur; 1526 struct addrinfo sentinel, *cur;
1527 struct addrinfo hints, *res, *res0; 1527 struct addrinfo hints, *res, *res0;
1528 int error; 1528 int error;
1529 char *p; 1529 char *p;
1530 const char *addr, *canonname; 1530 const char *addr, *canonname;
1531 char *nextline; 1531 char *nextline;
1532 char *cp; 1532 char *cp;
1533 1533
1534 _DIAGASSERT(line != NULL); 1534 _DIAGASSERT(line != NULL);
1535 _DIAGASSERT(pai != NULL); 1535 _DIAGASSERT(pai != NULL);
1536 1536
1537 p = line; 1537 p = line;
1538 addr = canonname = NULL; 1538 addr = canonname = NULL;
1539 1539
1540 memset(&sentinel, 0, sizeof(sentinel)); 1540 memset(&sentinel, 0, sizeof(sentinel));
1541 cur = &sentinel; 1541 cur = &sentinel;
1542 1542
1543nextline: 1543nextline:
1544 /* terminate line */ 1544 /* terminate line */
1545 cp = strchr(p, '\n'); 1545 cp = strchr(p, '\n');
1546 if (cp) { 1546 if (cp) {
1547 *cp++ = '\0'; 1547 *cp++ = '\0';
1548 nextline = cp; 1548 nextline = cp;
1549 } else 1549 } else
1550 nextline = NULL; 1550 nextline = NULL;
1551 1551
1552 cp = strpbrk(p, " \t"); 1552 cp = strpbrk(p, " \t");
1553 if (cp == NULL) { 1553 if (cp == NULL) {
1554 if (canonname == NULL) 1554 if (canonname == NULL)
1555 return (NULL); 1555 return (NULL);
1556 else 1556 else
1557 goto done; 1557 goto done;
1558 } 1558 }
1559 *cp++ = '\0'; 1559 *cp++ = '\0';
1560 1560
1561 addr = p; 1561 addr = p;
1562 1562
1563 while (cp && *cp) { 1563 while (cp && *cp) {
1564 if (*cp == ' ' || *cp == '\t') { 1564 if (*cp == ' ' || *cp == '\t') {
1565 cp++; 1565 cp++;
1566 continue; 1566 continue;
1567 } 1567 }
1568 if (!canonname) 1568 if (!canonname)
1569 canonname = cp; 1569 canonname = cp;
1570 if ((cp = strpbrk(cp, " \t")) != NULL) 1570 if ((cp = strpbrk(cp, " \t")) != NULL)
1571 *cp++ = '\0'; 1571 *cp++ = '\0';
1572 } 1572 }
1573 1573
1574 hints = *pai; 1574 hints = *pai;
1575 hints.ai_flags = AI_NUMERICHOST; 1575 hints.ai_flags = AI_NUMERICHOST;
1576 error = getaddrinfo(addr, NULL, &hints, &res0); 1576 error = getaddrinfo(addr, NULL, &hints, &res0);
1577 if (error == 0) { 1577 if (error == 0) {
1578 for (res = res0; res; res = res->ai_next) { 1578 for (res = res0; res; res = res->ai_next) {
1579 /* cover it up */ 1579 /* cover it up */
1580 res->ai_flags = pai->ai_flags; 1580 res->ai_flags = pai->ai_flags;
1581 1581
1582 if (pai->ai_flags & AI_CANONNAME) 1582 if (pai->ai_flags & AI_CANONNAME)
1583 (void)get_canonname(pai, res, canonname); 1583 (void)get_canonname(pai, res, canonname);
1584 } 1584 }
1585 } else 1585 } else
1586 res0 = NULL; 1586 res0 = NULL;
1587 if (res0) { 1587 if (res0) {
1588 cur->ai_next = res0; 1588 cur->ai_next = res0;
1589 while (cur->ai_next) 1589 while (cur->ai_next)
1590 cur = cur->ai_next; 1590 cur = cur->ai_next;
1591 } 1591 }
1592 1592
1593 if (nextline) { 1593 if (nextline) {
1594 p = nextline; 1594 p = nextline;
1595 goto nextline; 1595 goto nextline;
1596 } 1596 }
1597 1597
1598done: 1598done:
1599 return sentinel.ai_next; 1599 return sentinel.ai_next;
1600} 1600}
1601 1601
1602/*ARGSUSED*/ 1602/*ARGSUSED*/
1603static int 1603static int
1604_yp_getaddrinfo(void *rv, void *cb_data, va_list ap) 1604_yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
1605{ 1605{
1606 struct addrinfo sentinel, *cur; 1606 struct addrinfo sentinel, *cur;
1607 struct addrinfo *ai = NULL; 1607 struct addrinfo *ai = NULL;
1608 char *ypbuf; 1608 char *ypbuf;
1609 int ypbuflen, r; 1609 int ypbuflen, r;
1610 const char *name; 1610 const char *name;
1611 const struct addrinfo *pai; 1611 const struct addrinfo *pai;
1612 char *ypdomain; 1612 char *ypdomain;
1613 1613
1614 if (_yp_check(&ypdomain) == 0) 1614 if (_yp_check(&ypdomain) == 0)
1615 return NS_UNAVAIL; 1615 return NS_UNAVAIL;
1616 1616
1617 name = va_arg(ap, char *); 1617 name = va_arg(ap, char *);
1618 pai = va_arg(ap, const struct addrinfo *); 1618 pai = va_arg(ap, const struct addrinfo *);
1619 1619
1620 memset(&sentinel, 0, sizeof(sentinel)); 1620 memset(&sentinel, 0, sizeof(sentinel));
1621 cur = &sentinel; 1621 cur = &sentinel;
1622 1622
1623 /* hosts.byname is only for IPv4 (Solaris8) */ 1623 /* hosts.byname is only for IPv4 (Solaris8) */
1624 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) { 1624 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
1625 r = yp_match(ypdomain, "hosts.byname", name, 1625 r = yp_match(ypdomain, "hosts.byname", name,
1626 (int)strlen(name), &ypbuf, &ypbuflen); 1626 (int)strlen(name), &ypbuf, &ypbuflen);
1627 if (r == 0) { 1627 if (r == 0) {
1628 struct addrinfo ai4; 1628 struct addrinfo ai4;
1629 1629
1630 ai4 = *pai; 1630 ai4 = *pai;
1631 ai4.ai_family = AF_INET; 1631 ai4.ai_family = AF_INET;
1632 ai = _yphostent(ypbuf, &ai4); 1632 ai = _yphostent(ypbuf, &ai4);
1633 if (ai) { 1633 if (ai) {
1634 cur->ai_next = ai; 1634 cur->ai_next = ai;
1635 while (cur && cur->ai_next) 1635 while (cur && cur->ai_next)
1636 cur = cur->ai_next; 1636 cur = cur->ai_next;
1637 } 1637 }
1638 } 1638 }
1639 free(ypbuf); 1639 free(ypbuf);
1640 } 1640 }
1641 1641
1642 /* ipnodes.byname can hold both IPv4/v6 */ 1642 /* ipnodes.byname can hold both IPv4/v6 */
1643 r = yp_match(ypdomain, "ipnodes.byname", name, 1643 r = yp_match(ypdomain, "ipnodes.byname", name,
1644 (int)strlen(name), &ypbuf, &ypbuflen); 1644 (int)strlen(name), &ypbuf, &ypbuflen);
1645 if (r == 0) { 1645 if (r == 0) {
1646 ai = _yphostent(ypbuf, pai); 1646 ai = _yphostent(ypbuf, pai);
1647 if (ai) 1647 if (ai)
1648 cur->ai_next = ai; 1648 cur->ai_next = ai;
1649 free(ypbuf); 1649 free(ypbuf);
1650 } 1650 }
1651 1651
1652 if (sentinel.ai_next == NULL) { 1652 if (sentinel.ai_next == NULL) {
1653 h_errno = HOST_NOT_FOUND; 1653 h_errno = HOST_NOT_FOUND;
1654 return NS_NOTFOUND; 1654 return NS_NOTFOUND;
1655 } 1655 }
1656 *((struct addrinfo **)rv) = sentinel.ai_next; 1656 *((struct addrinfo **)rv) = sentinel.ai_next;
1657 return NS_SUCCESS; 1657 return NS_SUCCESS;
1658} 1658}
1659#endif 1659#endif
1660 1660
1661/* resolver logic */ 1661/* resolver logic */
1662 1662
1663/* 1663/*
1664 * Formulate a normal query, send, and await answer. 1664 * Formulate a normal query, send, and await answer.
1665 * Returned answer is placed in supplied buffer "answer". 1665 * Returned answer is placed in supplied buffer "answer".
1666 * Perform preliminary check of answer, returning success only 1666 * Perform preliminary check of answer, returning success only
1667 * if no error is indicated and the answer count is nonzero. 1667 * if no error is indicated and the answer count is nonzero.
1668 * Return the size of the response on success, -1 on error. 1668 * Return the size of the response on success, -1 on error.
1669 * Error number is left in h_errno. 1669 * Error number is left in h_errno.
1670 * 1670 *
1671 * Caller must parse answer and determine whether it answers the question. 1671 * Caller must parse answer and determine whether it answers the question.
1672 */ 1672 */
1673static int 1673static int
1674res_queryN(const char *name, /* domain name */ struct res_target *target, 1674res_queryN(const char *name, /* domain name */ struct res_target *target,
1675 res_state res) 1675 res_state res)
1676{ 1676{
1677 u_char buf[MAXPACKET]; 1677 u_char buf[MAXPACKET];
1678 HEADER *hp; 1678 HEADER *hp;
1679 int n; 1679 int n;
1680 struct res_target *t; 1680 struct res_target *t;
1681 int rcode; 1681 int rcode;
1682 int ancount; 1682 int ancount;
1683 1683
1684 _DIAGASSERT(name != NULL); 1684 _DIAGASSERT(name != NULL);
1685 /* XXX: target may be NULL??? */ 1685 /* XXX: target may be NULL??? */
1686 1686
1687 rcode = NOERROR; 1687 rcode = NOERROR;
1688 ancount = 0; 1688 ancount = 0;
1689 1689
1690 for (t = target; t; t = t->next) { 1690 for (t = target; t; t = t->next) {
1691 int class, type; 1691 int class, type;
1692 u_char *answer; 1692 u_char *answer;
1693 int anslen; 1693 int anslen;
1694 1694
1695 hp = (HEADER *)(void *)t->answer; 1695 hp = (HEADER *)(void *)t->answer;
1696 hp->rcode = NOERROR; /* default */ 1696 hp->rcode = NOERROR; /* default */
1697 1697
1698 /* make it easier... */ 1698 /* make it easier... */
1699 class = t->qclass; 1699 class = t->qclass;
1700 type = t->qtype; 1700 type = t->qtype;
1701 answer = t->answer; 1701 answer = t->answer;
1702 anslen = t->anslen; 1702 anslen = t->anslen;
1703#ifdef DEBUG 1703#ifdef DEBUG
1704 if (res->options & RES_DEBUG) 1704 if (res->options & RES_DEBUG)
1705 printf(";; res_nquery(%s, %d, %d)\n", name, class, type); 1705 printf(";; res_nquery(%s, %d, %d)\n", name, class, type);
1706#endif 1706#endif
1707 1707
1708 n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL, 1708 n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
1709 buf, sizeof(buf)); 1709 buf, sizeof(buf));
1710#ifdef RES_USE_EDNS0 1710#ifdef RES_USE_EDNS0
1711 if (n > 0 && (res->options & RES_USE_EDNS0) != 0) 1711 if (n > 0 && (res->options & RES_USE_EDNS0) != 0)
1712 n = res_nopt(res, n, buf, sizeof(buf), anslen); 1712 n = res_nopt(res, n, buf, sizeof(buf), anslen);
1713#endif 1713#endif
1714 if (n <= 0) { 1714 if (n <= 0) {
1715#ifdef DEBUG 1715#ifdef DEBUG
1716 if (res->options & RES_DEBUG) 1716 if (res->options & RES_DEBUG)
1717 printf(";; res_nquery: mkquery failed\n"); 1717 printf(";; res_nquery: mkquery failed\n");
1718#endif 1718#endif
1719 h_errno = NO_RECOVERY; 1719 h_errno = NO_RECOVERY;
1720 return n; 1720 return n;
1721 } 1721 }
1722 n = res_nsend(res, buf, n, answer, anslen); 1722 n = res_nsend(res, buf, n, answer, anslen);
1723#if 0 1723#if 0
1724 if (n < 0) { 1724 if (n < 0) {
1725#ifdef DEBUG 1725#ifdef DEBUG
1726 if (res->options & RES_DEBUG) 1726 if (res->options & RES_DEBUG)
1727 printf(";; res_query: send error\n"); 1727 printf(";; res_query: send error\n");
1728#endif 1728#endif
1729 h_errno = TRY_AGAIN; 1729 h_errno = TRY_AGAIN;
1730 return n; 1730 return n;
1731 } 1731 }
1732#endif 1732#endif
1733 1733
1734 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 1734 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1735 rcode = hp->rcode; /* record most recent error */ 1735 rcode = hp->rcode; /* record most recent error */
1736#ifdef DEBUG 1736#ifdef DEBUG
1737 if (res->options & RES_DEBUG) 1737 if (res->options & RES_DEBUG)
1738 printf(";; rcode = %u, ancount=%u\n", hp->rcode, 1738 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1739 ntohs(hp->ancount)); 1739 ntohs(hp->ancount));
1740#endif 1740#endif
1741 continue; 1741 continue;
1742 } 1742 }
1743 1743
1744 ancount += ntohs(hp->ancount); 1744 ancount += ntohs(hp->ancount);
1745 1745
1746 t->n = n; 1746 t->n = n;
1747 } 1747 }
1748 1748
1749 if (ancount == 0) { 1749 if (ancount == 0) {
1750 switch (rcode) { 1750 switch (rcode) {
1751 case NXDOMAIN: 1751 case NXDOMAIN:
1752 h_errno = HOST_NOT_FOUND; 1752 h_errno = HOST_NOT_FOUND;
1753 break; 1753 break;
1754 case SERVFAIL: 1754 case SERVFAIL:
1755 h_errno = TRY_AGAIN; 1755 h_errno = TRY_AGAIN;
1756 break; 1756 break;
1757 case NOERROR: 1757 case NOERROR:
1758 h_errno = NO_DATA; 1758 h_errno = NO_DATA;
1759 break; 1759 break;
1760 case FORMERR: 1760 case FORMERR:
1761 case NOTIMP: 1761 case NOTIMP:
1762 case REFUSED: 1762 case REFUSED:
1763 default: 1763 default:
1764 h_errno = NO_RECOVERY; 1764 h_errno = NO_RECOVERY;
1765 break; 1765 break;
1766 } 1766 }
1767 return -1; 1767 return -1;
1768 } 1768 }
1769 return ancount; 1769 return ancount;
1770} 1770}
1771 1771
1772/* 1772/*
1773 * Formulate a normal query, send, and retrieve answer in supplied buffer. 1773 * Formulate a normal query, send, and retrieve answer in supplied buffer.
1774 * Return the size of the response on success, -1 on error. 1774 * Return the size of the response on success, -1 on error.
1775 * If enabled, implement search rules until answer or unrecoverable failure 1775 * If enabled, implement search rules until answer or unrecoverable failure
1776 * is detected. Error code, if any, is left in h_errno. 1776 * is detected. Error code, if any, is left in h_errno.
1777 */ 1777 */
1778static int 1778static int
1779res_searchN(const char *name, struct res_target *target, res_state res) 1779res_searchN(const char *name, struct res_target *target, res_state res)
1780{ 1780{
1781 const char *cp, * const *domain; 1781 const char *cp, * const *domain;
1782 HEADER *hp; 1782 HEADER *hp;
1783 u_int dots; 1783 u_int dots;
1784 int trailing_dot, ret, saved_herrno; 1784 int trailing_dot, ret, saved_herrno;
1785 int got_nodata = 0, got_servfail = 0, tried_as_is = 0; 1785 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1786 1786
1787 _DIAGASSERT(name != NULL); 1787 _DIAGASSERT(name != NULL);
1788 _DIAGASSERT(target != NULL); 1788 _DIAGASSERT(target != NULL);
1789 1789
1790 hp = (HEADER *)(void *)target->answer; /*XXX*/ 1790 hp = (HEADER *)(void *)target->answer; /*XXX*/
1791 1791
1792 errno = 0; 1792 errno = 0;
1793 h_errno = HOST_NOT_FOUND; /* default, if we never query */ 1793 h_errno = HOST_NOT_FOUND; /* default, if we never query */
1794 dots = 0; 1794 dots = 0;
1795 for (cp = name; *cp; cp++) 1795 for (cp = name; *cp; cp++)
1796 dots += (*cp == '.'); 1796 dots += (*cp == '.');
1797 trailing_dot = 0; 1797 trailing_dot = 0;
1798 if (cp > name && *--cp == '.') 1798 if (cp > name && *--cp == '.')
1799 trailing_dot++; 1799 trailing_dot++;
1800 1800
1801 /* 1801 /*
1802 * if there aren't any dots, it could be a user-level alias 1802 * if there aren't any dots, it could be an user-level alias
1803 */ 1803 */
1804 if (!dots && (cp = __hostalias(name)) != NULL) { 1804 if (!dots && (cp = __hostalias(name)) != NULL) {
1805 ret = res_queryN(cp, target, res); 1805 ret = res_queryN(cp, target, res);
1806 return ret; 1806 return ret;
1807 } 1807 }
1808 1808
1809 /* 1809 /*
1810 * If there are dots in the name already, let's just give it a try 1810 * If there are dots in the name already, let's just give it a try
1811 * 'as is'. The threshold can be set with the "ndots" option. 1811 * 'as is'. The threshold can be set with the "ndots" option.
1812 */ 1812 */
1813 saved_herrno = -1; 1813 saved_herrno = -1;
1814 if (dots >= res->ndots) { 1814 if (dots >= res->ndots) {
1815 ret = res_querydomainN(name, NULL, target, res); 1815 ret = res_querydomainN(name, NULL, target, res);
1816 if (ret > 0) 1816 if (ret > 0)
1817 return (ret); 1817 return (ret);
1818 saved_herrno = h_errno; 1818 saved_herrno = h_errno;
1819 tried_as_is++; 1819 tried_as_is++;
1820 } 1820 }
1821 1821
1822 /* 1822 /*
1823 * We do at least one level of search if 1823 * We do at least one level of search if
1824 * - there is no dot and RES_DEFNAME is set, or 1824 * - there is no dot and RES_DEFNAME is set, or
1825 * - there is at least one dot, there is no trailing dot, 1825 * - there is at least one dot, there is no trailing dot,
1826 * and RES_DNSRCH is set. 1826 * and RES_DNSRCH is set.
1827 */ 1827 */
1828 if ((!dots && (res->options & RES_DEFNAMES)) || 1828 if ((!dots && (res->options & RES_DEFNAMES)) ||
1829 (dots && !trailing_dot && (res->options & RES_DNSRCH))) { 1829 (dots && !trailing_dot && (res->options & RES_DNSRCH))) {
1830 int done = 0; 1830 int done = 0;
1831 1831
1832 for (domain = (const char * const *)res->dnsrch; 1832 for (domain = (const char * const *)res->dnsrch;
1833 *domain && !done; 1833 *domain && !done;
1834 domain++) { 1834 domain++) {
1835 1835
1836 ret = res_querydomainN(name, *domain, target, res); 1836 ret = res_querydomainN(name, *domain, target, res);
1837 if (ret > 0) 1837 if (ret > 0)
1838 return ret; 1838 return ret;
1839 1839
1840 /* 1840 /*
1841 * If no server present, give up. 1841 * If no server present, give up.
1842 * If name isn't found in this domain, 1842 * If name isn't found in this domain,
1843 * keep trying higher domains in the search list 1843 * keep trying higher domains in the search list
1844 * (if that's enabled). 1844 * (if that's enabled).
1845 * On a NO_DATA error, keep trying, otherwise 1845 * On a NO_DATA error, keep trying, otherwise
1846 * a wildcard entry of another type could keep us 1846 * a wildcard entry of another type could keep us
1847 * from finding this entry higher in the domain. 1847 * from finding this entry higher in the domain.
1848 * If we get some other error (negative answer or 1848 * If we get some other error (negative answer or
1849 * server failure), then stop searching up, 1849 * server failure), then stop searching up,
1850 * but try the input name below in case it's 1850 * but try the input name below in case it's
1851 * fully-qualified. 1851 * fully-qualified.
1852 */ 1852 */
1853 if (errno == ECONNREFUSED) { 1853 if (errno == ECONNREFUSED) {
1854 h_errno = TRY_AGAIN; 1854 h_errno = TRY_AGAIN;
1855 return -1; 1855 return -1;
1856 } 1856 }
1857 1857
1858 switch (h_errno) { 1858 switch (h_errno) {
1859 case NO_DATA: 1859 case NO_DATA:
1860 got_nodata++; 1860 got_nodata++;
1861 /* FALLTHROUGH */ 1861 /* FALLTHROUGH */
1862 case HOST_NOT_FOUND: 1862 case HOST_NOT_FOUND:
1863 /* keep trying */ 1863 /* keep trying */
1864 break; 1864 break;
1865 case TRY_AGAIN: 1865 case TRY_AGAIN:
1866 if (hp->rcode == SERVFAIL) { 1866 if (hp->rcode == SERVFAIL) {
1867 /* try next search element, if any */ 1867 /* try next search element, if any */
1868 got_servfail++; 1868 got_servfail++;
1869 break; 1869 break;
1870 } 1870 }
1871 /* FALLTHROUGH */ 1871 /* FALLTHROUGH */
1872 default: 1872 default:
1873 /* anything else implies that we're done */ 1873 /* anything else implies that we're done */
1874 done++; 1874 done++;
1875 } 1875 }
1876 /* 1876 /*
1877 * if we got here for some reason other than DNSRCH, 1877 * if we got here for some reason other than DNSRCH,
1878 * we only wanted one iteration of the loop, so stop. 1878 * we only wanted one iteration of the loop, so stop.
1879 */ 1879 */
1880 if (!(res->options & RES_DNSRCH)) 1880 if (!(res->options & RES_DNSRCH))
1881 done++; 1881 done++;
1882 } 1882 }
1883 } 1883 }
1884 1884
1885 /* 1885 /*
1886 * if we have not already tried the name "as is", do that now. 1886 * if we have not already tried the name "as is", do that now.
1887 * note that we do this regardless of how many dots were in the 1887 * note that we do this regardless of how many dots were in the
1888 * name or whether it ends with a dot. 1888 * name or whether it ends with a dot.
1889 */ 1889 */
1890 if (!tried_as_is) { 1890 if (!tried_as_is) {
1891 ret = res_querydomainN(name, NULL, target, res); 1891 ret = res_querydomainN(name, NULL, target, res);
1892 if (ret > 0) 1892 if (ret > 0)
1893 return ret; 1893 return ret;
1894 } 1894 }
1895 1895
1896 /* 1896 /*
1897 * if we got here, we didn't satisfy the search. 1897 * if we got here, we didn't satisfy the search.
1898 * if we did an initial full query, return that query's h_errno 1898 * if we did an initial full query, return that query's h_errno
1899 * (note that we wouldn't be here if that query had succeeded). 1899 * (note that we wouldn't be here if that query had succeeded).
1900 * else if we ever got a nodata, send that back as the reason. 1900 * else if we ever got a nodata, send that back as the reason.
1901 * else send back meaningless h_errno, that being the one from 1901 * else send back meaningless h_errno, that being the one from
1902 * the last DNSRCH we did. 1902 * the last DNSRCH we did.
1903 */ 1903 */
1904 if (saved_herrno != -1) 1904 if (saved_herrno != -1)
1905 h_errno = saved_herrno; 1905 h_errno = saved_herrno;
1906 else if (got_nodata) 1906 else if (got_nodata)
1907 h_errno = NO_DATA; 1907 h_errno = NO_DATA;
1908 else if (got_servfail) 1908 else if (got_servfail)
1909 h_errno = TRY_AGAIN; 1909 h_errno = TRY_AGAIN;
1910 return -1; 1910 return -1;
1911} 1911}
1912 1912
1913/* 1913/*
1914 * Perform a call on res_query on the concatenation of name and domain, 1914 * Perform a call on res_query on the concatenation of name and domain,
1915 * removing a trailing dot from name if domain is NULL. 1915 * removing a trailing dot from name if domain is NULL.
1916 */ 1916 */
1917static int 1917static int
1918res_querydomainN(const char *name, const char *domain, 1918res_querydomainN(const char *name, const char *domain,
1919 struct res_target *target, res_state res) 1919 struct res_target *target, res_state res)
1920{ 1920{
1921 char nbuf[MAXDNAME]; 1921 char nbuf[MAXDNAME];
1922 const char *longname = nbuf; 1922 const char *longname = nbuf;
1923 size_t n, d; 1923 size_t n, d;
1924 1924
1925 _DIAGASSERT(name != NULL); 1925 _DIAGASSERT(name != NULL);
1926 /* XXX: target may be NULL??? */ 1926 /* XXX: target may be NULL??? */
1927 1927
1928#ifdef DEBUG 1928#ifdef DEBUG
1929 if (res->options & RES_DEBUG) 1929 if (res->options & RES_DEBUG)
1930 printf(";; res_querydomain(%s, %s)\n", 1930 printf(";; res_querydomain(%s, %s)\n",
1931 name, domain?domain:"<Nil>"); 1931 name, domain?domain:"<Nil>");
1932#endif 1932#endif
1933 if (domain == NULL) { 1933 if (domain == NULL) {
1934 /* 1934 /*
1935 * Check for trailing '.'; 1935 * Check for trailing '.';
1936 * copy without '.' if present. 1936 * copy without '.' if present.
1937 */ 1937 */
1938 n = strlen(name); 1938 n = strlen(name);
1939 if (n + 1 > sizeof(nbuf)) { 1939 if (n + 1 > sizeof(nbuf)) {
1940 h_errno = NO_RECOVERY; 1940 h_errno = NO_RECOVERY;
1941 return -1; 1941 return -1;
1942 } 1942 }
1943 if (n > 0 && name[--n] == '.') { 1943 if (n > 0 && name[--n] == '.') {
1944 strncpy(nbuf, name, n); 1944 strncpy(nbuf, name, n);
1945 nbuf[n] = '\0'; 1945 nbuf[n] = '\0';
1946 } else 1946 } else
1947 longname = name; 1947 longname = name;
1948 } else { 1948 } else {
1949 n = strlen(name); 1949 n = strlen(name);
1950 d = strlen(domain); 1950 d = strlen(domain);
1951 if (n + 1 + d + 1 > sizeof(nbuf)) { 1951 if (n + 1 + d + 1 > sizeof(nbuf)) {
1952 h_errno = NO_RECOVERY; 1952 h_errno = NO_RECOVERY;
1953 return -1; 1953 return -1;
1954 } 1954 }
1955 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); 1955 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
1956 } 1956 }
1957 return res_queryN(longname, target, res); 1957 return res_queryN(longname, target, res);
1958} 1958}

cvs diff -r1.73 -r1.74 src/lib/libc/net/gethnamaddr.c (switch to unified diff)

--- src/lib/libc/net/gethnamaddr.c 2007/01/27 22:27:35 1.73
+++ src/lib/libc/net/gethnamaddr.c 2009/10/02 06:49:23 1.74
@@ -1,1441 +1,1441 @@ @@ -1,1441 +1,1441 @@
1/* $NetBSD: gethnamaddr.c,v 1.73 2007/01/27 22:27:35 christos Exp $ */ 1/* $NetBSD: gethnamaddr.c,v 1.74 2009/10/02 06:49:23 cegger Exp $ */
2 2
3/* 3/*
4 * ++Copyright++ 1985, 1988, 1993 4 * ++Copyright++ 1985, 1988, 1993
5 * - 5 * -
6 * Copyright (c) 1985, 1988, 1993 6 * Copyright (c) 1985, 1988, 1993
7 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
8 *  8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors 17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 19 * without specific prior written permission.
20 *  20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE. 31 * SUCH DAMAGE.
32 * - 32 * -
33 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 33 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *  34 *
35 * Permission to use, copy, modify, and distribute this software for any 35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above 36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that 37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or 38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without 39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission. 40 * specific, written prior permission.
41 *  41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE. 49 * SOFTWARE.
50 * - 50 * -
51 * --Copyright-- 51 * --Copyright--
52 */ 52 */
53 53
54#include <sys/cdefs.h> 54#include <sys/cdefs.h>
55#if defined(LIBC_SCCS) && !defined(lint) 55#if defined(LIBC_SCCS) && !defined(lint)
56#if 0 56#if 0
57static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; 57static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
58static char rcsid[] = "Id: gethnamaddr.c,v 8.21 1997/06/01 20:34:37 vixie Exp "; 58static char rcsid[] = "Id: gethnamaddr.c,v 8.21 1997/06/01 20:34:37 vixie Exp ";
59#else 59#else
60__RCSID("$NetBSD: gethnamaddr.c,v 1.73 2007/01/27 22:27:35 christos Exp $"); 60__RCSID("$NetBSD: gethnamaddr.c,v 1.74 2009/10/02 06:49:23 cegger Exp $");
61#endif 61#endif
62#endif /* LIBC_SCCS and not lint */ 62#endif /* LIBC_SCCS and not lint */
63 63
64#if defined(_LIBC) 64#if defined(_LIBC)
65#include "namespace.h" 65#include "namespace.h"
66#endif 66#endif
67#include <sys/param.h> 67#include <sys/param.h>
68#include <sys/socket.h> 68#include <sys/socket.h>
69#include <netinet/in.h> 69#include <netinet/in.h>
70#include <arpa/inet.h> 70#include <arpa/inet.h>
71#include <arpa/nameser.h> 71#include <arpa/nameser.h>
72 72
73#include <assert.h> 73#include <assert.h>
74#include <ctype.h> 74#include <ctype.h>
75#include <errno.h> 75#include <errno.h>
76#include <netdb.h> 76#include <netdb.h>
77#include <resolv.h> 77#include <resolv.h>
78#include <stdarg.h> 78#include <stdarg.h>
79#include <stdio.h> 79#include <stdio.h>
80#include <syslog.h> 80#include <syslog.h>
81 81
82#ifndef LOG_AUTH 82#ifndef LOG_AUTH
83# define LOG_AUTH 0 83# define LOG_AUTH 0
84#endif 84#endif
85 85
86#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ 86#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
87 87
88#include <nsswitch.h> 88#include <nsswitch.h>
89#include <stdlib.h> 89#include <stdlib.h>
90#include <string.h> 90#include <string.h>
91 91
92#ifdef YP 92#ifdef YP
93#include <rpc/rpc.h> 93#include <rpc/rpc.h>
94#include <rpcsvc/yp_prot.h> 94#include <rpcsvc/yp_prot.h>
95#include <rpcsvc/ypclnt.h> 95#include <rpcsvc/ypclnt.h>
96#endif 96#endif
97 97
98#if defined(_LIBC) && defined(__weak_alias) 98#if defined(_LIBC) && defined(__weak_alias)
99__weak_alias(gethostbyaddr,_gethostbyaddr) 99__weak_alias(gethostbyaddr,_gethostbyaddr)
100__weak_alias(gethostbyname,_gethostbyname) 100__weak_alias(gethostbyname,_gethostbyname)
101__weak_alias(gethostent,_gethostent) 101__weak_alias(gethostent,_gethostent)
102#endif 102#endif
103 103
104#define MAXALIASES 35 104#define MAXALIASES 35
105#define MAXADDRS 35 105#define MAXADDRS 35
106 106
107static const char AskedForGot[] = 107static const char AskedForGot[] =
108 "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 108 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
109 109
110static char *h_addr_ptrs[MAXADDRS + 1]; 110static char *h_addr_ptrs[MAXADDRS + 1];
111 111
112#ifdef YP 112#ifdef YP
113static char *__ypdomain; 113static char *__ypdomain;
114#endif 114#endif
115 115
116static struct hostent host; 116static struct hostent host;
117static char *host_aliases[MAXALIASES]; 117static char *host_aliases[MAXALIASES];
118static char hostbuf[8*1024]; 118static char hostbuf[8*1024];
119static u_int32_t host_addr[16 / sizeof(u_int32_t)]; /* IPv4 or IPv6 */ 119static u_int32_t host_addr[16 / sizeof(u_int32_t)]; /* IPv4 or IPv6 */
120static FILE *hostf = NULL; 120static FILE *hostf = NULL;
121static int stayopen = 0; 121static int stayopen = 0;
122 122
123#define MAXPACKET (64*1024) 123#define MAXPACKET (64*1024)
124 124
125typedef union { 125typedef union {
126 HEADER hdr; 126 HEADER hdr;
127 u_char buf[MAXPACKET]; 127 u_char buf[MAXPACKET];
128} querybuf; 128} querybuf;
129 129
130typedef union { 130typedef union {
131 int32_t al; 131 int32_t al;
132 char ac; 132 char ac;
133} align; 133} align;
134 134
135#ifdef DEBUG 135#ifdef DEBUG
136static void dprintf(const char *, res_state, ...) 136static void dprintf(const char *, res_state, ...)
137 __attribute__((__format__(__printf__, 1, 3))); 137 __attribute__((__format__(__printf__, 1, 3)));
138#endif 138#endif
139static struct hostent *getanswer(const querybuf *, int, const char *, int, 139static struct hostent *getanswer(const querybuf *, int, const char *, int,
140 res_state); 140 res_state);
141static void map_v4v6_address(const char *, char *); 141static void map_v4v6_address(const char *, char *);
142static void map_v4v6_hostent(struct hostent *, char **, char *); 142static void map_v4v6_hostent(struct hostent *, char **, char *);
143static void addrsort(char **, int, res_state); 143static void addrsort(char **, int, res_state);
144 144
145void _sethtent(int); 145void _sethtent(int);
146void _endhtent(void); 146void _endhtent(void);
147struct hostent *_gethtent(void); 147struct hostent *_gethtent(void);
148void ht_sethostent(int); 148void ht_sethostent(int);
149void ht_endhostent(void); 149void ht_endhostent(void);
150struct hostent *ht_gethostbyname(char *); 150struct hostent *ht_gethostbyname(char *);
151struct hostent *ht_gethostbyaddr(const char *, int, int); 151struct hostent *ht_gethostbyaddr(const char *, int, int);
152void dns_service(void); 152void dns_service(void);
153#undef dn_skipname 153#undef dn_skipname
154int dn_skipname(const u_char *, const u_char *); 154int dn_skipname(const u_char *, const u_char *);
155int _gethtbyaddr(void *, void *, va_list); 155int _gethtbyaddr(void *, void *, va_list);
156int _gethtbyname(void *, void *, va_list); 156int _gethtbyname(void *, void *, va_list);
157struct hostent *_gethtbyname2(const char *, int); 157struct hostent *_gethtbyname2(const char *, int);
158int _dns_gethtbyaddr(void *, void *, va_list); 158int _dns_gethtbyaddr(void *, void *, va_list);
159int _dns_gethtbyname(void *, void *, va_list); 159int _dns_gethtbyname(void *, void *, va_list);
160#ifdef YP 160#ifdef YP
161struct hostent *_yphostent(char *, int); 161struct hostent *_yphostent(char *, int);
162int _yp_gethtbyaddr(void *, void *, va_list); 162int _yp_gethtbyaddr(void *, void *, va_list);
163int _yp_gethtbyname(void *, void *, va_list); 163int _yp_gethtbyname(void *, void *, va_list);
164#endif 164#endif
165 165
166static struct hostent *gethostbyname_internal(const char *, int, res_state); 166static struct hostent *gethostbyname_internal(const char *, int, res_state);
167 167
168static const ns_src default_dns_files[] = { 168static const ns_src default_dns_files[] = {
169 { NSSRC_FILES, NS_SUCCESS }, 169 { NSSRC_FILES, NS_SUCCESS },
170 { NSSRC_DNS, NS_SUCCESS }, 170 { NSSRC_DNS, NS_SUCCESS },
171 { 0, 0 } 171 { 0, 0 }
172}; 172};
173 173
174 174
175#ifdef DEBUG 175#ifdef DEBUG
176static void 176static void
177dprintf(const char *msg, res_state res, ...) 177dprintf(const char *msg, res_state res, ...)
178{ 178{
179 _DIAGASSERT(msg != NULL); 179 _DIAGASSERT(msg != NULL);
180 180
181 if (res->options & RES_DEBUG) { 181 if (res->options & RES_DEBUG) {
182 int save = errno; 182 int save = errno;
183 va_list ap; 183 va_list ap;
184 184
185 va_start (ap, res); 185 va_start (ap, res);
186 vprintf(msg, ap); 186 vprintf(msg, ap);
187 va_end (ap); 187 va_end (ap);
188  188
189 errno = save; 189 errno = save;
190 } 190 }
191} 191}
192#else 192#else
193# define dprintf(msg, res, num) /*nada*/ 193# define dprintf(msg, res, num) /*nada*/
194#endif 194#endif
195 195
196#define BOUNDED_INCR(x) \ 196#define BOUNDED_INCR(x) \
197 do { \ 197 do { \
198 cp += (x); \ 198 cp += (x); \
199 if (cp > eom) { \ 199 if (cp > eom) { \
200 h_errno = NO_RECOVERY; \ 200 h_errno = NO_RECOVERY; \
201 return NULL; \ 201 return NULL; \
202 } \ 202 } \
203 } while (/*CONSTCOND*/0) 203 } while (/*CONSTCOND*/0)
204 204
205#define BOUNDS_CHECK(ptr, count) \ 205#define BOUNDS_CHECK(ptr, count) \
206 do { \ 206 do { \
207 if ((ptr) + (count) > eom) { \ 207 if ((ptr) + (count) > eom) { \
208 h_errno = NO_RECOVERY; \ 208 h_errno = NO_RECOVERY; \
209 return NULL; \ 209 return NULL; \
210 } \ 210 } \
211 } while (/*CONSTCOND*/0) 211 } while (/*CONSTCOND*/0)
212 212
213static struct hostent * 213static struct hostent *
214getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 214getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
215 res_state res) 215 res_state res)
216{ 216{
217 const HEADER *hp; 217 const HEADER *hp;
218 const u_char *cp; 218 const u_char *cp;
219 int n; 219 int n;
220 const u_char *eom, *erdata; 220 const u_char *eom, *erdata;
221 char *bp, **ap, **hap, *ep; 221 char *bp, **ap, **hap, *ep;
222 int type, class, ancount, qdcount; 222 int type, class, ancount, qdcount;
223 int haveanswer, had_error; 223 int haveanswer, had_error;
224 int toobig = 0; 224 int toobig = 0;
225 char tbuf[MAXDNAME]; 225 char tbuf[MAXDNAME];
226 const char *tname; 226 const char *tname;
227 int (*name_ok)(const char *); 227 int (*name_ok)(const char *);
228 228
229 _DIAGASSERT(answer != NULL); 229 _DIAGASSERT(answer != NULL);
230 _DIAGASSERT(qname != NULL); 230 _DIAGASSERT(qname != NULL);
231 231
232 tname = qname; 232 tname = qname;
233 host.h_name = NULL; 233 host.h_name = NULL;
234 eom = answer->buf + anslen; 234 eom = answer->buf + anslen;
235 switch (qtype) { 235 switch (qtype) {
236 case T_A: 236 case T_A:
237 case T_AAAA: 237 case T_AAAA:
238 name_ok = res_hnok; 238 name_ok = res_hnok;
239 break; 239 break;
240 case T_PTR: 240 case T_PTR:
241 name_ok = res_dnok; 241 name_ok = res_dnok;
242 break; 242 break;
243 default: 243 default:
244 return NULL; /* XXX should be abort(); */ 244 return NULL; /* XXX should be abort(); */
245 } 245 }
246 /* 246 /*
247 * find first satisfactory answer 247 * find first satisfactory answer
248 */ 248 */
249 hp = &answer->hdr; 249 hp = &answer->hdr;
250 ancount = ntohs(hp->ancount); 250 ancount = ntohs(hp->ancount);
251 qdcount = ntohs(hp->qdcount); 251 qdcount = ntohs(hp->qdcount);
252 bp = hostbuf; 252 bp = hostbuf;
253 ep = hostbuf + sizeof hostbuf; 253 ep = hostbuf + sizeof hostbuf;
254 cp = answer->buf; 254 cp = answer->buf;
255 BOUNDED_INCR(HFIXEDSZ); 255 BOUNDED_INCR(HFIXEDSZ);
256 if (qdcount != 1) { 256 if (qdcount != 1) {
257 h_errno = NO_RECOVERY; 257 h_errno = NO_RECOVERY;
258 return NULL; 258 return NULL;
259 } 259 }
260 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 260 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
261 if ((n < 0) || !(*name_ok)(bp)) { 261 if ((n < 0) || !(*name_ok)(bp)) {
262 h_errno = NO_RECOVERY; 262 h_errno = NO_RECOVERY;
263 return NULL; 263 return NULL;
264 } 264 }
265 BOUNDED_INCR(n + QFIXEDSZ); 265 BOUNDED_INCR(n + QFIXEDSZ);
266 if (qtype == T_A || qtype == T_AAAA) { 266 if (qtype == T_A || qtype == T_AAAA) {
267 /* res_send() has already verified that the query name is the 267 /* res_send() has already verified that the query name is the
268 * same as the one we sent; this just gets the expanded name 268 * same as the one we sent; this just gets the expanded name
269 * (i.e., with the succeeding search-domain tacked on). 269 * (i.e., with the succeeding search-domain tacked on).
270 */ 270 */
271 n = strlen(bp) + 1; /* for the \0 */ 271 n = strlen(bp) + 1; /* for the \0 */
272 if (n >= MAXHOSTNAMELEN) { 272 if (n >= MAXHOSTNAMELEN) {
273 h_errno = NO_RECOVERY; 273 h_errno = NO_RECOVERY;
274 return NULL; 274 return NULL;
275 } 275 }
276 host.h_name = bp; 276 host.h_name = bp;
277 bp += n; 277 bp += n;
278 /* The qname can be abbreviated, but h_name is now absolute. */ 278 /* The qname can be abbreviated, but h_name is now absolute. */
279 qname = host.h_name; 279 qname = host.h_name;
280 } 280 }
281 ap = host_aliases; 281 ap = host_aliases;
282 *ap = NULL; 282 *ap = NULL;
283 host.h_aliases = host_aliases; 283 host.h_aliases = host_aliases;
284 hap = h_addr_ptrs; 284 hap = h_addr_ptrs;
285 *hap = NULL; 285 *hap = NULL;
286 host.h_addr_list = h_addr_ptrs; 286 host.h_addr_list = h_addr_ptrs;
287 haveanswer = 0; 287 haveanswer = 0;
288 had_error = 0; 288 had_error = 0;
289 while (ancount-- > 0 && cp < eom && !had_error) { 289 while (ancount-- > 0 && cp < eom && !had_error) {
290 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 290 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
291 if ((n < 0) || !(*name_ok)(bp)) { 291 if ((n < 0) || !(*name_ok)(bp)) {
292 had_error++; 292 had_error++;
293 continue; 293 continue;
294 } 294 }
295 cp += n; /* name */ 295 cp += n; /* name */
296 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); 296 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
297 type = _getshort(cp); 297 type = _getshort(cp);
298 cp += INT16SZ; /* type */ 298 cp += INT16SZ; /* type */
299 class = _getshort(cp); 299 class = _getshort(cp);
300 cp += INT16SZ + INT32SZ; /* class, TTL */ 300 cp += INT16SZ + INT32SZ; /* class, TTL */
301 n = _getshort(cp); 301 n = _getshort(cp);
302 cp += INT16SZ; /* len */ 302 cp += INT16SZ; /* len */
303 BOUNDS_CHECK(cp, n); 303 BOUNDS_CHECK(cp, n);
304 erdata = cp + n; 304 erdata = cp + n;
305 if (class != C_IN) { 305 if (class != C_IN) {
306 /* XXX - debug? syslog? */ 306 /* XXX - debug? syslog? */
307 cp += n; 307 cp += n;
308 continue; /* XXX - had_error++ ? */ 308 continue; /* XXX - had_error++ ? */
309 } 309 }
310 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { 310 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
311 if (ap >= &host_aliases[MAXALIASES-1]) 311 if (ap >= &host_aliases[MAXALIASES-1])
312 continue; 312 continue;
313 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 313 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
314 if ((n < 0) || !(*name_ok)(tbuf)) { 314 if ((n < 0) || !(*name_ok)(tbuf)) {
315 had_error++; 315 had_error++;
316 continue; 316 continue;
317 } 317 }
318 cp += n; 318 cp += n;
319 if (cp != erdata) { 319 if (cp != erdata) {
320 h_errno = NO_RECOVERY; 320 h_errno = NO_RECOVERY;
321 return NULL; 321 return NULL;
322 } 322 }
323 /* Store alias. */ 323 /* Store alias. */
324 *ap++ = bp; 324 *ap++ = bp;
325 n = strlen(bp) + 1; /* for the \0 */ 325 n = strlen(bp) + 1; /* for the \0 */
326 if (n >= MAXHOSTNAMELEN) { 326 if (n >= MAXHOSTNAMELEN) {
327 had_error++; 327 had_error++;
328 continue; 328 continue;
329 } 329 }
330 bp += n; 330 bp += n;
331 /* Get canonical name. */ 331 /* Get canonical name. */
332 n = strlen(tbuf) + 1; /* for the \0 */ 332 n = strlen(tbuf) + 1; /* for the \0 */
333 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 333 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
334 had_error++; 334 had_error++;
335 continue; 335 continue;
336 } 336 }
337 strlcpy(bp, tbuf, (size_t)(ep - bp)); 337 strlcpy(bp, tbuf, (size_t)(ep - bp));
338 host.h_name = bp; 338 host.h_name = bp;
339 bp += n; 339 bp += n;
340 continue; 340 continue;
341 } 341 }
342 if (qtype == T_PTR && type == T_CNAME) { 342 if (qtype == T_PTR && type == T_CNAME) {
343 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 343 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
344 if (n < 0 || !res_dnok(tbuf)) { 344 if (n < 0 || !res_dnok(tbuf)) {
345 had_error++; 345 had_error++;
346 continue; 346 continue;
347 } 347 }
348 cp += n; 348 cp += n;
349 if (cp != erdata) { 349 if (cp != erdata) {
350 h_errno = NO_RECOVERY; 350 h_errno = NO_RECOVERY;
351 return NULL; 351 return NULL;
352 } 352 }
353 /* Get canonical name. */ 353 /* Get canonical name. */
354 n = strlen(tbuf) + 1; /* for the \0 */ 354 n = strlen(tbuf) + 1; /* for the \0 */
355 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 355 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
356 had_error++; 356 had_error++;
357 continue; 357 continue;
358 } 358 }
359 strlcpy(bp, tbuf, (size_t)(ep - bp)); 359 strlcpy(bp, tbuf, (size_t)(ep - bp));
360 tname = bp; 360 tname = bp;
361 bp += n; 361 bp += n;
362 continue; 362 continue;
363 } 363 }
364 if (type != qtype) { 364 if (type != qtype) {
365 if (type != T_KEY && type != T_SIG) 365 if (type != T_KEY && type != T_SIG)
366 syslog(LOG_NOTICE|LOG_AUTH, 366 syslog(LOG_NOTICE|LOG_AUTH,
367 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 367 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
368 qname, p_class(C_IN), p_type(qtype), 368 qname, p_class(C_IN), p_type(qtype),
369 p_type(type)); 369 p_type(type));
370 cp += n; 370 cp += n;
371 continue; /* XXX - had_error++ ? */ 371 continue; /* XXX - had_error++ ? */
372 } 372 }
373 switch (type) { 373 switch (type) {
374 case T_PTR: 374 case T_PTR:
375 if (strcasecmp(tname, bp) != 0) { 375 if (strcasecmp(tname, bp) != 0) {
376 syslog(LOG_NOTICE|LOG_AUTH, 376 syslog(LOG_NOTICE|LOG_AUTH,
377 AskedForGot, qname, bp); 377 AskedForGot, qname, bp);
378 cp += n; 378 cp += n;
379 continue; /* XXX - had_error++ ? */ 379 continue; /* XXX - had_error++ ? */
380 } 380 }
381 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 381 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
382 if ((n < 0) || !res_hnok(bp)) { 382 if ((n < 0) || !res_hnok(bp)) {
383 had_error++; 383 had_error++;
384 break; 384 break;
385 } 385 }
386#if MULTI_PTRS_ARE_ALIASES 386#if MULTI_PTRS_ARE_ALIASES
387 cp += n; 387 cp += n;
388 if (cp != erdata) { 388 if (cp != erdata) {
389 h_errno = NO_RECOVERY; 389 h_errno = NO_RECOVERY;
390 return NULL; 390 return NULL;
391 } 391 }
392 if (!haveanswer) 392 if (!haveanswer)
393 host.h_name = bp; 393 host.h_name = bp;
394 else if (ap < &host_aliases[MAXALIASES-1]) 394 else if (ap < &host_aliases[MAXALIASES-1])
395 *ap++ = bp; 395 *ap++ = bp;
396 else 396 else
397 n = -1; 397 n = -1;
398 if (n != -1) { 398 if (n != -1) {
399 n = strlen(bp) + 1; /* for the \0 */ 399 n = strlen(bp) + 1; /* for the \0 */
400 if (n >= MAXHOSTNAMELEN) { 400 if (n >= MAXHOSTNAMELEN) {
401 had_error++; 401 had_error++;
402 break; 402 break;
403 } 403 }
404 bp += n; 404 bp += n;
405 } 405 }
406 break; 406 break;
407#else 407#else
408 host.h_name = bp; 408 host.h_name = bp;
409 if (res->options & RES_USE_INET6) { 409 if (res->options & RES_USE_INET6) {
410 n = strlen(bp) + 1; /* for the \0 */ 410 n = strlen(bp) + 1; /* for the \0 */
411 if (n >= MAXHOSTNAMELEN) { 411 if (n >= MAXHOSTNAMELEN) {
412 had_error++; 412 had_error++;
413 break; 413 break;
414 } 414 }
415 bp += n; 415 bp += n;
416 map_v4v6_hostent(&host, &bp, ep); 416 map_v4v6_hostent(&host, &bp, ep);
417 } 417 }
418 h_errno = NETDB_SUCCESS; 418 h_errno = NETDB_SUCCESS;
419 return &host; 419 return &host;
420#endif 420#endif
421 case T_A: 421 case T_A:
422 case T_AAAA: 422 case T_AAAA:
423 if (strcasecmp(host.h_name, bp) != 0) { 423 if (strcasecmp(host.h_name, bp) != 0) {
424 syslog(LOG_NOTICE|LOG_AUTH, 424 syslog(LOG_NOTICE|LOG_AUTH,
425 AskedForGot, host.h_name, bp); 425 AskedForGot, host.h_name, bp);
426 cp += n; 426 cp += n;
427 continue; /* XXX - had_error++ ? */ 427 continue; /* XXX - had_error++ ? */
428 } 428 }
429 if (n != host.h_length) { 429 if (n != host.h_length) {
430 cp += n; 430 cp += n;
431 continue; 431 continue;
432 } 432 }
433 if (type == T_AAAA) { 433 if (type == T_AAAA) {
434 struct in6_addr in6; 434 struct in6_addr in6;
435 memcpy(&in6, cp, IN6ADDRSZ); 435 memcpy(&in6, cp, IN6ADDRSZ);
436 if (IN6_IS_ADDR_V4MAPPED(&in6)) { 436 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
437 cp += n; 437 cp += n;
438 continue; 438 continue;
439 } 439 }
440 } 440 }
441 if (!haveanswer) { 441 if (!haveanswer) {
442 int nn; 442 int nn;
443 443
444 host.h_name = bp; 444 host.h_name = bp;
445 nn = strlen(bp) + 1; /* for the \0 */ 445 nn = strlen(bp) + 1; /* for the \0 */
446 bp += nn; 446 bp += nn;
447 } 447 }
448 448
449 bp += sizeof(align) - 449 bp += sizeof(align) -
450 (size_t)((u_long)bp % sizeof(align)); 450 (size_t)((u_long)bp % sizeof(align));
451 451
452 if (bp + n >= &hostbuf[sizeof hostbuf]) { 452 if (bp + n >= &hostbuf[sizeof hostbuf]) {
453 dprintf("size (%d) too big\n", res, n); 453 dprintf("size (%d) too big\n", res, n);
454 had_error++; 454 had_error++;
455 continue; 455 continue;
456 } 456 }
457 if (hap >= &h_addr_ptrs[MAXADDRS-1]) { 457 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
458 if (!toobig++) { 458 if (!toobig++) {
459 dprintf("Too many addresses (%d)\n", 459 dprintf("Too many addresses (%d)\n",
460 res, MAXADDRS); 460 res, MAXADDRS);
461 } 461 }
462 cp += n; 462 cp += n;
463 continue; 463 continue;
464 } 464 }
465 (void)memcpy(*hap++ = bp, cp, (size_t)n); 465 (void)memcpy(*hap++ = bp, cp, (size_t)n);
466 bp += n; 466 bp += n;
467 cp += n; 467 cp += n;
468 if (cp != erdata) { 468 if (cp != erdata) {
469 h_errno = NO_RECOVERY; 469 h_errno = NO_RECOVERY;
470 return NULL; 470 return NULL;
471 } 471 }
472 break; 472 break;
473 default: 473 default:
474 abort(); 474 abort();
475 } 475 }
476 if (!had_error) 476 if (!had_error)
477 haveanswer++; 477 haveanswer++;
478 } 478 }
479 if (haveanswer) { 479 if (haveanswer) {
480 *ap = NULL; 480 *ap = NULL;
481 *hap = NULL; 481 *hap = NULL;
482 /* 482 /*
483 * Note: we sort even if host can take only one address 483 * Note: we sort even if host can take only one address
484 * in its return structures - should give it the "best" 484 * in its return structures - should give it the "best"
485 * address in that case, not some random one 485 * address in that case, not some random one
486 */ 486 */
487 if (res->nsort && haveanswer > 1 && qtype == T_A) 487 if (res->nsort && haveanswer > 1 && qtype == T_A)
488 addrsort(h_addr_ptrs, haveanswer, res); 488 addrsort(h_addr_ptrs, haveanswer, res);
489 if (!host.h_name) { 489 if (!host.h_name) {
490 n = strlen(qname) + 1; /* for the \0 */ 490 n = strlen(qname) + 1; /* for the \0 */
491 if (n > ep - bp || n >= MAXHOSTNAMELEN) 491 if (n > ep - bp || n >= MAXHOSTNAMELEN)
492 goto no_recovery; 492 goto no_recovery;
493 strlcpy(bp, qname, (size_t)(ep - bp)); 493 strlcpy(bp, qname, (size_t)(ep - bp));
494 host.h_name = bp; 494 host.h_name = bp;
495 bp += n; 495 bp += n;
496 } 496 }
497 if (res->options & RES_USE_INET6) 497 if (res->options & RES_USE_INET6)
498 map_v4v6_hostent(&host, &bp, ep); 498 map_v4v6_hostent(&host, &bp, ep);
499 h_errno = NETDB_SUCCESS; 499 h_errno = NETDB_SUCCESS;
500 return &host; 500 return &host;
501 } 501 }
502 no_recovery: 502 no_recovery:
503 h_errno = NO_RECOVERY; 503 h_errno = NO_RECOVERY;
504 return NULL; 504 return NULL;
505} 505}
506 506
507struct hostent * 507struct hostent *
508gethostbyname(const char *name) 508gethostbyname(const char *name)
509{ 509{
510 struct hostent *hp; 510 struct hostent *hp;
511 res_state res = __res_get_state(); 511 res_state res = __res_get_state();
512 512
513 if (res == NULL) 513 if (res == NULL)
514 return NULL; 514 return NULL;
515 515
516 _DIAGASSERT(name != NULL); 516 _DIAGASSERT(name != NULL);
517 517
518 if (res->options & RES_USE_INET6) { 518 if (res->options & RES_USE_INET6) {
519 hp = gethostbyname_internal(name, AF_INET6, res); 519 hp = gethostbyname_internal(name, AF_INET6, res);
520 if (hp) { 520 if (hp) {
521 __res_put_state(res); 521 __res_put_state(res);
522 return hp; 522 return hp;
523 } 523 }
524 } 524 }
525 hp = gethostbyname_internal(name, AF_INET, res); 525 hp = gethostbyname_internal(name, AF_INET, res);
526 __res_put_state(res); 526 __res_put_state(res);
527 return hp; 527 return hp;
528} 528}
529 529
530struct hostent * 530struct hostent *
531gethostbyname2(const char *name, int af) 531gethostbyname2(const char *name, int af)
532{ 532{
533 struct hostent *hp; 533 struct hostent *hp;
534 res_state res = __res_get_state(); 534 res_state res = __res_get_state();
535 535
536 if (res == NULL) 536 if (res == NULL)
537 return NULL; 537 return NULL;
538 hp = gethostbyname_internal(name, af, res); 538 hp = gethostbyname_internal(name, af, res);
539 __res_put_state(res); 539 __res_put_state(res);
540 return hp; 540 return hp;
541} 541}
542 542
543static struct hostent * 543static struct hostent *
544gethostbyname_internal(const char *name, int af, res_state res) 544gethostbyname_internal(const char *name, int af, res_state res)
545{ 545{
546 const char *cp; 546 const char *cp;
547 char *bp, *ep; 547 char *bp, *ep;
548 int size; 548 int size;
549 struct hostent *hp; 549 struct hostent *hp;
550 static const ns_dtab dtab[] = { 550 static const ns_dtab dtab[] = {
551 NS_FILES_CB(_gethtbyname, NULL) 551 NS_FILES_CB(_gethtbyname, NULL)
552 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */ 552 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */
553 NS_NIS_CB(_yp_gethtbyname, NULL) 553 NS_NIS_CB(_yp_gethtbyname, NULL)
554 NS_NULL_CB 554 NS_NULL_CB
555 }; 555 };
556 556
557 _DIAGASSERT(name != NULL); 557 _DIAGASSERT(name != NULL);
558 558
559 switch (af) { 559 switch (af) {
560 case AF_INET: 560 case AF_INET:
561 size = INADDRSZ; 561 size = INADDRSZ;
562 break; 562 break;
563 case AF_INET6: 563 case AF_INET6:
564 size = IN6ADDRSZ; 564 size = IN6ADDRSZ;
565 break; 565 break;
566 default: 566 default:
567 h_errno = NETDB_INTERNAL; 567 h_errno = NETDB_INTERNAL;
568 errno = EAFNOSUPPORT; 568 errno = EAFNOSUPPORT;
569 return NULL; 569 return NULL;
570 } 570 }
571 571
572 host.h_addrtype = af; 572 host.h_addrtype = af;
573 host.h_length = size; 573 host.h_length = size;
574 574
575 /* 575 /*
576 * if there aren't any dots, it could be a user-level alias. 576 * if there aren't any dots, it could be an user-level alias.
577 * this is also done in res_nquery() since we are not the only 577 * this is also done in res_nquery() since we are not the only
578 * function that looks up host names. 578 * function that looks up host names.
579 */ 579 */
580 if (!strchr(name, '.') && (cp = __hostalias(name))) 580 if (!strchr(name, '.') && (cp = __hostalias(name)))
581 name = cp; 581 name = cp;
582 582
583 /* 583 /*
584 * disallow names consisting only of digits/dots, unless 584 * disallow names consisting only of digits/dots, unless
585 * they end in a dot. 585 * they end in a dot.
586 */ 586 */
587 if (isdigit((u_char) name[0])) 587 if (isdigit((u_char) name[0]))
588 for (cp = name;; ++cp) { 588 for (cp = name;; ++cp) {
589 if (!*cp) { 589 if (!*cp) {
590 if (*--cp == '.') 590 if (*--cp == '.')
591 break; 591 break;
592 /* 592 /*
593 * All-numeric, no dot at the end. 593 * All-numeric, no dot at the end.
594 * Fake up a hostent as if we'd actually 594 * Fake up a hostent as if we'd actually
595 * done a lookup. 595 * done a lookup.
596 */ 596 */
597 if (inet_pton(af, name, 597 if (inet_pton(af, name,
598 (char *)(void *)host_addr) <= 0) { 598 (char *)(void *)host_addr) <= 0) {
599 h_errno = HOST_NOT_FOUND; 599 h_errno = HOST_NOT_FOUND;
600 return NULL; 600 return NULL;
601 } 601 }
602 strncpy(hostbuf, name, MAXDNAME); 602 strncpy(hostbuf, name, MAXDNAME);
603 hostbuf[MAXDNAME] = '\0'; 603 hostbuf[MAXDNAME] = '\0';
604 bp = hostbuf + MAXDNAME; 604 bp = hostbuf + MAXDNAME;
605 ep = hostbuf + sizeof hostbuf; 605 ep = hostbuf + sizeof hostbuf;
606 host.h_name = hostbuf; 606 host.h_name = hostbuf;
607 host.h_aliases = host_aliases; 607 host.h_aliases = host_aliases;
608 host_aliases[0] = NULL; 608 host_aliases[0] = NULL;
609 h_addr_ptrs[0] = (char *)(void *)host_addr; 609 h_addr_ptrs[0] = (char *)(void *)host_addr;
610 h_addr_ptrs[1] = NULL; 610 h_addr_ptrs[1] = NULL;
611 host.h_addr_list = h_addr_ptrs; 611 host.h_addr_list = h_addr_ptrs;
612 if (res->options & RES_USE_INET6) 612 if (res->options & RES_USE_INET6)
613 map_v4v6_hostent(&host, &bp, ep); 613 map_v4v6_hostent(&host, &bp, ep);
614 h_errno = NETDB_SUCCESS; 614 h_errno = NETDB_SUCCESS;
615 return &host; 615 return &host;
616 } 616 }
617 if (!isdigit((u_char) *cp) && *cp != '.')  617 if (!isdigit((u_char) *cp) && *cp != '.')
618 break; 618 break;
619 } 619 }
620 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) || 620 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
621 name[0] == ':') 621 name[0] == ':')
622 for (cp = name;; ++cp) { 622 for (cp = name;; ++cp) {
623 if (!*cp) { 623 if (!*cp) {
624 if (*--cp == '.') 624 if (*--cp == '.')
625 break; 625 break;
626 /* 626 /*
627 * All-IPv6-legal, no dot at the end. 627 * All-IPv6-legal, no dot at the end.
628 * Fake up a hostent as if we'd actually 628 * Fake up a hostent as if we'd actually
629 * done a lookup. 629 * done a lookup.
630 */ 630 */
631 if (inet_pton(af, name, 631 if (inet_pton(af, name,
632 (char *)(void *)host_addr) <= 0) { 632 (char *)(void *)host_addr) <= 0) {
633 h_errno = HOST_NOT_FOUND; 633 h_errno = HOST_NOT_FOUND;
634 return NULL; 634 return NULL;
635 } 635 }
636 strncpy(hostbuf, name, MAXDNAME); 636 strncpy(hostbuf, name, MAXDNAME);
637 hostbuf[MAXDNAME] = '\0'; 637 hostbuf[MAXDNAME] = '\0';
638 bp = hostbuf + MAXDNAME; 638 bp = hostbuf + MAXDNAME;
639 ep = hostbuf + sizeof hostbuf; 639 ep = hostbuf + sizeof hostbuf;
640 host.h_name = hostbuf; 640 host.h_name = hostbuf;
641 host.h_aliases = host_aliases; 641 host.h_aliases = host_aliases;
642 host_aliases[0] = NULL; 642 host_aliases[0] = NULL;
643 h_addr_ptrs[0] = (char *)(void *)host_addr; 643 h_addr_ptrs[0] = (char *)(void *)host_addr;
644 h_addr_ptrs[1] = NULL; 644 h_addr_ptrs[1] = NULL;
645 host.h_addr_list = h_addr_ptrs; 645 host.h_addr_list = h_addr_ptrs;
646 h_errno = NETDB_SUCCESS; 646 h_errno = NETDB_SUCCESS;
647 return &host; 647 return &host;
648 } 648 }
649 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') 649 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
650 break; 650 break;
651 } 651 }
652 652
653 hp = NULL; 653 hp = NULL;
654 h_errno = NETDB_INTERNAL; 654 h_errno = NETDB_INTERNAL;
655 if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyname", 655 if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyname",
656 default_dns_files, name, strlen(name), af) != NS_SUCCESS) 656 default_dns_files, name, strlen(name), af) != NS_SUCCESS)
657 return NULL; 657 return NULL;
658 h_errno = NETDB_SUCCESS; 658 h_errno = NETDB_SUCCESS;
659 return hp; 659 return hp;
660} 660}
661 661
662struct hostent * 662struct hostent *
663gethostbyaddr(const char *addr, /* XXX should have been def'd as u_char! */ 663gethostbyaddr(const char *addr, /* XXX should have been def'd as u_char! */
664 socklen_t len, int af) 664 socklen_t len, int af)
665{ 665{
666 const u_char *uaddr = (const u_char *)addr; 666 const u_char *uaddr = (const u_char *)addr;
667 socklen_t size; 667 socklen_t size;
668 struct hostent *hp; 668 struct hostent *hp;
669 static const ns_dtab dtab[] = { 669 static const ns_dtab dtab[] = {
670 NS_FILES_CB(_gethtbyaddr, NULL) 670 NS_FILES_CB(_gethtbyaddr, NULL)
671 { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */ 671 { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */
672 NS_NIS_CB(_yp_gethtbyaddr, NULL) 672 NS_NIS_CB(_yp_gethtbyaddr, NULL)
673 NS_NULL_CB 673 NS_NULL_CB
674 }; 674 };
675  675
676 _DIAGASSERT(addr != NULL); 676 _DIAGASSERT(addr != NULL);
677 677
678 if (af == AF_INET6 && len == IN6ADDRSZ && 678 if (af == AF_INET6 && len == IN6ADDRSZ &&
679 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)(const void *)uaddr) || 679 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)(const void *)uaddr) ||
680 IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)(const void *)uaddr))) { 680 IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)(const void *)uaddr))) {
681 h_errno = HOST_NOT_FOUND; 681 h_errno = HOST_NOT_FOUND;
682 return NULL; 682 return NULL;
683 } 683 }
684 if (af == AF_INET6 && len == IN6ADDRSZ && 684 if (af == AF_INET6 && len == IN6ADDRSZ &&
685 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)(const void *)uaddr) || 685 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)(const void *)uaddr) ||
686 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)(const void *)uaddr))) { 686 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)(const void *)uaddr))) {
687 /* Unmap. */ 687 /* Unmap. */
688 addr += IN6ADDRSZ - INADDRSZ; 688 addr += IN6ADDRSZ - INADDRSZ;
689 uaddr += IN6ADDRSZ - INADDRSZ; 689 uaddr += IN6ADDRSZ - INADDRSZ;
690 af = AF_INET; 690 af = AF_INET;
691 len = INADDRSZ; 691 len = INADDRSZ;
692 } 692 }
693 switch (af) { 693 switch (af) {
694 case AF_INET: 694 case AF_INET:
695 size = INADDRSZ; 695 size = INADDRSZ;
696 break; 696 break;
697 case AF_INET6: 697 case AF_INET6:
698 size = IN6ADDRSZ; 698 size = IN6ADDRSZ;
699 break; 699 break;
700 default: 700 default:
701 errno = EAFNOSUPPORT; 701 errno = EAFNOSUPPORT;
702 h_errno = NETDB_INTERNAL; 702 h_errno = NETDB_INTERNAL;
703 return NULL; 703 return NULL;
704 } 704 }
705 if (size != len) { 705 if (size != len) {
706 errno = EINVAL; 706 errno = EINVAL;
707 h_errno = NETDB_INTERNAL; 707 h_errno = NETDB_INTERNAL;
708 return NULL; 708 return NULL;
709 } 709 }
710 hp = NULL; 710 hp = NULL;
711 h_errno = NETDB_INTERNAL; 711 h_errno = NETDB_INTERNAL;
712 if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr", 712 if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr",
713 default_dns_files, uaddr, len, af) != NS_SUCCESS) 713 default_dns_files, uaddr, len, af) != NS_SUCCESS)
714 return NULL; 714 return NULL;
715 h_errno = NETDB_SUCCESS; 715 h_errno = NETDB_SUCCESS;
716 return hp; 716 return hp;
717} 717}
718 718
719void 719void
720_sethtent(int f) 720_sethtent(int f)
721{ 721{
722 if (!hostf) 722 if (!hostf)
723 hostf = fopen(_PATH_HOSTS, "r" ); 723 hostf = fopen(_PATH_HOSTS, "r" );
724 else 724 else
725 rewind(hostf); 725 rewind(hostf);
726 stayopen = f; 726 stayopen = f;
727} 727}
728 728
729void 729void
730_endhtent(void) 730_endhtent(void)
731{ 731{
732 if (hostf && !stayopen) { 732 if (hostf && !stayopen) {
733 (void) fclose(hostf); 733 (void) fclose(hostf);
734 hostf = NULL; 734 hostf = NULL;
735 } 735 }
736} 736}
737 737
738struct hostent * 738struct hostent *
739_gethtent(void) 739_gethtent(void)
740{ 740{
741 char *p; 741 char *p;
742 char *cp, **q; 742 char *cp, **q;
743 int af, len; 743 int af, len;
744 744
745 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { 745 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
746 h_errno = NETDB_INTERNAL; 746 h_errno = NETDB_INTERNAL;
747 return NULL; 747 return NULL;
748 } 748 }
749 again: 749 again:
750 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { 750 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
751 h_errno = HOST_NOT_FOUND; 751 h_errno = HOST_NOT_FOUND;
752 return NULL; 752 return NULL;
753 } 753 }
754 if (*p == '#') 754 if (*p == '#')
755 goto again; 755 goto again;
756 if (!(cp = strpbrk(p, "#\n"))) 756 if (!(cp = strpbrk(p, "#\n")))
757 goto again; 757 goto again;
758 *cp = '\0'; 758 *cp = '\0';
759 if (!(cp = strpbrk(p, " \t"))) 759 if (!(cp = strpbrk(p, " \t")))
760 goto again; 760 goto again;
761 *cp++ = '\0'; 761 *cp++ = '\0';
762 if (inet_pton(AF_INET6, p, (char *)(void *)host_addr) > 0) { 762 if (inet_pton(AF_INET6, p, (char *)(void *)host_addr) > 0) {
763 af = AF_INET6; 763 af = AF_INET6;
764 len = IN6ADDRSZ; 764 len = IN6ADDRSZ;
765 } else if (inet_pton(AF_INET, p, (char *)(void *)host_addr) > 0) { 765 } else if (inet_pton(AF_INET, p, (char *)(void *)host_addr) > 0) {
766 res_state res = __res_get_state(); 766 res_state res = __res_get_state();
767 if (res == NULL) 767 if (res == NULL)
768 return NULL; 768 return NULL;
769 if (res->options & RES_USE_INET6) { 769 if (res->options & RES_USE_INET6) {
770 map_v4v6_address((char *)(void *)host_addr, 770 map_v4v6_address((char *)(void *)host_addr,
771 (char *)(void *)host_addr); 771 (char *)(void *)host_addr);
772 af = AF_INET6; 772 af = AF_INET6;
773 len = IN6ADDRSZ; 773 len = IN6ADDRSZ;
774 } else { 774 } else {
775 af = AF_INET; 775 af = AF_INET;
776 len = INADDRSZ; 776 len = INADDRSZ;
777 } 777 }
778 __res_put_state(res); 778 __res_put_state(res);
779 } else { 779 } else {
780 goto again; 780 goto again;
781 } 781 }
782 /* if this is not something we're looking for, skip it. */ 782 /* if this is not something we're looking for, skip it. */
783 if (host.h_addrtype != 0 && host.h_addrtype != af) 783 if (host.h_addrtype != 0 && host.h_addrtype != af)
784 goto again; 784 goto again;
785 if (host.h_length != 0 && host.h_length != len) 785 if (host.h_length != 0 && host.h_length != len)
786 goto again; 786 goto again;
787 h_addr_ptrs[0] = (char *)(void *)host_addr; 787 h_addr_ptrs[0] = (char *)(void *)host_addr;
788 h_addr_ptrs[1] = NULL; 788 h_addr_ptrs[1] = NULL;
789 host.h_addr_list = h_addr_ptrs; 789 host.h_addr_list = h_addr_ptrs;
790 host.h_length = len; 790 host.h_length = len;
791 host.h_addrtype = af; 791 host.h_addrtype = af;
792 while (*cp == ' ' || *cp == '\t') 792 while (*cp == ' ' || *cp == '\t')
793 cp++; 793 cp++;
794 host.h_name = cp; 794 host.h_name = cp;
795 q = host.h_aliases = host_aliases; 795 q = host.h_aliases = host_aliases;
796 if ((cp = strpbrk(cp, " \t")) != NULL) 796 if ((cp = strpbrk(cp, " \t")) != NULL)
797 *cp++ = '\0'; 797 *cp++ = '\0';
798 while (cp && *cp) { 798 while (cp && *cp) {
799 if (*cp == ' ' || *cp == '\t') { 799 if (*cp == ' ' || *cp == '\t') {
800 cp++; 800 cp++;
801 continue; 801 continue;
802 } 802 }
803 if (q < &host_aliases[MAXALIASES - 1]) 803 if (q < &host_aliases[MAXALIASES - 1])
804 *q++ = cp; 804 *q++ = cp;
805 if ((cp = strpbrk(cp, " \t")) != NULL) 805 if ((cp = strpbrk(cp, " \t")) != NULL)
806 *cp++ = '\0'; 806 *cp++ = '\0';
807 } 807 }
808 *q = NULL; 808 *q = NULL;
809 h_errno = NETDB_SUCCESS; 809 h_errno = NETDB_SUCCESS;
810 return &host; 810 return &host;
811} 811}
812 812
813/*ARGSUSED*/ 813/*ARGSUSED*/
814int 814int
815_gethtbyname(void *rv, void *cb_data, va_list ap) 815_gethtbyname(void *rv, void *cb_data, va_list ap)
816{ 816{
817 struct hostent *hp; 817 struct hostent *hp;
818 const char *name; 818 const char *name;
819 int af; 819 int af;
820 820
821 _DIAGASSERT(rv != NULL); 821 _DIAGASSERT(rv != NULL);
822 822
823 name = va_arg(ap, char *); 823 name = va_arg(ap, char *);
824 /* NOSTRICT skip len */(void)va_arg(ap, int); 824 /* NOSTRICT skip len */(void)va_arg(ap, int);
825 af = va_arg(ap, int); 825 af = va_arg(ap, int);
826 826
827 hp = NULL; 827 hp = NULL;
828#if 0 828#if 0
829 { 829 {
830 res_state res = __res_get_state(); 830 res_state res = __res_get_state();
831 if (res == NULL) 831 if (res == NULL)
832 return NS_NOTFOUND; 832 return NS_NOTFOUND;
833 if (res->options & RES_USE_INET6) 833 if (res->options & RES_USE_INET6)
834 hp = _gethtbyname2(name, AF_INET6); 834 hp = _gethtbyname2(name, AF_INET6);
835 if (hp==NULL) 835 if (hp==NULL)
836 hp = _gethtbyname2(name, AF_INET); 836 hp = _gethtbyname2(name, AF_INET);
837 __res_put_state(res); 837 __res_put_state(res);
838 } 838 }
839#else 839#else
840 hp = _gethtbyname2(name, af); 840 hp = _gethtbyname2(name, af);
841#endif 841#endif
842 *((struct hostent **)rv) = hp; 842 *((struct hostent **)rv) = hp;
843 if (hp == NULL) { 843 if (hp == NULL) {
844 h_errno = HOST_NOT_FOUND; 844 h_errno = HOST_NOT_FOUND;
845 return NS_NOTFOUND; 845 return NS_NOTFOUND;
846 } 846 }
847 return NS_SUCCESS; 847 return NS_SUCCESS;
848} 848}
849 849
850struct hostent * 850struct hostent *
851_gethtbyname2(const char *name, int af) 851_gethtbyname2(const char *name, int af)
852{ 852{
853 struct hostent *p; 853 struct hostent *p;
854 char *tmpbuf, *ptr, **cp; 854 char *tmpbuf, *ptr, **cp;
855 int num; 855 int num;
856 size_t len; 856 size_t len;
857 857
858 _DIAGASSERT(name != NULL); 858 _DIAGASSERT(name != NULL);
859 859
860 _sethtent(stayopen); 860 _sethtent(stayopen);
861 ptr = tmpbuf = NULL; 861 ptr = tmpbuf = NULL;
862 num = 0; 862 num = 0;
863 while ((p = _gethtent()) != NULL && num < MAXADDRS) { 863 while ((p = _gethtent()) != NULL && num < MAXADDRS) {
864 if (p->h_addrtype != af) 864 if (p->h_addrtype != af)
865 continue; 865 continue;
866 if (strcasecmp(p->h_name, name) != 0) { 866 if (strcasecmp(p->h_name, name) != 0) {
867 for (cp = p->h_aliases; *cp != NULL; cp++) 867 for (cp = p->h_aliases; *cp != NULL; cp++)
868 if (strcasecmp(*cp, name) == 0) 868 if (strcasecmp(*cp, name) == 0)
869 break; 869 break;
870 if (*cp == NULL) continue; 870 if (*cp == NULL) continue;
871 } 871 }
872 872
873 if (num == 0) { 873 if (num == 0) {
874 size_t bufsize; 874 size_t bufsize;
875 char *src; 875 char *src;
876 876
877 bufsize = strlen(p->h_name) + 2 + 877 bufsize = strlen(p->h_name) + 2 +
878 MAXADDRS * p->h_length + 878 MAXADDRS * p->h_length +
879 ALIGNBYTES; 879 ALIGNBYTES;
880 for (cp = p->h_aliases; *cp != NULL; cp++) 880 for (cp = p->h_aliases; *cp != NULL; cp++)
881 bufsize += strlen(*cp) + 1; 881 bufsize += strlen(*cp) + 1;
882 882
883 if ((tmpbuf = malloc(bufsize)) == NULL) { 883 if ((tmpbuf = malloc(bufsize)) == NULL) {
884 h_errno = NETDB_INTERNAL; 884 h_errno = NETDB_INTERNAL;
885 return NULL; 885 return NULL;
886 } 886 }
887 887
888 ptr = tmpbuf; 888 ptr = tmpbuf;
889 src = p->h_name; 889 src = p->h_name;
890 while ((*ptr++ = *src++) != '\0'); 890 while ((*ptr++ = *src++) != '\0');
891 for (cp = p->h_aliases; *cp != NULL; cp++) { 891 for (cp = p->h_aliases; *cp != NULL; cp++) {
892 src = *cp; 892 src = *cp;
893 while ((*ptr++ = *src++) != '\0'); 893 while ((*ptr++ = *src++) != '\0');
894 } 894 }
895 *ptr++ = '\0'; 895 *ptr++ = '\0';
896 896
897 ptr = (char *)(void *)ALIGN(ptr); 897 ptr = (char *)(void *)ALIGN(ptr);
898 } 898 }
899 899
900 (void)memcpy(ptr, p->h_addr_list[0], (size_t)p->h_length); 900 (void)memcpy(ptr, p->h_addr_list[0], (size_t)p->h_length);
901 ptr += p->h_length; 901 ptr += p->h_length;
902 num++; 902 num++;
903 } 903 }
904 _endhtent(); 904 _endhtent();
905 if (num == 0) return NULL; 905 if (num == 0) return NULL;
906 906
907 len = ptr - tmpbuf; 907 len = ptr - tmpbuf;
908 if (len > (sizeof(hostbuf) - ALIGNBYTES)) { 908 if (len > (sizeof(hostbuf) - ALIGNBYTES)) {
909 free(tmpbuf); 909 free(tmpbuf);
910 errno = ENOSPC; 910 errno = ENOSPC;
911 h_errno = NETDB_INTERNAL; 911 h_errno = NETDB_INTERNAL;
912 return NULL; 912 return NULL;
913 } 913 }
914 ptr = memcpy((void *)ALIGN(hostbuf), tmpbuf, len); 914 ptr = memcpy((void *)ALIGN(hostbuf), tmpbuf, len);
915 free(tmpbuf); 915 free(tmpbuf);
916 916
917 host.h_name = ptr; 917 host.h_name = ptr;
918 while (*ptr++); 918 while (*ptr++);
919 919
920 cp = host_aliases; 920 cp = host_aliases;
921 while (*ptr) { 921 while (*ptr) {
922 *cp++ = ptr; 922 *cp++ = ptr;
923 while (*ptr++); 923 while (*ptr++);
924 } 924 }
925 ptr++; 925 ptr++;
926 *cp = NULL; 926 *cp = NULL;
927 927
928 ptr = (char *)(void *)ALIGN(ptr); 928 ptr = (char *)(void *)ALIGN(ptr);
929 cp = h_addr_ptrs; 929 cp = h_addr_ptrs;
930 while (num--) { 930 while (num--) {
931 *cp++ = ptr; 931 *cp++ = ptr;
932 ptr += host.h_length; 932 ptr += host.h_length;
933 } 933 }
934 *cp = NULL; 934 *cp = NULL;
935 935
936 return &host; 936 return &host;
937} 937}
938 938
939/*ARGSUSED*/ 939/*ARGSUSED*/
940int 940int
941_gethtbyaddr(void *rv, void *cb_data, va_list ap) 941_gethtbyaddr(void *rv, void *cb_data, va_list ap)
942{ 942{
943 struct hostent *p; 943 struct hostent *p;
944 const unsigned char *addr; 944 const unsigned char *addr;
945 int len, af; 945 int len, af;
946 946
947 _DIAGASSERT(rv != NULL); 947 _DIAGASSERT(rv != NULL);
948 948
949 addr = va_arg(ap, unsigned char *); 949 addr = va_arg(ap, unsigned char *);
950 len = va_arg(ap, int); 950 len = va_arg(ap, int);
951 af = va_arg(ap, int); 951 af = va_arg(ap, int);
952  952
953 host.h_length = len; 953 host.h_length = len;
954 host.h_addrtype = af; 954 host.h_addrtype = af;
955 955
956 _sethtent(stayopen); 956 _sethtent(stayopen);
957 while ((p = _gethtent()) != NULL) 957 while ((p = _gethtent()) != NULL)
958 if (p->h_addrtype == af && !memcmp(p->h_addr, addr, 958 if (p->h_addrtype == af && !memcmp(p->h_addr, addr,
959 (size_t)len)) 959 (size_t)len))
960 break; 960 break;
961 _endhtent(); 961 _endhtent();
962 *((struct hostent **)rv) = p; 962 *((struct hostent **)rv) = p;
963 if (p==NULL) { 963 if (p==NULL) {
964 h_errno = HOST_NOT_FOUND; 964 h_errno = HOST_NOT_FOUND;
965 return NS_NOTFOUND; 965 return NS_NOTFOUND;
966 } 966 }
967 return NS_SUCCESS; 967 return NS_SUCCESS;
968} 968}
969 969
970static void 970static void
971map_v4v6_address(const char *src, char *dst) 971map_v4v6_address(const char *src, char *dst)
972{ 972{
973 u_char *p = (u_char *)dst; 973 u_char *p = (u_char *)dst;
974 char tmp[INADDRSZ]; 974 char tmp[INADDRSZ];
975 int i; 975 int i;
976 976
977 _DIAGASSERT(src != NULL); 977 _DIAGASSERT(src != NULL);
978 _DIAGASSERT(dst != NULL); 978 _DIAGASSERT(dst != NULL);
979 979
980 /* Stash a temporary copy so our caller can update in place. */ 980 /* Stash a temporary copy so our caller can update in place. */
981 (void)memcpy(tmp, src, INADDRSZ); 981 (void)memcpy(tmp, src, INADDRSZ);
982 /* Mark this ipv6 addr as a mapped ipv4. */ 982 /* Mark this ipv6 addr as a mapped ipv4. */
983 for (i = 0; i < 10; i++) 983 for (i = 0; i < 10; i++)
984 *p++ = 0x00; 984 *p++ = 0x00;
985 *p++ = 0xff; 985 *p++ = 0xff;
986 *p++ = 0xff; 986 *p++ = 0xff;
987 /* Retrieve the saved copy and we're done. */ 987 /* Retrieve the saved copy and we're done. */
988 (void)memcpy((void *)p, tmp, INADDRSZ); 988 (void)memcpy((void *)p, tmp, INADDRSZ);
989} 989}
990 990
991static void 991static void
992map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) 992map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
993{ 993{
994 char **ap; 994 char **ap;
995 995
996 _DIAGASSERT(hp != NULL); 996 _DIAGASSERT(hp != NULL);
997 _DIAGASSERT(bpp != NULL); 997 _DIAGASSERT(bpp != NULL);
998 _DIAGASSERT(ep != NULL); 998 _DIAGASSERT(ep != NULL);
999 999
1000 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) 1000 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
1001 return; 1001 return;
1002 hp->h_addrtype = AF_INET6; 1002 hp->h_addrtype = AF_INET6;
1003 hp->h_length = IN6ADDRSZ; 1003 hp->h_length = IN6ADDRSZ;
1004 for (ap = hp->h_addr_list; *ap; ap++) { 1004 for (ap = hp->h_addr_list; *ap; ap++) {
1005 int i = sizeof(align) - (size_t)((u_long)*bpp % sizeof(align)); 1005 int i = sizeof(align) - (size_t)((u_long)*bpp % sizeof(align));
1006 1006
1007 if (ep - *bpp < (i + IN6ADDRSZ)) { 1007 if (ep - *bpp < (i + IN6ADDRSZ)) {
1008 /* Out of memory. Truncate address list here. XXX */ 1008 /* Out of memory. Truncate address list here. XXX */
1009 *ap = NULL; 1009 *ap = NULL;
1010 return; 1010 return;
1011 } 1011 }
1012 *bpp += i; 1012 *bpp += i;
1013 map_v4v6_address(*ap, *bpp); 1013 map_v4v6_address(*ap, *bpp);
1014 *ap = *bpp; 1014 *ap = *bpp;
1015 *bpp += IN6ADDRSZ; 1015 *bpp += IN6ADDRSZ;
1016 } 1016 }
1017} 1017}
1018 1018
1019static void 1019static void
1020addrsort(char **ap, int num, res_state res) 1020addrsort(char **ap, int num, res_state res)
1021{ 1021{
1022 int i, j; 1022 int i, j;
1023 char **p; 1023 char **p;
1024 short aval[MAXADDRS]; 1024 short aval[MAXADDRS];
1025 int needsort = 0; 1025 int needsort = 0;
1026 1026
1027 _DIAGASSERT(ap != NULL); 1027 _DIAGASSERT(ap != NULL);
1028 1028
1029 p = ap; 1029 p = ap;
1030 for (i = 0; i < num; i++, p++) { 1030 for (i = 0; i < num; i++, p++) {
1031 for (j = 0 ; (unsigned)j < res->nsort; j++) 1031 for (j = 0 ; (unsigned)j < res->nsort; j++)
1032 if (res->sort_list[j].addr.s_addr ==  1032 if (res->sort_list[j].addr.s_addr ==
1033 (((struct in_addr *)(void *)(*p))->s_addr & 1033 (((struct in_addr *)(void *)(*p))->s_addr &
1034 res->sort_list[j].mask)) 1034 res->sort_list[j].mask))
1035 break; 1035 break;
1036 aval[i] = j; 1036 aval[i] = j;
1037 if (needsort == 0 && i > 0 && j < aval[i-1]) 1037 if (needsort == 0 && i > 0 && j < aval[i-1])
1038 needsort = i; 1038 needsort = i;
1039 } 1039 }
1040 if (!needsort) 1040 if (!needsort)
1041 return; 1041 return;
1042 1042
1043 while (needsort < num) { 1043 while (needsort < num) {
1044 for (j = needsort - 1; j >= 0; j--) { 1044 for (j = needsort - 1; j >= 0; j--) {
1045 if (aval[j] > aval[j+1]) { 1045 if (aval[j] > aval[j+1]) {
1046 char *hp; 1046 char *hp;
1047 1047
1048 i = aval[j]; 1048 i = aval[j];
1049 aval[j] = aval[j+1]; 1049 aval[j] = aval[j+1];
1050 aval[j+1] = i; 1050 aval[j+1] = i;
1051 1051
1052 hp = ap[j]; 1052 hp = ap[j];
1053 ap[j] = ap[j+1]; 1053 ap[j] = ap[j+1];
1054 ap[j+1] = hp; 1054 ap[j+1] = hp;
1055 } else 1055 } else
1056 break; 1056 break;
1057 } 1057 }
1058 needsort++; 1058 needsort++;
1059 } 1059 }
1060} 1060}
1061 1061
1062struct hostent * 1062struct hostent *
1063gethostent(void) 1063gethostent(void)
1064{ 1064{
1065 host.h_addrtype = 0; 1065 host.h_addrtype = 0;
1066 host.h_length = 0; 1066 host.h_length = 0;
1067 return _gethtent(); 1067 return _gethtent();
1068} 1068}
1069 1069
1070/*ARGSUSED*/ 1070/*ARGSUSED*/
1071int 1071int
1072_dns_gethtbyname(void *rv, void *cb_data, va_list ap) 1072_dns_gethtbyname(void *rv, void *cb_data, va_list ap)
1073{ 1073{
1074 querybuf *buf; 1074 querybuf *buf;
1075 int n, type; 1075 int n, type;
1076 struct hostent *hp; 1076 struct hostent *hp;
1077 const char *name; 1077 const char *name;
1078 int af; 1078 int af;
1079 res_state res; 1079 res_state res;
1080 1080
1081 _DIAGASSERT(rv != NULL); 1081 _DIAGASSERT(rv != NULL);
1082 1082
1083 name = va_arg(ap, char *); 1083 name = va_arg(ap, char *);
1084 /* NOSTRICT skip len */(void)va_arg(ap, int); 1084 /* NOSTRICT skip len */(void)va_arg(ap, int);
1085 af = va_arg(ap, int); 1085 af = va_arg(ap, int);
1086 1086
1087 switch (af) { 1087 switch (af) {
1088 case AF_INET: 1088 case AF_INET:
1089 type = T_A; 1089 type = T_A;
1090 break; 1090 break;
1091 case AF_INET6: 1091 case AF_INET6:
1092 type = T_AAAA; 1092 type = T_AAAA;
1093 break; 1093 break;
1094 default: 1094 default:
1095 return NS_UNAVAIL; 1095 return NS_UNAVAIL;
1096 } 1096 }
1097 buf = malloc(sizeof(*buf)); 1097 buf = malloc(sizeof(*buf));
1098 if (buf == NULL) { 1098 if (buf == NULL) {
1099 h_errno = NETDB_INTERNAL; 1099 h_errno = NETDB_INTERNAL;
1100 return NS_NOTFOUND; 1100 return NS_NOTFOUND;
1101 } 1101 }
1102 res = __res_get_state(); 1102 res = __res_get_state();
1103 if (res == NULL) { 1103 if (res == NULL) {
1104 free(buf); 1104 free(buf);
1105 return NS_NOTFOUND; 1105 return NS_NOTFOUND;
1106 } 1106 }
1107 n = res_nsearch(res, name, C_IN, type, buf->buf, sizeof(buf->buf)); 1107 n = res_nsearch(res, name, C_IN, type, buf->buf, sizeof(buf->buf));
1108 if (n < 0) { 1108 if (n < 0) {
1109 free(buf); 1109 free(buf);
1110 dprintf("res_nsearch failed (%d)\n", res, n); 1110 dprintf("res_nsearch failed (%d)\n", res, n);
1111 __res_put_state(res); 1111 __res_put_state(res);
1112 return NS_NOTFOUND; 1112 return NS_NOTFOUND;
1113 } 1113 }
1114 hp = getanswer(buf, n, name, type, res); 1114 hp = getanswer(buf, n, name, type, res);
1115 free(buf); 1115 free(buf);
1116 __res_put_state(res); 1116 __res_put_state(res);
1117 if (hp == NULL) 1117 if (hp == NULL)
1118 switch (h_errno) { 1118 switch (h_errno) {
1119 case HOST_NOT_FOUND: 1119 case HOST_NOT_FOUND:
1120 return NS_NOTFOUND; 1120 return NS_NOTFOUND;
1121 case TRY_AGAIN: 1121 case TRY_AGAIN:
1122 return NS_TRYAGAIN; 1122 return NS_TRYAGAIN;
1123 default: 1123 default:
1124 return NS_UNAVAIL; 1124 return NS_UNAVAIL;
1125 } 1125 }
1126 *((struct hostent **)rv) = hp; 1126 *((struct hostent **)rv) = hp;
1127 return NS_SUCCESS; 1127 return NS_SUCCESS;
1128} 1128}
1129 1129
1130/*ARGSUSED*/ 1130/*ARGSUSED*/
1131int 1131int
1132_dns_gethtbyaddr(void *rv, void *cb_data, va_list ap) 1132_dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1133{ 1133{
1134 char qbuf[MAXDNAME + 1], *qp, *ep; 1134 char qbuf[MAXDNAME + 1], *qp, *ep;
1135 int n; 1135 int n;
1136 querybuf *buf; 1136 querybuf *buf;
1137 struct hostent *hp; 1137 struct hostent *hp;
1138 const unsigned char *uaddr; 1138 const unsigned char *uaddr;
1139 int len, af, advance; 1139 int len, af, advance;
1140 res_state res; 1140 res_state res;
1141 1141
1142 _DIAGASSERT(rv != NULL); 1142 _DIAGASSERT(rv != NULL);
1143 1143
1144 uaddr = va_arg(ap, unsigned char *); 1144 uaddr = va_arg(ap, unsigned char *);
1145 len = va_arg(ap, int); 1145 len = va_arg(ap, int);
1146 af = va_arg(ap, int); 1146 af = va_arg(ap, int);
1147 1147
1148 switch (af) { 1148 switch (af) {
1149 case AF_INET: 1149 case AF_INET:
1150 (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", 1150 (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
1151 (uaddr[3] & 0xff), (uaddr[2] & 0xff), 1151 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
1152 (uaddr[1] & 0xff), (uaddr[0] & 0xff)); 1152 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
1153 break; 1153 break;
1154 1154
1155 case AF_INET6: 1155 case AF_INET6:
1156 qp = qbuf; 1156 qp = qbuf;
1157 ep = qbuf + sizeof(qbuf) - 1; 1157 ep = qbuf + sizeof(qbuf) - 1;
1158 for (n = IN6ADDRSZ - 1; n >= 0; n--) { 1158 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
1159 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.", 1159 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
1160 uaddr[n] & 0xf, 1160 uaddr[n] & 0xf,
1161 ((unsigned int)uaddr[n] >> 4) & 0xf); 1161 ((unsigned int)uaddr[n] >> 4) & 0xf);
1162 if (advance > 0 && qp + advance < ep) 1162 if (advance > 0 && qp + advance < ep)
1163 qp += advance; 1163 qp += advance;
1164 else { 1164 else {
1165 h_errno = NETDB_INTERNAL; 1165 h_errno = NETDB_INTERNAL;
1166 return NS_NOTFOUND; 1166 return NS_NOTFOUND;
1167 } 1167 }
1168 } 1168 }
1169 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) { 1169 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
1170 h_errno = NETDB_INTERNAL; 1170 h_errno = NETDB_INTERNAL;
1171 return NS_NOTFOUND; 1171 return NS_NOTFOUND;
1172 } 1172 }
1173 break; 1173 break;
1174 default: 1174 default:
1175 abort(); 1175 abort();
1176 } 1176 }
1177 1177
1178 buf = malloc(sizeof(*buf)); 1178 buf = malloc(sizeof(*buf));
1179 if (buf == NULL) { 1179 if (buf == NULL) {
1180 h_errno = NETDB_INTERNAL; 1180 h_errno = NETDB_INTERNAL;
1181 return NS_NOTFOUND; 1181 return NS_NOTFOUND;
1182 } 1182 }
1183 res = __res_get_state(); 1183 res = __res_get_state();
1184 if (res == NULL) { 1184 if (res == NULL) {
1185 free(buf); 1185 free(buf);
1186 return NS_NOTFOUND; 1186 return NS_NOTFOUND;
1187 } 1187 }
1188 n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, sizeof(buf->buf)); 1188 n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, sizeof(buf->buf));
1189 if (n < 0) { 1189 if (n < 0) {
1190 free(buf); 1190 free(buf);
1191 dprintf("res_nquery failed (%d)\n", res, n); 1191 dprintf("res_nquery failed (%d)\n", res, n);
1192 __res_put_state(res); 1192 __res_put_state(res);
1193 return NS_NOTFOUND; 1193 return NS_NOTFOUND;
1194 } 1194 }
1195 hp = getanswer(buf, n, qbuf, T_PTR, res); 1195 hp = getanswer(buf, n, qbuf, T_PTR, res);
1196 free(buf); 1196 free(buf);
1197 if (hp == NULL) { 1197 if (hp == NULL) {
1198 __res_put_state(res); 1198 __res_put_state(res);
1199 switch (h_errno) { 1199 switch (h_errno) {
1200 case HOST_NOT_FOUND: 1200 case HOST_NOT_FOUND:
1201 return NS_NOTFOUND; 1201 return NS_NOTFOUND;
1202 case TRY_AGAIN: 1202 case TRY_AGAIN:
1203 return NS_TRYAGAIN; 1203 return NS_TRYAGAIN;
1204 default: 1204 default:
1205 return NS_UNAVAIL; 1205 return NS_UNAVAIL;
1206 } 1206 }
1207 } 1207 }
1208 hp->h_addrtype = af; 1208 hp->h_addrtype = af;
1209 hp->h_length = len; 1209 hp->h_length = len;
1210 (void)memcpy(host_addr, uaddr, (size_t)len); 1210 (void)memcpy(host_addr, uaddr, (size_t)len);
1211 h_addr_ptrs[0] = (char *)(void *)host_addr; 1211 h_addr_ptrs[0] = (char *)(void *)host_addr;
1212 h_addr_ptrs[1] = NULL; 1212 h_addr_ptrs[1] = NULL;
1213 if (af == AF_INET && (res->options & RES_USE_INET6)) { 1213 if (af == AF_INET && (res->options & RES_USE_INET6)) {
1214 map_v4v6_address((char *)(void *)host_addr, 1214 map_v4v6_address((char *)(void *)host_addr,
1215 (char *)(void *)host_addr); 1215 (char *)(void *)host_addr);
1216 hp->h_addrtype = AF_INET6; 1216 hp->h_addrtype = AF_INET6;
1217 hp->h_length = IN6ADDRSZ; 1217 hp->h_length = IN6ADDRSZ;
1218 } 1218 }
1219 1219
1220 __res_put_state(res); 1220 __res_put_state(res);
1221 *((struct hostent **)rv) = hp; 1221 *((struct hostent **)rv) = hp;
1222 h_errno = NETDB_SUCCESS; 1222 h_errno = NETDB_SUCCESS;
1223 return NS_SUCCESS; 1223 return NS_SUCCESS;
1224} 1224}
1225 1225
1226#ifdef YP 1226#ifdef YP
1227/*ARGSUSED*/ 1227/*ARGSUSED*/
1228struct hostent * 1228struct hostent *
1229_yphostent(char *line, int af) 1229_yphostent(char *line, int af)
1230{ 1230{
1231 static struct in_addr host_addrs[MAXADDRS]; 1231 static struct in_addr host_addrs[MAXADDRS];
1232 static struct in6_addr host6_addrs[MAXADDRS]; 1232 static struct in6_addr host6_addrs[MAXADDRS];
1233 char *p = line; 1233 char *p = line;
1234 char *cp, **q; 1234 char *cp, **q;
1235 char **hap; 1235 char **hap;
1236 int addrok; 1236 int addrok;
1237 int more; 1237 int more;
1238 size_t naddrs; 1238 size_t naddrs;
1239 1239
1240 _DIAGASSERT(line != NULL); 1240 _DIAGASSERT(line != NULL);
1241 1241
1242 host.h_name = NULL; 1242 host.h_name = NULL;
1243 host.h_addr_list = h_addr_ptrs; 1243 host.h_addr_list = h_addr_ptrs;
1244 host.h_addrtype = af; 1244 host.h_addrtype = af;
1245 switch (af) { 1245 switch (af) {
1246 case AF_INET: 1246 case AF_INET:
1247 host.h_length = INADDRSZ; 1247 host.h_length = INADDRSZ;
1248 break; 1248 break;
1249 case AF_INET6: 1249 case AF_INET6:
1250 host.h_length = IN6ADDRSZ; 1250 host.h_length = IN6ADDRSZ;
1251 break; 1251 break;
1252 default: 1252 default:
1253 return NULL; 1253 return NULL;
1254 } 1254 }
1255 hap = h_addr_ptrs; 1255 hap = h_addr_ptrs;
1256 q = host.h_aliases = host_aliases; 1256 q = host.h_aliases = host_aliases;
1257 naddrs = 0; 1257 naddrs = 0;
1258 1258
1259nextline: 1259nextline:
1260 /* check for host_addrs overflow */ 1260 /* check for host_addrs overflow */
1261 if (naddrs >= sizeof(host_addrs) / sizeof(host_addrs[0])) 1261 if (naddrs >= sizeof(host_addrs) / sizeof(host_addrs[0]))
1262 goto done; 1262 goto done;
1263 if (naddrs >= sizeof(host6_addrs) / sizeof(host6_addrs[0])) 1263 if (naddrs >= sizeof(host6_addrs) / sizeof(host6_addrs[0]))
1264 goto done; 1264 goto done;
1265 1265
1266 more = 0; 1266 more = 0;
1267 cp = strpbrk(p, " \t"); 1267 cp = strpbrk(p, " \t");
1268 if (cp == NULL) 1268 if (cp == NULL)
1269 goto done; 1269 goto done;
1270 *cp++ = '\0'; 1270 *cp++ = '\0';
1271 1271
1272 /* p has should have an address */ 1272 /* p has should have an address */
1273 addrok = 0; 1273 addrok = 0;
1274 switch (af) { 1274 switch (af) {
1275 case AF_INET: 1275 case AF_INET:
1276 addrok = inet_aton(p, &host_addrs[naddrs]); 1276 addrok = inet_aton(p, &host_addrs[naddrs]);
1277 break; 1277 break;
1278 case AF_INET6: 1278 case AF_INET6:
1279 addrok = inet_pton(af, p, &host6_addrs[naddrs]); 1279 addrok = inet_pton(af, p, &host6_addrs[naddrs]);
1280 break; 1280 break;
1281 } 1281 }
1282 if (addrok != 1) { 1282 if (addrok != 1) {
1283 /* skip to the next line */ 1283 /* skip to the next line */
1284 while (cp && *cp) { 1284 while (cp && *cp) {
1285 if (*cp == '\n') { 1285 if (*cp == '\n') {
1286 cp++; 1286 cp++;
1287 goto nextline; 1287 goto nextline;
1288 } 1288 }
1289 cp++; 1289 cp++;
1290 } 1290 }
1291 1291
1292 goto done; 1292 goto done;
1293 } 1293 }
1294 1294
1295 switch (af) { 1295 switch (af) {
1296 case AF_INET: 1296 case AF_INET:
1297 *hap++ = (char *)(void *)&host_addrs[naddrs++]; 1297 *hap++ = (char *)(void *)&host_addrs[naddrs++];
1298 break; 1298 break;
1299 case AF_INET6: 1299 case AF_INET6:
1300 *hap++ = (char *)(void *)&host6_addrs[naddrs++]; 1300 *hap++ = (char *)(void *)&host6_addrs[naddrs++];
1301 break; 1301 break;
1302 } 1302 }
1303 1303
1304 while (*cp == ' ' || *cp == '\t') 1304 while (*cp == ' ' || *cp == '\t')
1305 cp++; 1305 cp++;
1306 p = cp; 1306 p = cp;
1307 cp = strpbrk(p, " \t\n"); 1307 cp = strpbrk(p, " \t\n");
1308 if (cp != NULL) { 1308 if (cp != NULL) {
1309 if (*cp == '\n') 1309 if (*cp == '\n')
1310 more = 1; 1310 more = 1;
1311 *cp++ = '\0'; 1311 *cp++ = '\0';
1312 } 1312 }
1313 if (!host.h_name) 1313 if (!host.h_name)
1314 host.h_name = p; 1314 host.h_name = p;
1315 else if (strcmp(host.h_name, p)==0) 1315 else if (strcmp(host.h_name, p)==0)
1316 ; 1316 ;
1317 else if (q < &host_aliases[MAXALIASES - 1]) 1317 else if (q < &host_aliases[MAXALIASES - 1])
1318 *q++ = p; 1318 *q++ = p;
1319 p = cp; 1319 p = cp;
1320 if (more) 1320 if (more)
1321 goto nextline; 1321 goto nextline;
1322 1322
1323 while (cp && *cp) { 1323 while (cp && *cp) {
1324 if (*cp == ' ' || *cp == '\t') { 1324 if (*cp == ' ' || *cp == '\t') {
1325 cp++; 1325 cp++;
1326 continue; 1326 continue;
1327 } 1327 }
1328 if (*cp == '\n') { 1328 if (*cp == '\n') {
1329 cp++; 1329 cp++;
1330 goto nextline; 1330 goto nextline;
1331 } 1331 }
1332 if (q < &host_aliases[MAXALIASES - 1]) 1332 if (q < &host_aliases[MAXALIASES - 1])
1333 *q++ = cp; 1333 *q++ = cp;
1334 cp = strpbrk(cp, " \t"); 1334 cp = strpbrk(cp, " \t");
1335 if (cp != NULL) 1335 if (cp != NULL)
1336 *cp++ = '\0'; 1336 *cp++ = '\0';
1337 } 1337 }
1338 1338
1339done: 1339done:
1340 if (host.h_name == NULL) 1340 if (host.h_name == NULL)
1341 return NULL; 1341 return NULL;
1342 *q = NULL; 1342 *q = NULL;
1343 *hap = NULL; 1343 *hap = NULL;
1344 return &host; 1344 return &host;
1345} 1345}
1346 1346
1347/*ARGSUSED*/ 1347/*ARGSUSED*/
1348int 1348int
1349_yp_gethtbyaddr(void *rv, void *cb_data, va_list ap) 1349_yp_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1350{ 1350{
1351 struct hostent *hp = NULL; 1351 struct hostent *hp = NULL;
1352 static char *__ypcurrent; 1352 static char *__ypcurrent;
1353 int __ypcurrentlen, r; 1353 int __ypcurrentlen, r;
1354 char name[INET6_ADDRSTRLEN]; /* XXX enough? */ 1354 char name[INET6_ADDRSTRLEN]; /* XXX enough? */
1355 const unsigned char *uaddr; 1355 const unsigned char *uaddr;
1356 int af; 1356 int af;
1357 const char *map; 1357 const char *map;
1358 1358
1359 _DIAGASSERT(rv != NULL); 1359 _DIAGASSERT(rv != NULL);
1360 1360
1361 uaddr = va_arg(ap, unsigned char *); 1361 uaddr = va_arg(ap, unsigned char *);
1362 /* NOSTRICT skip len */(void)va_arg(ap, int); 1362 /* NOSTRICT skip len */(void)va_arg(ap, int);
1363 af = va_arg(ap, int); 1363 af = va_arg(ap, int);
1364  1364
1365 if (!__ypdomain) { 1365 if (!__ypdomain) {
1366 if (_yp_check(&__ypdomain) == 0) 1366 if (_yp_check(&__ypdomain) == 0)
1367 return NS_UNAVAIL; 1367 return NS_UNAVAIL;
1368 } 1368 }
1369 /* 1369 /*
1370 * XXX unfortunately, we cannot support IPv6 extended scoped address 1370 * XXX unfortunately, we cannot support IPv6 extended scoped address
1371 * notation here. gethostbyaddr() is not scope-aware. too bad. 1371 * notation here. gethostbyaddr() is not scope-aware. too bad.
1372 */ 1372 */
1373 if (inet_ntop(af, uaddr, name, sizeof(name)) == NULL) 1373 if (inet_ntop(af, uaddr, name, sizeof(name)) == NULL)
1374 return NS_UNAVAIL; 1374 return NS_UNAVAIL;
1375 if (__ypcurrent) 1375 if (__ypcurrent)
1376 free(__ypcurrent); 1376 free(__ypcurrent);
1377 __ypcurrent = NULL; 1377 __ypcurrent = NULL;
1378 switch (af) { 1378 switch (af) {
1379 case AF_INET: 1379 case AF_INET:
1380 map = "hosts.byaddr"; 1380 map = "hosts.byaddr";
1381 break; 1381 break;
1382 default: 1382 default:
1383 map = "ipnodes.byaddr"; 1383 map = "ipnodes.byaddr";
1384 break; 1384 break;
1385 } 1385 }
1386 r = yp_match(__ypdomain, map, name, 1386 r = yp_match(__ypdomain, map, name,
1387 (int)strlen(name), &__ypcurrent, &__ypcurrentlen); 1387 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1388 if (r == 0) 1388 if (r == 0)
1389 hp = _yphostent(__ypcurrent, af); 1389 hp = _yphostent(__ypcurrent, af);
1390 if (hp == NULL) { 1390 if (hp == NULL) {
1391 h_errno = HOST_NOT_FOUND; 1391 h_errno = HOST_NOT_FOUND;
1392 return NS_NOTFOUND; 1392 return NS_NOTFOUND;
1393 } 1393 }
1394 *((struct hostent **)rv) = hp; 1394 *((struct hostent **)rv) = hp;
1395 return NS_SUCCESS; 1395 return NS_SUCCESS;
1396} 1396}
1397 1397
1398/*ARGSUSED*/ 1398/*ARGSUSED*/
1399int 1399int
1400_yp_gethtbyname(void *rv, void *cb_data, va_list ap) 1400_yp_gethtbyname(void *rv, void *cb_data, va_list ap)
1401{ 1401{
1402 struct hostent *hp = NULL; 1402 struct hostent *hp = NULL;
1403 static char *__ypcurrent; 1403 static char *__ypcurrent;
1404 int __ypcurrentlen, r; 1404 int __ypcurrentlen, r;
1405 const char *name; 1405 const char *name;
1406 int af; 1406 int af;
1407 const char *map; 1407 const char *map;
1408 1408
1409 _DIAGASSERT(rv != NULL); 1409 _DIAGASSERT(rv != NULL);
1410 1410
1411 name = va_arg(ap, char *); 1411 name = va_arg(ap, char *);
1412 /* NOSTRICT skip len */(void)va_arg(ap, int); 1412 /* NOSTRICT skip len */(void)va_arg(ap, int);
1413 af = va_arg(ap, int); 1413 af = va_arg(ap, int);
1414 1414
1415 if (!__ypdomain) { 1415 if (!__ypdomain) {
1416 if (_yp_check(&__ypdomain) == 0) 1416 if (_yp_check(&__ypdomain) == 0)
1417 return NS_UNAVAIL; 1417 return NS_UNAVAIL;
1418 } 1418 }
1419 if (__ypcurrent) 1419 if (__ypcurrent)
1420 free(__ypcurrent); 1420 free(__ypcurrent);
1421 __ypcurrent = NULL; 1421 __ypcurrent = NULL;
1422 switch (af) { 1422 switch (af) {
1423 case AF_INET: 1423 case AF_INET:
1424 map = "hosts.byname"; 1424 map = "hosts.byname";
1425 break; 1425 break;
1426 default: 1426 default:
1427 map = "ipnodes.byname"; 1427 map = "ipnodes.byname";
1428 break; 1428 break;
1429 } 1429 }
1430 r = yp_match(__ypdomain, map, name, 1430 r = yp_match(__ypdomain, map, name,
1431 (int)strlen(name), &__ypcurrent, &__ypcurrentlen); 1431 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1432 if (r == 0) 1432 if (r == 0)
1433 hp = _yphostent(__ypcurrent, af); 1433 hp = _yphostent(__ypcurrent, af);
1434 if (hp == NULL) { 1434 if (hp == NULL) {
1435 h_errno = HOST_NOT_FOUND; 1435 h_errno = HOST_NOT_FOUND;
1436 return NS_NOTFOUND; 1436 return NS_NOTFOUND;
1437 } 1437 }
1438 *((struct hostent **)rv) = hp; 1438 *((struct hostent **)rv) = hp;
1439 return NS_SUCCESS; 1439 return NS_SUCCESS;
1440} 1440}
1441#endif 1441#endif

cvs diff -r1.22 -r1.23 src/lib/libc/net/resolver.3 (switch to unified diff)

--- src/lib/libc/net/resolver.3 2009/06/08 16:55:30 1.22
+++ src/lib/libc/net/resolver.3 2009/10/02 06:49:23 1.23
@@ -1,717 +1,717 @@ @@ -1,717 +1,717 @@
1.\" $NetBSD: resolver.3,v 1.22 2009/06/08 16:55:30 christos Exp $ 1.\" $NetBSD: resolver.3,v 1.23 2009/10/02 06:49:23 cegger Exp $
2.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 2.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3.\" 3.\"
4.\" Permission to use, copy, modify, and distribute this software for any 4.\" Permission to use, copy, modify, and distribute this software for any
5.\" purpose with or without fee is hereby granted, provided that the above 5.\" purpose with or without fee is hereby granted, provided that the above
6.\" copyright notice and this permission notice appear in all copies. 6.\" copyright notice and this permission notice appear in all copies.
7.\" 7.\"
8.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 8.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
9.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 10.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
11.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 13.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15.\" 15.\"
16.\" Copyright (c) 1985, 1995 The Regents of the University of California. 16.\" Copyright (c) 1985, 1995 The Regents of the University of California.
17.\" All rights reserved. 17.\" All rights reserved.
18.\" 18.\"
19.\" Redistribution and use in source and binary forms are permitted provided 19.\" Redistribution and use in source and binary forms are permitted provided
20.\" that: (1) source distributions retain this entire copyright notice and 20.\" that: (1) source distributions retain this entire copyright notice and
21.\" comment, and (2) distributions including binaries display the following 21.\" comment, and (2) distributions including binaries display the following
22.\" acknowledgement: ``This product includes software developed by the 22.\" acknowledgement: ``This product includes software developed by the
23.\" University of California, Berkeley and its contributors'' in the 23.\" University of California, Berkeley and its contributors'' in the
24.\" documentation or other materials provided with the distribution and in 24.\" documentation or other materials provided with the distribution and in
25.\" all advertising materials mentioning features or use of this software. 25.\" all advertising materials mentioning features or use of this software.
26.\" Neither the name of the University nor the names of its contributors may 26.\" Neither the name of the University nor the names of its contributors may
27.\" be used to endorse or promote products derived from this software without 27.\" be used to endorse or promote products derived from this software without
28.\" specific prior written permission. 28.\" specific prior written permission.
29.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 29.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
30.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 30.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
31.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 31.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32.\" 32.\"
33.\" @(#)resolver.3 6.5 (Berkeley) 6/23/90 33.\" @(#)resolver.3 6.5 (Berkeley) 6/23/90
34.\" Id: resolver.man3,v 1.2 2009/01/21 00:12:34 each Exp 34.\" Id: resolver.man3,v 1.2 2009/01/21 00:12:34 each Exp
35.\" 35.\"
36.Dd July 4, 2000 36.Dd July 4, 2000
37.Dt RESOLVER 3  37.Dt RESOLVER 3
38.Os 38.Os
39.Sh NAME 39.Sh NAME
40.Nm res_ninit , 40.Nm res_ninit ,
41.Nm res_ourserver_p , 41.Nm res_ourserver_p ,
42.Nm fp_resstat , 42.Nm fp_resstat ,
43.Nm res_hostalias , 43.Nm res_hostalias ,
44.Nm res_pquery , 44.Nm res_pquery ,
45.Nm res_nquery , 45.Nm res_nquery ,
46.Nm res_nsearch , 46.Nm res_nsearch ,
47.Nm res_nquerydomain , 47.Nm res_nquerydomain ,
48.Nm res_nmkquery , 48.Nm res_nmkquery ,
49.Nm res_nsend , 49.Nm res_nsend ,
50.Nm res_nupdate , 50.Nm res_nupdate ,
51.Nm res_nmkupdate , 51.Nm res_nmkupdate ,
52.Nm res_nclose , 52.Nm res_nclose ,
53.Nm res_nsendsigned , 53.Nm res_nsendsigned ,
54.Nm res_findzonecut , 54.Nm res_findzonecut ,
55.Nm res_getservers , 55.Nm res_getservers ,
56.Nm res_setservers , 56.Nm res_setservers ,
57.Nm res_ndestroy , 57.Nm res_ndestroy ,
58.Nm dn_comp , 58.Nm dn_comp ,
59.Nm dn_expand , 59.Nm dn_expand ,
60.\" .Nm hstrerror , 60.\" .Nm hstrerror ,
61.Nm res_init , 61.Nm res_init ,
62.Nm res_isourserver , 62.Nm res_isourserver ,
63.Nm fp_nquery , 63.Nm fp_nquery ,
64.Nm p_query , 64.Nm p_query ,
65.Nm hostalias , 65.Nm hostalias ,
66.Nm res_query , 66.Nm res_query ,
67.Nm res_search , 67.Nm res_search ,
68.Nm res_querydomain , 68.Nm res_querydomain ,
69.Nm res_mkquery , 69.Nm res_mkquery ,
70.Nm res_send , 70.Nm res_send ,
71.Nm res_update , 71.Nm res_update ,
72.Nm res_close , 72.Nm res_close ,
73.\" .Nm herror 73.\" .Nm herror
74.Nd resolver routines 74.Nd resolver routines
75.Sh LIBRARY 75.Sh LIBRARY
76.Lb libc 76.Lb libc
77.Sh SYNOPSIS 77.Sh SYNOPSIS
78.In sys/types.h 78.In sys/types.h
79.In netinet/in.h 79.In netinet/in.h
80.In arpa/nameser.h 80.In arpa/nameser.h
81.In resolv.h 81.In resolv.h
82.In res_update.h 82.In res_update.h
83.Vt typedef struct __res_state *res_state ; 83.Vt typedef struct __res_state *res_state ;
84.Pp 84.Pp
85.Ft int 85.Ft int
86.Fn res_ninit "res_state statp" 86.Fn res_ninit "res_state statp"
87.Ft int 87.Ft int
88.Fn res_ourserver_p "const res_state statp" "const struct sockaddr_in *addr" 88.Fn res_ourserver_p "const res_state statp" "const struct sockaddr_in *addr"
89.Ft void 89.Ft void
90.Fn fp_resstat "const res_state statp" "FILE *fp" 90.Fn fp_resstat "const res_state statp" "FILE *fp"
91.Ft "const char *" 91.Ft "const char *"
92.Fn res_hostalias "const res_state statp" "const char *name" "char *buf" "size_t buflen" 92.Fn res_hostalias "const res_state statp" "const char *name" "char *buf" "size_t buflen"
93.Ft int 93.Ft int
94.Fn res_pquery "const res_state statp" "const u_char *msg" "int msglen" "FILE *fp" 94.Fn res_pquery "const res_state statp" "const u_char *msg" "int msglen" "FILE *fp"
95.Ft int 95.Ft int
96.Fn res_nquery "res_state statp" "const char *dname" "int class" "int type" "u_char *answer" "int anslen" 96.Fn res_nquery "res_state statp" "const char *dname" "int class" "int type" "u_char *answer" "int anslen"
97.Ft int 97.Ft int
98.Fn res_nsearch "res_state statp" "const char *dname" "int class" "int type" "u_char * answer" "int anslen" 98.Fn res_nsearch "res_state statp" "const char *dname" "int class" "int type" "u_char * answer" "int anslen"
99.Ft int 99.Ft int
100.Fn res_nquerydomain "res_state statp" "const char *name" "const char *domain" "int class" "int type" "u_char *answer" "int anslen" 100.Fn res_nquerydomain "res_state statp" "const char *name" "const char *domain" "int class" "int type" "u_char *answer" "int anslen"
101.Ft int 101.Ft int
102.Fo res_nmkquery 102.Fo res_nmkquery
103.Fa "res_state statp" 103.Fa "res_state statp"
104.Fa "int op" 104.Fa "int op"
105.Fa "const char *dname" 105.Fa "const char *dname"
106.Fa "int class" 106.Fa "int class"
107.Fa "int type" 107.Fa "int type"
108.Fa "const u_char *data" 108.Fa "const u_char *data"
109.Fa "int datalen" 109.Fa "int datalen"
110.Fa "const u_char *newrr" 110.Fa "const u_char *newrr"
111.Fa "u_char *buf" 111.Fa "u_char *buf"
112.Fa "int buflen" 112.Fa "int buflen"
113.Fc 113.Fc
114.Ft int 114.Ft int
115.Fn res_nsend "res_state statp" "const u_char *msg" "int msglen" "u_char *answer" "int anslen" 115.Fn res_nsend "res_state statp" "const u_char *msg" "int msglen" "u_char *answer" "int anslen"
116.Ft int 116.Ft int
117.Fn res_nupdate "res_state statp" "ns_updrec *rrecp_in" 117.Fn res_nupdate "res_state statp" "ns_updrec *rrecp_in"
118.Ft int 118.Ft int
119.Fn res_nmkupdate "res_state statp" "ns_updrec *rrecp_in" "u_char *buf" "int buflen" 119.Fn res_nmkupdate "res_state statp" "ns_updrec *rrecp_in" "u_char *buf" "int buflen"
120.Ft void 120.Ft void
121.Fn res_nclose "res_state statp" 121.Fn res_nclose "res_state statp"
122.Ft int 122.Ft int
123.Fn res_nsendsigned "res_state statp" "const u_char *msg" "int msglen" "ns_tsig_key *key" "u_char *answer" "int anslen" 123.Fn res_nsendsigned "res_state statp" "const u_char *msg" "int msglen" "ns_tsig_key *key" "u_char *answer" "int anslen"
124.Ft int 124.Ft int
125.Fn res_findzonecut "res_state statp" "const char *dname" "ns_class class" "int options" "char *zname" "size_t zsize" "struct in_addr *addrs" "int naddrs" 125.Fn res_findzonecut "res_state statp" "const char *dname" "ns_class class" "int options" "char *zname" "size_t zsize" "struct in_addr *addrs" "int naddrs"
126.Ft int 126.Ft int
127.Fn res_getservers "res_state statp" "union res_sockaddr_union *set" "int cnt" 127.Fn res_getservers "res_state statp" "union res_sockaddr_union *set" "int cnt"
128.Ft void 128.Ft void
129.Fn res_setservers "res_state statp" "const union res_sockaddr_union *set" "int cnt" 129.Fn res_setservers "res_state statp" "const union res_sockaddr_union *set" "int cnt"
130.Ft void 130.Ft void
131.Fn res_ndestroy "res_state statp" 131.Fn res_ndestroy "res_state statp"
132.Ft int 132.Ft int
133.Fn dn_comp "const char *exp_dn" "u_char *comp_dn" "int length" "u_char **dnptrs" "u_char **lastdnptr" 133.Fn dn_comp "const char *exp_dn" "u_char *comp_dn" "int length" "u_char **dnptrs" "u_char **lastdnptr"
134.Ft int 134.Ft int
135.Fn dn_expand "const u_char *msg" "const u_char *eomorig" "const u_char *comp_dn" "char *exp_dn" "int length" 135.Fn dn_expand "const u_char *msg" "const u_char *eomorig" "const u_char *comp_dn" "char *exp_dn" "int length"
136.\" .Ft "const char *" 136.\" .Ft "const char *"
137.\" .Fn hstrerror "int err" 137.\" .Fn hstrerror "int err"
138.Ss DEPRECATED 138.Ss DEPRECATED
139.In sys/types.h 139.In sys/types.h
140.In netinet/in.h 140.In netinet/in.h
141.In arpa/nameser.h 141.In arpa/nameser.h
142.In resolv.h 142.In resolv.h
143.In res_update.h 143.In res_update.h
144.Ft int 144.Ft int
145.Fn res_init "void" 145.Fn res_init "void"
146.Ft int 146.Ft int
147.Fn res_isourserver "const struct sockaddr_in *addr" 147.Fn res_isourserver "const struct sockaddr_in *addr"
148.Ft int 148.Ft int
149.Fn fp_nquery "const u_char *msg" "int msglen" "FILE *fp" 149.Fn fp_nquery "const u_char *msg" "int msglen" "FILE *fp"
150.Ft void 150.Ft void
151.Fn p_query "const u_char *msg" "FILE *fp" 151.Fn p_query "const u_char *msg" "FILE *fp"
152.Ft "const char *" 152.Ft "const char *"
153.Fn hostalias "const char *name" 153.Fn hostalias "const char *name"
154.Ft int 154.Ft int
155.Fn res_query "const char *dname" "int class" "int type" "u_char *answer" "int anslen" 155.Fn res_query "const char *dname" "int class" "int type" "u_char *answer" "int anslen"
156.Ft int 156.Ft int
157.Fn res_search "const char *dname" "int class" "int type" "u_char *answer" "int anslen" 157.Fn res_search "const char *dname" "int class" "int type" "u_char *answer" "int anslen"
158.Ft int 158.Ft int
159.Fn res_querydomain "const char *name" "const char *domain" "int class" "int type" "u_char *answer" "int anslen" 159.Fn res_querydomain "const char *name" "const char *domain" "int class" "int type" "u_char *answer" "int anslen"
160.Ft int 160.Ft int
161.Fo res_mkquery 161.Fo res_mkquery
162.Fa "int op" 162.Fa "int op"
163.Fa "const char *dname" 163.Fa "const char *dname"
164.Fa "int class" 164.Fa "int class"
165.Fa "int type" 165.Fa "int type"
166.Fa "const char *data" 166.Fa "const char *data"
167.Fa "int datalen" 167.Fa "int datalen"
168.Fa "struct rrec *newrr" 168.Fa "struct rrec *newrr"
169.Fa "u_char *buf" 169.Fa "u_char *buf"
170.Fa "int buflen" 170.Fa "int buflen"
171.Fc 171.Fc
172.Ft int 172.Ft int
173.Fn res_send "const u_char *msg" "int msglen" "u_char *answer" "int anslen" 173.Fn res_send "const u_char *msg" "int msglen" "u_char *answer" "int anslen"
174.Ft int 174.Ft int
175.Fn res_update "ns_updrec *rrecp_in" 175.Fn res_update "ns_updrec *rrecp_in"
176.Ft void 176.Ft void
177.Fn res_close "void" 177.Fn res_close "void"
178.\" .Ft void 178.\" .Ft void
179.\" .Fn herror "const char *s" 179.\" .Fn herror "const char *s"
180.Sh DESCRIPTION 180.Sh DESCRIPTION
181These routines are used for making, sending and interpreting 181These routines are used for making, sending and interpreting
182query and reply messages with Internet domain name servers. 182query and reply messages with Internet domain name servers.
183.Pp 183.Pp
184State information is kept in 184State information is kept in
185.Fa statp 185.Fa statp
186and is used to control the behavior of these functions. 186and is used to control the behavior of these functions.
187.Fa statp 187.Fa statp
188should be set to all zeros prior to the first call to any of these functions. 188should be set to all zeros prior to the first call to any of these functions.
189.Pp 189.Pp
190The functions 190The functions
191.Fn res_init , 191.Fn res_init ,
192.Fn res_isourserver , 192.Fn res_isourserver ,
193.Fn fp_nquery , 193.Fn fp_nquery ,
194.Fn p_query , 194.Fn p_query ,
195.Fn hostalias , 195.Fn hostalias ,
196.Fn res_query , 196.Fn res_query ,
197.Fn res_search , 197.Fn res_search ,
198.Fn res_querydomain , 198.Fn res_querydomain ,
199.Fn res_mkquery , 199.Fn res_mkquery ,
200.Fn res_send , 200.Fn res_send ,
201.Fn res_update , 201.Fn res_update ,
202.Fn res_close 202.Fn res_close
203.\" and 203.\" and
204.\" .Fn herror 204.\" .Fn herror
205are deprecated and are supplied for compatability with old source 205are deprecated and are supplied for compatability with old source
206code. 206code.
207They use global configuration and state information that is 207They use global configuration and state information that is
208kept in the structure 208kept in the structure
209.Ft _res 209.Ft _res
210rather than that referenced through 210rather than that referenced through
211.Ft statp . 211.Ft statp .
212.Pp 212.Pp
213Most of the values in  213Most of the values in
214.Ft statp 214.Ft statp
215and 215and
216.Ft _res 216.Ft _res
217are initialized on the first call to 217are initialized on the first call to
218.Fn res_ninit 218.Fn res_ninit
219/ 219/
220.Fn res_init 220.Fn res_init
221to reasonable defaults and can be ignored. 221to reasonable defaults and can be ignored.
222Options 222Options
223stored in 223stored in
224.Ft statp->options 224.Ft statp->options
225/ 225/
226.Ft _res.options 226.Ft _res.options
227are defined in 227are defined in
228.Pa resolv.h 228.Pa resolv.h
229and are as follows. 229and are as follows.
230Options are stored as a simple bit mask containing the bitwise  230Options are stored as a simple bit mask containing the bitwise
231.Dq OR 231.Dq OR
232of the options enabled. 232of the options enabled.
233.Bl -tag -width "RES_USE_INET6" 233.Bl -tag -width "RES_USE_INET6"
234.It Dv RES_INIT 234.It Dv RES_INIT
235True if the initial name server address and default domain name are 235True if the initial name server address and default domain name are
236initialized (i.e., 236initialized (i.e.,
237.Fn res_ninit 237.Fn res_ninit
238/ 238/
239.Fn res_init 239.Fn res_init
240has been called). 240has been called).
241.It Dv RES_DEBUG 241.It Dv RES_DEBUG
242Print debugging messages. 242Print debugging messages.
243.It Dv RES_AAONLY 243.It Dv RES_AAONLY
244Accept authoritative answers only. 244Accept authoritative answers only.
245Should continue until it finds an authoritative answer or finds an error. 245Should continue until it finds an authoritative answer or finds an error.
246Currently this is not implemented. 246Currently this is not implemented.
247.It Dv RES_USEVC 247.It Dv RES_USEVC
248Use TCP connections for queries instead of UDP datagrams. 248Use TCP connections for queries instead of UDP datagrams.
249.It Dv RES_STAYOPEN 249.It Dv RES_STAYOPEN
250Used with  250Used with
251.Dv RES_USEVC  251.Dv RES_USEVC
252to keep the TCP connection open between queries. 252to keep the TCP connection open between queries.
253This is useful only in programs that regularly do many queries. 253This is useful only in programs that regularly do many queries.
254UDP should be the normal mode used. 254UDP should be the normal mode used.
255.It Dv RES_IGNTC 255.It Dv RES_IGNTC
256Ignore truncation errors, i.e., don't retry with TCP. 256Ignore truncation errors, i.e., don't retry with TCP.
257.It Dv RES_RECURSE 257.It Dv RES_RECURSE
258Set the recursion-desired bit in queries. 258Set the recursion-desired bit in queries.
259This is the default. 259This is the default.
260(\c 260(\c
261.Fn res_nsend 261.Fn res_nsend
262/ 262/
263.Fn res_send 263.Fn res_send
264does not do iterative queries and expects the name server 264does not do iterative queries and expects the name server
265to handle recursion.) 265to handle recursion.)
266.It Dv RES_DEFNAMES 266.It Dv RES_DEFNAMES
267If set, 267If set,
268.Fn res_nsearch 268.Fn res_nsearch
269/ 269/
270.Fn res_search 270.Fn res_search
271will append the default domain name to single-component names 271will append the default domain name to single-component names
272(those that do not contain a dot). 272(those that do not contain a dot).
273This option is enabled by default. 273This option is enabled by default.
274.It Dv RES_DNSRCH 274.It Dv RES_DNSRCH
275If this option is set, 275If this option is set,
276.Fn res_nsearch 276.Fn res_nsearch
277/ 277/
278.Fn res_search 278.Fn res_search
279will search for host names in the current domain and in parent domains; see 279will search for host names in the current domain and in parent domains; see
280.Xr hostname 7 . 280.Xr hostname 7 .
281This is used by the standard host lookup routine 281This is used by the standard host lookup routine
282.Xr gethostbyname 3 . 282.Xr gethostbyname 3 .
283This option is enabled by default. 283This option is enabled by default.
284.It Dv RES_USE_INET6 284.It Dv RES_USE_INET6
285Enables support for IPv6-only applications. 285Enables support for IPv6-only applications.
286This causes IPv4 addresses to be returned as an IPv4 mapped address. 286This causes IPv4 addresses to be returned as an IPv4 mapped address.
287For example, 10.1.1.1 will be returned as ::ffff:10.1.1.1. 287For example, 10.1.1.1 will be returned as ::ffff:10.1.1.1.
288The option is meaningful with certain kernel configuration only. 288The option is meaningful with certain kernel configuration only.
289.It Dv RES_USE_EDNS0 289.It Dv RES_USE_EDNS0
290Enables support for OPT pseudo-RR for EDNS0 extension. 290Enables support for OPT pseudo-RR for EDNS0 extension.
291With the option, resolver code will attach OPT pseudo-RR into DNS queries, 291With the option, resolver code will attach OPT pseudo-RR into DNS queries,
292to inform of our receive buffer size. 292to inform of our receive buffer size.
293The option will allow DNS servers to take advantage of non-default receive 293The option will allow DNS servers to take advantage of non-default receive
294buffer size, and to send larger replies. 294buffer size, and to send larger replies.
295DNS query packets with EDNS0 extension is not compatible with 295DNS query packets with EDNS0 extension is not compatible with
296non-EDNS0 DNS servers. 296non-EDNS0 DNS servers.
297.It Dv RES_NOALIASES 297.It Dv RES_NOALIASES
298This option turns off the user level aliasing feature controlled by 298This option turns off the user level aliasing feature controlled by
299the  299the
300.Ev HOSTALIASES  300.Ev HOSTALIASES
301environment variable. 301environment variable.
302Network daemons should set this option. 302Network daemons should set this option.
303.It Dv RES_ROTATE 303.It Dv RES_ROTATE
304This options causes the 304This options causes the
305.Fn res_nsend 305.Fn res_nsend
306/ 306/
307.Fn res_send 307.Fn res_send
308to rotate the list of nameservers in 308to rotate the list of nameservers in
309.Fa statp->nsaddr_list 309.Fa statp->nsaddr_list
310/ 310/
311.Fa _res.nsaddr_list . 311.Fa _res.nsaddr_list .
312.It Dv RES_KEEPTSIG 312.It Dv RES_KEEPTSIG
313This option causes 313This option causes
314.Fn res_nsendsigned 314.Fn res_nsendsigned
315to leave the message unchanged after TSIG verification; otherwise the TSIG 315to leave the message unchanged after TSIG verification; otherwise the TSIG
316record would be removed and the header updated. 316record would be removed and the header updated.
317.It Dv RES_NOTLDQUERY 317.It Dv RES_NOTLDQUERY
318This option causes 318This option causes
319.Fn res_nsearch 319.Fn res_nsearch
320to not attempt to resolve a unqualified name as if it were a top level 320to not attempt to resolve an unqualified name as if it were a top level
321domain (TLD). 321domain (TLD).
322This option can cause problems if the site has "localhost" as a TLD rather 322This option can cause problems if the site has "localhost" as a TLD rather
323than having localhost on one or more elements of the search list. 323than having localhost on one or more elements of the search list.
324This option has no effect if neither 324This option has no effect if neither
325.Dv RES_DEFNAMES 325.Dv RES_DEFNAMES
326or 326or
327.Dv RES_DNSRCH 327.Dv RES_DNSRCH
328is set. 328is set.
329.El 329.El
330.Pp 330.Pp
331The 331The
332.Fn res_ninit 332.Fn res_ninit
333/ 333/
334.Fn res_init 334.Fn res_init
335routine 335routine
336reads the configuration file (if any; see 336reads the configuration file (if any; see
337.Xr resolv.conf 5 ) 337.Xr resolv.conf 5 )
338to get the default domain name, search list and 338to get the default domain name, search list and
339the Internet address of the local name server(s). 339the Internet address of the local name server(s).
340If no server is configured, the host running the resolver is tried. 340If no server is configured, the host running the resolver is tried.
341The current domain name is defined by the hostname 341The current domain name is defined by the hostname
342if not specified in the configuration file; 342if not specified in the configuration file;
343it can be overridden by the environment variable  343it can be overridden by the environment variable
344.Ev LOCALDOMAIN . 344.Ev LOCALDOMAIN .
345This environment variable may contain several blank-separated 345This environment variable may contain several blank-separated
346tokens if you wish to override the 346tokens if you wish to override the
347.Fa search list 347.Fa search list
348on a per-process basis. This is similar to the 348on a per-process basis. This is similar to the
349.Fa search 349.Fa search
350command in the configuration file. 350command in the configuration file.
351Another environment variable  351Another environment variable
352.Ev RES_OPTIONS  352.Ev RES_OPTIONS
353can be set to override certain internal resolver options which are otherwise 353can be set to override certain internal resolver options which are otherwise
354set by changing fields in the 354set by changing fields in the
355.Ft statp 355.Ft statp
356/ 356/
357.Ft _res 357.Ft _res
358structure or are inherited from the configuration file's 358structure or are inherited from the configuration file's
359.Fa options 359.Fa options
360command. 360command.
361The syntax of the  361The syntax of the
362.Ev RES_OPTIONS  362.Ev RES_OPTIONS
363environment variable is explained in 363environment variable is explained in
364.Xr resolv.conf 5 . 364.Xr resolv.conf 5 .
365Initialization normally occurs on the first call 365Initialization normally occurs on the first call
366to one of the other resolver routines. 366to one of the other resolver routines.
367.Pp 367.Pp
368The memory referred to by 368The memory referred to by
369.Ft statp 369.Ft statp
370must be set to all zeros prior to the first call to 370must be set to all zeros prior to the first call to
371.Fn res_ninit . 371.Fn res_ninit .
372.Fn res_ndestroy 372.Fn res_ndestroy
373should be call to free memory allocated by 373should be call to free memory allocated by
374.Fn res_ninit  374.Fn res_ninit
375after last use. 375after last use.
376.Pp 376.Pp
377The 377The
378.Fn res_nquery 378.Fn res_nquery
379/ 379/
380.Fn res_query 380.Fn res_query
381functions provides interfaces to the server query mechanism. 381functions provides interfaces to the server query mechanism.
382They constructs a query, sends it to the local server, 382They constructs a query, sends it to the local server,
383awaits a response, and makes preliminary checks on the reply. 383awaits a response, and makes preliminary checks on the reply.
384The query requests information of the specified 384The query requests information of the specified
385.Fa type 385.Fa type
386and 386and
387.Fa class 387.Fa class
388for the specified fully-qualified domain name 388for the specified fully-qualified domain name
389.Fa dname . 389.Fa dname .
390The reply message is left in the 390The reply message is left in the
391.Fa answer 391.Fa answer
392buffer with length 392buffer with length
393.Fa anslen 393.Fa anslen
394supplied by the caller. 394supplied by the caller.
395.Fn res_nquery 395.Fn res_nquery
396/ 396/
397.Fn res_query 397.Fn res_query
398return -1 on error or the length of the answer. 398return -1 on error or the length of the answer.
399.Pp 399.Pp
400The 400The
401.Fn res_nsearch 401.Fn res_nsearch
402/ 402/
403.Fn res_search 403.Fn res_search
404routines make a query and awaits a response like 404routines make a query and awaits a response like
405.Fn res_nquery 405.Fn res_nquery
406/ 406/
407.Fn res_query , 407.Fn res_query ,
408but in addition, it implements the default and search rules 408but in addition, it implements the default and search rules
409controlled by the  409controlled by the
410.Dv RES_DEFNAMES  410.Dv RES_DEFNAMES
411and  411and
412.Dv RES_DNSRCH  412.Dv RES_DNSRCH
413options. 413options.
414It returns the length of the first successful reply which is stored in 414It returns the length of the first successful reply which is stored in
415.Ft answer 415.Ft answer
416or -1 on error. 416or -1 on error.
417.Pp 417.Pp
418The remaining routines are lower-level routines used by 418The remaining routines are lower-level routines used by
419.Fn res_nquery 419.Fn res_nquery
420/ 420/
421.Fn res_query . 421.Fn res_query .
422The 422The
423.Fn res_nmkquery 423.Fn res_nmkquery
424/ 424/
425.Fn res_mkquery 425.Fn res_mkquery
426functions 426functions
427constructs a standard query message and places it in 427constructs a standard query message and places it in
428.Fa buf . 428.Fa buf .
429It returns the size of the query, or \-1 if the query is 429It returns the size of the query, or \-1 if the query is
430larger than 430larger than
431.Fa buflen . 431.Fa buflen .
432The query type 432The query type
433.Fa op 433.Fa op
434is usually  434is usually
435.Dv QUERY ,  435.Dv QUERY ,
436but can be any of the query types defined in 436but can be any of the query types defined in
437.Pa <arpa/nameser.h> . 437.Pa <arpa/nameser.h> .
438The domain name for the query is given by 438The domain name for the query is given by
439.Fa dname . 439.Fa dname .
440.Fa newrr 440.Fa newrr
441is currently unused but is intended for making update messages. 441is currently unused but is intended for making update messages.
442.Pp 442.Pp
443The 443The
444.Fn res_nsend 444.Fn res_nsend
445/ 445/
446.Fn res_send 446.Fn res_send
447/ 447/
448.Fn res_nsendsigned 448.Fn res_nsendsigned
449routines 449routines
450sends a pre-formatted query and returns an answer. 450sends a pre-formatted query and returns an answer.
451It will call 451It will call
452.Fn res_ninit 452.Fn res_ninit
453/ 453/
454.Fn res_init 454.Fn res_init
455if  455if
456.Dv RES_INIT  456.Dv RES_INIT
457is not set, send the query to the local name server, and 457is not set, send the query to the local name server, and
458handle timeouts and retries. Additionally, 458handle timeouts and retries. Additionally,
459.Fn res_nsendsigned 459.Fn res_nsendsigned
460will use TSIG signatures to add authentication to the query and verify the 460will use TSIG signatures to add authentication to the query and verify the
461response. In this case, only one nameserver will be contacted. 461response. In this case, only one nameserver will be contacted.
462The length of the reply message is returned, or \-1 if there were errors. 462The length of the reply message is returned, or \-1 if there were errors.
463.Pp 463.Pp
464.Fn res_nquery 464.Fn res_nquery
465/ 465/
466.Fn res_query , 466.Fn res_query ,
467.Fn res_nsearch 467.Fn res_nsearch
468/ 468/
469.Fn res_search 469.Fn res_search
470and 470and
471.Fn res_nsend 471.Fn res_nsend
472/ 472/
473.Fn res_send 473.Fn res_send
474return a length that may be bigger than 474return a length that may be bigger than
475.Fa anslen . 475.Fa anslen .
476In that case the query should be retried with a bigger buffer. 476In that case the query should be retried with a bigger buffer.
477NOTE the answer to the second query may be larger still so supplying 477NOTE the answer to the second query may be larger still so supplying
478a buffer that bigger that the answer returned by the previous 478a buffer that bigger that the answer returned by the previous
479query is recommended. 479query is recommended.
480.Pp 480.Pp
481.Fa answer 481.Fa answer
482MUST be big enough to receive a maximum UDP response from the server or  482MUST be big enough to receive a maximum UDP response from the server or
483parts of the answer will be silently discarded. 483parts of the answer will be silently discarded.
484The default maximum UDP response size is 512 bytes. 484The default maximum UDP response size is 512 bytes.
485.Pp 485.Pp
486The function 486The function
487.Fn res_ourserver_p 487.Fn res_ourserver_p
488returns true when  488returns true when
489.Fa inp 489.Fa inp
490is one of the servers in 490is one of the servers in
491.Fa statp->nsaddr_list 491.Fa statp->nsaddr_list
492/ 492/
493.Fa _res.nsaddr_list . 493.Fa _res.nsaddr_list .
494.Pp 494.Pp
495The functions 495The functions
496.Fn fp_nquery 496.Fn fp_nquery
497/ 497/
498.Fn p_query 498.Fn p_query
499print out the query and any answer in 499print out the query and any answer in
500.Fa msg 500.Fa msg
501on 501on
502.Fa fp . 502.Fa fp .
503.Fn p_query 503.Fn p_query
504is equivalent to 504is equivalent to
505.Fn fp_nquery 505.Fn fp_nquery
506with 506with
507.Fa msglen 507.Fa msglen
508set to 512. 508set to 512.
509.Pp 509.Pp
510The function 510The function
511.Fn fp_resstat 511.Fn fp_resstat
512prints out the active flag bits in 512prints out the active flag bits in
513.Fa statp->options 513.Fa statp->options
514preceeded by the text ";; res options:" on  514preceeded by the text ";; res options:" on
515.Fa file . 515.Fa file .
516.Pp 516.Pp
517The functions 517The functions
518.Fn res_hostalias 518.Fn res_hostalias
519/ 519/
520.Fn hostalias 520.Fn hostalias
521lookup up name in the file referred to by the 521lookup up name in the file referred to by the
522.Ev HOSTALIASES 522.Ev HOSTALIASES
523files return a fully qualified hostname if found or NULL if 523files return a fully qualified hostname if found or NULL if
524not found or an error occurred. 524not found or an error occurred.
525.Fn res_hostalias 525.Fn res_hostalias
526uses 526uses
527.Fa buf 527.Fa buf
528to store the result in, 528to store the result in,
529.Fn hostalias 529.Fn hostalias
530uses a static buffer. 530uses a static buffer.
531.Pp 531.Pp
532The functions 532The functions
533.Fn res_getservers 533.Fn res_getservers
534and 534and
535.Fn res_setservers 535.Fn res_setservers
536are used to get and set the list of server to be queried. 536are used to get and set the list of server to be queried.
537.Pp 537.Pp
538The functions 538The functions
539.Fn res_nupdate 539.Fn res_nupdate
540/ 540/
541.Fn res_update 541.Fn res_update
542take a list of ns_updrec 542take a list of ns_updrec
543.Fa rrecp_in . 543.Fa rrecp_in .
544Identifies the containing zone for each record and groups the records 544Identifies the containing zone for each record and groups the records
545according to containing zone maintaining in zone order then sends and update 545according to containing zone maintaining in zone order then sends and update
546request to the servers for these zones. The number of zones updated is 546request to the servers for these zones. The number of zones updated is
547returned or -1 on error. Note that 547returned or -1 on error. Note that
548.Fn res_nupdate 548.Fn res_nupdate
549will perform TSIG authenticated dynamic update operations if the key is not 549will perform TSIG authenticated dynamic update operations if the key is not
550NULL. 550NULL.
551.Pp 551.Pp
552The function 552The function
553.Fn res_findzonecut 553.Fn res_findzonecut
554discovers the closest enclosing zone cut for a specified domain name, 554discovers the closest enclosing zone cut for a specified domain name,
555and finds the IP addresses of the zone's master servers. 555and finds the IP addresses of the zone's master servers.
556.Pp 556.Pp
557The functions  557The functions
558.Fn res_nmkupdate 558.Fn res_nmkupdate
559/ 559/
560.Fn res_mkupdate 560.Fn res_mkupdate
561take a linked list of ns_updrec 561take a linked list of ns_updrec
562.Fa rrecp_in 562.Fa rrecp_in
563and construct a UPDATE message in 563and construct a UPDATE message in
564.Fa buf . 564.Fa buf .
565.Fn res_nmkupdate 565.Fn res_nmkupdate
566/ 566/
567.Fn res_mkupdate 567.Fn res_mkupdate
568return the length of the constructed message on no error or one of the 568return the length of the constructed message on no error or one of the
569following error values. 569following error values.
570.Bl -inset -width "-5" 570.Bl -inset -width "-5"
571.It -1 571.It -1
572An error occurred parsing  572An error occurred parsing
573.Fa rrecp_in . 573.Fa rrecp_in .
574.It -2 574.It -2
575The buffer  575The buffer
576.Fa buf 576.Fa buf
577was too small. 577was too small.
578.It -3 578.It -3
579The first record was not a zone section or there was a section order problem. 579The first record was not a zone section or there was a section order problem.
580The section order is S_ZONE, S_PREREQ and S_UPDATE.  580The section order is S_ZONE, S_PREREQ and S_UPDATE.
581.It -4 581.It -4
582A number overflow occurred. 582A number overflow occurred.
583.It -5 583.It -5
584Unknown operation or no records. 584Unknown operation or no records.
585.El 585.El
586.Pp 586.Pp
587The functions 587The functions
588.Fn res_nclose 588.Fn res_nclose
589/ 589/
590.Fn res_close 590.Fn res_close
591close any open files referenced through 591close any open files referenced through
592.Fa statp 592.Fa statp
593/ 593/
594.Fa _res . 594.Fa _res .
595.Pp 595.Pp
596The function 596The function
597.Fn res_ndestroy 597.Fn res_ndestroy
598calls 598calls
599.Fn res_nclose 599.Fn res_nclose
600then frees any memory allocated by 600then frees any memory allocated by
601.Fn res_ninit . 601.Fn res_ninit .
602.Pp 602.Pp
603The 603The
604.Fn dn_comp 604.Fn dn_comp
605function 605function
606compresses the domain name 606compresses the domain name
607.Fa exp_dn 607.Fa exp_dn
608and stores it in 608and stores it in
609.Fa comp_dn . 609.Fa comp_dn .
610The size of the compressed name is returned or \-1 if there were errors. 610The size of the compressed name is returned or \-1 if there were errors.
611The size of the array pointed to by 611The size of the array pointed to by
612.Fa comp_dn 612.Fa comp_dn
613is given by 613is given by
614.Fa length . 614.Fa length .
615The compression uses 615The compression uses
616an array of pointers 616an array of pointers
617.Fa dnptrs 617.Fa dnptrs
618to previously-compressed names in the current message. 618to previously-compressed names in the current message.
619The first pointer points to 619The first pointer points to
620the beginning of the message and the list ends with  620the beginning of the message and the list ends with
621.Dv NULL . 621.Dv NULL .
622The limit to the array is specified by 622The limit to the array is specified by
623.Fa lastdnptr . 623.Fa lastdnptr .
624A side effect of 624A side effect of
625.Fn dn_comp 625.Fn dn_comp
626is to update the list of pointers for labels inserted into the message 626is to update the list of pointers for labels inserted into the message
627as the name is compressed. If 627as the name is compressed. If
628.Fa dnptr 628.Fa dnptr
629is  629is
630.Dv NULL ,  630.Dv NULL ,
631names are not compressed. If 631names are not compressed. If
632.Fa lastdnptr 632.Fa lastdnptr
633is  633is
634.Dv NULL ,  634.Dv NULL ,
635the list of labels is not updated. 635the list of labels is not updated.
636.Pp 636.Pp
637The 637The
638.Fn dn_expand 638.Fn dn_expand
639entry expands the compressed domain name 639entry expands the compressed domain name
640.Fa comp_dn 640.Fa comp_dn
641to a full domain name. 641to a full domain name.
642The compressed name is contained in a query or reply message; 642The compressed name is contained in a query or reply message;
643.Fa msg 643.Fa msg
644is a pointer to the beginning of the message. 644is a pointer to the beginning of the message.
645.Fa eomorig 645.Fa eomorig
646is a pointer to the first location after the message. 646is a pointer to the first location after the message.
647The uncompressed name is placed in the buffer indicated by 647The uncompressed name is placed in the buffer indicated by
648.Fa exp_dn 648.Fa exp_dn
649which is of size 649which is of size
650.Fa length . 650.Fa length .
651The size of compressed name is returned or \-1 if there was an error. 651The size of compressed name is returned or \-1 if there was an error.
652.Pp 652.Pp
653The variables 653The variables
654.Ft statp->res_h_errno 654.Ft statp->res_h_errno
655/ 655/
656.Ft _res.res_h_errno 656.Ft _res.res_h_errno
657and external variable 657and external variable
658.Ft h_errno 658.Ft h_errno
659is set whenever an error occurs during resolver operation. The following 659is set whenever an error occurs during resolver operation. The following
660definitions are given in 660definitions are given in
661.Pa <netdb.h> : 661.Pa <netdb.h> :
662.Bd -literal 662.Bd -literal
663#define NETDB_INTERNAL -1  663#define NETDB_INTERNAL -1
664/* see errno */ 664/* see errno */
665#define NETDB_SUCCESS 0  665#define NETDB_SUCCESS 0
666/* no problem */ 666/* no problem */
667#define HOST_NOT_FOUND 1  667#define HOST_NOT_FOUND 1
668/* Authoritative Answer Host not found */ 668/* Authoritative Answer Host not found */
669#define TRY_AGAIN 2  669#define TRY_AGAIN 2
670/* Non-Authoritative not found, or SERVFAIL */ 670/* Non-Authoritative not found, or SERVFAIL */
671#define NO_RECOVERY 3  671#define NO_RECOVERY 3
672/* Non-Recoverable: FORMERR, REFUSED, NOTIMP */ 672/* Non-Recoverable: FORMERR, REFUSED, NOTIMP */
673#define NO_DATA 4  673#define NO_DATA 4
674/* Valid name, no data for requested type */ 674/* Valid name, no data for requested type */
675.Ed 675.Ed
676.\" .Pp 676.\" .Pp
677.\" The 677.\" The
678.\" .Fn herror 678.\" .Fn herror
679.\" function writes a message to the diagnostic output consisting of the string 679.\" function writes a message to the diagnostic output consisting of the string
680.\" parameter 680.\" parameter
681.\" .Fa s , 681.\" .Fa s ,
682.\" the constant string ": ", and a message corresponding to the value of 682.\" the constant string ": ", and a message corresponding to the value of
683.\" .Ft h_errno . 683.\" .Ft h_errno .
684.\" .Pp 684.\" .Pp
685.\" The 685.\" The
686.\" .Fn hstrerror 686.\" .Fn hstrerror
687.\" function returns a string which is the message text corresponding to the 687.\" function returns a string which is the message text corresponding to the
688.\" value of the 688.\" value of the
689.\" .Fa err 689.\" .Fa err
690.\" parameter. 690.\" parameter.
691.Sh FILES 691.Sh FILES
692.Bl -tag -width "/etc/resolv.conf " 692.Bl -tag -width "/etc/resolv.conf "
693.It Pa 693.It Pa
694/etc/resolv.conf 694/etc/resolv.conf
695The configuration file, see 695The configuration file, see
696.Xr resolv.conf 5 . 696.Xr resolv.conf 5 .
697.El 697.El
698.Sh SEE ALSO 698.Sh SEE ALSO
699.Xr gethostbyname 3 ,  699.Xr gethostbyname 3 ,
700.Xr hostname 7 , 700.Xr hostname 7 ,
701.Xr resolv.conf 5 , 701.Xr resolv.conf 5 ,
702.Xr named 8 702.Xr named 8
703.Pp 703.Pp
704.%T RFC 974 , 704.%T RFC 974 ,
705.%T RFC 1032 , 705.%T RFC 1032 ,
706.%T RFC 1033 , 706.%T RFC 1033 ,
707.%T RFC 1034 , 707.%T RFC 1034 ,
708.%T RFC 1035 , 708.%T RFC 1035 ,
709.%T RFC 1535 709.%T RFC 1535
710.Rs 710.Rs
711.%T "Name Server Operations Guide for BIND" 711.%T "Name Server Operations Guide for BIND"
712.Re 712.Re
713.Sh HISTORY 713.Sh HISTORY
714The 714The
715.Nm 715.Nm
716function appeared in 716function appeared in
717.Bx 4.3 . 717.Bx 4.3 .