From 1c210139fff660eb3f27f3af0a9b1c648809304c Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sat, 27 Jan 2024 22:08:46 +1100 Subject: [PATCH] support for AF_PACKET --- Package.swift | 8 +- .../CLinuxSockAddr.h} | 1 + Sources/CLinuxSockAddr/module.modulemap | 3 + Sources/CNetLink/module.modulemap | 3 - Sources/IORingUtils/Socket.swift | 77 ++++++++++++++++++- 5 files changed, 84 insertions(+), 8 deletions(-) rename Sources/{CNetLink/CNetLink.h => CLinuxSockAddr/CLinuxSockAddr.h} (95%) create mode 100644 Sources/CLinuxSockAddr/module.modulemap delete mode 100644 Sources/CNetLink/module.modulemap diff --git a/Package.swift b/Package.swift index 82ba469..a399f9c 100644 --- a/Package.swift +++ b/Package.swift @@ -56,8 +56,8 @@ let package = Package( targets: ["IORingFoundation"] ), .library( - name: "CNetLink", - targets: ["CNetLink"] + name: "CLinuxSockAddr", + targets: ["CLinuxSockAddr"] ), ], dependencies: [ @@ -72,7 +72,7 @@ let package = Package( providers: [.apt(["liburing-dev"])] ), .systemLibrary( - name: "CNetLink" + name: "CLinuxSockAddr" ), .target( name: "CIORingShims", @@ -118,7 +118,7 @@ let package = Package( name: "IORingUtils", dependencies: ["IORing", "AsyncExtensions", - "CNetLink", + "CLinuxSockAddr", .product(name: "AsyncAlgorithms", package: "swift-async-algorithms")], swiftSettings: [ .enableExperimentalFeature("StrictConcurrency"), diff --git a/Sources/CNetLink/CNetLink.h b/Sources/CLinuxSockAddr/CLinuxSockAddr.h similarity index 95% rename from Sources/CNetLink/CNetLink.h rename to Sources/CLinuxSockAddr/CLinuxSockAddr.h index 69c676c..2c6bf4f 100644 --- a/Sources/CNetLink/CNetLink.h +++ b/Sources/CLinuxSockAddr/CLinuxSockAddr.h @@ -16,5 +16,6 @@ #pragma once +#include #include #include diff --git a/Sources/CLinuxSockAddr/module.modulemap b/Sources/CLinuxSockAddr/module.modulemap new file mode 100644 index 0000000..633fc85 --- /dev/null +++ b/Sources/CLinuxSockAddr/module.modulemap @@ -0,0 +1,3 @@ +module CLinuxSockAddr { + header "CLinuxSockAddr.h" +} diff --git a/Sources/CNetLink/module.modulemap b/Sources/CNetLink/module.modulemap deleted file mode 100644 index 71220f6..0000000 --- a/Sources/CNetLink/module.modulemap +++ /dev/null @@ -1,3 +0,0 @@ -module CNetLink { - header "CNetLink.h" -} diff --git a/Sources/IORingUtils/Socket.swift b/Sources/IORingUtils/Socket.swift index 946804a..dd928ad 100644 --- a/Sources/IORingUtils/Socket.swift +++ b/Sources/IORingUtils/Socket.swift @@ -17,7 +17,7 @@ import AsyncAlgorithms @preconcurrency import AsyncExtensions -import CNetLink +import CLinuxSockAddr import Glibc import IORing @@ -333,6 +333,8 @@ extension sockaddr: SocketAddress, @unchecked Sendable { return socklen_t(MemoryLayout.size) case AF_LOCAL: return socklen_t(MemoryLayout.size) + case AF_PACKET: + return socklen_t(MemoryLayout.size) case AF_NETLINK: return socklen_t(MemoryLayout.size) default: @@ -365,6 +367,10 @@ extension sockaddr: SocketAddress, @unchecked Sendable { try $0.withMemoryRebound(to: sockaddr_un.self, capacity: 1) { try $0.pointee.presentationAddress } + case AF_PACKET: + try $0.withMemoryRebound(to: sockaddr_ll.self, capacity: 1) { + try $0.pointee.presentationAddress + } case AF_NETLINK: try $0.withMemoryRebound(to: sockaddr_nl.self, capacity: 1) { try $0.pointee.presentationAddress @@ -571,6 +577,70 @@ extension sockaddr_un: SocketAddress, @unchecked Sendable { } } +extension sockaddr_ll: SocketAddress, @unchecked Sendable { + public static var family: sa_family_t { + sa_family_t(AF_PACKET) + } + + public init(family: sa_family_t, presentationAddress: String) throws { + guard family == AF_PACKET else { throw Errno.invalidArgument } + + var sll = sockaddr_ll() + sll.sll_family = family + + let bytes = try presentationAddress.split(separator: ":").map { + guard let byte = UInt8($0) else { throw Errno.invalidArgument } + return byte + } + + guard bytes.count == 6 else { throw Errno.invalidArgument } + + try withUnsafeMutablePointer(to: &sll.sll_addr) { addr in + let start = addr.propertyBasePointer(to: \.0)! + let capacity = MemoryLayout.size(ofValue: addr.pointee) + if capacity <= presentationAddress.utf8.count { + throw Errno.outOfRange + } + _ = start.withMemoryRebound(to: UInt8.self, capacity: capacity) { dst in + memcpy(UnsafeMutableRawPointer(mutating: dst), bytes, capacity) + } + } + self = sll + } + + public var size: socklen_t { + socklen_t(MemoryLayout.size) + } + + public var presentationAddress: String { + get throws { + String( + format: "%02x:%02x:%02x:%02x:%02x:%02x", + sll_addr.0, + sll_addr.1, + sll_addr.2, + sll_addr.3, + sll_addr.4, + sll_addr.5 + ) + } + } + + public var port: UInt16 { + get throws { + throw Errno.addressFamilyNotSupported + } + } + + public func withSockAddr(_ body: (_ sa: UnsafePointer) throws -> T) rethrows -> T { + try withUnsafePointer(to: self) { sun in + try sun.withMemoryRebound(to: sockaddr.self, capacity: 1) { sa in + try body(sa) + } + } + } +} + extension sockaddr_nl: SocketAddress, @unchecked Sendable { public static var family: sa_family_t { sa_family_t(AF_NETLINK) @@ -632,6 +702,9 @@ extension sockaddr_storage: SocketAddress, @unchecked Sendable { case AF_LOCAL: var sun = try sockaddr_un(family: family, presentationAddress: presentationAddress) _ = memcpy(&ss, &sun, Int(sun.size)) + case AF_PACKET: + var sll = try sockaddr_ll(family: family, presentationAddress: presentationAddress) + _ = memcpy(&ss, &sll, Int(sll.size)) case AF_NETLINK: var snl = try sockaddr_nl(family: family, presentationAddress: presentationAddress) _ = memcpy(&ss, &snl, Int(snl.size)) @@ -693,6 +766,8 @@ public extension sockaddr_storage { bytesRequired = MemoryLayout.size case AF_LOCAL: bytesRequired = MemoryLayout.size + case AF_PACKET: + bytesRequired = MemoryLayout.size case AF_NETLINK: bytesRequired = MemoryLayout.size default: