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