From 23191d34b51ae03d223186134daf928194ae36a2 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Wed, 22 May 2024 17:55:50 +0900 Subject: [PATCH] Fix to get peer ip address If we try to read the IP address from a struct sockaddr_in while getpeername() filled it with struct sockaddr_in6 information, we are actually reading the sin6_flowinfo part of the struct sockaddr_in6. That flow information is usually zero, unless the connection is explicitely flagged with a flow ID. So we would read a zeroed IP address. Reference: https://stackoverflow.com/a/25640794 AS-IS root@42dot-ak7:~# bluechictl status NODE | STATE | IP | LAST SEEN ========================================================================================== ak7_master_main | online | 0.0.0.0 | now ak7_master_sub | online | 0.0.0.0 | now TO-BE root@42dot-ak7:~# bluechictl status NODE | STATE | IP | LAST SEEN ========================================================================================== ak7_master_main | online | ::ffff:192.168.16.103 | now ak7_master_sub | online | ::ffff:192.168.16.104 | now Signed-off-by: Joonyoung Shim --- src/client/method-status.c | 4 +-- src/controller/node.c | 2 +- src/libbluechi/bus/bus.c | 51 +++++++++++++++++++------------------- src/libbluechi/bus/bus.h | 2 +- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/client/method-status.c b/src/client/method-status.c index 11855a3ba0..4d8279dcdb 100644 --- a/src/client/method-status.c +++ b/src/client/method-status.c @@ -540,14 +540,14 @@ static void print_nodes(Nodes *nodes, bool clear_screen) { } /* print monitor header */ - printf("%-30.30s| %-10.10s| %-15.15s| %-28.28s\n", "NODE", "STATE", "IP", "LAST SEEN"); + printf("%-30.30s| %-10.10s| %-24.24s| %-28.28s\n", "NODE", "STATE", "IP", "LAST SEEN"); printf("==========================================================================================\n"); Node *curr = NULL; Node *next = NULL; LIST_FOREACH_SAFE(nodes, curr, next, nodes->nodes) { _cleanup_free_ char *last_seen = node_connection_fmt_last_seen(curr->connection); - printf("%-30.30s| %-10.10s| %-15.15s| %-28.28s\n", + printf("%-30.30s| %-10.10s| %-24.24s| %-28.28s\n", curr->connection->name, curr->connection->state, curr->connection->ip, diff --git a/src/controller/node.c b/src/controller/node.c index 864242468e..ccf155794e 100644 --- a/src/controller/node.c +++ b/src/controller/node.c @@ -645,7 +645,7 @@ bool node_set_agent_bus(Node *node, sd_bus *bus) { // If getting peer IP fails, only log and proceed as normal. _cleanup_free_ char *peer_ip = NULL; uint16_t peer_port = 0; - r = get_peer_address(node->agent_bus, false, &peer_ip, &peer_port); + r = get_peer_address(node->agent_bus, &peer_ip, &peer_port); if (r < 0) { bc_log_errorf("Failed to get peer IP: %s", strerror(-r)); } else { diff --git a/src/libbluechi/bus/bus.c b/src/libbluechi/bus/bus.c index a96f38a046..f4a6eca611 100644 --- a/src/libbluechi/bus/bus.c +++ b/src/libbluechi/bus/bus.c @@ -294,43 +294,42 @@ sd_bus *user_bus_open(sd_event *event) { } -int get_peer_address(sd_bus *bus, bool ipv6, char **ret_address, uint16_t *ret_port) { +int get_peer_address(sd_bus *bus, char **ret_address, uint16_t *ret_port) { int fd = sd_bus_get_fd(bus); if (fd < 0) { bc_log_errorf("Failed to file descriptor from bus: %s", strerror(-fd)); return fd; } - if (ipv6) { - struct sockaddr_in6 addr = { 0 }; - socklen_t len = sizeof(addr); - int r = getpeername(fd, (struct sockaddr *) &addr, &len); - if (r < 0) { - bc_log_errorf("Failed to get peer ipv6 address: %s", strerror(errno)); - return -errno; - } - if (ret_address != NULL) { - *ret_address = typesafe_inet_ntop6(&addr); - } - if (ret_port != NULL) { - *ret_port = ntohs(addr.sin6_port); - } - - return 0; - } - - struct sockaddr_in addr = { 0 }; + struct sockaddr_storage addr = { 0 }; socklen_t len = sizeof(addr); int r = getpeername(fd, (struct sockaddr *) &addr, &len); if (r < 0) { - bc_log_errorf("Failed to get peer ipv4 address: %s", strerror(errno)); + bc_log_errorf("Failed to get peer ip address: %s", strerror(errno)); return -errno; } - if (ret_address != NULL) { - *ret_address = typesafe_inet_ntop4(&addr); - } - if (ret_port != NULL) { - *ret_port = ntohs(addr.sin_port); + + if (addr.ss_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *) &addr; + + if (ret_address != NULL) { + *ret_address = typesafe_inet_ntop4(s); + } + if (ret_port != NULL) { + *ret_port = ntohs(s->sin_port); + } + } else if (addr.ss_family == AF_INET6) { + struct sockaddr_in6 *s = (struct sockaddr_in6 *) &addr; + + if (ret_address != NULL) { + *ret_address = typesafe_inet_ntop6(s); + } + if (ret_port != NULL) { + *ret_port = ntohs(s->sin6_port); + } + } else { + bc_log_errorf("Invalid address family: %u", (unsigned int) addr.ss_family); + return -EINVAL; } return 0; diff --git a/src/libbluechi/bus/bus.h b/src/libbluechi/bus/bus.h index fe169b225e..2d46ca603b 100644 --- a/src/libbluechi/bus/bus.h +++ b/src/libbluechi/bus/bus.h @@ -18,4 +18,4 @@ sd_bus *system_bus_open(sd_event *event); sd_bus *systemd_bus_open(sd_event *event); sd_bus *user_bus_open(sd_event *event); -int get_peer_address(sd_bus *bus, bool ipv6, char **ret_address, uint16_t *ret_port); +int get_peer_address(sd_bus *bus, char **ret_address, uint16_t *ret_port);