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