ntp_rfc2553.c revision 1.1.1.1.8.1 1 1.1.1.1.8.1 snj /* $NetBSD: ntp_rfc2553.c,v 1.1.1.1.8.1 2014/12/25 02:34:36 snj Exp $ */
2 1.1 kardel
3 1.1 kardel /*
4 1.1 kardel * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 1.1 kardel * All rights reserved.
6 1.1 kardel *
7 1.1 kardel * Redistribution and use in source and binary forms, with or without
8 1.1 kardel * modification, are permitted provided that the following conditions
9 1.1 kardel * are met:
10 1.1 kardel * 1. Redistributions of source code must retain the above copyright
11 1.1 kardel * notice, this list of conditions and the following disclaimer.
12 1.1 kardel * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 kardel * notice, this list of conditions and the following disclaimer in the
14 1.1 kardel * documentation and/or other materials provided with the distribution.
15 1.1 kardel * 3. Neither the name of the project nor the names of its contributors
16 1.1 kardel * may be used to endorse or promote products derived from this software
17 1.1 kardel * without specific prior written permission.
18 1.1 kardel *
19 1.1 kardel * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 1.1 kardel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 1.1 kardel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 1.1 kardel * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 1.1 kardel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 1.1 kardel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 1.1 kardel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 1.1 kardel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 1.1 kardel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.1 kardel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.1 kardel * SUCH DAMAGE.
30 1.1 kardel */
31 1.1 kardel
32 1.1 kardel /*
33 1.1 kardel * Copyright (c) 1982, 1986, 1990, 1993
34 1.1 kardel * The Regents of the University of California. All rights reserved.
35 1.1 kardel *
36 1.1 kardel * Redistribution and use in source and binary forms, with or without
37 1.1 kardel * modification, are permitted provided that the following conditions
38 1.1 kardel * are met:
39 1.1 kardel * 1. Redistributions of source code must retain the above copyright
40 1.1 kardel * notice, this list of conditions and the following disclaimer.
41 1.1 kardel * 2. Redistributions in binary form must reproduce the above copyright
42 1.1 kardel * notice, this list of conditions and the following disclaimer in the
43 1.1 kardel * documentation and/or other materials provided with the distribution.
44 1.1 kardel * 3. All advertising materials mentioning features or use of this software
45 1.1 kardel * must display the following acknowledgement:
46 1.1 kardel * This product includes software developed by the University of
47 1.1 kardel * California, Berkeley and its contributors.
48 1.1 kardel * 4. Neither the name of the University nor the names of its contributors
49 1.1 kardel * may be used to endorse or promote products derived from this software
50 1.1 kardel * without specific prior written permission.
51 1.1 kardel *
52 1.1 kardel * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 1.1 kardel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 1.1 kardel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 1.1 kardel * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 1.1 kardel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 1.1 kardel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 1.1 kardel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 1.1 kardel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 1.1 kardel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 1.1 kardel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 1.1 kardel * SUCH DAMAGE.
63 1.1 kardel *
64 1.1 kardel */
65 1.1 kardel
66 1.1 kardel /*
67 1.1 kardel * Compatability shims with the rfc2553 API to simplify ntp.
68 1.1 kardel */
69 1.1 kardel
70 1.1 kardel #include <config.h>
71 1.1 kardel
72 1.1 kardel #include <sys/types.h>
73 1.1 kardel #include <ctype.h>
74 1.1 kardel #ifdef HAVE_SYS_SOCKET_H
75 1.1 kardel #include <sys/socket.h>
76 1.1 kardel #endif
77 1.1 kardel #include <isc/net.h>
78 1.1 kardel #ifdef HAVE_NETINET_IN_H
79 1.1 kardel #include <netinet/in.h>
80 1.1 kardel #endif
81 1.1 kardel #include "ntp_rfc2553.h"
82 1.1 kardel
83 1.1 kardel #include "ntpd.h"
84 1.1 kardel #include "ntp_malloc.h"
85 1.1 kardel #include "ntp_string.h"
86 1.1.1.1.8.1 snj #include "ntp_debug.h"
87 1.1.1.1.8.1 snj
88 1.1.1.1.8.1 snj
89 1.1.1.1.8.1 snj /*
90 1.1.1.1.8.1 snj * copy_addrinfo() - copy a single addrinfo to malloc()'d block.
91 1.1.1.1.8.1 snj * copy_addrinfo_list() - copy an addrinfo list to malloc()'d block.
92 1.1.1.1.8.1 snj *
93 1.1.1.1.8.1 snj * Copies an addrinfo list and its associated data to a contiguous block
94 1.1.1.1.8.1 snj * of storage from emalloc(). Callback routines invoked via
95 1.1.1.1.8.1 snj * getaddrinfo_sometime() have access to the resulting addrinfo list
96 1.1.1.1.8.1 snj * only until they return. This routine provides an easy way to make a
97 1.1.1.1.8.1 snj * persistent copy. Although the list provided to gai_sometime_callback
98 1.1.1.1.8.1 snj * routines is similarly contiguous, to keep this code usable in any
99 1.1.1.1.8.1 snj * context where we might want to duplicate an addrinfo list, it does
100 1.1.1.1.8.1 snj * not require the input list be contiguous.
101 1.1.1.1.8.1 snj *
102 1.1.1.1.8.1 snj * The returned list head pointer is passed to free() to release the
103 1.1.1.1.8.1 snj * entire list.
104 1.1.1.1.8.1 snj *
105 1.1.1.1.8.1 snj * In keeping with the rest of the NTP distribution, sockaddr_u is used
106 1.1.1.1.8.1 snj * in preference to struct sockaddr_storage, which is a member of the
107 1.1.1.1.8.1 snj * former union and so compatible.
108 1.1.1.1.8.1 snj *
109 1.1.1.1.8.1 snj * The rest of ntp_rfc2553.c is conditioned on ISC_PLATFORM_HAVEIPV6
110 1.1.1.1.8.1 snj * not being defined, copy_addrinfo_*() are exceptions.
111 1.1.1.1.8.1 snj */
112 1.1.1.1.8.1 snj struct addrinfo * copy_addrinfo_common(const struct addrinfo *, int
113 1.1.1.1.8.1 snj #ifdef EREALLOC_CALLSITE
114 1.1.1.1.8.1 snj ,
115 1.1.1.1.8.1 snj const char *, int
116 1.1.1.1.8.1 snj #endif
117 1.1.1.1.8.1 snj );
118 1.1.1.1.8.1 snj
119 1.1.1.1.8.1 snj
120 1.1.1.1.8.1 snj struct addrinfo *
121 1.1.1.1.8.1 snj copy_addrinfo_impl(
122 1.1.1.1.8.1 snj const struct addrinfo * src
123 1.1.1.1.8.1 snj #ifdef EREALLOC_CALLSITE
124 1.1.1.1.8.1 snj ,
125 1.1.1.1.8.1 snj const char * caller_file,
126 1.1.1.1.8.1 snj int caller_line
127 1.1.1.1.8.1 snj #endif
128 1.1.1.1.8.1 snj )
129 1.1.1.1.8.1 snj {
130 1.1.1.1.8.1 snj return copy_addrinfo_common(src, TRUE
131 1.1.1.1.8.1 snj #ifdef EREALLOC_CALLSITE
132 1.1.1.1.8.1 snj ,
133 1.1.1.1.8.1 snj caller_file, caller_line
134 1.1.1.1.8.1 snj #endif
135 1.1.1.1.8.1 snj );
136 1.1.1.1.8.1 snj }
137 1.1.1.1.8.1 snj
138 1.1.1.1.8.1 snj
139 1.1.1.1.8.1 snj struct addrinfo *
140 1.1.1.1.8.1 snj copy_addrinfo_list_impl(
141 1.1.1.1.8.1 snj const struct addrinfo * src
142 1.1.1.1.8.1 snj #ifdef EREALLOC_CALLSITE
143 1.1.1.1.8.1 snj ,
144 1.1.1.1.8.1 snj const char * caller_file,
145 1.1.1.1.8.1 snj int caller_line
146 1.1.1.1.8.1 snj #endif
147 1.1.1.1.8.1 snj )
148 1.1.1.1.8.1 snj {
149 1.1.1.1.8.1 snj return copy_addrinfo_common(src, FALSE
150 1.1.1.1.8.1 snj #ifdef EREALLOC_CALLSITE
151 1.1.1.1.8.1 snj ,
152 1.1.1.1.8.1 snj caller_file, caller_line
153 1.1.1.1.8.1 snj #endif
154 1.1.1.1.8.1 snj );
155 1.1.1.1.8.1 snj }
156 1.1.1.1.8.1 snj
157 1.1.1.1.8.1 snj
158 1.1.1.1.8.1 snj struct addrinfo *
159 1.1.1.1.8.1 snj copy_addrinfo_common(
160 1.1.1.1.8.1 snj const struct addrinfo * src,
161 1.1.1.1.8.1 snj int just_one
162 1.1.1.1.8.1 snj #ifdef EREALLOC_CALLSITE
163 1.1.1.1.8.1 snj ,
164 1.1.1.1.8.1 snj const char * caller_file,
165 1.1.1.1.8.1 snj int caller_line
166 1.1.1.1.8.1 snj #endif
167 1.1.1.1.8.1 snj )
168 1.1.1.1.8.1 snj {
169 1.1.1.1.8.1 snj const struct addrinfo * ai_src;
170 1.1.1.1.8.1 snj const struct addrinfo * ai_nxt;
171 1.1.1.1.8.1 snj struct addrinfo * ai_cpy;
172 1.1.1.1.8.1 snj struct addrinfo * dst;
173 1.1.1.1.8.1 snj sockaddr_u * psau;
174 1.1.1.1.8.1 snj char * pcanon;
175 1.1.1.1.8.1 snj u_int elements;
176 1.1.1.1.8.1 snj size_t octets;
177 1.1.1.1.8.1 snj size_t canons_octets;
178 1.1.1.1.8.1 snj size_t str_octets;
179 1.1.1.1.8.1 snj
180 1.1.1.1.8.1 snj elements = 0;
181 1.1.1.1.8.1 snj canons_octets = 0;
182 1.1.1.1.8.1 snj
183 1.1.1.1.8.1 snj for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
184 1.1.1.1.8.1 snj if (just_one)
185 1.1.1.1.8.1 snj ai_nxt = NULL;
186 1.1.1.1.8.1 snj else
187 1.1.1.1.8.1 snj ai_nxt = ai_src->ai_next;
188 1.1.1.1.8.1 snj ++elements;
189 1.1.1.1.8.1 snj if (NULL != ai_src->ai_canonname)
190 1.1.1.1.8.1 snj canons_octets += 1 + strlen(ai_src->ai_canonname);
191 1.1.1.1.8.1 snj }
192 1.1.1.1.8.1 snj
193 1.1.1.1.8.1 snj octets = elements * (sizeof(*ai_cpy) + sizeof(*psau));
194 1.1.1.1.8.1 snj octets += canons_octets;
195 1.1.1.1.8.1 snj
196 1.1.1.1.8.1 snj dst = erealloczsite(NULL, octets, 0, TRUE, caller_file,
197 1.1.1.1.8.1 snj caller_line);
198 1.1.1.1.8.1 snj ai_cpy = dst;
199 1.1.1.1.8.1 snj psau = (void *)(ai_cpy + elements);
200 1.1.1.1.8.1 snj pcanon = (void *)(psau + elements);
201 1.1.1.1.8.1 snj
202 1.1.1.1.8.1 snj for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
203 1.1.1.1.8.1 snj if (just_one)
204 1.1.1.1.8.1 snj ai_nxt = NULL;
205 1.1.1.1.8.1 snj else
206 1.1.1.1.8.1 snj ai_nxt = ai_src->ai_next;
207 1.1.1.1.8.1 snj *ai_cpy = *ai_src;
208 1.1.1.1.8.1 snj REQUIRE(ai_src->ai_addrlen <= sizeof(sockaddr_u));
209 1.1.1.1.8.1 snj memcpy(psau, ai_src->ai_addr, ai_src->ai_addrlen);
210 1.1.1.1.8.1 snj ai_cpy->ai_addr = &psau->sa;
211 1.1.1.1.8.1 snj ++psau;
212 1.1.1.1.8.1 snj if (NULL != ai_cpy->ai_canonname) {
213 1.1.1.1.8.1 snj ai_cpy->ai_canonname = pcanon;
214 1.1.1.1.8.1 snj str_octets = 1 + strlen(ai_src->ai_canonname);
215 1.1.1.1.8.1 snj memcpy(pcanon, ai_src->ai_canonname, str_octets);
216 1.1.1.1.8.1 snj pcanon += str_octets;
217 1.1.1.1.8.1 snj }
218 1.1.1.1.8.1 snj if (NULL != ai_cpy->ai_next) {
219 1.1.1.1.8.1 snj if (just_one)
220 1.1.1.1.8.1 snj ai_cpy->ai_next = NULL;
221 1.1.1.1.8.1 snj else
222 1.1.1.1.8.1 snj ai_cpy->ai_next = ai_cpy + 1;
223 1.1.1.1.8.1 snj }
224 1.1.1.1.8.1 snj ++ai_cpy;
225 1.1.1.1.8.1 snj }
226 1.1.1.1.8.1 snj NTP_ENSURE(pcanon == ((char *)dst + octets));
227 1.1.1.1.8.1 snj
228 1.1.1.1.8.1 snj return dst;
229 1.1.1.1.8.1 snj }
230 1.1.1.1.8.1 snj
231 1.1 kardel
232 1.1 kardel #ifndef ISC_PLATFORM_HAVEIPV6
233 1.1 kardel
234 1.1 kardel static char *ai_errlist[] = {
235 1.1 kardel "Success",
236 1.1 kardel "Address family for hostname not supported", /* EAI_ADDRFAMILY */
237 1.1 kardel "Temporary failure in name resolution", /* EAI_AGAIN */
238 1.1 kardel "Invalid value for ai_flags", /* EAI_BADFLAGS */
239 1.1 kardel "Non-recoverable failure in name resolution", /* EAI_FAIL */
240 1.1 kardel "ai_family not supported", /* EAI_FAMILY */
241 1.1 kardel "Memory allocation failure", /* EAI_MEMORY */
242 1.1 kardel "No address associated with hostname", /* EAI_NODATA */
243 1.1 kardel "hostname nor servname provided, or not known", /* EAI_NONAME */
244 1.1 kardel "servname not supported for ai_socktype", /* EAI_SERVICE */
245 1.1 kardel "ai_socktype not supported", /* EAI_SOCKTYPE */
246 1.1 kardel "System error returned in errno", /* EAI_SYSTEM */
247 1.1 kardel "Invalid value for hints", /* EAI_BADHINTS */
248 1.1 kardel "Resolved protocol is unknown", /* EAI_PROTOCOL */
249 1.1 kardel "Unknown error", /* EAI_MAX */
250 1.1 kardel };
251 1.1 kardel
252 1.1 kardel /*
253 1.1 kardel * Local declaration
254 1.1 kardel */
255 1.1 kardel int
256 1.1 kardel DNSlookup_name(
257 1.1 kardel const char *name,
258 1.1 kardel int ai_family,
259 1.1 kardel struct hostent **Addresses
260 1.1 kardel );
261 1.1 kardel
262 1.1 kardel #ifndef SYS_WINNT
263 1.1 kardel /*
264 1.1 kardel * Encapsulate gethostbyname to control the error code
265 1.1 kardel */
266 1.1 kardel int
267 1.1 kardel DNSlookup_name(
268 1.1 kardel const char *name,
269 1.1 kardel int ai_family,
270 1.1 kardel struct hostent **Addresses
271 1.1 kardel )
272 1.1 kardel {
273 1.1 kardel *Addresses = gethostbyname(name);
274 1.1 kardel return (h_errno);
275 1.1 kardel }
276 1.1 kardel #endif
277 1.1 kardel
278 1.1 kardel static int do_nodename (const char *nodename, struct addrinfo *ai,
279 1.1 kardel const struct addrinfo *hints);
280 1.1 kardel
281 1.1 kardel int
282 1.1 kardel getaddrinfo (const char *nodename, const char *servname,
283 1.1 kardel const struct addrinfo *hints, struct addrinfo **res)
284 1.1 kardel {
285 1.1 kardel int rval;
286 1.1 kardel struct servent *sp;
287 1.1 kardel struct addrinfo *ai = NULL;
288 1.1 kardel int port;
289 1.1 kardel const char *proto = NULL;
290 1.1 kardel int family, socktype, flags, protocol;
291 1.1 kardel
292 1.1 kardel
293 1.1 kardel /*
294 1.1 kardel * If no name is provide just return an error
295 1.1 kardel */
296 1.1 kardel if (nodename == NULL && servname == NULL)
297 1.1 kardel return (EAI_NONAME);
298 1.1 kardel
299 1.1 kardel ai = calloc(sizeof(struct addrinfo), 1);
300 1.1 kardel if (ai == NULL)
301 1.1 kardel return (EAI_MEMORY);
302 1.1 kardel
303 1.1 kardel /*
304 1.1 kardel * Copy default values from hints, if available
305 1.1 kardel */
306 1.1 kardel if (hints != NULL) {
307 1.1 kardel ai->ai_flags = hints->ai_flags;
308 1.1 kardel ai->ai_family = hints->ai_family;
309 1.1 kardel ai->ai_socktype = hints->ai_socktype;
310 1.1 kardel ai->ai_protocol = hints->ai_protocol;
311 1.1 kardel
312 1.1 kardel family = hints->ai_family;
313 1.1 kardel socktype = hints->ai_socktype;
314 1.1 kardel protocol = hints->ai_protocol;
315 1.1 kardel flags = hints->ai_flags;
316 1.1 kardel
317 1.1 kardel switch (family) {
318 1.1 kardel case AF_UNSPEC:
319 1.1 kardel switch (hints->ai_socktype) {
320 1.1 kardel case SOCK_STREAM:
321 1.1 kardel proto = "tcp";
322 1.1 kardel break;
323 1.1 kardel case SOCK_DGRAM:
324 1.1 kardel proto = "udp";
325 1.1 kardel break;
326 1.1 kardel }
327 1.1 kardel break;
328 1.1 kardel case AF_INET:
329 1.1 kardel case AF_INET6:
330 1.1 kardel switch (hints->ai_socktype) {
331 1.1 kardel case 0:
332 1.1 kardel break;
333 1.1 kardel case SOCK_STREAM:
334 1.1 kardel proto = "tcp";
335 1.1 kardel break;
336 1.1 kardel case SOCK_DGRAM:
337 1.1 kardel proto = "udp";
338 1.1 kardel break;
339 1.1 kardel case SOCK_RAW:
340 1.1 kardel break;
341 1.1 kardel default:
342 1.1 kardel return (EAI_SOCKTYPE);
343 1.1 kardel }
344 1.1 kardel break;
345 1.1 kardel #ifdef AF_LOCAL
346 1.1 kardel case AF_LOCAL:
347 1.1 kardel switch (hints->ai_socktype) {
348 1.1 kardel case 0:
349 1.1 kardel break;
350 1.1 kardel case SOCK_STREAM:
351 1.1 kardel break;
352 1.1 kardel case SOCK_DGRAM:
353 1.1 kardel break;
354 1.1 kardel default:
355 1.1 kardel return (EAI_SOCKTYPE);
356 1.1 kardel }
357 1.1 kardel break;
358 1.1 kardel #endif
359 1.1 kardel default:
360 1.1 kardel return (EAI_FAMILY);
361 1.1 kardel }
362 1.1 kardel } else {
363 1.1 kardel protocol = 0;
364 1.1 kardel family = 0;
365 1.1 kardel socktype = 0;
366 1.1 kardel flags = 0;
367 1.1 kardel }
368 1.1 kardel
369 1.1 kardel rval = do_nodename(nodename, ai, hints);
370 1.1 kardel if (rval != 0) {
371 1.1 kardel freeaddrinfo(ai);
372 1.1 kardel return (rval);
373 1.1 kardel }
374 1.1 kardel
375 1.1 kardel /*
376 1.1 kardel * First, look up the service name (port) if it was
377 1.1 kardel * requested. If the socket type wasn't specified, then
378 1.1 kardel * try and figure it out.
379 1.1 kardel */
380 1.1 kardel if (servname != NULL) {
381 1.1 kardel char *e;
382 1.1 kardel
383 1.1 kardel port = strtol(servname, &e, 10);
384 1.1 kardel if (*e == '\0') {
385 1.1 kardel if (socktype == 0)
386 1.1 kardel return (EAI_SOCKTYPE);
387 1.1 kardel if (port < 0 || port > 65535)
388 1.1 kardel return (EAI_SERVICE);
389 1.1 kardel port = htons((unsigned short) port);
390 1.1 kardel } else {
391 1.1 kardel sp = getservbyname(servname, proto);
392 1.1 kardel if (sp == NULL)
393 1.1 kardel return (EAI_SERVICE);
394 1.1 kardel port = sp->s_port;
395 1.1 kardel if (socktype == 0) {
396 1.1 kardel if (strcmp(sp->s_proto, "tcp") == 0)
397 1.1 kardel socktype = SOCK_STREAM;
398 1.1 kardel else if (strcmp(sp->s_proto, "udp") == 0)
399 1.1 kardel socktype = SOCK_DGRAM;
400 1.1 kardel }
401 1.1 kardel }
402 1.1 kardel } else
403 1.1 kardel port = 0;
404 1.1 kardel
405 1.1 kardel /*
406 1.1 kardel *
407 1.1 kardel * Set up the port number
408 1.1 kardel */
409 1.1 kardel if (ai->ai_family == AF_INET)
410 1.1 kardel ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port;
411 1.1 kardel else if (ai->ai_family == AF_INET6)
412 1.1 kardel ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port;
413 1.1 kardel *res = ai;
414 1.1 kardel return (0);
415 1.1 kardel }
416 1.1 kardel
417 1.1 kardel void
418 1.1 kardel freeaddrinfo(struct addrinfo *ai)
419 1.1 kardel {
420 1.1 kardel if (ai->ai_canonname != NULL)
421 1.1 kardel {
422 1.1 kardel free(ai->ai_canonname);
423 1.1 kardel ai->ai_canonname = NULL;
424 1.1 kardel }
425 1.1 kardel if (ai->ai_addr != NULL)
426 1.1 kardel {
427 1.1 kardel free(ai->ai_addr);
428 1.1 kardel ai->ai_addr = NULL;
429 1.1 kardel }
430 1.1 kardel free(ai);
431 1.1 kardel ai = NULL;
432 1.1 kardel }
433 1.1 kardel
434 1.1 kardel int
435 1.1 kardel getnameinfo (const struct sockaddr *sa, u_int salen, char *host,
436 1.1 kardel size_t hostlen, char *serv, size_t servlen, int flags)
437 1.1 kardel {
438 1.1 kardel struct hostent *hp;
439 1.1 kardel
440 1.1 kardel if (sa->sa_family != AF_INET)
441 1.1 kardel return (EAI_FAMILY);
442 1.1 kardel hp = gethostbyaddr(
443 1.1 kardel (const char *)&((const struct sockaddr_in *)sa)->sin_addr,
444 1.1 kardel 4, AF_INET);
445 1.1 kardel if (hp == NULL) {
446 1.1 kardel if (h_errno == TRY_AGAIN)
447 1.1 kardel return (EAI_AGAIN);
448 1.1 kardel else
449 1.1 kardel return (EAI_FAIL);
450 1.1 kardel }
451 1.1.1.1.8.1 snj if (host != NULL && hostlen > 0)
452 1.1.1.1.8.1 snj strlcpy(host, hp->h_name, hostlen);
453 1.1 kardel return (0);
454 1.1 kardel }
455 1.1 kardel
456 1.1 kardel char *
457 1.1 kardel gai_strerror(int ecode)
458 1.1 kardel {
459 1.1 kardel if (ecode < 0 || ecode > EAI_MAX)
460 1.1 kardel ecode = EAI_MAX;
461 1.1 kardel return ai_errlist[ecode];
462 1.1 kardel }
463 1.1 kardel
464 1.1 kardel static int
465 1.1 kardel do_nodename(
466 1.1 kardel const char *nodename,
467 1.1 kardel struct addrinfo *ai,
468 1.1 kardel const struct addrinfo *hints)
469 1.1 kardel {
470 1.1 kardel struct hostent *hp = NULL;
471 1.1 kardel struct sockaddr_in *sockin;
472 1.1 kardel struct sockaddr_in6 *sockin6;
473 1.1 kardel int errval;
474 1.1 kardel
475 1.1 kardel ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
476 1.1 kardel if (ai->ai_addr == NULL)
477 1.1 kardel return (EAI_MEMORY);
478 1.1 kardel
479 1.1 kardel /*
480 1.1 kardel * For an empty node name just use the wildcard.
481 1.1 kardel * NOTE: We need to assume that the address family is
482 1.1 kardel * set elsewhere so that we can set the appropriate wildcard
483 1.1 kardel */
484 1.1 kardel if (nodename == NULL) {
485 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_storage);
486 1.1 kardel if (ai->ai_family == AF_INET)
487 1.1 kardel {
488 1.1 kardel sockin = (struct sockaddr_in *)ai->ai_addr;
489 1.1 kardel sockin->sin_family = (short) ai->ai_family;
490 1.1 kardel sockin->sin_addr.s_addr = htonl(INADDR_ANY);
491 1.1 kardel }
492 1.1 kardel else
493 1.1 kardel {
494 1.1 kardel sockin6 = (struct sockaddr_in6 *)ai->ai_addr;
495 1.1 kardel sockin6->sin6_family = (short) ai->ai_family;
496 1.1 kardel /*
497 1.1 kardel * we have already zeroed out the address
498 1.1 kardel * so we don't actually need to do this
499 1.1 kardel * This assignment is causing problems so
500 1.1 kardel * we don't do what this would do.
501 1.1 kardel sockin6->sin6_addr = in6addr_any;
502 1.1 kardel */
503 1.1 kardel }
504 1.1 kardel #ifdef ISC_PLATFORM_HAVESALEN
505 1.1 kardel ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
506 1.1 kardel #endif
507 1.1 kardel
508 1.1 kardel return (0);
509 1.1 kardel }
510 1.1 kardel
511 1.1 kardel /*
512 1.1 kardel * See if we have an IPv6 address
513 1.1 kardel */
514 1.1 kardel if(strchr(nodename, ':') != NULL) {
515 1.1 kardel if (inet_pton(AF_INET6, nodename,
516 1.1 kardel &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) {
517 1.1 kardel ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6;
518 1.1 kardel ai->ai_family = AF_INET6;
519 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in6);
520 1.1 kardel return (0);
521 1.1 kardel }
522 1.1 kardel }
523 1.1 kardel
524 1.1 kardel /*
525 1.1 kardel * See if we have an IPv4 address
526 1.1 kardel */
527 1.1 kardel if (inet_pton(AF_INET, nodename,
528 1.1 kardel &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
529 1.1 kardel ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
530 1.1 kardel ai->ai_family = AF_INET;
531 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in);
532 1.1 kardel return (0);
533 1.1 kardel }
534 1.1 kardel
535 1.1 kardel /*
536 1.1 kardel * If the numeric host flag is set, don't attempt resolution
537 1.1 kardel */
538 1.1 kardel if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST))
539 1.1 kardel return (EAI_NONAME);
540 1.1 kardel
541 1.1 kardel /*
542 1.1 kardel * Look for a name
543 1.1 kardel */
544 1.1 kardel
545 1.1 kardel errval = DNSlookup_name(nodename, AF_INET, &hp);
546 1.1 kardel
547 1.1 kardel if (hp == NULL) {
548 1.1 kardel if (errval == TRY_AGAIN || errval == EAI_AGAIN)
549 1.1 kardel return (EAI_AGAIN);
550 1.1 kardel else if (errval == EAI_NONAME) {
551 1.1 kardel if (inet_pton(AF_INET, nodename,
552 1.1 kardel &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
553 1.1 kardel ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
554 1.1 kardel ai->ai_family = AF_INET;
555 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in);
556 1.1 kardel return (0);
557 1.1 kardel }
558 1.1 kardel return (errval);
559 1.1 kardel }
560 1.1 kardel else
561 1.1 kardel {
562 1.1 kardel return (errval);
563 1.1 kardel }
564 1.1 kardel }
565 1.1 kardel ai->ai_family = hp->h_addrtype;
566 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr);
567 1.1 kardel sockin = (struct sockaddr_in *)ai->ai_addr;
568 1.1 kardel memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
569 1.1 kardel ai->ai_addr->sa_family = hp->h_addrtype;
570 1.1 kardel #ifdef ISC_PLATFORM_HAVESALEN
571 1.1 kardel ai->ai_addr->sa_len = sizeof(struct sockaddr);
572 1.1 kardel #endif
573 1.1.1.1.8.1 snj if (hints != NULL && (hints->ai_flags & AI_CANONNAME))
574 1.1 kardel ai->ai_canonname = estrdup(hp->h_name);
575 1.1 kardel return (0);
576 1.1 kardel }
577 1.1 kardel
578 1.1 kardel #endif /* !ISC_PLATFORM_HAVEIPV6 */
579