]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/bio/b_addr.c
Check for OPENSSL_USE_APPLINK in $config{cflags} as well
[thirdparty/openssl.git] / crypto / bio / b_addr.c
CommitLineData
28a0841b
RL
1/* ====================================================================
2 * Copyright (c) 2015 The OpenSSL Project. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * 3. All advertising materials mentioning features or use of this
17 * software must display the following acknowledgment:
18 * "This product includes software developed by the OpenSSL Project
19 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20 *
21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22 * endorse or promote products derived from this software without
23 * prior written permission. For written permission, please contact
24 * openssl-core@openssl.org.
25 *
26 * 5. Products derived from this software may not be called "OpenSSL"
27 * nor may "OpenSSL" appear in their names without prior written
28 * permission of the OpenSSL Project.
29 *
30 * 6. Redistributions of any form whatsoever must retain the following
31 * acknowledgment:
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46 * OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This product includes cryptographic software written by Eric Young
50 * (eay@cryptsoft.com). This product includes software written by Tim
51 * Hudson (tjh@cryptsoft.com).
52 *
53 */
54
55#include <string.h>
56
57#include "bio_lcl.h"
58
59#include <openssl/err.h>
60#include <openssl/buffer.h>
d40cf9bc 61#include <ctype.h>
28a0841b
RL
62
63/*
64 * Throughout this file and bio_lcl.h, the existence of the macro
65 * AI_PASSIVE is used to detect the availability of struct addrinfo,
66 * getnameinfo() and getaddrinfo(). If that macro doesn't exist,
67 * we use our own implementation instead, using gethostbyname,
68 * getservbyname and a few other.
69 */
70
71/**********************************************************************
72 *
73 * Address structure
74 *
75 */
76
77BIO_ADDR *BIO_ADDR_new(void)
78{
43ecb9c3
RS
79 BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret));
80
7d1d48a2 81 ret->sa.sa_family = AF_UNSPEC;
28a0841b
RL
82 return ret;
83}
84
85void BIO_ADDR_free(BIO_ADDR *ap)
86{
87 OPENSSL_free(ap);
88}
89
7d1d48a2
MC
90void BIO_ADDR_clear(BIO_ADDR *ap)
91{
92 memset(ap, 0, sizeof(*ap));
93 ap->sa.sa_family = AF_UNSPEC;
94}
95
28a0841b
RL
96/*
97 * BIO_ADDR_make - non-public routine to fill a BIO_ADDR with the contents
98 * of a struct sockaddr.
99 */
100int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa)
101{
102 if (sa->sa_family == AF_INET) {
103 ap->sin = *(const struct sockaddr_in *)sa;
104 return 1;
105 }
106#ifdef AF_INET6
107 if (sa->sa_family == AF_INET6) {
108 ap->sin6 = *(const struct sockaddr_in6 *)sa;
109 return 1;
110 }
111#endif
112#ifdef AF_UNIX
113 if (ap->sa.sa_family == AF_UNIX) {
114 ap->sun = *(const struct sockaddr_un *)sa;
115 return 1;
116 }
117#endif
118
119 return 0;
120}
121
122int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
123 const void *where, size_t wherelen,
124 unsigned short port)
125{
126#ifdef AF_UNIX
127 if (family == AF_UNIX) {
128 if (wherelen + 1 > sizeof(ap->sun.sun_path))
129 return 0;
130 memset(&ap->sun, 0, sizeof(ap->sun));
131 ap->sun.sun_family = family;
132 strncpy(ap->sun.sun_path, where, sizeof(ap->sun.sun_path) - 1);
133 return 1;
134 }
135#endif
136 if (family == AF_INET) {
137 if (wherelen != sizeof(struct in_addr))
138 return 0;
139 memset(&ap->sin, 0, sizeof(ap->sin));
140 ap->sin.sin_family = family;
141 ap->sin.sin_port = port;
142 ap->sin.sin_addr = *(struct in_addr *)where;
143 return 1;
144 }
145#ifdef AF_INET6
146 if (family == AF_INET6) {
147 if (wherelen != sizeof(struct in6_addr))
148 return 0;
149 memset(&ap->sin6, 0, sizeof(ap->sin6));
150 ap->sin6.sin6_family = family;
151 ap->sin6.sin6_port = port;
152 ap->sin6.sin6_addr = *(struct in6_addr *)where;
153 return 1;
154 }
155#endif
156
157 return 0;
158}
159
160int BIO_ADDR_family(const BIO_ADDR *ap)
161{
162 return ap->sa.sa_family;
163}
164
165int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l)
166{
167 size_t len = 0;
168 const void *addrptr = NULL;
169
170 if (ap->sa.sa_family == AF_INET) {
171 len = sizeof(ap->sin.sin_addr);
172 addrptr = &ap->sin.sin_addr;
173 }
174#ifdef AF_INET6
175 else if (ap->sa.sa_family == AF_INET6) {
176 len = sizeof(ap->sin6.sin6_addr);
177 addrptr = &ap->sin6.sin6_addr;
178 }
179#endif
180#ifdef AF_UNIX
181 else if (ap->sa.sa_family == AF_UNIX) {
182 len = strlen(ap->sun.sun_path);
183 addrptr = &ap->sun.sun_path;
184 }
185#endif
186
187 if (addrptr == NULL)
188 return 0;
189
190 if (p != NULL) {
191 memcpy(p, addrptr, len);
192 }
193 if (l != NULL)
194 *l = len;
195
196 return 1;
197}
198
199unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap)
200{
201 if (ap->sa.sa_family == AF_INET)
202 return ap->sin.sin_port;
203#ifdef AF_INET6
204 if (ap->sa.sa_family == AF_INET6)
205 return ap->sin6.sin6_port;
206#endif
207 return 0;
208}
209
210/*-
211 * addr_strings - helper function to get host and service names
212 * @ap: the BIO_ADDR that has the input info
213 * @numeric: 0 if actual names should be returned, 1 if the numeric
214 * representation should be returned.
215 * @hostname: a pointer to a pointer to a memory area to store the
216 * host name or numeric representation. Unused if NULL.
217 * @service: a pointer to a pointer to a memory area to store the
218 * service name or numeric representation. Unused if NULL.
219 *
220 * The return value is 0 on failure, with the error code in the error
221 * stack, and 1 on success.
222 */
223static int addr_strings(const BIO_ADDR *ap, int numeric,
224 char **hostname, char **service)
225{
ed03c461
RL
226 if (BIO_sock_init() != 1)
227 return 0;
228
28a0841b
RL
229 if (1) {
230#ifdef AI_PASSIVE
231 int ret = 0;
6faffd0a 232 char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
28a0841b
RL
233 int flags = 0;
234
235 if (numeric)
236 flags |= NI_NUMERICHOST | NI_NUMERICSERV;
237
238 if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap),
239 BIO_ADDR_sockaddr_size(ap),
240 host, sizeof(host), serv, sizeof(serv),
241 flags)) != 0) {
242# ifdef EAI_SYSTEM
243 if (ret == EAI_SYSTEM) {
244 SYSerr(SYS_F_GETNAMEINFO, get_last_socket_error());
245 BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
246 } else
247# endif
248 {
249 BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
250 ERR_add_error_data(1, gai_strerror(ret));
251 }
252 return 0;
253 }
d40cf9bc 254
6faffd0a
RL
255 /* VMS getnameinfo() has a bug, it doesn't fill in serv, which
256 * leaves it with whatever garbage that happens to be there.
257 * However, we initialise serv with the empty string (serv[0]
258 * is therefore NUL), so it gets real easy to detect when things
259 * didn't go the way one might expect.
d40cf9bc 260 */
6faffd0a 261 if (serv[0] == '\0') {
d40cf9bc
RL
262 BIO_snprintf(serv, sizeof(serv), "%d",
263 ntohs(BIO_ADDR_rawport(ap)));
264 }
265
28a0841b
RL
266 if (hostname)
267 *hostname = OPENSSL_strdup(host);
268 if (service)
269 *service = OPENSSL_strdup(serv);
270 } else {
271#endif
272 if (hostname)
273 *hostname = OPENSSL_strdup(inet_ntoa(ap->sin.sin_addr));
274 if (service) {
275 char serv[6]; /* port is 16 bits => max 5 decimal digits */
276 BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->sin.sin_port));
277 *service = OPENSSL_strdup(serv);
278 }
279 }
280
281 return 1;
282}
283
284char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric)
285{
286 char *hostname = NULL;
287
288 if (addr_strings(ap, numeric, &hostname, NULL))
289 return hostname;
290
291 return NULL;
292}
293
294char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric)
295{
296 char *service = NULL;
297
298 if (addr_strings(ap, numeric, NULL, &service))
299 return service;
300
301 return NULL;
302}
303
304char *BIO_ADDR_path_string(const BIO_ADDR *ap)
305{
306#ifdef AF_UNIX
307 if (ap->sa.sa_family == AF_UNIX)
308 return OPENSSL_strdup(ap->sun.sun_path);
309#endif
310 return NULL;
311}
312
313/*
314 * BIO_ADDR_sockaddr - non-public routine to return the struct sockaddr
315 * for a given BIO_ADDR. In reality, this is simply a type safe cast.
316 * The returned struct sockaddr is const, so it can't be tampered with.
317 */
318const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap)
319{
320 return &(ap->sa);
321}
322
323/*
324 * BIO_ADDR_sockaddr_noconst - non-public function that does the same
325 * as BIO_ADDR_sockaddr, but returns a non-const. USE WITH CARE, as
326 * it allows you to tamper with the data (and thereby the contents
327 * of the input BIO_ADDR).
328 */
329struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap)
330{
331 return &(ap->sa);
332}
333
334/*
335 * BIO_ADDR_sockaddr_size - non-public function that returns the size
336 * of the struct sockaddr the BIO_ADDR is using. If the protocol family
337 * isn't set or is something other than AF_INET, AF_INET6 or AF_UNIX,
338 * the size of the BIO_ADDR type is returned.
339 */
340socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap)
341{
342 if (ap->sa.sa_family == AF_INET)
343 return sizeof(ap->sin);
344#ifdef AF_INET6
345 if (ap->sa.sa_family == AF_INET6)
346 return sizeof(ap->sin6);
347#endif
348#ifdef AF_UNIX
349 if (ap->sa.sa_family == AF_UNIX)
350 return sizeof(ap->sun);
351#endif
352 return sizeof(*ap);
353}
354
355/**********************************************************************
356 *
e5a82bfd 357 * Address info database
28a0841b
RL
358 *
359 */
360
361const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai)
362{
363 if (bai != NULL)
364 return bai->bai_next;
365 return NULL;
366}
367
368int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai)
369{
370 if (bai != NULL)
371 return bai->bai_family;
372 return 0;
373}
374
375int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai)
376{
377 if (bai != NULL)
378 return bai->bai_socktype;
379 return 0;
380}
381
382int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai)
383{
c72fb77f
RL
384 if (bai != NULL) {
385 if (bai->bai_protocol != 0)
386 return bai->bai_protocol;
387
388#ifdef AF_UNIX
389 if (bai->bai_family == AF_UNIX)
390 return 0;
391#endif
392
393 switch (bai->bai_socktype) {
394 case SOCK_STREAM:
395 return IPPROTO_TCP;
396 case SOCK_DGRAM:
397 return IPPROTO_UDP;
398 default:
399 break;
400 }
401 }
28a0841b
RL
402 return 0;
403}
404
405/*
406 * BIO_ADDRINFO_sockaddr_size - non-public function that returns the size
407 * of the struct sockaddr inside the BIO_ADDRINFO.
408 */
409socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai)
410{
411 if (bai != NULL)
412 return bai->bai_addrlen;
413 return 0;
414}
415
416/*
417 * BIO_ADDRINFO_sockaddr - non-public function that returns bai_addr
418 * as the struct sockaddr it is.
419 */
420const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai)
421{
422 if (bai != NULL)
423 return bai->bai_addr;
424 return NULL;
425}
426
427const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai)
428{
429 if (bai != NULL)
430 return (BIO_ADDR *)bai->bai_addr;
431 return NULL;
432}
433
434void BIO_ADDRINFO_free(BIO_ADDRINFO *bai)
435{
436 if (bai == NULL)
437 return;
438
439#ifdef AI_PASSIVE
440# ifdef AF_UNIX
441# define _cond bai->bai_family != AF_UNIX
442# else
443# define _cond 1
444# endif
445 if (_cond) {
446 freeaddrinfo(bai);
447 return;
448 }
449#endif
450
451 /* Free manually when we know that addrinfo_wrap() was used.
452 * See further comment above addrinfo_wrap()
453 */
454 while (bai != NULL) {
455 BIO_ADDRINFO *next = bai->bai_next;
456 OPENSSL_free(bai->bai_addr);
457 OPENSSL_free(bai);
458 bai = next;
459 }
460}
461
462/**********************************************************************
463 *
464 * Service functions
465 *
466 */
467
468/*-
469 * The specs in hostserv can take these forms:
470 *
471 * host:service => *host = "host", *service = "service"
472 * host:* => *host = "host", *service = NULL
473 * host: => *host = "host", *service = NULL
474 * :service => *host = NULL, *service = "service"
475 * *:service => *host = NULL, *service = "service"
476 *
477 * in case no : is present in the string, the result depends on
478 * hostserv_prio, as follows:
479 *
480 * when hostserv_prio == BIO_PARSE_PRIO_HOST
481 * host => *host = "host", *service untouched
482 *
483 * when hostserv_prio == BIO_PARSE_PRIO_SERV
484 * service => *host untouched, *service = "service"
485 *
486 */
487int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
488 enum BIO_hostserv_priorities hostserv_prio)
489{
490 const char *h = NULL; size_t hl = 0;
491 const char *p = NULL; size_t pl = 0;
492
493 if (*hostserv == '[') {
494 if ((p = strchr(hostserv, ']')) == NULL)
495 goto spec_err;
496 h = hostserv + 1;
497 hl = p - h;
498 p++;
499 if (*p == '\0')
500 p = NULL;
501 else if (*p != ':')
502 goto spec_err;
503 else {
504 p++;
505 pl = strlen(p);
506 }
507 } else {
508 const char *p2 = strrchr(hostserv, ':');
509 p = strchr(hostserv, ':');
510
511 /*-
512 * Check for more than one colon. There are three possible
513 * interpretations:
514 * 1. IPv6 address with port number, last colon being separator.
515 * 2. IPv6 address only.
516 * 3. IPv6 address only if hostserv_prio == BIO_PARSE_PRIO_HOST,
517 * IPv6 address and port number if hostserv_prio == BIO_PARSE_PRIO_SERV
518 * Because of this ambiguity, we currently choose to make it an
519 * error.
520 */
521 if (p != p2)
522 goto amb_err;
523
524 if (p != NULL) {
525 h = hostserv;
526 hl = p - h;
527 p++;
528 pl = strlen(p);
529 } else if (hostserv_prio == BIO_PARSE_PRIO_HOST) {
530 h = hostserv;
531 hl = strlen(h);
532 } else {
533 p = hostserv;
534 pl = strlen(p);
535 }
536 }
537
80926502 538 if (p != NULL && strchr(p, ':'))
28a0841b
RL
539 goto spec_err;
540
541 if (h != NULL && host != NULL) {
542 if (hl == 0
543 || (hl == 1 && h[0] == '*')) {
544 *host = NULL;
545 } else {
546 *host = OPENSSL_strndup(h, hl);
547 if (*host == NULL)
548 goto memerr;
549 }
550 }
551 if (p != NULL && service != NULL) {
552 if (pl == 0
553 || (pl == 1 && p[0] == '*')) {
554 *service = NULL;
555 } else {
556 *service = OPENSSL_strndup(p, pl);
557 if (*service == NULL)
558 goto memerr;
559 }
560 }
561
562 return 1;
563 amb_err:
564 BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_AMBIGUOUS_HOST_OR_SERVICE);
565 return 0;
566 spec_err:
567 BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_MALFORMED_HOST_OR_SERVICE);
568 return 0;
569 memerr:
570 BIOerr(BIO_F_BIO_PARSE_HOSTSERV, ERR_R_MALLOC_FAILURE);
571 return 0;
572}
573
574/* addrinfo_wrap is used to build our own addrinfo "chain".
575 * (it has only one entry, so calling it a chain may be a stretch)
576 * It should ONLY be called when getaddrinfo() and friends
577 * aren't available, OR when dealing with a non IP protocol
578 * family, such as AF_UNIX
579 *
580 * the return value is 1 on success, or 0 on failure, which
581 * only happens if a memory allocation error occured.
582 */
583static int addrinfo_wrap(int family, int socktype,
584 const void *where, size_t wherelen,
585 unsigned short port,
586 BIO_ADDRINFO **bai)
587{
588 OPENSSL_assert(bai != NULL);
589
43ecb9c3 590 *bai = OPENSSL_zalloc(sizeof(**bai));
28a0841b
RL
591 if (*bai == NULL)
592 return 0;
43ecb9c3 593
28a0841b
RL
594 (*bai)->bai_family = family;
595 (*bai)->bai_socktype = socktype;
596 if (socktype == SOCK_STREAM)
597 (*bai)->bai_protocol = IPPROTO_TCP;
598 if (socktype == SOCK_DGRAM)
599 (*bai)->bai_protocol = IPPROTO_UDP;
600#ifdef AF_UNIX
601 if (family == AF_UNIX)
602 (*bai)->bai_protocol = 0;
603#endif
604 {
605 /* Magic: We know that BIO_ADDR_sockaddr_noconst is really
606 just an advanced cast of BIO_ADDR* to struct sockaddr *
607 by the power of union, so while it may seem that we're
608 creating a memory leak here, we are not. It will be
609 all right. */
610 BIO_ADDR *addr = BIO_ADDR_new();
611 if (addr != NULL) {
612 BIO_ADDR_rawmake(addr, family, where, wherelen, port);
613 (*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr);
614 }
615 }
616 (*bai)->bai_next = NULL;
617 if ((*bai)->bai_addr == NULL) {
618 BIO_ADDRINFO_free(*bai);
619 *bai = NULL;
620 return 0;
621 }
622 return 1;
623}
624
625/*-
626 * BIO_lookup - look up the node and service you want to connect to.
627 * @node: the node you want to connect to.
628 * @service: the service you want to connect to.
629 * @lookup_type: declare intent with the result, client or server.
630 * @family: the address family you want to use. Use AF_UNSPEC for any, or
631 * AF_INET, AF_INET6 or AF_UNIX.
632 * @socktype: The socket type you want to use. Can be SOCK_STREAM, SOCK_DGRAM
633 * or 0 for all.
634 * @res: Storage place for the resulting list of returned addresses
635 *
636 * This will do a lookup of the node and service that you want to connect to.
637 * It returns a linked list of different addresses you can try to connect to.
638 *
639 * When no longer needed you should call BIO_ADDRINFO_free() to free the result.
640 *
641 * The return value is 1 on success or 0 in case of error.
642 */
643int BIO_lookup(const char *host, const char *service,
644 enum BIO_lookup_type lookup_type,
645 int family, int socktype, BIO_ADDRINFO **res)
646{
647 int ret = 0; /* Assume failure */
648
649 switch(family) {
650 case AF_INET:
651#ifdef AF_INET6
652 case AF_INET6:
653#endif
654#ifdef AF_UNIX
655 case AF_UNIX:
656#endif
657#ifdef AF_UNSPEC
658 case AF_UNSPEC:
659#endif
660 break;
661 default:
662 BIOerr(BIO_F_BIO_LOOKUP, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
663 return 0;
664 }
665
666#ifdef AF_UNIX
667 if (family == AF_UNIX) {
668 if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res))
669 return 1;
670 else
671 BIOerr(BIO_F_BIO_LOOKUP, ERR_R_MALLOC_FAILURE);
672 return 0;
673 }
674#endif
675
ed03c461
RL
676 if (BIO_sock_init() != 1)
677 return 0;
678
28a0841b 679 if (1) {
ed03c461 680 int gai_ret = 0;
28a0841b
RL
681#ifdef AI_PASSIVE
682 struct addrinfo hints;
683
684 hints.ai_flags = 0;
685# ifdef AI_ADDRCONFIG
686 hints.ai_flags = AI_ADDRCONFIG;
687# endif
688 hints.ai_family = family;
689 hints.ai_socktype = socktype;
690 hints.ai_protocol = 0;
691 hints.ai_addrlen = 0;
692 hints.ai_addr = NULL;
693 hints.ai_canonname = NULL;
694 hints.ai_next = NULL;
695
696 if (lookup_type == BIO_LOOKUP_SERVER)
697 hints.ai_flags |= AI_PASSIVE;
698
699 /* Note that |res| SHOULD be a 'struct addrinfo **' thanks to
700 * macro magic in bio_lcl.h
701 */
ed03c461 702 switch ((gai_ret = getaddrinfo(host, service, &hints, res))) {
28a0841b
RL
703# ifdef EAI_SYSTEM
704 case EAI_SYSTEM:
705 SYSerr(SYS_F_GETADDRINFO, get_last_socket_error());
706 BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
707 break;
708# endif
709 case 0:
710 ret = 1; /* Success */
711 break;
712 default:
713 BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
ed03c461 714 ERR_add_error_data(1, gai_strerror(gai_ret));
28a0841b
RL
715 break;
716 }
717 } else {
718#endif
37e3daf4 719 const struct hostent *he;
28a0841b
RL
720 /* Windows doesn't seem to have in_addr_t */
721#ifdef OPENSSL_SYS_WINDOWS
37e3daf4
KR
722 static uint32_t he_fallback_address;
723 static const uint32_t *he_fallback_addresses[] =
724 { &he_fallback_address, NULL };
28a0841b 725#else
37e3daf4
KR
726 static in_addr_t he_fallback_address;
727 static const in_addr_t *he_fallback_addresses[] =
728 { &he_fallback_address, NULL };
28a0841b 729#endif
37e3daf4
KR
730 static const struct hostent he_fallback =
731 { NULL, NULL, AF_INET, sizeof(he_fallback_address),
732 (char **)&he_fallback_addresses };
28a0841b
RL
733 struct servent *se;
734 /* Apprently, on WIN64, s_proto and s_port have traded places... */
735#ifdef _WIN64
736 struct servent se_fallback = { NULL, NULL, NULL, 0 };
737#else
738 struct servent se_fallback = { NULL, NULL, 0, NULL };
739#endif
740 char *proto = NULL;
741
742 CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
743 CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
37e3daf4 744 he_fallback_address = INADDR_ANY;
28a0841b
RL
745 if (host == NULL) {
746 he = &he_fallback;
747 switch(lookup_type) {
748 case BIO_LOOKUP_CLIENT:
749 he_fallback_address = INADDR_LOOPBACK;
750 break;
751 case BIO_LOOKUP_SERVER:
752 he_fallback_address = INADDR_ANY;
753 break;
754 default:
755 OPENSSL_assert(("We forgot to handle a lookup type!" == 0));
756 break;
757 }
758 } else {
759 he = gethostbyname(host);
760
761 if (he == NULL) {
c86d1f19 762#ifndef OPENSSL_SYS_WINDOWS
28a0841b
RL
763 BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
764 ERR_add_error_data(1, hstrerror(h_errno));
c86d1f19
KR
765#else
766 SYSerr(SYS_F_GETHOSTBYNAME, WSAGetLastError());
767#endif
28a0841b
RL
768 ret = 0;
769 goto err;
770 }
771 }
772
773 if (service == NULL) {
774 se_fallback.s_port = 0;
775 se_fallback.s_proto = proto;
776 se = &se_fallback;
777 } else {
778 char *endp = NULL;
779 long portnum = strtol(service, &endp, 10);
780
781 if (endp != service && *endp == '\0'
782 && portnum > 0 && portnum < 65536) {
783 se_fallback.s_port = htons(portnum);
784 se_fallback.s_proto = proto;
785 se = &se_fallback;
786 } else if (endp == service) {
787 switch (socktype) {
788 case SOCK_STREAM:
789 proto = "tcp";
790 break;
791 case SOCK_DGRAM:
792 proto = "udp";
793 break;
794 }
795 se = getservbyname(service, proto);
796
797 if (se == NULL) {
c86d1f19 798#ifndef OPENSSL_SYS_WINDOWS
28a0841b
RL
799 BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
800 ERR_add_error_data(1, hstrerror(h_errno));
c86d1f19
KR
801#else
802 SYSerr(SYS_F_GETSERVBYNAME, WSAGetLastError());
803#endif
28a0841b
RL
804 goto err;
805 }
806 } else {
807 BIOerr(BIO_F_BIO_LOOKUP, BIO_R_MALFORMED_HOST_OR_SERVICE);
808 goto err;
809 }
810 }
811
812 *res = NULL;
813
814 {
815 char **addrlistp;
816 size_t addresses;
817 BIO_ADDRINFO *tmp_bai = NULL;
818
819 /* The easiest way to create a linked list from an
820 array is to start from the back */
821 for(addrlistp = he->h_addr_list; *addrlistp != NULL;
822 addrlistp++)
823 ;
824
825 for(addresses = addrlistp - he->h_addr_list;
826 addrlistp--, addresses-- > 0; ) {
827 if (!addrinfo_wrap(he->h_addrtype, socktype,
828 *addrlistp, he->h_length,
829 se->s_port, &tmp_bai))
830 goto addrinfo_malloc_err;
831 tmp_bai->bai_next = *res;
832 *res = tmp_bai;
833 continue;
834 addrinfo_malloc_err:
835 BIO_ADDRINFO_free(*res);
836 *res = NULL;
837 BIOerr(BIO_F_BIO_LOOKUP, ERR_R_MALLOC_FAILURE);
838 ret = 0;
839 goto err;
840 }
841
842 ret = 1;
843 }
844 err:
845 CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
846 CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
847 }
848
849 return ret;
850}