ntp_rfc2553.c revision 1.1.1.1.14.3 1 1.1.1.1.14.3 snj /* $NetBSD: ntp_rfc2553.c,v 1.1.1.1.14.3 2016/05/08 21:51:00 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.14.1 snj #include "ntp_debug.h"
87 1.1.1.1.14.1 snj
88 1.1.1.1.14.1 snj
89 1.1.1.1.14.1 snj /*
90 1.1.1.1.14.1 snj * copy_addrinfo() - copy a single addrinfo to malloc()'d block.
91 1.1.1.1.14.1 snj * copy_addrinfo_list() - copy an addrinfo list to malloc()'d block.
92 1.1.1.1.14.1 snj *
93 1.1.1.1.14.1 snj * Copies an addrinfo list and its associated data to a contiguous block
94 1.1.1.1.14.1 snj * of storage from emalloc(). Callback routines invoked via
95 1.1.1.1.14.1 snj * getaddrinfo_sometime() have access to the resulting addrinfo list
96 1.1.1.1.14.1 snj * only until they return. This routine provides an easy way to make a
97 1.1.1.1.14.1 snj * persistent copy. Although the list provided to gai_sometime_callback
98 1.1.1.1.14.1 snj * routines is similarly contiguous, to keep this code usable in any
99 1.1.1.1.14.1 snj * context where we might want to duplicate an addrinfo list, it does
100 1.1.1.1.14.1 snj * not require the input list be contiguous.
101 1.1.1.1.14.1 snj *
102 1.1.1.1.14.1 snj * The returned list head pointer is passed to free() to release the
103 1.1.1.1.14.1 snj * entire list.
104 1.1.1.1.14.1 snj *
105 1.1.1.1.14.1 snj * In keeping with the rest of the NTP distribution, sockaddr_u is used
106 1.1.1.1.14.1 snj * in preference to struct sockaddr_storage, which is a member of the
107 1.1.1.1.14.1 snj * former union and so compatible.
108 1.1.1.1.14.1 snj *
109 1.1.1.1.14.1 snj * The rest of ntp_rfc2553.c is conditioned on ISC_PLATFORM_HAVEIPV6
110 1.1.1.1.14.1 snj * not being defined, copy_addrinfo_*() are exceptions.
111 1.1.1.1.14.1 snj */
112 1.1.1.1.14.1 snj struct addrinfo * copy_addrinfo_common(const struct addrinfo *, int
113 1.1.1.1.14.1 snj #ifdef EREALLOC_CALLSITE
114 1.1.1.1.14.1 snj ,
115 1.1.1.1.14.1 snj const char *, int
116 1.1.1.1.14.1 snj #endif
117 1.1.1.1.14.1 snj );
118 1.1.1.1.14.1 snj
119 1.1.1.1.14.1 snj
120 1.1.1.1.14.1 snj struct addrinfo *
121 1.1.1.1.14.1 snj copy_addrinfo_impl(
122 1.1.1.1.14.1 snj const struct addrinfo * src
123 1.1.1.1.14.1 snj #ifdef EREALLOC_CALLSITE
124 1.1.1.1.14.1 snj ,
125 1.1.1.1.14.1 snj const char * caller_file,
126 1.1.1.1.14.1 snj int caller_line
127 1.1.1.1.14.1 snj #endif
128 1.1.1.1.14.1 snj )
129 1.1.1.1.14.1 snj {
130 1.1.1.1.14.1 snj return copy_addrinfo_common(src, TRUE
131 1.1.1.1.14.1 snj #ifdef EREALLOC_CALLSITE
132 1.1.1.1.14.1 snj ,
133 1.1.1.1.14.1 snj caller_file, caller_line
134 1.1.1.1.14.1 snj #endif
135 1.1.1.1.14.1 snj );
136 1.1.1.1.14.1 snj }
137 1.1.1.1.14.1 snj
138 1.1.1.1.14.1 snj
139 1.1.1.1.14.1 snj struct addrinfo *
140 1.1.1.1.14.1 snj copy_addrinfo_list_impl(
141 1.1.1.1.14.1 snj const struct addrinfo * src
142 1.1.1.1.14.1 snj #ifdef EREALLOC_CALLSITE
143 1.1.1.1.14.1 snj ,
144 1.1.1.1.14.1 snj const char * caller_file,
145 1.1.1.1.14.1 snj int caller_line
146 1.1.1.1.14.1 snj #endif
147 1.1.1.1.14.1 snj )
148 1.1.1.1.14.1 snj {
149 1.1.1.1.14.1 snj return copy_addrinfo_common(src, FALSE
150 1.1.1.1.14.1 snj #ifdef EREALLOC_CALLSITE
151 1.1.1.1.14.1 snj ,
152 1.1.1.1.14.1 snj caller_file, caller_line
153 1.1.1.1.14.1 snj #endif
154 1.1.1.1.14.1 snj );
155 1.1.1.1.14.1 snj }
156 1.1.1.1.14.1 snj
157 1.1.1.1.14.1 snj
158 1.1.1.1.14.1 snj struct addrinfo *
159 1.1.1.1.14.1 snj copy_addrinfo_common(
160 1.1.1.1.14.1 snj const struct addrinfo * src,
161 1.1.1.1.14.1 snj int just_one
162 1.1.1.1.14.1 snj #ifdef EREALLOC_CALLSITE
163 1.1.1.1.14.1 snj ,
164 1.1.1.1.14.1 snj const char * caller_file,
165 1.1.1.1.14.1 snj int caller_line
166 1.1.1.1.14.1 snj #endif
167 1.1.1.1.14.1 snj )
168 1.1.1.1.14.1 snj {
169 1.1.1.1.14.1 snj const struct addrinfo * ai_src;
170 1.1.1.1.14.1 snj const struct addrinfo * ai_nxt;
171 1.1.1.1.14.1 snj struct addrinfo * ai_cpy;
172 1.1.1.1.14.1 snj struct addrinfo * dst;
173 1.1.1.1.14.1 snj sockaddr_u * psau;
174 1.1.1.1.14.1 snj char * pcanon;
175 1.1.1.1.14.1 snj u_int elements;
176 1.1.1.1.14.1 snj size_t octets;
177 1.1.1.1.14.1 snj size_t canons_octets;
178 1.1.1.1.14.1 snj size_t str_octets;
179 1.1.1.1.14.1 snj
180 1.1.1.1.14.1 snj elements = 0;
181 1.1.1.1.14.1 snj canons_octets = 0;
182 1.1.1.1.14.1 snj
183 1.1.1.1.14.1 snj for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
184 1.1.1.1.14.1 snj if (just_one)
185 1.1.1.1.14.1 snj ai_nxt = NULL;
186 1.1.1.1.14.1 snj else
187 1.1.1.1.14.1 snj ai_nxt = ai_src->ai_next;
188 1.1.1.1.14.1 snj ++elements;
189 1.1.1.1.14.1 snj if (NULL != ai_src->ai_canonname)
190 1.1.1.1.14.1 snj canons_octets += 1 + strlen(ai_src->ai_canonname);
191 1.1.1.1.14.1 snj }
192 1.1.1.1.14.1 snj
193 1.1.1.1.14.1 snj octets = elements * (sizeof(*ai_cpy) + sizeof(*psau));
194 1.1.1.1.14.1 snj octets += canons_octets;
195 1.1.1.1.14.1 snj
196 1.1.1.1.14.1 snj dst = erealloczsite(NULL, octets, 0, TRUE, caller_file,
197 1.1.1.1.14.1 snj caller_line);
198 1.1.1.1.14.1 snj ai_cpy = dst;
199 1.1.1.1.14.1 snj psau = (void *)(ai_cpy + elements);
200 1.1.1.1.14.1 snj pcanon = (void *)(psau + elements);
201 1.1.1.1.14.1 snj
202 1.1.1.1.14.1 snj for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
203 1.1.1.1.14.1 snj if (just_one)
204 1.1.1.1.14.1 snj ai_nxt = NULL;
205 1.1.1.1.14.1 snj else
206 1.1.1.1.14.1 snj ai_nxt = ai_src->ai_next;
207 1.1.1.1.14.1 snj *ai_cpy = *ai_src;
208 1.1.1.1.14.3 snj DEBUG_INSIST(ai_cpy->ai_canonname == ai_src->ai_canonname);
209 1.1.1.1.14.3 snj INSIST(ai_src->ai_addrlen <= sizeof(sockaddr_u));
210 1.1.1.1.14.1 snj memcpy(psau, ai_src->ai_addr, ai_src->ai_addrlen);
211 1.1.1.1.14.1 snj ai_cpy->ai_addr = &psau->sa;
212 1.1.1.1.14.1 snj ++psau;
213 1.1.1.1.14.3 snj if (NULL != ai_src->ai_canonname) {
214 1.1.1.1.14.1 snj ai_cpy->ai_canonname = pcanon;
215 1.1.1.1.14.1 snj str_octets = 1 + strlen(ai_src->ai_canonname);
216 1.1.1.1.14.1 snj memcpy(pcanon, ai_src->ai_canonname, str_octets);
217 1.1.1.1.14.1 snj pcanon += str_octets;
218 1.1.1.1.14.1 snj }
219 1.1.1.1.14.1 snj if (NULL != ai_cpy->ai_next) {
220 1.1.1.1.14.1 snj if (just_one)
221 1.1.1.1.14.1 snj ai_cpy->ai_next = NULL;
222 1.1.1.1.14.1 snj else
223 1.1.1.1.14.1 snj ai_cpy->ai_next = ai_cpy + 1;
224 1.1.1.1.14.1 snj }
225 1.1.1.1.14.1 snj ++ai_cpy;
226 1.1.1.1.14.1 snj }
227 1.1.1.1.14.2 snj ENSURE(pcanon == ((char *)dst + octets));
228 1.1.1.1.14.1 snj
229 1.1.1.1.14.1 snj return dst;
230 1.1.1.1.14.1 snj }
231 1.1.1.1.14.1 snj
232 1.1 kardel
233 1.1 kardel #ifndef ISC_PLATFORM_HAVEIPV6
234 1.1 kardel
235 1.1 kardel static char *ai_errlist[] = {
236 1.1 kardel "Success",
237 1.1 kardel "Address family for hostname not supported", /* EAI_ADDRFAMILY */
238 1.1 kardel "Temporary failure in name resolution", /* EAI_AGAIN */
239 1.1 kardel "Invalid value for ai_flags", /* EAI_BADFLAGS */
240 1.1 kardel "Non-recoverable failure in name resolution", /* EAI_FAIL */
241 1.1 kardel "ai_family not supported", /* EAI_FAMILY */
242 1.1 kardel "Memory allocation failure", /* EAI_MEMORY */
243 1.1 kardel "No address associated with hostname", /* EAI_NODATA */
244 1.1 kardel "hostname nor servname provided, or not known", /* EAI_NONAME */
245 1.1 kardel "servname not supported for ai_socktype", /* EAI_SERVICE */
246 1.1 kardel "ai_socktype not supported", /* EAI_SOCKTYPE */
247 1.1 kardel "System error returned in errno", /* EAI_SYSTEM */
248 1.1 kardel "Invalid value for hints", /* EAI_BADHINTS */
249 1.1 kardel "Resolved protocol is unknown", /* EAI_PROTOCOL */
250 1.1 kardel "Unknown error", /* EAI_MAX */
251 1.1 kardel };
252 1.1 kardel
253 1.1 kardel /*
254 1.1 kardel * Local declaration
255 1.1 kardel */
256 1.1 kardel int
257 1.1 kardel DNSlookup_name(
258 1.1 kardel const char *name,
259 1.1 kardel int ai_family,
260 1.1 kardel struct hostent **Addresses
261 1.1 kardel );
262 1.1 kardel
263 1.1 kardel #ifndef SYS_WINNT
264 1.1 kardel /*
265 1.1 kardel * Encapsulate gethostbyname to control the error code
266 1.1 kardel */
267 1.1 kardel int
268 1.1 kardel DNSlookup_name(
269 1.1 kardel const char *name,
270 1.1 kardel int ai_family,
271 1.1 kardel struct hostent **Addresses
272 1.1 kardel )
273 1.1 kardel {
274 1.1 kardel *Addresses = gethostbyname(name);
275 1.1 kardel return (h_errno);
276 1.1 kardel }
277 1.1 kardel #endif
278 1.1 kardel
279 1.1 kardel static int do_nodename (const char *nodename, struct addrinfo *ai,
280 1.1 kardel const struct addrinfo *hints);
281 1.1 kardel
282 1.1 kardel int
283 1.1 kardel getaddrinfo (const char *nodename, const char *servname,
284 1.1 kardel const struct addrinfo *hints, struct addrinfo **res)
285 1.1 kardel {
286 1.1 kardel int rval;
287 1.1 kardel struct servent *sp;
288 1.1 kardel struct addrinfo *ai = NULL;
289 1.1 kardel int port;
290 1.1 kardel const char *proto = NULL;
291 1.1 kardel int family, socktype, flags, protocol;
292 1.1 kardel
293 1.1 kardel
294 1.1 kardel /*
295 1.1 kardel * If no name is provide just return an error
296 1.1 kardel */
297 1.1 kardel if (nodename == NULL && servname == NULL)
298 1.1 kardel return (EAI_NONAME);
299 1.1 kardel
300 1.1 kardel ai = calloc(sizeof(struct addrinfo), 1);
301 1.1 kardel if (ai == NULL)
302 1.1 kardel return (EAI_MEMORY);
303 1.1 kardel
304 1.1 kardel /*
305 1.1 kardel * Copy default values from hints, if available
306 1.1 kardel */
307 1.1 kardel if (hints != NULL) {
308 1.1 kardel ai->ai_flags = hints->ai_flags;
309 1.1 kardel ai->ai_family = hints->ai_family;
310 1.1 kardel ai->ai_socktype = hints->ai_socktype;
311 1.1 kardel ai->ai_protocol = hints->ai_protocol;
312 1.1 kardel
313 1.1 kardel family = hints->ai_family;
314 1.1 kardel socktype = hints->ai_socktype;
315 1.1 kardel protocol = hints->ai_protocol;
316 1.1 kardel flags = hints->ai_flags;
317 1.1 kardel
318 1.1 kardel switch (family) {
319 1.1 kardel case AF_UNSPEC:
320 1.1 kardel switch (hints->ai_socktype) {
321 1.1 kardel case SOCK_STREAM:
322 1.1 kardel proto = "tcp";
323 1.1 kardel break;
324 1.1 kardel case SOCK_DGRAM:
325 1.1 kardel proto = "udp";
326 1.1 kardel break;
327 1.1 kardel }
328 1.1 kardel break;
329 1.1 kardel case AF_INET:
330 1.1 kardel case AF_INET6:
331 1.1 kardel switch (hints->ai_socktype) {
332 1.1 kardel case 0:
333 1.1 kardel break;
334 1.1 kardel case SOCK_STREAM:
335 1.1 kardel proto = "tcp";
336 1.1 kardel break;
337 1.1 kardel case SOCK_DGRAM:
338 1.1 kardel proto = "udp";
339 1.1 kardel break;
340 1.1 kardel case SOCK_RAW:
341 1.1 kardel break;
342 1.1 kardel default:
343 1.1 kardel return (EAI_SOCKTYPE);
344 1.1 kardel }
345 1.1 kardel break;
346 1.1 kardel #ifdef AF_LOCAL
347 1.1 kardel case AF_LOCAL:
348 1.1 kardel switch (hints->ai_socktype) {
349 1.1 kardel case 0:
350 1.1 kardel break;
351 1.1 kardel case SOCK_STREAM:
352 1.1 kardel break;
353 1.1 kardel case SOCK_DGRAM:
354 1.1 kardel break;
355 1.1 kardel default:
356 1.1 kardel return (EAI_SOCKTYPE);
357 1.1 kardel }
358 1.1 kardel break;
359 1.1 kardel #endif
360 1.1 kardel default:
361 1.1 kardel return (EAI_FAMILY);
362 1.1 kardel }
363 1.1 kardel } else {
364 1.1 kardel protocol = 0;
365 1.1 kardel family = 0;
366 1.1 kardel socktype = 0;
367 1.1 kardel flags = 0;
368 1.1 kardel }
369 1.1 kardel
370 1.1 kardel rval = do_nodename(nodename, ai, hints);
371 1.1 kardel if (rval != 0) {
372 1.1 kardel freeaddrinfo(ai);
373 1.1 kardel return (rval);
374 1.1 kardel }
375 1.1 kardel
376 1.1 kardel /*
377 1.1 kardel * First, look up the service name (port) if it was
378 1.1 kardel * requested. If the socket type wasn't specified, then
379 1.1 kardel * try and figure it out.
380 1.1 kardel */
381 1.1 kardel if (servname != NULL) {
382 1.1 kardel char *e;
383 1.1 kardel
384 1.1 kardel port = strtol(servname, &e, 10);
385 1.1 kardel if (*e == '\0') {
386 1.1 kardel if (socktype == 0)
387 1.1 kardel return (EAI_SOCKTYPE);
388 1.1 kardel if (port < 0 || port > 65535)
389 1.1 kardel return (EAI_SERVICE);
390 1.1 kardel port = htons((unsigned short) port);
391 1.1 kardel } else {
392 1.1 kardel sp = getservbyname(servname, proto);
393 1.1 kardel if (sp == NULL)
394 1.1 kardel return (EAI_SERVICE);
395 1.1 kardel port = sp->s_port;
396 1.1 kardel if (socktype == 0) {
397 1.1 kardel if (strcmp(sp->s_proto, "tcp") == 0)
398 1.1 kardel socktype = SOCK_STREAM;
399 1.1 kardel else if (strcmp(sp->s_proto, "udp") == 0)
400 1.1 kardel socktype = SOCK_DGRAM;
401 1.1 kardel }
402 1.1 kardel }
403 1.1 kardel } else
404 1.1 kardel port = 0;
405 1.1 kardel
406 1.1 kardel /*
407 1.1 kardel *
408 1.1 kardel * Set up the port number
409 1.1 kardel */
410 1.1 kardel if (ai->ai_family == AF_INET)
411 1.1 kardel ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port;
412 1.1 kardel else if (ai->ai_family == AF_INET6)
413 1.1 kardel ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port;
414 1.1 kardel *res = ai;
415 1.1 kardel return (0);
416 1.1 kardel }
417 1.1 kardel
418 1.1 kardel void
419 1.1 kardel freeaddrinfo(struct addrinfo *ai)
420 1.1 kardel {
421 1.1 kardel if (ai->ai_canonname != NULL)
422 1.1 kardel {
423 1.1 kardel free(ai->ai_canonname);
424 1.1 kardel ai->ai_canonname = NULL;
425 1.1 kardel }
426 1.1 kardel if (ai->ai_addr != NULL)
427 1.1 kardel {
428 1.1 kardel free(ai->ai_addr);
429 1.1 kardel ai->ai_addr = NULL;
430 1.1 kardel }
431 1.1 kardel free(ai);
432 1.1 kardel ai = NULL;
433 1.1 kardel }
434 1.1 kardel
435 1.1 kardel int
436 1.1 kardel getnameinfo (const struct sockaddr *sa, u_int salen, char *host,
437 1.1 kardel size_t hostlen, char *serv, size_t servlen, int flags)
438 1.1 kardel {
439 1.1 kardel struct hostent *hp;
440 1.1 kardel
441 1.1 kardel if (sa->sa_family != AF_INET)
442 1.1 kardel return (EAI_FAMILY);
443 1.1 kardel hp = gethostbyaddr(
444 1.1 kardel (const char *)&((const struct sockaddr_in *)sa)->sin_addr,
445 1.1 kardel 4, AF_INET);
446 1.1 kardel if (hp == NULL) {
447 1.1 kardel if (h_errno == TRY_AGAIN)
448 1.1 kardel return (EAI_AGAIN);
449 1.1 kardel else
450 1.1 kardel return (EAI_FAIL);
451 1.1 kardel }
452 1.1.1.1.14.1 snj if (host != NULL && hostlen > 0)
453 1.1.1.1.14.1 snj strlcpy(host, hp->h_name, hostlen);
454 1.1 kardel return (0);
455 1.1 kardel }
456 1.1 kardel
457 1.1 kardel char *
458 1.1 kardel gai_strerror(int ecode)
459 1.1 kardel {
460 1.1 kardel if (ecode < 0 || ecode > EAI_MAX)
461 1.1 kardel ecode = EAI_MAX;
462 1.1 kardel return ai_errlist[ecode];
463 1.1 kardel }
464 1.1 kardel
465 1.1 kardel static int
466 1.1 kardel do_nodename(
467 1.1 kardel const char *nodename,
468 1.1 kardel struct addrinfo *ai,
469 1.1 kardel const struct addrinfo *hints)
470 1.1 kardel {
471 1.1 kardel struct hostent *hp = NULL;
472 1.1 kardel struct sockaddr_in *sockin;
473 1.1 kardel struct sockaddr_in6 *sockin6;
474 1.1 kardel int errval;
475 1.1 kardel
476 1.1 kardel ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
477 1.1 kardel if (ai->ai_addr == NULL)
478 1.1 kardel return (EAI_MEMORY);
479 1.1 kardel
480 1.1 kardel /*
481 1.1 kardel * For an empty node name just use the wildcard.
482 1.1 kardel * NOTE: We need to assume that the address family is
483 1.1 kardel * set elsewhere so that we can set the appropriate wildcard
484 1.1 kardel */
485 1.1 kardel if (nodename == NULL) {
486 1.1 kardel if (ai->ai_family == AF_INET)
487 1.1 kardel {
488 1.1.1.1.14.3 snj ai->ai_addrlen = sizeof(struct sockaddr_in);
489 1.1 kardel sockin = (struct sockaddr_in *)ai->ai_addr;
490 1.1 kardel sockin->sin_family = (short) ai->ai_family;
491 1.1 kardel sockin->sin_addr.s_addr = htonl(INADDR_ANY);
492 1.1 kardel }
493 1.1 kardel else
494 1.1 kardel {
495 1.1.1.1.14.3 snj ai->ai_addrlen = sizeof(struct sockaddr_in6);
496 1.1 kardel sockin6 = (struct sockaddr_in6 *)ai->ai_addr;
497 1.1 kardel sockin6->sin6_family = (short) ai->ai_family;
498 1.1 kardel /*
499 1.1 kardel * we have already zeroed out the address
500 1.1 kardel * so we don't actually need to do this
501 1.1 kardel * This assignment is causing problems so
502 1.1 kardel * we don't do what this would do.
503 1.1 kardel sockin6->sin6_addr = in6addr_any;
504 1.1 kardel */
505 1.1 kardel }
506 1.1 kardel #ifdef ISC_PLATFORM_HAVESALEN
507 1.1 kardel ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
508 1.1 kardel #endif
509 1.1 kardel
510 1.1 kardel return (0);
511 1.1 kardel }
512 1.1 kardel
513 1.1 kardel /*
514 1.1 kardel * See if we have an IPv6 address
515 1.1 kardel */
516 1.1 kardel if(strchr(nodename, ':') != NULL) {
517 1.1 kardel if (inet_pton(AF_INET6, nodename,
518 1.1 kardel &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) {
519 1.1 kardel ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6;
520 1.1 kardel ai->ai_family = AF_INET6;
521 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in6);
522 1.1 kardel return (0);
523 1.1 kardel }
524 1.1 kardel }
525 1.1 kardel
526 1.1 kardel /*
527 1.1 kardel * See if we have an IPv4 address
528 1.1 kardel */
529 1.1 kardel if (inet_pton(AF_INET, nodename,
530 1.1 kardel &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
531 1.1 kardel ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
532 1.1 kardel ai->ai_family = AF_INET;
533 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in);
534 1.1 kardel return (0);
535 1.1 kardel }
536 1.1 kardel
537 1.1 kardel /*
538 1.1 kardel * If the numeric host flag is set, don't attempt resolution
539 1.1 kardel */
540 1.1 kardel if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST))
541 1.1 kardel return (EAI_NONAME);
542 1.1 kardel
543 1.1 kardel /*
544 1.1 kardel * Look for a name
545 1.1 kardel */
546 1.1 kardel
547 1.1 kardel errval = DNSlookup_name(nodename, AF_INET, &hp);
548 1.1 kardel
549 1.1 kardel if (hp == NULL) {
550 1.1 kardel if (errval == TRY_AGAIN || errval == EAI_AGAIN)
551 1.1 kardel return (EAI_AGAIN);
552 1.1 kardel else if (errval == EAI_NONAME) {
553 1.1 kardel if (inet_pton(AF_INET, nodename,
554 1.1 kardel &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
555 1.1 kardel ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
556 1.1 kardel ai->ai_family = AF_INET;
557 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in);
558 1.1 kardel return (0);
559 1.1 kardel }
560 1.1 kardel return (errval);
561 1.1 kardel }
562 1.1 kardel else
563 1.1 kardel {
564 1.1 kardel return (errval);
565 1.1 kardel }
566 1.1 kardel }
567 1.1 kardel ai->ai_family = hp->h_addrtype;
568 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr);
569 1.1 kardel sockin = (struct sockaddr_in *)ai->ai_addr;
570 1.1 kardel memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
571 1.1 kardel ai->ai_addr->sa_family = hp->h_addrtype;
572 1.1 kardel #ifdef ISC_PLATFORM_HAVESALEN
573 1.1 kardel ai->ai_addr->sa_len = sizeof(struct sockaddr);
574 1.1 kardel #endif
575 1.1.1.1.14.1 snj if (hints != NULL && (hints->ai_flags & AI_CANONNAME))
576 1.1 kardel ai->ai_canonname = estrdup(hp->h_name);
577 1.1 kardel return (0);
578 1.1 kardel }
579 1.1 kardel
580 1.1 kardel #endif /* !ISC_PLATFORM_HAVEIPV6 */
581