From 753d9970b13a12aab077f85fd20998786243caf3 Mon Sep 17 00:00:00 2001 From: Caleb James DeLisle Date: Sat, 28 Sep 2024 00:08:48 +0200 Subject: [PATCH] Make ETH address an official Sockaddr type. --- .clangd | 1 + interface/ETHInterface.h | 14 ----- interface/ETHInterface_admin.c | 16 ++---- interface/ETHInterface_darwin.c | 26 ++++----- interface/ETHInterface_linux.c | 24 ++++---- net/InterfaceController_admin.c | 14 +---- util/platform/Sockaddr.c | 99 +++++++++++++++++++++++++++++---- util/platform/Sockaddr.h | 15 +++-- 8 files changed, 128 insertions(+), 81 deletions(-) diff --git a/.clangd b/.clangd index fcff4a39..6b31347a 100644 --- a/.clangd +++ b/.clangd @@ -3,6 +3,7 @@ CompileFlags: # Tweak the parse settings, example directory given to show format - "-DPARANOIA=1" - "-DIdentity_CHECK=1" - "-DCJDNS_RAND_U64_PER_FILE=1" + - "-DHAS_ETH_INTERFACE=1" - "-Wall" - "-Wextra" diff --git a/interface/ETHInterface.h b/interface/ETHInterface.h index e9860e8d..2b44775f 100644 --- a/interface/ETHInterface.h +++ b/interface/ETHInterface.h @@ -44,20 +44,6 @@ struct ETHInterface_Header #define ETHInterface_Header_SIZE 6 Assert_compileTime(sizeof(struct ETHInterface_Header) == ETHInterface_Header_SIZE); -/** The content of a Sockaddr emitted from ETHInterface. */ -struct ETHInterface_Sockaddr -{ - struct Sockaddr generic; - /* - * We need to make the first byte following the Sockaddr be 0 because - * Sockaddr_normalizeNative will zero it. - */ - uint16_t zero; - uint8_t mac[6]; -}; -#define ETHInterface_Sockaddr_SIZE 16 -Assert_compileTime(sizeof(struct ETHInterface_Sockaddr) == ETHInterface_Sockaddr_SIZE); - #define ETHInterface_CURRENT_VERSION 0 struct ETHInterface diff --git a/interface/ETHInterface_admin.c b/interface/ETHInterface_admin.c index 2bb25aff..dc3b48ca 100644 --- a/interface/ETHInterface_admin.c +++ b/interface/ETHInterface_admin.c @@ -13,7 +13,6 @@ * along with this program. If not, see . */ #include "interface/ETHInterface_admin.h" -#include "exception/Err.h" #include "interface/ETHInterface.h" #include "benc/Int.h" #include "admin/Admin.h" @@ -22,8 +21,8 @@ #include "net/InterfaceController.h" #include "rust/cjdns_sys/RTypes.h" #include "rust/cjdns_sys/Rffi.h" -#include "util/AddrTools.h" #include "util/Identity.h" +#include "util/platform/Sockaddr.h" struct Context { @@ -56,19 +55,16 @@ static void beginConnection(Dict* args, uint8_t pkBytes[32]; - struct ETHInterface_Sockaddr sockaddr = { - .generic = { - .addrLen = ETHInterface_Sockaddr_SIZE - } - }; - + struct Sockaddr_storage ss; if (Key_parse(publicKey, pkBytes, NULL)) { error = "invalid publicKey"; - } else if (macAddress->len < 17 || AddrTools_parseMac(sockaddr.mac, macAddress->bytes)) { + } else if (Sockaddr_parse(macAddress->bytes, &ss)) { + error = "invalid macAddress"; + } else if (ss.addr.type != Sockaddr_ETHERNET) { error = "invalid macAddress"; } else { int ret = InterfaceController_bootstrapPeer( - ctx->ic, ifNum, pkBytes, &sockaddr.generic, password, login, peerName, version); + ctx->ic, ifNum, pkBytes, &ss.addr, password, login, peerName, version); if (ret == InterfaceController_bootstrapPeer_BAD_IFNUM) { error = "invalid interfaceNumber"; diff --git a/interface/ETHInterface_darwin.c b/interface/ETHInterface_darwin.c index 5c66208b..966dd59d 100644 --- a/interface/ETHInterface_darwin.c +++ b/interface/ETHInterface_darwin.c @@ -14,6 +14,7 @@ */ #include "interface/ETHInterface.h" #include "exception/Err.h" +#include "util/platform/Sockaddr.h" #include "wire/Message.h" #include "wire/Ethernet.h" #include "util/Assert.h" @@ -73,12 +74,8 @@ static Iface_DEFUN sendMessage(Message_t* msg, struct Iface* iface) { struct ETHInterface_pvt* ctx = Identity_containerOf(iface, struct ETHInterface_pvt, iface); - struct Sockaddr* sa = (struct Sockaddr*) Message_bytes(msg); - Assert_true(Message_getLength(msg) >= Sockaddr_OVERHEAD); - Assert_true(sa->addrLen <= ETHInterface_Sockaddr_SIZE); - - struct ETHInterface_Sockaddr sockaddr = { .generic = { .addrLen = 0 } }; - Err(Message_epop(msg, &sockaddr, sa->addrLen)); + struct Sockaddr_storage ss = { .addr.addrLen = 0 }; + Err(Sockaddr_read(&ss, msg)); struct ETHInterface_Header hdr = { .version = ETHInterface_CURRENT_VERSION, @@ -91,10 +88,12 @@ static Iface_DEFUN sendMessage(Message_t* msg, struct Iface* iface) struct ethernet_frame ethFr = { .type = Ethernet_TYPE_CJDNS }; - if (sockaddr.generic.flags & Sockaddr_flags_BCAST) { + if (ss.addr.flags & Sockaddr_flags_BCAST) { Bits_memset(ethFr.dest, 0xff, 6); } else { - Bits_memcpy(ethFr.dest, sockaddr.mac, 6); + if (Sockaddr_getMac(ethFr.dest, &ss.addr)) { + Err_raise(Message_getAlloc(msg), "Sockaddr on message not ETH type"); + } } Bits_memcpy(ethFr.src, ctx->myMac, 6); Err(Message_epush(msg, ðFr, ethernet_frame_SIZE)); @@ -152,14 +151,9 @@ static void handleEvent2(struct ETHInterface_pvt* context, return; } - struct ETHInterface_Sockaddr sockaddr = { .zero = 0 }; - Bits_memcpy(sockaddr.mac, src, 6); - sockaddr.generic.addrLen = ETHInterface_Sockaddr_SIZE; - if (dst[0] == 0xff) { - sockaddr.generic.flags |= Sockaddr_flags_BCAST; - } - - Err_assert(Message_epush(msg, &sockaddr, ETHInterface_Sockaddr_SIZE)); + struct Sockaddr_storage ss = { .addr.addrLen = 0 }; + struct Sockaddr* sa = Sockaddr_initFromEth(&ss, src); + Err_assert(Sockaddr_write(sa, msg)); Assert_true(!((uintptr_t)Message_bytes(msg) % 4) && "Alignment fault"); diff --git a/interface/ETHInterface_linux.c b/interface/ETHInterface_linux.c index d6ba8ca1..6fb3bc3f 100644 --- a/interface/ETHInterface_linux.c +++ b/interface/ETHInterface_linux.c @@ -16,6 +16,7 @@ #include "exception/Err.h" #include "memory/Allocator.h" #include "net/InterfaceController.h" +#include "util/platform/Sockaddr.h" #include "wire/Headers.h" #include "wire/Message.h" #include "wire/Error.h" @@ -103,20 +104,18 @@ static Iface_DEFUN sendMessage(Message_t* msg, struct Iface* iface) { struct ETHInterface_pvt* ctx = Identity_containerOf(iface, struct ETHInterface_pvt, iface); - struct Sockaddr* sa = (struct Sockaddr*) Message_bytes(msg); - Assert_true(Message_getLength(msg) >= Sockaddr_OVERHEAD); - Assert_true(sa->addrLen <= ETHInterface_Sockaddr_SIZE); - - struct ETHInterface_Sockaddr sockaddr = { .generic = { .addrLen = 0 } }; - Err(Message_epop(msg, &sockaddr, sa->addrLen)); + struct Sockaddr_storage ss = { .addr.addrLen = 0 }; + Err(Sockaddr_read(&ss, msg)); struct sockaddr_ll addr; Bits_memcpy(&addr, &ctx->addrBase, sizeof(struct sockaddr_ll)); - if (sockaddr.generic.flags & Sockaddr_flags_BCAST) { + if (ss.addr.flags & Sockaddr_flags_BCAST) { Bits_memset(addr.sll_addr, 0xff, 6); } else { - Bits_memcpy(addr.sll_addr, sockaddr.mac, 6); + if (Sockaddr_getMac(addr.sll_addr, &ss.addr)) { + Err_raise(Message_getAlloc(msg), "Sockaddr on message not ETH type"); + } } struct ETHInterface_Header hdr = { @@ -180,14 +179,13 @@ static void handleEvent2(struct ETHInterface_pvt* context, struct Allocator* mes return; } - struct ETHInterface_Sockaddr sockaddr = { .zero = 0 }; - Bits_memcpy(sockaddr.mac, addr.sll_addr, 6); - sockaddr.generic.addrLen = ETHInterface_Sockaddr_SIZE; + struct Sockaddr_storage ss; + Sockaddr_initFromEth(&ss, addr.sll_addr); if (addr.sll_pkttype == PACKET_BROADCAST) { - sockaddr.generic.flags |= Sockaddr_flags_BCAST; + ss.addr.flags |= Sockaddr_flags_BCAST; } - Err_assert(Message_epush(msg, &sockaddr, ETHInterface_Sockaddr_SIZE)); + Err_assert(Sockaddr_write(&ss.addr, msg)); Assert_true(!((uintptr_t)Message_bytes(msg) % 4) && "Alignment fault"); diff --git a/net/InterfaceController_admin.c b/net/InterfaceController_admin.c index 93a3a172..7d73e2db 100644 --- a/net/InterfaceController_admin.c +++ b/net/InterfaceController_admin.c @@ -89,19 +89,7 @@ static void adminPeerStats(Dict* args, void* vcontext, String* txid, struct Allo Dict_putStringC(d, "addr", Address_toStringKey(&stats[i].addr, alloc), alloc); - String* lladdrString; -#ifdef HAS_ETH_INTERFACE - if (ETHInterface_Sockaddr_SIZE == stats[i].lladdr->addrLen) { - struct ETHInterface_Sockaddr* eth = (struct ETHInterface_Sockaddr*) stats[i].lladdr; - uint8_t printedMac[18]; - AddrTools_printMac(printedMac, eth->mac); - lladdrString = String_new(printedMac, alloc); - } else { - lladdrString = String_new(Sockaddr_print(stats[i].lladdr, alloc), alloc); - } -#else - lladdrString = String_new(Sockaddr_print(stats[i].lladdr, alloc), alloc); -#endif + String* lladdrString = String_new(Sockaddr_print(stats[i].lladdr, alloc), alloc); Dict_putStringC(d, "lladdr", lladdrString, alloc); String* stateString = String_new(InterfaceController_stateString(stats[i].state), alloc); diff --git a/util/platform/Sockaddr.c b/util/platform/Sockaddr.c index ff0b2b0b..da6db6bc 100644 --- a/util/platform/Sockaddr.c +++ b/util/platform/Sockaddr.c @@ -12,15 +12,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include "exception/Err.h" #include "rust/cjdns_sys/Rffi.h" #include "benc/String.h" #include "memory/Allocator.h" #include "util/platform/Sockaddr.h" +#include "util/AddrTools.h" #include "util/CString.h" #include "util/Bits.h" #include "util/Hex.h" #include "util/Hash.h" #include "util/Base10.h" +#include "wire/Message.h" #include @@ -53,6 +56,13 @@ struct Sockaddr_in6_pvt struct Sockaddr pub; struct sockaddr_in6 si; }; +typedef struct Sockaddr_eth_pvt +{ + struct Sockaddr pub; + uint16_t zero; + uint8_t mac[6]; +} Sockaddr_eth_pvt_t; +Assert_compileTime(sizeof(Sockaddr_eth_pvt_t) == 16); const struct Sockaddr* const Sockaddr_LOOPBACK_be = (const struct Sockaddr*) &((const struct Sockaddr_in_pvt) { @@ -106,6 +116,18 @@ int Sockaddr_parse(const char* input, struct Sockaddr_storage* out) } CString_safeStrncpy(buff, input, 63); + if (CString_strlen(buff) == 17) { + // 17 bytes long, try it as a MAC + Bits_memset(out, 0, sizeof(struct Sockaddr_storage)); + Sockaddr_eth_pvt_t* eth = (Sockaddr_eth_pvt_t*) out; + if (AddrTools_parseMac(eth->mac, buff) == 0) { + out->addr.addrLen = sizeof *eth; + out->addr.type = Sockaddr_ETHERNET; + return 0; + } + // not a MaC, keep trying, lots of things are 17 bytes. + } + int64_t port = 0; char* lastColon = CString_strrchr(buff, ':'); char* firstColon = CString_strchr(buff, ':'); @@ -191,6 +213,16 @@ char* Sockaddr_print(struct Sockaddr* sockaddr, struct Allocator* alloc) return out->bytes; } + if (sockaddr->type == Sockaddr_ETHERNET) { + if (sockaddr->addrLen != sizeof(Sockaddr_eth_pvt_t)) { + return "eth/invalid"; + } + Sockaddr_eth_pvt_t* eth = (Sockaddr_eth_pvt_t*) sockaddr; + String* out = String_printf(alloc, "%02x:%02x:%02x:%02x:%02x:%02x", + eth->mac[0], eth->mac[1], eth->mac[2], eth->mac[3], eth->mac[4], eth->mac[5]); + return out->bytes; + } + struct Sockaddr_pvt* addr = (struct Sockaddr_pvt*) sockaddr; void* inAddr; @@ -244,6 +276,9 @@ static uint16_t* getPortPtr(struct Sockaddr* sockaddr) if (sockaddr->addrLen < (2 + Sockaddr_OVERHEAD)) { return NULL; } + if (sockaddr->type != Sockaddr_PLATFORM) { + return NULL; + } struct Sockaddr_pvt* sa = (struct Sockaddr_pvt*) sockaddr; switch (sa->ss.ss_family) { case AF_INET: return &((struct sockaddr_in*)&sa->ss)->sin_port; @@ -281,6 +316,9 @@ int Sockaddr_getAddress(struct Sockaddr* sockaddr, void* addrPtr) if (sockaddr->addrLen < (2 + Sockaddr_OVERHEAD)) { return -1; } + if (sockaddr->type != Sockaddr_PLATFORM) { + return -2; + } struct Sockaddr_pvt* sa = (struct Sockaddr_pvt*) sockaddr; if (addrPtr) { void** ap = (void**) addrPtr; @@ -303,6 +341,9 @@ int Sockaddr_getFamily(const struct Sockaddr* sockaddr) if (sockaddr->addrLen < (2 + Sockaddr_OVERHEAD)) { return -1; } + if (sockaddr->type != Sockaddr_PLATFORM) { + return -2; + } const struct Sockaddr_pvt* sa = (const struct Sockaddr_pvt*) sockaddr; return sa->ss.ss_family; } @@ -312,6 +353,27 @@ int Sockaddr_getFamily_fromRust(const struct Sockaddr* sockaddr) return Sockaddr_getFamily(sockaddr); } +struct Sockaddr* Sockaddr_initFromEth(struct Sockaddr_storage* out, const uint8_t mac[static 6]) { + Sockaddr_eth_pvt_t* eth = (Sockaddr_eth_pvt_t*) out; + Bits_memset(eth, 0, sizeof *eth); + Bits_memcpy(eth->mac, mac, 6); + eth->pub.addrLen = sizeof *eth; + eth->pub.type = Sockaddr_ETHERNET; + if (mac[0] == 0xff) { + eth->pub.flags |= Sockaddr_flags_BCAST; + } + return &out->addr; +} + +int Sockaddr_getMac(uint8_t out[static 6], const struct Sockaddr* sockaddr) { + if (sockaddr->addrLen != sizeof(Sockaddr_eth_pvt_t) || sockaddr->type != Sockaddr_ETHERNET) { + return -1; + } + Sockaddr_eth_pvt_t* eth = (Sockaddr_eth_pvt_t*) sockaddr; + Bits_memcpy(out, eth->mac, 6); + return 0; +} + struct Sockaddr* Sockaddr_initFromBytes(struct Sockaddr_storage* out, const uint8_t* bytes, int addrFamily) { switch (addrFamily) { @@ -351,13 +413,6 @@ struct Sockaddr* Sockaddr_fromBytes(const uint8_t* bytes, int addrFamily, struct return Sockaddr_clone(sa, alloc); } -void Sockaddr_normalizeNative(void* nativeSockaddr) -{ -#if defined(freebsd) || defined(openbsd) || defined(netbsd) || defined(darwin) - ((struct sockaddr*)nativeSockaddr)->sa_len = 0; -#endif -} - uint32_t Sockaddr_hash(const struct Sockaddr* addr) { return Hash_compute((uint8_t*)addr, addr->addrLen); @@ -375,7 +430,7 @@ void Sockaddr_asIp6(uint8_t addrOut[static 16], const struct Sockaddr* sockaddr) } struct Sockaddr_pvt* sa = (struct Sockaddr_pvt*) sockaddr; Bits_memset(addrOut, 0, 16); - switch (sa->ss.ss_family) { + switch (Sockaddr_getFamily(sockaddr)) { case AF_INET: { // IPv4 in 6 addrOut[10] = 0xff; @@ -392,7 +447,7 @@ void Sockaddr_asIp6(uint8_t addrOut[static 16], const struct Sockaddr* sockaddr) uint16_t len = sa->pub.addrLen - Sockaddr_OVERHEAD; if (len <= 14) { addrOut[0] = 0xff; - addrOut[1] = 0xfe; + addrOut[1] = 0xfe - sockaddr->type; Bits_memcpy(&addrOut[16-len], &sa->ss, len); } else { uint8_t hash[32]; @@ -411,7 +466,13 @@ void Sockaddr_asIp6_fromRust(uint8_t addrOut[static 16], const struct Sockaddr* int Sockaddr_compare(const struct Sockaddr* a, const struct Sockaddr* b) { - return Bits_memcmp(a, b, a->addrLen); + if (a->addrLen < b->addrLen) { + return -1; + } else if (a->addrLen > b->addrLen) { + return 1; + } else { + return Bits_memcmp(a, b, a->addrLen); + } } uint32_t Sockaddr_addrHandle(const struct Sockaddr* addr) @@ -436,3 +497,21 @@ void Sockaddr_addrFromHandle(struct Sockaddr* addr, uint32_t handle) addr->addrLen = sizeof(struct Sockaddr); Bits_memcpy(&((uint8_t*)addr)[4], &handle, 4); } + +Err_DEFUN Sockaddr_read(struct Sockaddr_storage* out, Message_t* readFrom) { + if (Message_getLength(readFrom) < Sockaddr_OVERHEAD) { + Err_raise(Message_getAlloc(readFrom), + "Error: Message len [%d] too short to contain Sockaddr", + Message_getLength(readFrom)); + } + Err(Message_epop(readFrom, &out->addr, sizeof out->addr)); + if (out->addr.addrLen < Sockaddr_OVERHEAD) { + Err_raise(Message_getAlloc(readFrom), + "Invalid addrLen in Sockaddr: [%d]", out->addr.addrLen); + } + Err(Message_epop(readFrom, &out->nativeAddr, out->addr.addrLen - Sockaddr_OVERHEAD)); + return NULL; +} +Err_DEFUN Sockaddr_write(const struct Sockaddr* from, Message_t* writeTo) { + return Message_epush(writeTo, from, from->addrLen); +} \ No newline at end of file diff --git a/util/platform/Sockaddr.h b/util/platform/Sockaddr.h index f0b64a24..de3b7b58 100644 --- a/util/platform/Sockaddr.h +++ b/util/platform/Sockaddr.h @@ -15,9 +15,11 @@ #ifndef Sockaddr_H #define Sockaddr_H +#include "exception/Err.h" #include "memory/Allocator.h" #include "util/Endian.h" #include "util/Linker.h" +#include "wire/Message.h" Linker_require("util/platform/Sockaddr.c") #include @@ -33,6 +35,7 @@ typedef struct Sockaddr #define Sockaddr_PLATFORM 0 #define Sockaddr_HANDLE 1 + #define Sockaddr_ETHERNET 2 uint8_t type; /** Only applies if flags & Sockaddr_flags_PREFIX is true. */ @@ -177,11 +180,6 @@ Sockaddr_t* Sockaddr_fromBytes(const uint8_t* bytes, int addrFamily, struct Allo */ Sockaddr_t* Sockaddr_clone(const Sockaddr_t* addr, struct Allocator* alloc); -/** - * Normalize inconsistent native sockaddr implementations - */ -void Sockaddr_normalizeNative(void* nativeSockaddr); - /** * Get a hash for hashtable lookup. */ @@ -192,4 +190,11 @@ uint32_t Sockaddr_hash(const Sockaddr_t* addr); */ int Sockaddr_compare(const Sockaddr_t* a, const Sockaddr_t* b); +struct Sockaddr* Sockaddr_initFromEth(struct Sockaddr_storage* out, const uint8_t mac[static 6]); + +int Sockaddr_getMac(uint8_t out[static 6], const struct Sockaddr* sockaddr); + +Err_DEFUN Sockaddr_read(struct Sockaddr_storage* out, Message_t* readFrom); +Err_DEFUN Sockaddr_write(const struct Sockaddr* out, Message_t* writeTo); + #endif