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