1 Commits

Author SHA1 Message Date
Will Greenberg
01915a22a6 wip 2026-01-08 18:30:27 -08:00
6 changed files with 2224 additions and 47 deletions

12
Cargo.lock generated
View File

@@ -2790,6 +2790,7 @@ dependencies = [
"telcom-parser",
"thiserror 1.0.69",
"tokio",
"uds",
]
[[package]]
@@ -2833,6 +2834,7 @@ dependencies = [
"tokio-stream",
"tokio-util",
"toml",
"uds",
]
[[package]]
@@ -3789,6 +3791,16 @@ version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "uds"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "885c31f06fce836457fe3ef09a59f83fe8db95d270b11cd78f40a4666c4d1661"
dependencies = [
"libc",
"tokio",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"

View File

@@ -33,3 +33,4 @@ anyhow = "1.0.98"
reqwest = { version = "0.12.20", default-features = false }
rustls-rustcrypto = { version = "0.0.2-alpha", optional = true }
async-trait = "0.1.88"
uds = { version = "0.4.2", features = ["tokio"] }

View File

@@ -1172,6 +1172,7 @@
"integrity": "sha512-bGs473Gj4TwFf7dw6ZUwQI0ayaDb83E7G06QnYeNQC2DmAaktgFU2uB0tSfZVhpHqYH4o8GsLBkG3ZjThtmsIA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@standard-schema/spec": "^1.0.0",
"@sveltejs/acorn-typescript": "^1.0.5",
@@ -1211,6 +1212,7 @@
"integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@sveltejs/vite-plugin-svelte-inspector": "^5.0.0",
"debug": "^4.4.1",
@@ -1299,6 +1301,7 @@
"integrity": "sha512-IbKooQVqUBrlzWTi79E8Fw78l8k1RNtlDDNWsFZs7XonuQSJ8oNYfEeclhprUldXISRMLzBpILuKgPlIxm+/Yw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"undici-types": "~7.14.0"
}
@@ -1349,6 +1352,7 @@
"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.46.0",
"@typescript-eslint/types": "8.46.0",
@@ -1682,6 +1686,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -1935,6 +1940,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.9",
"caniuse-lite": "^1.0.30001746",
@@ -2310,6 +2316,7 @@
"integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -3021,6 +3028,7 @@
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"jiti": "bin/jiti.js"
}
@@ -3494,6 +3502,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@@ -3541,6 +3550,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -3741,6 +3751,7 @@
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -4225,6 +4236,7 @@
"integrity": "sha512-Q3gqCGIgl4r0CR7OaWYjVo22nqFmLLSfn1MiWNFaITamvqhGBD3kyqk51EKuO4Nd1z8QliO5KIz7a2Ka9Rxilw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@jridgewell/remapping": "^2.3.4",
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -4649,6 +4661,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -4742,6 +4755,7 @@
"integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
@@ -5065,21 +5079,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/yaml": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
"integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
"dev": true,
"license": "ISC",
"optional": true,
"peer": true,
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14.6"
}
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",

2125
daemon/web/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -26,5 +26,6 @@ futures = { version = "0.3.30", default-features = false }
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0"
num_enum = "0.7.4"
uds = { version = "0.4.2", features = ["tokio"] }
[dev-dependencies]

View File

