From 1e75c08f06f73709266442258717dd30092da57d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Sch=C3=A4ffersmann?= Date: Wed, 20 Nov 2024 19:11:28 +0100 Subject: [PATCH] cm_networking: Replace non-reentrant ntoa functions Also create a new tools header for ntoa helper functions. --- .../src/modules/cm_networking/cm_mdns.cpp | 17 +++-- .../src/modules/cm_networking/cm_protocol.cpp | 37 ++++++--- software/src/tools/net.h | 76 +++++++++++++++++++ 3 files changed, 112 insertions(+), 18 deletions(-) create mode 100644 software/src/tools/net.h diff --git a/software/src/modules/cm_networking/cm_mdns.cpp b/software/src/modules/cm_networking/cm_mdns.cpp index cd327c96f..72dd0126b 100644 --- a/software/src/modules/cm_networking/cm_mdns.cpp +++ b/software/src/modules/cm_networking/cm_mdns.cpp @@ -29,6 +29,7 @@ #include "event_log_prefix.h" #include "module_dependencies.h" #include "tools.h" +#include "tools/net.h" #include "cool_string.h" void CMNetworking::setup() @@ -107,7 +108,8 @@ void CMNetworking::resolve_hostname(uint8_t charger_idx) std::lock_guard lock{dns_resolve_mutex}; if (resolve_state[charger_idx] != RESOLVE_STATE_RESOLVED || dest_addrs[charger_idx].sin_addr.s_addr != in) { - const char *ip_str = ipaddr_ntoa(&ip); + char ip_str[16]; + tf_ip4addr_ntoa(&ip, ip_str, sizeof(ip_str)); // Show resolved hostname only if it wasn't already an IP if (strcmp(this->hosts[charger_idx], ip_str) != 0) { logger.printfln("Resolved %s to %s", this->hosts[charger_idx], ip_str); @@ -232,7 +234,9 @@ void CMNetworking::resolve_via_mdns(mdns_result_t *entry) if (host == entry->hostname) { this->dest_addrs[i].sin_addr.s_addr = entry->addr->addr.u_addr.ip4.addr; if (this->resolve_state[i] != RESOLVE_STATE_RESOLVED) { - logger.printfln("Resolved %s to %s (via mDNS scan)", this->hosts[i], ipaddr_ntoa((const ip_addr *)&entry->addr->addr)); + char addr_str[16]; + tf_ip4addr_ntoa(&entry->addr->addr, addr_str, sizeof(addr_str)); + logger.printfln("Resolved %s to %s (via mDNS scan)", this->hosts[i], addr_str); } this->resolve_state[i] = RESOLVE_STATE_RESOLVED; } @@ -275,10 +279,11 @@ void CMNetworking::add_scan_result_entry(mdns_result_t *entry, TFJsonSerializer json.addObject(); json.addMemberString("hostname", entry->hostname); - char buf[32] = "[no_address]"; - if (entry->addr && entry->addr->addr.type == IPADDR_TYPE_V4) - esp_ip4addr_ntoa(&entry->addr->addr.u_addr.ip4, buf, ARRAY_SIZE(buf)); - json.addMemberString("ip", buf); + char addr_str[32] = "[no_address]"; + if (entry->addr && entry->addr->addr.type == IPADDR_TYPE_V4) { + tf_ip4addr_ntoa(&entry->addr->addr, addr_str, sizeof(addr_str)); + } + json.addMemberString("ip", addr_str); json.addMemberString("display_name", display_name); json.addMemberNumber("error", error); diff --git a/software/src/modules/cm_networking/cm_protocol.cpp b/software/src/modules/cm_networking/cm_protocol.cpp index 664518771..3b0166dce 100644 --- a/software/src/modules/cm_networking/cm_protocol.cpp +++ b/software/src/modules/cm_networking/cm_protocol.cpp @@ -29,6 +29,7 @@ #include "event_log_prefix.h" #include "module_dependencies.h" #include "tools.h" +#include "tools/net.h" #include "modules/meters/meter_defs.h" int CMNetworking::create_socket(uint16_t port, bool blocking) @@ -300,16 +301,23 @@ void CMNetworking::register_manager(const char *const *const hosts, // Don't log in the first 20 seconds after startup: We are probably still resolving hostnames. if (charger_idx == -1) { - if (deadline_elapsed(20000)) - logger.printfln("Received packet from unknown %s. Is the config complete?", inet_ntoa(source_addr.sin_addr)); + if (deadline_elapsed(20_s)) { + char source_str[16]; + tf_ip4addr_ntoa(&source_addr, source_str, sizeof(source_str)); + + logger.printfln("Received packet from unknown %s. Is the config complete?", source_str); + } return; } String validation_error = validate_state_packet_header(&state_pkt, len); if (!validation_error.isEmpty()) { + char source_str[16]; + tf_ip4addr_ntoa(&source_addr, source_str, sizeof(source_str)); + logger.printfln("Received state packet from %s (%s) (%i bytes) failed validation: %s", charge_manager.get_charger_name(charger_idx), - inet_ntoa(source_addr.sin_addr), + source_str, len, validation_error.c_str()); if (manager_error_callback) { @@ -319,9 +327,12 @@ void CMNetworking::register_manager(const char *const *const hosts, } if (seq_num_invalid(state_pkt.header.seq_num, last_seen_seq_num[charger_idx])) { + char source_str[16]; + tf_ip4addr_ntoa(&source_addr, source_str, sizeof(source_str)); + logger.printfln("Received stale (out of order?) state packet from %s (%s). Last seen seq_num is %u, Received seq_num is %u", charge_manager.get_charger_name(charger_idx), - inet_ntoa(source_addr.sin_addr), + source_str, last_seen_seq_num[charger_idx], state_pkt.header.seq_num); return; @@ -330,9 +341,12 @@ void CMNetworking::register_manager(const char *const *const hosts, last_seen_seq_num[charger_idx] = state_pkt.header.seq_num; if (!CM_STATE_FLAGS_MANAGED_IS_SET(state_pkt.v1.state_flags)) { + char source_str[16]; + tf_ip4addr_ntoa(&source_addr, source_str, sizeof(source_str)); + logger.printfln("%s (%s) reports managed is not activated!", charge_manager.get_charger_name(charger_idx), - inet_ntoa(source_addr.sin_addr)); + source_str); if (manager_error_callback) { manager_error_callback(charger_idx, CM_NETWORKING_ERROR_NOT_MANAGED); } @@ -438,10 +452,9 @@ void CMNetworking::register_client(const std::functionsin_addr), - len, - validation_error.c_str()); + char from_str[16]; + tf_ip4addr_ntoa(&from_addr, from_str, sizeof(from_str)); + logger.printfln("Received command packet from %s (%i bytes) failed validation: %s", from_str, len, validation_error.c_str()); return; } @@ -455,8 +468,8 @@ void CMNetworking::register_client(const std::functionmanager_addr, &from_addr, from_addr.s2_len) != 0) { char manager_str[16]; char from_str[16]; - inet_ntoa_r(((struct sockaddr_in*)&manager_addr)->sin_addr, manager_str, sizeof(manager_str)); - inet_ntoa_r(((struct sockaddr_in*)&from_addr )->sin_addr, from_str, sizeof(from_str )); + tf_ip4addr_ntoa(&this->manager_addr, manager_str, sizeof(manager_str)); + tf_ip4addr_ntoa(&from_addr, from_str, sizeof(from_str )); if (deadline_elapsed(this->last_manager_addr_change + 1_m)) { if (this->manager_addr.s2_len > 0) { @@ -483,7 +496,7 @@ void CMNetworking::register_client(const std::functionmanager_addr_valid && this->manager_addr.s2_len > 0) { if (deadline_elapsed(this->last_manager_addr_change + 1_m)) { char manager_str[16]; - inet_ntoa_r(((struct sockaddr_in*)&manager_addr)->sin_addr, manager_str, sizeof(manager_str)); + tf_ip4addr_ntoa(&this->manager_addr, manager_str, sizeof(manager_str)); logger.printfln("Accepting manager address %s", manager_str); this->manager_addr_valid = true; diff --git a/software/src/tools/net.h b/software/src/tools/net.h new file mode 100644 index 000000000..5404997cc --- /dev/null +++ b/software/src/tools/net.h @@ -0,0 +1,76 @@ +/* esp32-firmware + * Copyright (C) 2024 Mattias Schäffersmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include "esp_netif_ip_addr.h" +#include "lwip/ip_addr.h" +#include "lwip/sockets.h" + +#if defined(__GNUC__) + #pragma GCC diagnostic push + #include "gcc_warnings.h" + + // Cast from sockaddr to sockaddr_in increases required alignment + #pragma GCC diagnostic ignored "-Wcast-align" +#endif + +// lwIP ipaddr + +extern inline void tf_ip4addr_ntoa(const ip4_addr_t *addr, char *buf, int buflen) { + ip4addr_ntoa_r(addr, buf, buflen); +} + +extern inline void tf_ip4addr_ntoa(const ip_addr_t *addr, char *buf, int buflen) { + tf_ip4addr_ntoa(&addr->u_addr.ip4, buf, buflen); +} + +// lwIP inaddr + +extern inline void tf_ip4addr_ntoa(const struct in_addr *addr, char *buf, int buflen) { + tf_ip4addr_ntoa(reinterpret_cast(addr), buf, buflen); +} + +// lwIP sockaddr + +extern inline void tf_ip4addr_ntoa(const struct sockaddr_in *addr, char *buf, int buflen) { + tf_ip4addr_ntoa(&addr->sin_addr, buf, buflen); +} + +extern inline void tf_ip4addr_ntoa(const struct sockaddr *addr, char *buf, int buflen) { + tf_ip4addr_ntoa(reinterpret_cast(addr), buf, buflen); +} + +extern inline void tf_ip4addr_ntoa(const struct sockaddr_storage *addr, char *buf, int buflen) { + tf_ip4addr_ntoa(reinterpret_cast(addr), buf, buflen); +} + +// ESP netif IP adresses + +extern inline void tf_ip4addr_ntoa(const esp_ip4_addr_t *addr, char *buf, int buflen) { + tf_ip4addr_ntoa(reinterpret_cast(addr), buf, buflen); +} + +extern inline void tf_ip4addr_ntoa(const esp_ip_addr_t *addr, char *buf, int buflen) { + tf_ip4addr_ntoa(reinterpret_cast(addr), buf, buflen); +} + +#if defined(__GNUC__) + #pragma GCC diagnostic pop +#endif