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