@@ -8,6 +8,8 @@ use crate::{Device, log_codes};
use deku::prelude::*;
use futures::TryStream;
use log::{debug, error, info};
use uds::UnixSocketAddr;
use uds::tokio::UnixSeqpacketConn;
use std::io::ErrorKind;
use std::os::fd::AsRawFd;
use std::time::Duration;
@@ -79,8 +81,13 @@ const DIAG_IOCTL_SWITCH_LOGGING: u64 = 7;
#[cfg(all(not(target_env = "musl"), target_arch = "aarch64"))]
const DIAG_IOCTL_SWITCH_LOGGING: u64 = 7;
enum DiagIO {
File(File),
Socket(UnixSeqpacketConn),
}
pub struct DiagDevice {
file: File,
file: DiagIO,
read_buf: Vec<u8>,
use_mdm: i32,
}
@@ -129,22 +136,32 @@ impl DiagDevice {
}
async fn try_new(configured_device: &Device) -> DiagResult<Self> {
let diag_file = File::options()
.read(true)
.write(true)
.open("/dev/diag")
.await
.map_err(DiagDeviceError::OpenDiagDeviceError)?;
let fd = diag_file.as_raw_fd();
if tokio::fs::try_exists("/dev/diag").await.unwrap() {
let diag_file = File::options()
.read(true)
.write(true)
.open("/dev/diag")
.await
.map_err(DiagDeviceError::OpenDiagDeviceError)?;
enable_frame_readwrite(fd, MEMORY_DEVICE_MODE, configured_device)?;
let use_mdm = determine_use_mdm(fd)?;
let fd = diag_file.as_raw_fd();
enable_frame_readwrite(fd, MEMORY_DEVICE_MODE, configured_device)?;
Ok(DiagDevice {
read_buf: vec![0; BUFFER_LEN],
file: diag_file,
use_mdm,
})
Ok(DiagDevice {
read_buf: vec![0; BUFFER_LEN],
file: DiagIO::File(diag_file),
use_mdm: determine_use_mdm(fd)?,
})
} else {
let addr = UnixSocketAddr::new(&[0; 108]).unwrap();
let socket = uds::tokio::UnixSeqpacketConn::connect_addr(&addr).unwrap();
Ok(DiagDevice {
read_buf: vec![0; BUFFER_LEN],
file: DiagIO::Socket(socket),
use_mdm: 0,
})
}
}
pub fn as_stream(
@@ -157,14 +174,21 @@ impl DiagDevice {
}
async fn get_next_messages_container(&mut self) -> Result<MessagesContainer, DiagDeviceError> {
info!("reading messages container...");
let mut bytes_read = 0;
// TP-Link M7350 sometimes sends too small messages, we need to be able to deal with short reads.
while bytes_read <= 8 {
bytes_read = self
.file
.read(&mut self.read_buf)
.await
.map_err(DiagDeviceError::DeviceReadFailed)?;
bytes_read += match &mut self.file {
DiagIO::File(file) => file
.read(&mut self.read_buf)
.await
.map_err(DiagDeviceError::DeviceReadFailed)?,
DiagIO::Socket(unix_datagram) => unix_datagram
.recv(&mut self.read_buf)
.await
.map_err(DiagDeviceError::DeviceReadFailed)?,
};
info!("{bytes_read} bytes read");
}
debug!(
@@ -189,20 +213,29 @@ impl DiagDevice {
}
.to_bytes()
.expect("Failed to serialize RequestContainer");
if let Err(err) = self.file.write(&buf).await {
// For reasons I don't entirely understand, calls to write(2) on
// /dev/diag always return 0 bytes written, though the written
// requests end up being interpreted. As such, we're not concerned
// about WriteZero errors
if err.kind() != ErrorKind::WriteZero {
return Err(DiagDeviceError::DeviceWriteFailed(err));
match &mut self.file {
DiagIO::File(file) => {
if let Err(err) = file.write(&buf).await {
// For reasons I don't entirely understand, calls to write(2) on
// /dev/diag always return 0 bytes written, though the written
// requests end up being interpreted. As such, we're not concerned
// about WriteZero errors
if err.kind() != ErrorKind::WriteZero {
return Err(DiagDeviceError::DeviceWriteFailed(err));
}
}
if let Err(err) = file.flush().await
&& err.kind() != ErrorKind::WriteZero
{
return Err(DiagDeviceError::DeviceWriteFailed(err));
}
},
DiagIO::Socket(unix_datagram) => {
unix_datagram.send(&buf)
.await
.map_err(DiagDeviceError::DeviceWriteFailed)?;
}
}
if let Err(err) = self.file.flush().await
&& err.kind() != ErrorKind::WriteZero
{
return Err(DiagDeviceError::DeviceWriteFailed(err));
}
Ok(())
}
@@ -210,6 +243,8 @@ impl DiagDevice {
loop {
let container = self.get_next_messages_container().await?;
if container.data_type != DataType::UserSpace {
info!("skipping non-userspace container...");
dbg!(&container);
continue;
}
return Ok(container.into_messages());
@@ -217,9 +252,11 @@ impl DiagDevice {
}
async fn retrieve_id_ranges(&mut self) -> DiagResult<[u32; 16]> {
info!("writing LogConfig request...");
let req = Request::LogConfig(LogConfigRequest::RetrieveIdRanges);
self.write_request(&req).await?;
info!("waiting for response...");
for msg in self.read_response().await? {
match msg {
Ok(Message::Log { .. }) => info!("skipping log response..."),
@@ -274,9 +311,11 @@ impl DiagDevice {
pub async fn config_logs(&mut self) -> DiagResult<()> {
info!("retrieving diag logging capabilities...");
let log_mask_sizes = self.retrieve_id_ranges().await?;
info!("got log mask sizes");
for (log_type, &log_mask_bitsize) in log_mask_sizes.iter().enumerate() {
if log_mask_bitsize > 0 {
info!("setting log mask for type {log_type}...");
self.set_log_mask(log_type as u32, log_mask_bitsize).await?;
info!("enabled logging for log type {log_type}");
}