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 #ifdef HAVE_IPV6 242 return inet_pton(AF_INET, str, &saddr->ipv4.sin_addr); 243 #else 244 #if defined(HAVE_INET_ATON) /*(Windows does not provide inet_aton())*/ 245 return (0 != inet_aton(str, &saddr->ipv4.sin_addr)); 246 #else 247 return ((saddr->ipv4.sin_addr.s_addr = inet_addr(str)) != INADDR_NONE); 248 #endif 249 #endif 250 #ifdef HAVE_IPV6 251 case AF_INET6: 252 memset(&saddr->ipv6, 0, sizeof(struct sockaddr_in6)); 253 saddr->ipv6.sin6_family = AF_INET6; 254 saddr->ipv6.sin6_port = htons(port); 255 return inet_pton(AF_INET6, str, &saddr->ipv6.sin6_addr); 256 #endif 257 default: 258 errno = EAFNOSUPPORT; 259 return -1; 260 } 261 } 262 263 264 const char * sock_addr_inet_ntop(const sock_addr * const restrict saddr, char * const restrict buf, socklen_t sz) 265 { 266 switch (saddr->plain.sa_family) { 267 case AF_INET: 268 #if defined(HAVE_INET_PTON) /*(expect inet_ntop if inet_pton)*/ 269 return inet_ntop(AF_INET,(const void *)&saddr->ipv4.sin_addr,buf,sz); 270 #else /*(inet_ntoa() not thread-safe)*/ 271 return inet_ntoa(saddr->ipv4.sin_addr); 272 #endif 273 #ifdef HAVE_IPV6 274 case AF_INET6: 275 return inet_ntop(AF_INET6,(const void *)&saddr->ipv6.sin6_addr,buf,sz); 276 #endif 277 #ifdef HAVE_SYS_UN_H 278 case AF_UNIX: 279 return saddr->un.sun_path; 280 #endif 281 default: 282 errno = EAFNOSUPPORT; 283 return NULL; 284 } 285 } 286 287 288 int sock_addr_inet_ntop_copy_buffer(buffer * const restrict b, const sock_addr * const restrict saddr) 289 { 290 /*(incur cost of extra copy to avoid potential extra memory allocation)*/ 291 char buf[UNIX_PATH_MAX]; 292 const char *s = sock_addr_inet_ntop(saddr, buf, sizeof(buf)); 293 if (NULL == s) return -1; /*(buffer not modified if any error occurs)*/ 294 buffer_copy_string(b, s); 295 return 0; 296 } 297 298 299 int sock_addr_inet_ntop_append_buffer(buffer * const restrict b, const sock_addr * const restrict saddr) 300 { 301 /*(incur cost of extra copy to avoid potential extra memory allocation)*/ 302 char buf[UNIX_PATH_MAX]; 303 const char *s = sock_addr_inet_ntop(saddr, buf, sizeof(buf)); 304 if (NULL == s) return -1; /*(buffer not modified if any error occurs)*/ 305 buffer_append_string(b, s); 306 return 0; 307 } 308 309 int sock_addr_stringify_append_buffer(buffer * const restrict b, const sock_addr * const restrict saddr) 310 { 311 switch (saddr->plain.sa_family) { 312 case AF_INET: 313 if (0 != sock_addr_inet_ntop_append_buffer(b, saddr)) return -1; 314 buffer_append_string_len(b, CONST_STR_LEN(":")); 315 buffer_append_int(b, ntohs(saddr->ipv4.sin_port)); 316 return 0; 317 #ifdef HAVE_IPV6 318 case AF_INET6: 319 buffer_append_string_len(b, CONST_STR_LEN("[")); 320 if (0 != sock_addr_inet_ntop_append_buffer(b, saddr)) { 321 #ifdef __COVERITY__ 322 force_assert(buffer_string_length(b) > 0); /*(appended "[")*/ 323 #endif 324 /* coverity[overflow_sink : FALSE] */ 325 buffer_string_set_length(b, buffer_string_length(b)-1); 326 return -1; 327 } 328 buffer_append_string_len(b, CONST_STR_LEN("]:")); 329 buffer_append_int(b, ntohs(saddr->ipv6.sin6_port)); 330 return 0; 331 #endif 332 #ifdef HAVE_SYS_UN_H 333 case AF_UNIX: 334 buffer_append_string(b, saddr->un.sun_path); 335 return 0; 336 #endif 337 default: 338 return 0; 339 } 340 } 341 342 343 int sock_addr_nameinfo_append_buffer(buffer * const restrict b, const sock_addr * const restrict saddr, log_error_st * const restrict errh) 344 { 345 /*(this routine originates from 346 * http-header-glue.c:http_response_redirect_to_directory())*/ 347 /*(note: name resolution here is *blocking*)*/ 348 switch (saddr->plain.sa_family) { 349 #ifndef HAVE_IPV6 350 case AF_INET: 351 { 352 struct hostent *he = gethostbyaddr((char *)&saddr->ipv4.sin_addr, 353 sizeof(struct in_addr), AF_INET); 354 if (NULL == he) { 355 log_error(errh, __FILE__, __LINE__, 356 "NOTICE: gethostbyaddr failed: %d, using ip-address instead", 357 h_errno); 358 359 sock_addr_inet_ntop_append_buffer(b, saddr); 360 } else { 361 buffer_append_string(b, he->h_name); 362 } 363 return 0; 364 } 365 #else /* HAVE_IPV6 */ 366 case AF_INET: 367 { 368 char hbuf[256]; 369 int rc = getnameinfo((const struct sockaddr *)(&saddr->ipv4), 370 sizeof(saddr->ipv4), 371 hbuf, sizeof(hbuf), NULL, 0, 0); 372 if (0 != rc) { 373 log_error(errh, __FILE__, __LINE__, 374 "NOTICE: getnameinfo failed; using ip-address instead: %s", 375 gai_strerror(rc)); 376 377 sock_addr_inet_ntop_append_buffer(b, saddr); 378 } else { 379 buffer_append_string(b, hbuf); 380 } 381 return 0; 382 } 383 case AF_INET6: 384 { 385 char hbuf[256]; 386 int rc = getnameinfo((const struct sockaddr *)(&saddr->ipv6), 387 sizeof(saddr->ipv6), 388 hbuf, sizeof(hbuf), NULL, 0, 0); 389 if (0 != rc) { 390 log_error(errh, __FILE__, __LINE__, 391 "NOTICE: getnameinfo failed; using ip-address instead: %s", 392 gai_strerror(rc)); 393 394 buffer_append_string_len(b, CONST_STR_LEN("[")); 395 sock_addr_inet_ntop_append_buffer(b, saddr); 396 buffer_append_string_len(b, CONST_STR_LEN("]")); 397 } else { 398 buffer_append_string(b, hbuf); 399 } 400 return 0; 401 } 402 #endif 403 default: 404 log_error(errh, __FILE__, __LINE__, "ERROR: unsupported address-type"); 405 return -1; 406 } 407 } 408 409 410 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) 411 { 412 /*(note: name resolution here is *blocking*)*/ 413 switch(family) { 414 case AF_UNSPEC: 415 if (0 == strcmp(str, "localhost")) { 416 /*(special-case "localhost" to IPv4 127.0.0.1)*/ 417 memset(saddr, 0, sizeof(struct sockaddr_in)); 418 saddr->ipv4.sin_family = AF_INET; 419 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 420 saddr->ipv4.sin_port = htons(port); 421 *len = sizeof(struct sockaddr_in); 422 return 1; 423 } 424 #ifdef HAVE_IPV6 425 else { 426 struct addrinfo hints, *res; 427 int rc; 428 memset(&hints, 0, sizeof(hints)); 429 hints.ai_family = AF_UNSPEC; 430 hints.ai_socktype = SOCK_STREAM; 431 hints.ai_protocol = IPPROTO_TCP; 432 433 if (0 != (rc = getaddrinfo(str, NULL, &hints, &res))) { 434 log_error(errh, __FILE__, __LINE__, 435 "getaddrinfo failed: %s '%s'", gai_strerror(rc), str); 436 return 0; 437 } 438 439 memcpy(saddr, res->ai_addr, res->ai_addrlen); 440 freeaddrinfo(res); 441 if (AF_INET6 == saddr->plain.sa_family) { 442 saddr->ipv6.sin6_port = htons(port); 443 *len = sizeof(struct sockaddr_in6); 444 } 445 else { /* AF_INET */ 446 saddr->ipv4.sin_port = htons(port); 447 *len = sizeof(struct sockaddr_in); 448 } 449 return 1; 450 } 451 #else 452 __attribute_fallthrough__ 453 #endif 454 #ifdef HAVE_IPV6 455 case AF_INET6: 456 memset(saddr, 0, sizeof(struct sockaddr_in6)); 457 saddr->ipv6.sin6_family = AF_INET6; 458 if (0 == strcmp(str, "::")) { 459 saddr->ipv6.sin6_addr = in6addr_any; 460 } 461 else if (0 == strcmp(str, "::1")) { 462 saddr->ipv6.sin6_addr = in6addr_loopback; 463 } 464 else { 465 struct addrinfo hints, *res; 466 int rc; 467 468 memset(&hints, 0, sizeof(hints)); 469 470 hints.ai_family = AF_INET6; 471 hints.ai_socktype = SOCK_STREAM; 472 hints.ai_protocol = IPPROTO_TCP; 473 474 if (0 != (rc = getaddrinfo(str, NULL, &hints, &res))) { 475 hints.ai_family = AF_INET; 476 if ( 477 #ifdef EAI_ADDRFAMILY 478 EAI_ADDRFAMILY == rc && 479 #endif 480 0 == getaddrinfo(str, NULL, &hints, &res)) { 481 memcpy(saddr, res->ai_addr, res->ai_addrlen); 482 saddr->ipv4.sin_family = AF_INET; 483 saddr->ipv4.sin_port = htons(port); 484 *len = sizeof(struct sockaddr_in); 485 /*assert(*len == res->ai_addrlen);*/ 486 freeaddrinfo(res); 487 return 1; 488 } 489 490 log_error(errh, __FILE__, __LINE__, 491 "getaddrinfo failed: %s '%s'", gai_strerror(rc), str); 492 493 return 0; 494 } 495 496 memcpy(saddr, res->ai_addr, res->ai_addrlen); 497 freeaddrinfo(res); 498 } 499 saddr->ipv6.sin6_port = htons(port); 500 *len = sizeof(struct sockaddr_in6); 501 return 1; 502 #endif 503 case AF_INET: 504 memset(saddr, 0, sizeof(struct sockaddr_in)); 505 saddr->ipv4.sin_family = AF_INET; 506 if (0 == strcmp(str, "0.0.0.0")) { 507 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_ANY); 508 } 509 else if (0 == strcmp(str, "127.0.0.1")) { 510 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 511 } 512 else { 513 #ifdef HAVE_INET_PTON 514 /*(reuse HAVE_INET_PTON for presence of getaddrinfo())*/ 515 struct addrinfo hints, *res; 516 int rc; 517 memset(&hints, 0, sizeof(hints)); 518 hints.ai_family = AF_INET; 519 hints.ai_socktype = SOCK_STREAM; 520 hints.ai_protocol = IPPROTO_TCP; 521 522 if (0 != (rc = getaddrinfo(str, NULL, &hints, &res))) { 523 log_error(errh, __FILE__, __LINE__, 524 "getaddrinfo failed: %s '%s'", gai_strerror(rc), str); 525 return 0; 526 } 527 528 memcpy(saddr, res->ai_addr, res->ai_addrlen); 529 freeaddrinfo(res); 530 #else 531 struct hostent *he = gethostbyname(str); 532 if (NULL == he) { 533 log_error(errh, __FILE__, __LINE__, 534 "gethostbyname failed: %d %s", h_errno, str); 535 return 0; 536 } 537 538 if (he->h_addrtype != AF_INET) { 539 log_error(errh, __FILE__, __LINE__, 540 "addr-type != AF_INET: %d", he->h_addrtype); 541 return 0; 542 } 543 544 if (he->h_length != sizeof(struct in_addr)) { 545 log_error(errh, __FILE__, __LINE__, 546 "addr-length != sizeof(in_addr): %d", he->h_length); 547 return 0; 548 } 549 550 memcpy(&saddr->ipv4.sin_addr.s_addr, 551 he->h_addr_list[0], he->h_length); 552 #endif 553 } 554 saddr->ipv4.sin_port = htons(port); 555 *len = sizeof(struct sockaddr_in); 556 return 1; 557 #ifdef HAVE_SYS_UN_H 558 case AF_UNIX: 559 memset(saddr, 0, sizeof(struct sockaddr_un)); 560 saddr->un.sun_family = AF_UNIX; 561 { 562 size_t hostlen = strlen(str) + 1; 563 if (hostlen > sizeof(saddr->un.sun_path)) { 564 log_error(errh, __FILE__, __LINE__, 565 "unix socket filename too long: %s", str); 566 /*errno = ENAMETOOLONG;*/ 567 return 0; 568 } 569 memcpy(saddr->un.sun_path, str, hostlen); 570 #if defined(SUN_LEN) 571 *len = SUN_LEN(&saddr->un)+1; 572 #else 573 *len = offsetof(struct sockaddr_un, sun_path) + hostlen; 574 #endif 575 } 576 return 1; 577 #else 578 case AF_UNIX: 579 log_error(errh, __FILE__, __LINE__, 580 "unix domain sockets are not supported."); 581 return 0; 582 #endif 583 default: 584 log_error(errh, __FILE__, __LINE__, 585 "address family unsupported: %d", family); 586 /*errno = EAFNOSUPPORT;*/ 587 return 0; 588 } 589 } 590 591 592 int sock_addr_from_str_numeric(sock_addr * const restrict saddr, const char * const restrict str, log_error_st * const restrict errh) 593 { 594 /*(note: does not handle port if getaddrinfo() is not available)*/ 595 /*(note: getaddrinfo() is stricter than inet_aton() in what is accepted)*/ 596 /*(this routine originates from mod_extforward.c:ipstr_to_sockaddr()*/ 597 #ifdef HAVE_IPV6 598 struct addrinfo hints, *addrlist = NULL; 599 int result; 600 601 /** 602 * quoting $ man getaddrinfo 603 * 604 * NOTES 605 * AI_ADDRCONFIG, AI_ALL, and AI_V4MAPPED are available since glibc 2.3.3. 606 * AI_NUMERICSERV is available since glibc 2.3.4. 607 */ 608 #ifndef AI_NUMERICSERV 609 #define AI_NUMERICSERV 0 610 #endif 611 memset(&hints, 0, sizeof(hints)); 612 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; 613 614 errno = 0; 615 result = getaddrinfo(str, NULL, &hints, &addrlist); 616 617 if (result != 0) { 618 log_perror(errh, __FILE__, __LINE__, 619 "could not parse ip address %s because %s", 620 str, gai_strerror(result)); 621 return result; 622 } else if (addrlist == NULL) { 623 log_error(errh, __FILE__, __LINE__, 624 "Problem in parsing ip address %s:" 625 "succeeded, but no information returned", str); 626 return -1; 627 } else switch (addrlist->ai_family) { 628 case AF_INET: 629 memcpy(&saddr->ipv4, addrlist->ai_addr, sizeof(saddr->ipv4)); 630 force_assert(AF_INET == saddr->plain.sa_family); 631 break; 632 case AF_INET6: 633 memcpy(&saddr->ipv6, addrlist->ai_addr, sizeof(saddr->ipv6)); 634 force_assert(AF_INET6 == saddr->plain.sa_family); 635 break; 636 default: 637 log_error(errh, __FILE__, __LINE__, 638 "Problem in parsing ip address %s:" 639 "succeeded, but unknown family", str); 640 result = -1; 641 break; 642 } 643 644 freeaddrinfo(addrlist); 645 return (0 == result); 646 #else 647 UNUSED(errh); 648 saddr->ipv4.sin_addr.s_addr = inet_addr(str); 649 saddr->plain.sa_family = AF_INET; 650 return (saddr->ipv4.sin_addr.s_addr != 0xFFFFFFFF); 651 #endif 652 } 653 654 655 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) 656 { 657 /*(this routine originates from mod_fastcgi.c and mod_scgi.c)*/ 658 if (buffer_string_is_empty(b)) { 659 /*(preserve existing behavior (for now))*/ 660 /*(would be better if initialized default when reading config)*/ 661 memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in)); 662 saddr->ipv4.sin_family = AF_INET; 663 saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 664 saddr->ipv4.sin_port = htons(port); 665 *len = sizeof(struct sockaddr_in); 666 return 1; 667 } 668 else if (1 == sock_addr_inet_pton(saddr, b->ptr, family, port)) { 669 *len = (family == AF_INET) 670 ? sizeof(struct sockaddr_in) /* family == AF_INET */ 671 : sizeof(struct sockaddr_in6); /* family == AF_INET6 */ 672 return 1; 673 } 674 #if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) 675 else if (family == AF_INET6) { 676 log_error(errh, __FILE__, __LINE__, 677 "invalid IPv6 address literal: %s", b->ptr); 678 return 0; 679 } 680 #endif 681 #ifndef HAVE_INET_PTON /*(preserve existing behavior (for now))*/ 682 else { 683 struct hostent *he = gethostbyname(b->ptr); 684 if (NULL == he) { 685 log_error(errh, __FILE__, __LINE__, 686 "gethostbyname failed: %d %s", h_errno, b->ptr); 687 return 0; 688 } 689 690 if (he->h_addrtype != AF_INET) { 691 log_error(errh, __FILE__, __LINE__, 692 "addr-type != AF_INET: %d", he->h_addrtype); 693 return 0; 694 } 695 696 if (he->h_length != sizeof(struct in_addr)) { 697 log_error(errh, __FILE__, __LINE__, 698 "addr-length != sizeof(in_addr): %d", he->h_length); 699 return 0; 700 } 701 702 memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in)); 703 memcpy(&saddr->ipv4.sin_addr.s_addr, he->h_addr_list[0], he->h_length); 704 saddr->ipv4.sin_family = AF_INET; 705 saddr->ipv4.sin_port = htons(port); 706 *len = sizeof(struct sockaddr_in); 707 } 708 #else 709 UNUSED(errh); 710 #endif 711 712 return 0; 713 } 714