1 /* 2 * sock_addr - sockaddr manipulation 3 * 4 * Copyright(c) 2017 Glenn Strauss gstrauss()gluelogic.com All rights reserved 5 * License: BSD 3-clause (same as lighttpd) 6 */ 7 #include "first.h" 8 9 #include "sock_addr.h" 10 11 #include "sys-socket.h" 12 #include <sys/types.h> 13 #include <errno.h> 14 #include <string.h> 15 #ifndef _WIN32 16 #include <netdb.h> 17 #include <arpa/inet.h> 18 #endif 19 20 #include "log.h" 21 22 23 unsigned short sock_addr_get_port (const sock_addr *saddr) 24 { 25 switch (saddr->plain.sa_family) { 26 case AF_INET: 27 return ntohs(saddr->ipv4.sin_port); 28 #ifdef HAVE_IPV6 29 case AF_INET6: 30 return ntohs(saddr->ipv6.sin6_port); 31 #endif 32 #ifdef HAVE_SYS_UN_H 33 /*case AF_UNIX:*/ 34 #endif 35 default: 36 return 0; 37 } 38 } 39 40 41 int sock_addr_is_addr_wildcard (const sock_addr *saddr) 42 { 43 switch (saddr->plain.sa_family) { 44 case AF_INET: 45 return (saddr->ipv4.sin_addr.s_addr == INADDR_ANY); /*(htonl(0x0))*/ 46 #ifdef HAVE_IPV6 47 case AF_INET6: 48 return !memcmp(&saddr->ipv6.sin6_addr,&in6addr_any,sizeof(in6addr_any)); 49 #endif 50 #ifdef HAVE_SYS_UN_H 51 /*case AF_UNIX:*/ 52 #endif 53 default: 54 return 0; 55 } 56 } 57 58 59 int sock_addr_is_family_eq (const sock_addr *saddr1, const sock_addr *saddr2) 60 { 61 return saddr1->plain.sa_family == saddr2->plain.sa_family; 62 } 63 64 65 int sock_addr_is_port_eq (const sock_addr *saddr1, const sock_addr *saddr2) 66 { 67 if (!sock_addr_is_family_eq(saddr1, saddr2)) return 0; 68 switch (saddr1->plain.sa_family) { 69 case AF_INET: 70 return saddr1->ipv4.sin_port == saddr2->ipv4.sin_port; 71 #ifdef HAVE_IPV6 72 case AF_INET6: 73 return saddr1->ipv6.sin6_port == saddr2->ipv6.sin6_port; 74 #endif 75 #ifdef HAVE_SYS_UN_H 76 case AF_UNIX: 77 return 1; 78 #endif 79 default: 80 return 0; 81 } 82 } 83 84 85 int sock_addr_is_addr_eq (const sock_addr *saddr1, const sock_addr *saddr2) 86 { 87 if (!sock_addr_is_family_eq(saddr1, saddr2)) return 0; 88 switch (saddr1->plain.sa_family) { 89 case AF_INET: 90 return saddr1->ipv4.sin_addr.s_addr == saddr2->ipv4.sin_addr.s_addr; 91 #ifdef HAVE_IPV6 92 case AF_INET6: 93 return 0 == memcmp(&saddr1->ipv6.sin6_addr, &saddr2->ipv6.sin6_addr, 94 sizeof(struct in6_addr)); 95 #endif 96 #ifdef HAVE_SYS_UN_H 97 case AF_UNIX: 98 return 0 == strcmp(saddr1->un.sun_path, saddr2->un.sun_path); 99 #endif 100 default: 101 return 0; 102 } 103 } 104 105 106 #if 0 107 int sock_addr_is_addr_port_eq (const sock_addr *saddr1, const sock_addr *saddr2) 108 { 109 if (!sock_addr_is_family_eq(saddr1, saddr2)) return 0; 110 switch (saddr1->plain.sa_family) { 111 case AF_INET: 112 return saddr1->ipv4.sin_port == saddr2->ipv4.sin_port 113 && saddr1->ipv4.sin_addr.s_addr == saddr2->ipv4.sin_addr.s_addr; 114 #ifdef HAVE_IPV6 115 case AF_INET6: 116 return saddr1->ipv6.sin6_port == saddr2->ipv6.sin6_port 117 && 0 == memcmp(&saddr1->ipv6.sin6_addr, &saddr2->ipv6.sin6_addr, 118 sizeof(struct in6_addr)); 119 #endif 120 #ifdef HAVE_SYS_UN_H 121 case AF_UNIX: 122 return 0 == strcmp(saddr1->un.sun_path, saddr2->un.sun_path); 123 #endif 124 default: 125 return 0; 126 } 127 } 128 #endif 129 130 131 int sock_addr_is_addr_eq_bits(const sock_addr *a, const sock_addr *b, int bits) { 132 switch (a->plain.sa_family) { 133 case AF_INET: 134 { 135 uint32_t nm; /* build netmask */ 136 if (bits > 32) bits = 32; 137 nm = htonl(~((1u << (32 - (0 != bits ? bits : 32))) - 1)); 138 if (b->plain.sa_family == AF_INET) { 139 return 140 (a->ipv4.sin_addr.s_addr & nm) == (b->ipv4.sin_addr.s_addr & nm); 141 } 142 #ifdef HAVE_IPV6 143 else if (b->plain.sa_family == AF_INET6 144 && IN6_IS_ADDR_V4MAPPED(&b->ipv6.sin6_addr)) { 145 #ifdef s6_addr32 146 in_addr_t x = b->ipv6.sin6_addr.s6_addr32[3]; 147 #else 148 in_addr_t x; 149 memcpy(&x, b->ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t)); 150 #endif 151 return ((a->ipv4.sin_addr.s_addr & nm) == (x & nm)); 152 } 153 #endif 154 return 0; 155 } 156 #ifdef HAVE_IPV6 157 case AF_INET6: 158 if (bits > 128) bits = 128; 159 if (b->plain.sa_family == AF_INET6) { 160 uint8_t *c = (uint8_t *)&a->ipv6.sin6_addr.s6_addr[0]; 161 uint8_t *d = (uint8_t *)&b->ipv6.sin6_addr.s6_addr[0]; 162 int match; 163 do { 164 match = (bits >= 8) 165 ? *c++ == *d++ 166 : (*c >> (8 - bits)) == (*d >> (8 - bits)); 167 } while (match && (bits -= 8) > 0); 168 return match; 169 } 170 else if (b->plain.sa_family == AF_INET 171 && IN6_IS_ADDR_V4MAPPED(&a->ipv6.sin6_addr)) { 172 uint32_t nm = bits < 128 173 ? htonl(~(~0u >> (bits > 96 ? bits - 96 : 0))) 174 : ~0u; 175 #ifdef s6_addr32 176 in_addr_t x = a->ipv6.sin6_addr.s6_addr32[3]; 177 #else 178 in_addr_t x; 179 memcpy(&x, a->ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t)); 180 #endif 181 return ((x & nm) == (b->ipv4.sin_addr.s_addr & nm)); 182 } 183 return 0; 184 #endif 185 #ifdef HAVE_SYS_UN_H 186 /*case AF_UNIX:*/ 187 #endif 188 default: 189 return 0; 190 } 191 } 192 193 194 int sock_addr_assign (sock_addr * const restrict saddr, int family, unsigned short nport, const void * const restrict naddr) 195 { 196 switch (family) { 197 case AF_INET: 198 memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in)); 199 saddr->ipv4.sin_family = AF_INET; 200 saddr->ipv4.sin_port = nport; 201 memcpy(&saddr->ipv4.sin_addr, naddr, 4); 202 return 0; 203 #ifdef HAVE_IPV6 204 case AF_INET6: 205 memset(&saddr->ipv6, 0, sizeof(struct sockaddr_in6)); 206 saddr->ipv6.sin6_family = AF_INET6; 207 saddr->ipv6.sin6_port = nport; 208 memcpy(&saddr->ipv6.sin6_addr, naddr, 16); 209 return 0; 210 #endif 211 #ifdef HAVE_SYS_UN_H 212 case AF_UNIX: 213 { 214 size_t len = strlen((char *)naddr) + 1; 215 if (len > sizeof(saddr->un.sun_path)) { 216 errno = ENAMETOOLONG; 217 return -1; 218 } 219 memset(&saddr->un, 0, sizeof(struct sockaddr_un)); 220 saddr->un.sun_family = AF_UNIX; 221 memcpy(saddr->un.sun_path, naddr, len); 222 return 0; 223 } 224 #endif 225 default: 226 errno = EAFNOSUPPORT; 227 return -1; 228 } 229 } 230 231 232 int sock_addr_inet_pton(sock_addr * const restrict saddr, 233 const char * const restrict str, 234 int family, unsigned short port) 235 { 236 switch (family) { 237 case AF_INET: 238 memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in)); 239 saddr->ipv4.sin_family = AF_INET; 240 saddr->ipv4.sin_port = htons(port); 241 #if defined(HAVE_INET_ATON) /*(Windows does not provide inet_aton())*/ 242 return (0 != inet_aton(str, &saddr->ipv4.sin_addr)); 243 #else 244 return ((saddr->ipv4.sin_addr.s_addr = inet_addr(str)) != INADDR_NONE); 245 #endif 246 #ifdef HAVE_IPV6 247 case AF_INET6: 248 memset(&saddr->ipv6, 0, sizeof(struct sockaddr_in6)); 249 saddr->ipv6.sin6_family = AF_INET6; 250 saddr->ipv6.sin6_port = htons(port); 251 return inet_pton(AF_INET6, str, &saddr->ipv6.sin6_addr); 252 #endif 253 default: 254 errno = EAFNOSUPPORT; 255 return -1; 256 } 257 } 258 259 260 const char * sock_addr_inet_ntop(const sock_addr * const restrict saddr, char * const restrict buf, socklen_t sz) 261 { 262 switch (saddr->plain.sa_family) { 263 case AF_INET: 264 #if defined(HAVE_INET_PTON) /*(expect inet_ntop if inet_pton)*/ 265 return inet_ntop(AF_INET,(const void *)&saddr->ipv4.sin_addr,buf,sz); 266 #else /*(inet_ntoa() not thread-safe)*/ 267 return inet_ntoa(saddr->ipv4.sin_addr); 268 #endif 269 #ifdef HAVE_IPV6 270 case AF_INET6: 271 return inet_ntop(AF_INET6,(const void *)&saddr->ipv6.sin6_addr,buf,sz); 272 #endif 273 #ifdef HAVE_SYS_UN_H 274 case AF_UNIX: 275 return saddr->un.sun_path; 276 #endif 277 default: 278 errno = EAFNOSUPPORT; 279 return NULL; 280 } 281 } 282 283 284 int sock_addr_inet_ntop_copy_buffer(buffer * const restrict b, const sock_addr * const restrict saddr) 285 { 286 /*(incur cost of extra copy to avoid potential extra memory allocation)*/ 287 char buf[UNIX_PATH_MAX]; 288 const char *s = sock_addr_inet_ntop(saddr, buf, sizeof(buf)); 289 if (NULL == s) return -1; /*(buffer not modified if any error occurs)*/ 290 buffer_copy_string(b, s); 291 return 0; 292 } 293 294 295 int sock_addr_inet_ntop_append_buffer(buffer * const restrict b, const sock_addr * const restrict saddr) 296 { 297 /*(incur cost of extra copy to avoid potential extra memory allocation)*/ 298 char buf[UNIX_PATH_MAX]; 299 const char *s = sock_addr_inet_ntop(saddr, buf, sizeof(buf)); 300 if (NULL == s) return -1; /*(buffer not modified if any error occurs)*/ 301 buffer_append_string(b, s); 302 return 0; 303 } 304 305 int sock_addr_stringify_append_buffer(buffer * const restrict b, const sock_addr * const restrict saddr) 306 { 307 switch (saddr->plain.sa_family) { 308 case AF_INET: 309 if (0 != sock_addr_inet_ntop_append_buffer(b, saddr)) return -1; 310 buffer_append_string_len(b, CONST_STR_LEN(":")); 311 buffer_append_int(b, ntohs(saddr->ipv4.sin_port)); 312 return 0; 313 #ifdef HAVE_IPV6 314 case AF_INET6: 315 buffer_append_string_len(b, CONST_STR_LEN("[")); 316 if (0 != sock_addr_inet_ntop_append_buffer(b, saddr)) { 317 #ifdef __COVERITY__ 318 force_assert(buffer_string_length(b) > 0); /*(appended "[")*/ 319 #endif 320 /* coverity[overflow_sink : FALSE] */ 321 buffer_string_set_length(b, buffer_string_length(b)-1); 322 return -1; 323 } 324 buffer_append_string_len(b, CONST_STR_LEN("]")); 325 buffer_append_string_len(b, CONST_STR_LEN(":")); 326 buffer_append_int(b, ntohs(saddr->ipv6.sin6_port)); 327 return 0; 328 #endif 329 #ifdef HAVE_SYS_UN_H 330 case AF_UNIX: 331 buffer_append_string(b, saddr->un.sun_path); 332 return 0; 333 #endif 334 default: 335 return 0; 336 } 337 } 338 339 340 int sock_addr_nameinfo_append_buffer(buffer * const restrict b, const sock_addr * const restrict saddr, log_error_st * const restrict errh) 341 { 342 /*(this routine originates from 343 * http-header-glue.c:http_response_redirect_to_directory())*/ 344 /*(note: name resolution here is *blocking*)*/ 345 switch (saddr->plain.sa_family) { 346 case AF_INET: 347 { 348 struct hostent *he = gethostbyaddr((char *)&saddr->ipv4.sin_addr, 349 sizeof(struct in_addr), AF_INET); 350 if (NULL == he) { 351 log_error(errh, __FILE__, __LINE__, 352 "NOTICE: gethostbyaddr failed: %d, using ip-address instead", 353 h_errno); 354 355 sock_addr_inet_ntop_append_buffer(b, saddr); 356 } else { 357 buffer_append_string(b, he->h_name); 358 } 359 return 0; 360 } 361 #ifdef HAVE_IPV6 362 case AF_INET6: 363 { 364 char hbuf[256]; 365 if (0 != getnameinfo((const struct sockaddr *)(&saddr->ipv6), 366 sizeof(saddr->ipv6), 367 hbuf, sizeof(hbuf), NULL, 0, 0)) { 368 log_perror(errh, __FILE__, __LINE__, 369 "NOTICE: getnameinfo failed; using ip-address instead"); 370 371 buffer_append_string_len(b, CONST_STR_LEN("[")); 372 sock_addr_inet_ntop_append_buffer(b, saddr); 373 buffer_append_string_len(b, CONST_STR_LEN("]")); 374 } else { 375 buffer_append_string(b, hbuf); 376 } 377 return 0; 378 } 379 #endif 380 default: 381 log_error(errh, __FILE__, __LINE__, "ERROR: unsupported address-type"); 382 return -1; 383 } 384 } 385 386 387 int sock_addr_from_str_hints(sock_addr * const restrict saddr, socklen_t * const restrict len, const char * const restrict str, int family, unsigned short port, log_error_st * const restrict errh) 388 { 389 /*(note: name resolution here is *blocking*)*/ 390 switch(family) { 391 case AF_UNSPEC: 392 if (0 == strcmp(str, "localhost")) { 393 /*(special-case "localhost" to IPv4 127.0.0.1)*/ 394 memset(saddr, 0, sizeof(struct sockaddr_in)); 395 saddr->ipv4.sin_family = AF_INET; 396 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 397 saddr->ipv4.sin_port = htons(port); 398 *len = sizeof(struct sockaddr_in); 399 return 1; 400 } 401 #ifdef HAVE_IPV6 402 else { 403 struct addrinfo hints, *res; 404 int rc; 405 memset(&hints, 0, sizeof(hints)); 406 hints.ai_family = AF_UNSPEC; 407 hints.ai_socktype = SOCK_STREAM; 408 hints.ai_protocol = IPPROTO_TCP; 409 410 if (0 != (rc = getaddrinfo(str, NULL, &hints, &res))) { 411 log_error(errh, __FILE__, __LINE__, 412 "getaddrinfo failed: %s '%s'", gai_strerror(rc), str); 413 return 0; 414 } 415 416 memcpy(saddr, res->ai_addr, res->ai_addrlen); 417 freeaddrinfo(res); 418 if (AF_INET6 == saddr->plain.sa_family) { 419 saddr->ipv6.sin6_port = htons(port); 420 *len = sizeof(struct sockaddr_in6); 421 } 422 else { /* AF_INET */ 423 saddr->ipv4.sin_port = htons(port); 424 *len = sizeof(struct sockaddr_in); 425 } 426 return 1; 427 } 428 #else 429 /* fall through */ 430 #endif 431 #ifdef HAVE_IPV6 432 case AF_INET6: 433 memset(saddr, 0, sizeof(struct sockaddr_in6)); 434 saddr->ipv6.sin6_family = AF_INET6; 435 if (0 == strcmp(str, "::")) { 436 saddr->ipv6.sin6_addr = in6addr_any; 437 } 438 else if (0 == strcmp(str, "::1")) { 439 saddr->ipv6.sin6_addr = in6addr_loopback; 440 } 441 else { 442 struct addrinfo hints, *res; 443 int rc; 444 445 memset(&hints, 0, sizeof(hints)); 446 447 hints.ai_family = AF_INET6; 448 hints.ai_socktype = SOCK_STREAM; 449 hints.ai_protocol = IPPROTO_TCP; 450 451 if (0 != (rc = getaddrinfo(str, NULL, &hints, &res))) { 452 hints.ai_family = AF_INET; 453 if ( 454 #ifdef EAI_ADDRFAMILY 455 EAI_ADDRFAMILY == rc && 456 #endif 457 0 == getaddrinfo(str, NULL, &hints, &res)) { 458 memcpy(saddr, res->ai_addr, res->ai_addrlen); 459 saddr->ipv4.sin_family = AF_INET; 460 saddr->ipv4.sin_port = htons(port); 461 *len = sizeof(struct sockaddr_in); 462 /*assert(*len == res->ai_addrlen);*/ 463 freeaddrinfo(res); 464 return 1; 465 } 466 467 log_error(errh, __FILE__, __LINE__, 468 "getaddrinfo failed: %s '%s'", gai_strerror(rc), str); 469 470 return 0; 471 } 472 473 memcpy(saddr, res->ai_addr, res->ai_addrlen); 474 freeaddrinfo(res); 475 } 476 saddr->ipv6.sin6_port = htons(port); 477 *len = sizeof(struct sockaddr_in6); 478 return 1; 479 #endif 480 case AF_INET: 481 memset(saddr, 0, sizeof(struct sockaddr_in)); 482 saddr->ipv4.sin_family = AF_INET; 483 if (0 == strcmp(str, "0.0.0.0")) { 484 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_ANY); 485 } 486 else if (0 == strcmp(str, "127.0.0.1")) { 487 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 488 } 489 else { 490 #ifdef HAVE_INET_PTON 491 /*(reuse HAVE_INET_PTON for presence of getaddrinfo())*/ 492 struct addrinfo hints, *res; 493 int rc; 494 memset(&hints, 0, sizeof(hints)); 495 hints.ai_family = AF_INET; 496 hints.ai_socktype = SOCK_STREAM; 497 hints.ai_protocol = IPPROTO_TCP; 498 499 if (0 != (rc = getaddrinfo(str, NULL, &hints, &res))) { 500 log_error(errh, __FILE__, __LINE__, 501 "getaddrinfo failed: %s '%s'", gai_strerror(rc), str); 502 return 0; 503 } 504 505 memcpy(saddr, res->ai_addr, res->ai_addrlen); 506 freeaddrinfo(res); 507 #else 508 struct hostent *he = gethostbyname(str); 509 if (NULL == he) { 510 log_error(errh, __FILE__, __LINE__, 511 "gethostbyname failed: %d %s", h_errno, str); 512 return 0; 513 } 514 515 if (he->h_addrtype != AF_INET) { 516 log_error(errh, __FILE__, __LINE__, 517 "addr-type != AF_INET: %d", he->h_addrtype); 518 return 0; 519 } 520 521 if (he->h_length != sizeof(struct in_addr)) { 522 log_error(errh, __FILE__, __LINE__, 523 "addr-length != sizeof(in_addr): %d", he->h_length); 524 return 0; 525 } 526 527 memcpy(&saddr->ipv4.sin_addr.s_addr, 528 he->h_addr_list[0], he->h_length); 529 #endif 530 } 531 saddr->ipv4.sin_port = htons(port); 532 *len = sizeof(struct sockaddr_in); 533 return 1; 534 #ifdef HAVE_SYS_UN_H 535 case AF_UNIX: 536 memset(saddr, 0, sizeof(struct sockaddr_un)); 537 saddr->un.sun_family = AF_UNIX; 538 { 539 size_t hostlen = strlen(str) + 1; 540 if (hostlen > sizeof(saddr->un.sun_path)) { 541 log_error(errh, __FILE__, __LINE__, 542 "unix socket filename too long: %s", str); 543 /*errno = ENAMETOOLONG;*/ 544 return 0; 545 } 546 memcpy(saddr->un.sun_path, str, hostlen); 547 #if defined(SUN_LEN) 548 *len = SUN_LEN(&saddr->un)+1; 549 #else 550 *len = offsetof(struct sockaddr_un, sun_path) + hostlen; 551 #endif 552 } 553 return 1; 554 #else 555 case AF_UNIX: 556 log_error(errh, __FILE__, __LINE__, 557 "unix domain sockets are not supported."); 558 return 0; 559 #endif 560 default: 561 log_error(errh, __FILE__, __LINE__, 562 "address family unsupported: %d", family); 563 /*errno = EAFNOSUPPORT;*/ 564 return 0; 565 } 566 } 567 568 569 int sock_addr_from_str_numeric(sock_addr * const restrict saddr, const char * const restrict str, log_error_st * const restrict errh) 570 { 571 /*(note: does not handle port if getaddrinfo() is not available)*/ 572 /*(note: getaddrinfo() is stricter than inet_aton() in what is accepted)*/ 573 /*(this routine originates from mod_extforward.c:ipstr_to_sockaddr()*/ 574 #ifdef HAVE_IPV6 575 struct addrinfo hints, *addrlist = NULL; 576 int result; 577 578 /** 579 * quoting $ man getaddrinfo 580 * 581 * NOTES 582 * AI_ADDRCONFIG, AI_ALL, and AI_V4MAPPED are available since glibc 2.3.3. 583 * AI_NUMERICSERV is available since glibc 2.3.4. 584 */ 585 #ifndef AI_NUMERICSERV 586 #define AI_NUMERICSERV 0 587 #endif 588 memset(&hints, 0, sizeof(hints)); 589 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; 590 591 errno = 0; 592 result = getaddrinfo(str, NULL, &hints, &addrlist); 593 594 if (result != 0) { 595 log_perror(errh, __FILE__, __LINE__, 596 "could not parse ip address %s because %s", 597 str, gai_strerror(result)); 598 return result; 599 } else if (addrlist == NULL) { 600 log_error(errh, __FILE__, __LINE__, 601 "Problem in parsing ip address %s:" 602 "succeeded, but no information returned", str); 603 return -1; 604 } else switch (addrlist->ai_family) { 605 case AF_INET: 606 memcpy(&saddr->ipv4, addrlist->ai_addr, sizeof(saddr->ipv4)); 607 force_assert(AF_INET == saddr->plain.sa_family); 608 break; 609 case AF_INET6: 610 memcpy(&saddr->ipv6, addrlist->ai_addr, sizeof(saddr->ipv6)); 611 force_assert(AF_INET6 == saddr->plain.sa_family); 612 break; 613 default: 614 log_error(errh, __FILE__, __LINE__, 615 "Problem in parsing ip address %s:" 616 "succeeded, but unknown family", str); 617 result = -1; 618 break; 619 } 620 621 freeaddrinfo(addrlist); 622 return (0 == result); 623 #else 624 UNUSED(errh); 625 saddr->ipv4.sin_addr.s_addr = inet_addr(str); 626 saddr->plain.sa_family = AF_INET; 627 return (saddr->ipv4.sin_addr.s_addr != 0xFFFFFFFF); 628 #endif 629 } 630 631 632 int sock_addr_from_buffer_hints_numeric(sock_addr * const restrict saddr, socklen_t * const restrict len, const buffer * const restrict b, int family, unsigned short port, log_error_st * const restrict errh) 633 { 634 /*(this routine originates from mod_fastcgi.c and mod_scgi.c)*/ 635 if (buffer_string_is_empty(b)) { 636 /*(preserve existing behavior (for now))*/ 637 /*(would be better if initialized default when reading config)*/ 638 memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in)); 639 saddr->ipv4.sin_family = AF_INET; 640 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 641 saddr->ipv4.sin_port = htons(port); 642 *len = sizeof(struct sockaddr_in); 643 return 1; 644 } 645 else if (1 == sock_addr_inet_pton(saddr, b->ptr, family, port)) { 646 *len = (family == AF_INET) 647 ? sizeof(struct sockaddr_in) /* family == AF_INET */ 648 : sizeof(struct sockaddr_in6); /* family == AF_INET6 */ 649 return 1; 650 } 651 #if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) 652 else if (family == AF_INET6) { 653 log_error(errh, __FILE__, __LINE__, 654 "invalid IPv6 address literal: %s", b->ptr); 655 return 0; 656 } 657 #endif 658 #ifndef HAVE_INET_PTON /*(preserve existing behavior (for now))*/ 659 else { 660 struct hostent *he = gethostbyname(b->ptr); 661 if (NULL == he) { 662 log_error(errh, __FILE__, __LINE__, 663 "gethostbyname failed: %d %s", h_errno, b->ptr); 664 return 0; 665 } 666 667 if (he->h_addrtype != AF_INET) { 668 log_error(errh, __FILE__, __LINE__, 669 "addr-type != AF_INET: %d", he->h_addrtype); 670 return 0; 671 } 672 673 if (he->h_length != sizeof(struct in_addr)) { 674 log_error(errh, __FILE__, __LINE__, 675 "addr-length != sizeof(in_addr): %d", he->h_length); 676 return 0; 677 } 678 679 memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in)); 680 memcpy(&saddr->ipv4.sin_addr.s_addr, he->h_addr_list[0], he->h_length); 681 saddr->ipv4.sin_family = AF_INET; 682 saddr->ipv4.sin_port = htons(port); 683 *len = sizeof(struct sockaddr_in); 684 } 685 #else 686 UNUSED(errh); 687 #endif 688 689 return 0; 690 } 691