| 548 | } |
| 549 | |
| 550 | int anetFdToString(int fd, char *ip, size_t ip_len, int *port, int fd_to_str_type) { |
| 551 | struct sockaddr_storage sa; |
| 552 | socklen_t salen = sizeof(sa); |
| 553 | |
| 554 | if (fd_to_str_type == FD_TO_PEER_NAME) { |
| 555 | if (getpeername(fd, (struct sockaddr *)&sa, &salen) == -1) goto error; |
| 556 | } else { |
| 557 | if (getsockname(fd, (struct sockaddr *)&sa, &salen) == -1) goto error; |
| 558 | } |
| 559 | if (ip_len == 0) goto error; |
| 560 | |
| 561 | if (sa.ss_family == AF_INET) { |
| 562 | struct sockaddr_in *s = (struct sockaddr_in *)&sa; |
| 563 | if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len); |
| 564 | if (port) *port = ntohs(s->sin_port); |
| 565 | } else if (sa.ss_family == AF_INET6) { |
| 566 | struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa; |
| 567 | if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len); |
| 568 | if (port) *port = ntohs(s->sin6_port); |
| 569 | } else if (sa.ss_family == AF_UNIX) { |
| 570 | if (ip) snprintf(ip, ip_len, "/unixsocket"); |
| 571 | if (port) *port = 0; |
| 572 | } else { |
| 573 | goto error; |
| 574 | } |
| 575 | return 0; |
| 576 | |
| 577 | error: |
| 578 | if (ip) { |
| 579 | if (ip_len >= 2) { |
| 580 | ip[0] = '?'; |
| 581 | ip[1] = '\0'; |
| 582 | } else if (ip_len == 1) { |
| 583 | ip[0] = '\0'; |
| 584 | } |
| 585 | } |
| 586 | if (port) *port = 0; |
| 587 | return -1; |
| 588 | } |
| 589 | |
| 590 | /* Format an IP,port pair into something easy to parse. If IP is IPv6 |
| 591 | * (matches for ":"), the ip is surrounded by []. IP and port are just |
no test coverage detected