mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-06-16 01:19:44 -07:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b8aa1c13a8 | |||
| 18bff68c88 | |||
| 8383342b34 | |||
| 973557e810 |
@@ -44,12 +44,11 @@ jobs:
|
||||
|
||||
# We rebuild everything if any of these conditions hold:
|
||||
# * We are on main
|
||||
# * The run was triggered by a tag
|
||||
# * Changes are made to github workflows
|
||||
# * A cargo-workspace file changed (lockfile or .cargo), as that could affect any crate anywhere
|
||||
# * Something from the script or dist folder changed (could be gated to installer, but some scripts like build_wpa_supplicant are part of the build process)
|
||||
# * #build-all was used by the user to explicitly ask for this
|
||||
if [ ${GITHUB_REF} = 'refs/heads/main' ] || [ ${GITHUB_REF_TYPE} = 'tag' ] || git diff --name-only $lcommit..HEAD | grep -qe ^.github/workflows/ -e ^.cargo -e '^Cargo\.lock$' -e '^Cargo\.toml$' -e ^dist/ -e ^scripts/ || git log -1 --format='%s %b' | grep -qF '#build-all'
|
||||
if [ ${GITHUB_REF} = 'refs/heads/main' ] || git diff --name-only $lcommit..HEAD | grep -qe ^.github/workflows/ -e ^.cargo -e '^Cargo\.lock$' -e '^Cargo\.toml$' -e ^dist/ -e ^scripts/ || git log -1 --format='%s %b' | grep -qF '#build-all'
|
||||
then
|
||||
echo "building everything"
|
||||
echo code_count=forced >> "$GITHUB_OUTPUT"
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# To learn how to use this workflow, please read CONTRIBUTING.md.
|
||||
# To use: navigate on Github to Actions, select "Release rayhunter" on the left, click "Run workflow" > "Run workflow" on the right.
|
||||
# https://github.com/EFForg/rayhunter/actions/workflows/release.yml
|
||||
name: Release rayhunter
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v[0-9]+.[0-9]+.[0-9]+"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
+6
-4
@@ -75,9 +75,11 @@ You can read our [full policy](https://www.eff.org/about/opportunities/volunteer
|
||||
This one is for maintainers of Rayhunter.
|
||||
|
||||
1. Make a PR changing the versions in `Cargo.toml` and other files.
|
||||
This can be done by running `scripts/set-versions.sh VERSION_NUM`.
|
||||
This could be automated better but right now it's manual. You can do this easily with sed:
|
||||
`sed -i "" -E 's/x.x.x/y.y.y/g' */Cargo.toml installer-gui/src-tauri/Cargo.toml`
|
||||
|
||||
2. Merge the PR, make a tag, and push the tag to GitHub. Pushing the tag should
|
||||
trigger the [release workflow](https://github.com/EFForg/rayhunter/actions/workflows/release.yml).
|
||||
2. Merge PR and make a tag.
|
||||
|
||||
3. Write changelog, edit it into the release, announce on mattermost.
|
||||
3. [Run release workflow.](https://github.com/EFForg/rayhunter/actions/workflows/release.yml)
|
||||
|
||||
4. Write changelog, edit it into the release, announce on mattermost.
|
||||
|
||||
@@ -7,18 +7,10 @@ use crate::config;
|
||||
use crate::display::DisplayState;
|
||||
|
||||
pub fn update_ui(
|
||||
task_tracker: &TaskTracker,
|
||||
_task_tracker: &TaskTracker,
|
||||
_config: &config::Config,
|
||||
shutdown_token: CancellationToken,
|
||||
mut ui_update_rx: Receiver<DisplayState>,
|
||||
_shutdown_token: CancellationToken,
|
||||
_ui_update_rx: Receiver<DisplayState>,
|
||||
) {
|
||||
info!("Headless mode, not spawning UI.");
|
||||
task_tracker.spawn(async move {
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = shutdown_token.cancelled() => break,
|
||||
_ = ui_update_rx.recv() => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Generated
+89
-107
@@ -27,7 +27,7 @@
|
||||
"tailwindcss": "^4.2.2",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.59.0",
|
||||
"vite": "^8.0.16",
|
||||
"vite": "^8.0.10",
|
||||
"vitest": "^4.1.5"
|
||||
}
|
||||
},
|
||||
@@ -329,9 +329,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-project/types": {
|
||||
"version": "0.133.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz",
|
||||
"integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==",
|
||||
"version": "0.127.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.127.0.tgz",
|
||||
"integrity": "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -346,9 +346,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@rolldown/binding-android-arm64": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz",
|
||||
"integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -363,9 +363,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-arm64": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz",
|
||||
"integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -380,9 +380,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-x64": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz",
|
||||
"integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -397,9 +397,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-freebsd-x64": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz",
|
||||
"integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -414,9 +414,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz",
|
||||
"integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -431,16 +431,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-gnu": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz",
|
||||
"integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -451,16 +448,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-musl": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz",
|
||||
"integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -471,16 +465,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz",
|
||||
"integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -491,16 +482,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-s390x-gnu": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz",
|
||||
"integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -511,16 +499,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-gnu": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz",
|
||||
"integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -531,16 +516,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-musl": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz",
|
||||
"integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -551,9 +533,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-openharmony-arm64": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz",
|
||||
"integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -568,9 +550,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-wasm32-wasi": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz",
|
||||
"integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==",
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
@@ -587,9 +569,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-arm64-msvc": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz",
|
||||
"integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -604,9 +586,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-x64-msvc": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz",
|
||||
"integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -621,9 +603,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/pluginutils": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
|
||||
"integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -2564,9 +2546,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.12",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
|
||||
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -2698,9 +2680,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.15",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
|
||||
"integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
|
||||
"version": "8.5.10",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz",
|
||||
"integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -2718,7 +2700,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.12",
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
@@ -2896,14 +2878,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rolldown": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz",
|
||||
"integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==",
|
||||
"version": "1.0.0-rc.17",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.17.tgz",
|
||||
"integrity": "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@oxc-project/types": "=0.133.0",
|
||||
"@rolldown/pluginutils": "^1.0.0"
|
||||
"@oxc-project/types": "=0.127.0",
|
||||
"@rolldown/pluginutils": "1.0.0-rc.17"
|
||||
},
|
||||
"bin": {
|
||||
"rolldown": "bin/cli.mjs"
|
||||
@@ -2912,21 +2894,21 @@
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rolldown/binding-android-arm64": "1.0.3",
|
||||
"@rolldown/binding-darwin-arm64": "1.0.3",
|
||||
"@rolldown/binding-darwin-x64": "1.0.3",
|
||||
"@rolldown/binding-freebsd-x64": "1.0.3",
|
||||
"@rolldown/binding-linux-arm-gnueabihf": "1.0.3",
|
||||
"@rolldown/binding-linux-arm64-gnu": "1.0.3",
|
||||
"@rolldown/binding-linux-arm64-musl": "1.0.3",
|
||||
"@rolldown/binding-linux-ppc64-gnu": "1.0.3",
|
||||
"@rolldown/binding-linux-s390x-gnu": "1.0.3",
|
||||
"@rolldown/binding-linux-x64-gnu": "1.0.3",
|
||||
"@rolldown/binding-linux-x64-musl": "1.0.3",
|
||||
"@rolldown/binding-openharmony-arm64": "1.0.3",
|
||||
"@rolldown/binding-wasm32-wasi": "1.0.3",
|
||||
"@rolldown/binding-win32-arm64-msvc": "1.0.3",
|
||||
"@rolldown/binding-win32-x64-msvc": "1.0.3"
|
||||
"@rolldown/binding-android-arm64": "1.0.0-rc.17",
|
||||
"@rolldown/binding-darwin-arm64": "1.0.0-rc.17",
|
||||
"@rolldown/binding-darwin-x64": "1.0.0-rc.17",
|
||||
"@rolldown/binding-freebsd-x64": "1.0.0-rc.17",
|
||||
"@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17",
|
||||
"@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17",
|
||||
"@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17",
|
||||
"@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17",
|
||||
"@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17",
|
||||
"@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17",
|
||||
"@rolldown/binding-linux-x64-musl": "1.0.0-rc.17",
|
||||
"@rolldown/binding-openharmony-arm64": "1.0.0-rc.17",
|
||||
"@rolldown/binding-wasm32-wasi": "1.0.0-rc.17",
|
||||
"@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17",
|
||||
"@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17"
|
||||
}
|
||||
},
|
||||
"node_modules/sade": {
|
||||
@@ -3201,9 +3183,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.17",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
|
||||
"integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
|
||||
"version": "0.2.16",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
|
||||
"integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -3334,17 +3316,17 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "8.0.16",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz",
|
||||
"integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==",
|
||||
"version": "8.0.10",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.10.tgz",
|
||||
"integrity": "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lightningcss": "^1.32.0",
|
||||
"picomatch": "^4.0.4",
|
||||
"postcss": "^8.5.15",
|
||||
"rolldown": "1.0.3",
|
||||
"tinyglobby": "^0.2.17"
|
||||
"postcss": "^8.5.10",
|
||||
"rolldown": "1.0.0-rc.17",
|
||||
"tinyglobby": "^0.2.16"
|
||||
},
|
||||
"bin": {
|
||||
"vite": "bin/vite.js"
|
||||
@@ -3360,7 +3342,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": "^20.19.0 || >=22.12.0",
|
||||
"@vitejs/devtools": "^0.1.18",
|
||||
"@vitejs/devtools": "^0.1.0",
|
||||
"esbuild": "^0.27.0 || ^0.28.0",
|
||||
"jiti": ">=1.21.0",
|
||||
"less": "^4.0.0",
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"tailwindcss": "^4.2.2",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.59.0",
|
||||
"vite": "^8.0.16",
|
||||
"vite": "^8.0.10",
|
||||
"vitest": "^4.1.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,13 +346,9 @@ async fn tplink_launch_telnet_v5(admin_ip: &str) -> Result<(), Error> {
|
||||
admin_ip: admin_ip.to_owned(),
|
||||
});
|
||||
|
||||
let bind_addr = "127.0.0.1:4000";
|
||||
let listener = tokio::net::TcpListener::bind(bind_addr)
|
||||
let listener = tokio::net::TcpListener::bind("127.0.0.1:4000")
|
||||
.await
|
||||
.with_context(|| format!(
|
||||
"Failed to bind to {bind_addr}. Is another process using this port?\n\
|
||||
Try closing any application that might be listening on port 4000 and rerun the installer."
|
||||
))?;
|
||||
.unwrap();
|
||||
|
||||
println!("Listening on http://{}", listener.local_addr().unwrap());
|
||||
println!("Please open above URL in your browser and log into the router to continue.");
|
||||
|
||||
@@ -0,0 +1,351 @@
|
||||
//! Diag ML1 measurement log serialization/deserialization. These are pretty
|
||||
//! much entirely based on Shinjo Park's work in scat, since we couldn't find
|
||||
//! any other documentation for the logs' structure.
|
||||
|
||||
use deku::prelude::*;
|
||||
use deku::ctx::Order;
|
||||
|
||||
fn decode_rsrp(rsrp: u16) -> f32 {
|
||||
rsrp as f32 / 16.0 - 180.0
|
||||
}
|
||||
|
||||
fn decode_rssi(rssi: u16) -> f32 {
|
||||
rssi as f32 / 16.0 - 110.0
|
||||
}
|
||||
|
||||
fn decode_rsrq(rsrq: u16) -> f32 {
|
||||
rsrq as f32 / 16.0 - 30.0
|
||||
}
|
||||
|
||||
pub mod serving_cell {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
#[deku(bit_order = "lsb")]
|
||||
pub struct MeasurementAndEvaluation {
|
||||
pub header: MeasurementAndEvaluationHeader,
|
||||
#[deku(bits = 12, pad_bits_after = "20")]
|
||||
meas_rsrp: u16,
|
||||
avg_rsrp: u32,
|
||||
#[deku(bits = 10, pad_bits_after = "22")]
|
||||
meas_rsrq: u16,
|
||||
#[deku(pad_bits_before = "10", bits = 11, pad_bits_after = "11")]
|
||||
meas_rssi: u16,
|
||||
rxlev: u32,
|
||||
s_search: u32,
|
||||
#[deku(cond = "header.get_rrc_rel() == 0x01")]
|
||||
r9_data: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
#[deku(ctx = "_: Order", id_type = "u8", bit_order = "lsb")]
|
||||
pub enum MeasurementAndEvaluationHeader {
|
||||
#[deku(id = "4")]
|
||||
V4 {
|
||||
rrc_rel: u8,
|
||||
_reserved: u16,
|
||||
earfcn: u16,
|
||||
#[deku(bits = 9)]
|
||||
pci: u16,
|
||||
#[deku(bits = 7)]
|
||||
serv_layer_priority: u8,
|
||||
},
|
||||
#[deku(id = "5")]
|
||||
V5 {
|
||||
rrc_rel: u8,
|
||||
_reserved: u16,
|
||||
earfcn: u32,
|
||||
#[deku(bits = 9)]
|
||||
pci: u16,
|
||||
#[deku(bits = 7, pad_bytes_after = "2")]
|
||||
serv_layer_priority: u8,
|
||||
},
|
||||
}
|
||||
|
||||
impl MeasurementAndEvaluationHeader {
|
||||
fn get_rrc_rel(&self) -> u8 {
|
||||
match self {
|
||||
MeasurementAndEvaluationHeader::V4 { rrc_rel, .. } => *rrc_rel,
|
||||
MeasurementAndEvaluationHeader::V5 { rrc_rel, .. } => *rrc_rel,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MeasurementAndEvaluation {
|
||||
pub fn get_pci(&self) -> u16 {
|
||||
match &self.header {
|
||||
MeasurementAndEvaluationHeader::V4 { pci, .. } => *pci,
|
||||
MeasurementAndEvaluationHeader::V5 { pci, .. } => *pci,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_earfcn(&self) -> u32 {
|
||||
match &self.header {
|
||||
MeasurementAndEvaluationHeader::V4 { earfcn, .. } => *earfcn as u32,
|
||||
MeasurementAndEvaluationHeader::V5 { earfcn, .. } => *earfcn,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_meas_rsrp(&self) -> f32 {
|
||||
decode_rsrp(self.meas_rsrp)
|
||||
}
|
||||
|
||||
pub fn get_meas_rssi(&self) -> f32 {
|
||||
decode_rssi(self.meas_rssi)
|
||||
}
|
||||
|
||||
pub fn get_meas_rsrq(&self) -> f32 {
|
||||
decode_rsrq(self.meas_rsrq)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod neighbor_cells {
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone, Debug, DekuRead, DekuWrite, PartialEq)]
|
||||
#[deku(id_type = "u8", bit_order = "lsb")]
|
||||
pub enum MeasurementsHeader {
|
||||
#[deku(id = "4")]
|
||||
V4 {
|
||||
rrc_rel: u8,
|
||||
_reserved1: u16,
|
||||
earfcn: u16,
|
||||
#[deku(bits = 6)]
|
||||
q_rxlevmin: u8,
|
||||
#[deku(bits = 10)]
|
||||
n_cells: u16,
|
||||
},
|
||||
#[deku(id = "5")]
|
||||
V5 {
|
||||
rrc_rel: u8,
|
||||
_reserved1: u16,
|
||||
earfcn: u32,
|
||||
#[deku(bits = 6)]
|
||||
q_rxlevmin: u8,
|
||||
#[deku(bits = 26)]
|
||||
n_cells: u32,
|
||||
},
|
||||
}
|
||||
|
||||
impl MeasurementsHeader {
|
||||
fn get_n_cells(&self) -> usize {
|
||||
match self {
|
||||
MeasurementsHeader::V4 { n_cells, .. } => *n_cells as usize,
|
||||
MeasurementsHeader::V5 { n_cells, .. } => *n_cells as usize,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, DekuRead, DekuWrite, PartialEq)]
|
||||
pub struct Measurements {
|
||||
pub header: MeasurementsHeader,
|
||||
#[deku(count = "header.get_n_cells()")]
|
||||
pub cells: Vec<MeasurementsCell>
|
||||
}
|
||||
|
||||
impl Measurements {
|
||||
pub fn get_earfcn(&self) -> u32 {
|
||||
match &self.header {
|
||||
MeasurementsHeader::V4 { earfcn, .. } => *earfcn as u32,
|
||||
MeasurementsHeader::V5 { earfcn, .. } => *earfcn,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug, DekuRead, DekuWrite, PartialEq)]
|
||||
#[deku(bit_order = "lsb")]
|
||||
pub struct MeasurementsCell {
|
||||
#[deku(bits = 9)]
|
||||
pub pci: u16,
|
||||
#[deku(bits = 11)]
|
||||
meas_rssi: u16,
|
||||
#[deku(bits = 12)]
|
||||
meas_rsrp: u16,
|
||||
#[deku(pad_bits_before = "12", bits = 12, pad_bits_after = "8")]
|
||||
avg_rsrp: u16,
|
||||
#[deku(pad_bits_before = "12", bits = 10, pad_bits_after = "10")]
|
||||
meas_rsrq: u16,
|
||||
#[deku(bits = 10, pad_bits_after = "10")]
|
||||
avg_rsrq: u16,
|
||||
#[deku(bits = 6, pad_bits_after = "6")]
|
||||
s_rxlev: u16,
|
||||
n_freq_offset: u16,
|
||||
val5: u16,
|
||||
ant0_offset: u32,
|
||||
ant1_offset: u32,
|
||||
unk1: u32,
|
||||
}
|
||||
|
||||
impl MeasurementsCell {
|
||||
pub fn get_meas_rsrp(&self) -> f32 {
|
||||
decode_rsrp(self.meas_rsrp)
|
||||
}
|
||||
|
||||
pub fn get_meas_rssi(&self) -> f32 {
|
||||
decode_rssi(self.meas_rssi)
|
||||
}
|
||||
|
||||
pub fn get_meas_rsrq(&self) -> f32 {
|
||||
decode_rsrq(self.meas_rsrq)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::diag::diaglog::LogBody;
|
||||
use crate::log_codes::{LOG_LTE_ML1_NEIGHBOR_MEAS, LOG_LTE_ML1_SERVING_CELL_MEAS_RESP_AND_EVAL};
|
||||
use std::io::{Cursor, Seek};
|
||||
|
||||
fn unhexlify(hexlified_bytes: &str) -> (usize, Reader<Cursor<Vec<u8>>>) {
|
||||
let byte_len = hexlified_bytes.len() / 2;
|
||||
let bytes = (0..hexlified_bytes.len())
|
||||
.step_by(2)
|
||||
.map(|i| u8::from_str_radix(&hexlified_bytes[i..i+2], 16).unwrap())
|
||||
.collect();
|
||||
(byte_len, Reader::new(Cursor::new(bytes)))
|
||||
}
|
||||
|
||||
fn parse_ncell_measurements(hexlified_bytes: &str) -> (u8, neighbor_cells::Measurements) {
|
||||
let (total_size, mut reader) = unhexlify(hexlified_bytes);
|
||||
match LogBody::from_reader_with_ctx(&mut reader, (LOG_LTE_ML1_NEIGHBOR_MEAS as u16, 0)) {
|
||||
Ok(LogBody::LteMl1NeighborCellsMeasurements { data }) => {
|
||||
if !reader.end() {
|
||||
let leftover_bits = reader.rest();
|
||||
let leftover_bytes = total_size - reader.stream_position().unwrap() as usize;
|
||||
panic!("failed to read entire buffer ({} bytes, {} bits left)", leftover_bytes, leftover_bits.len());
|
||||
}
|
||||
let pkt_version = match data.header {
|
||||
neighbor_cells::MeasurementsHeader::V4 { .. } => 4,
|
||||
neighbor_cells::MeasurementsHeader::V5 { .. } => 5,
|
||||
};
|
||||
(pkt_version, data)
|
||||
},
|
||||
Ok(x) => panic!("expected MeasurementAndEvaluation, but parsed {:?}", x),
|
||||
Err(x) => panic!("failed to parse MeasurementAndEvaluation {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_meas_eval(hexlified_bytes: &str) -> (u8, serving_cell::MeasurementAndEvaluation) {
|
||||
let (total_size, mut reader) = unhexlify(hexlified_bytes);
|
||||
match LogBody::from_reader_with_ctx(&mut reader, (LOG_LTE_ML1_SERVING_CELL_MEAS_RESP_AND_EVAL as u16, 0)) {
|
||||
Ok(LogBody::LteMl1ServingCellMeasurementAndEvaluation { data }) => {
|
||||
if !reader.end() {
|
||||
let leftover_bits = reader.rest();
|
||||
let leftover_bytes = total_size - reader.stream_position().unwrap() as usize;
|
||||
panic!("failed to read entire buffer ({} bytes, {} bits left)", leftover_bytes, leftover_bits.len());
|
||||
}
|
||||
let pkt_version = match data.header {
|
||||
serving_cell::MeasurementAndEvaluationHeader::V4 { .. } => 4,
|
||||
serving_cell::MeasurementAndEvaluationHeader::V5 { .. } => 5,
|
||||
};
|
||||
(pkt_version, data)
|
||||
},
|
||||
Ok(x) => panic!("expected MeasurementAndEvaluation, but parsed {:?}", x),
|
||||
Err(x) => panic!("failed to parse MeasurementAndEvaluation {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
fn scell_meas_and_eval_case(
|
||||
hexlified_bytes: &str,
|
||||
pkt_version: u8,
|
||||
pci: u16,
|
||||
earfcn: u32,
|
||||
rsrp: f32,
|
||||
rsrq: f32,
|
||||
rssi: f32
|
||||
) {
|
||||
let (parsed_pkt_version, data) = parse_meas_eval(hexlified_bytes);
|
||||
assert_eq!(parsed_pkt_version, pkt_version);
|
||||
assert_eq!(data.get_pci(), pci, "incorrect pci");
|
||||
assert_eq!(data.get_earfcn(), earfcn, "incorrect earfcn");
|
||||
assert_eq!(data.get_meas_rsrp(), rsrp, "incorrect rsrp");
|
||||
assert_eq!(data.get_meas_rsrq(), rsrq, "incorrect rsrq");
|
||||
assert_eq!(data.get_meas_rssi(), rssi, "incorrect rssi");
|
||||
}
|
||||
|
||||
// Adapted from scat's TestDiagLteLogParser::test_parse_lte_ml1_scell_meas,
|
||||
// but edited to print full-precision floats
|
||||
#[test]
|
||||
fn test_scell_meas() {
|
||||
scell_meas_and_eval_case(
|
||||
"040100009C18D60AECC44E00E2244E00FFFCE30FFED80A0047AD56021D310100A2624100",
|
||||
4,
|
||||
214,
|
||||
6300,
|
||||
-101.25,
|
||||
-14.0625,
|
||||
-66.625
|
||||
);
|
||||
scell_meas_and_eval_case(
|
||||
"05010000160d0000d40e00004bb444005444450039e514133149070048adfe019f310100a23f0000",
|
||||
5,
|
||||
212,
|
||||
3350,
|
||||
-111.3125,
|
||||
-10.4375,
|
||||
-80.875,
|
||||
);
|
||||
scell_meas_and_eval_case(
|
||||
"05010000f424000a4d43434d4e434d41524b45527c307c3236327c317c34323330333233347c7c4d",
|
||||
5,
|
||||
333,
|
||||
167781620,
|
||||
-127.125,
|
||||
-22.25,
|
||||
2.75,
|
||||
);
|
||||
scell_meas_and_eval_case(
|
||||
"0501000000190000a90d0000d9944d00d9944d006081d5d55d2568bc48ad3e027f314fe0891900e0",
|
||||
5,
|
||||
425,
|
||||
6400,
|
||||
-102.4375,
|
||||
-8.0,
|
||||
-77.4375,
|
||||
);
|
||||
}
|
||||
|
||||
fn ncell_meas_case(
|
||||
hexlified_bytes: &str,
|
||||
pkt_version: u8,
|
||||
earfcn: u32,
|
||||
cells: Vec<(u16, f32, f32, f32)>,
|
||||
) {
|
||||
let (parsed_pkt_version, data) = parse_ncell_measurements(hexlified_bytes);
|
||||
assert_eq!(parsed_pkt_version, pkt_version, "incorrect pkt_version");
|
||||
assert_eq!(data.cells.len(), cells.len(), "incorrect number of cells");
|
||||
assert_eq!(data.get_earfcn(), earfcn, "incorrect earfcn");
|
||||
for (parsed, (pci, rsrp, rssi, rsrq)) in data.cells.iter().zip(cells) {
|
||||
assert_eq!(parsed.pci, pci, "incorrect pci");
|
||||
assert_eq!(parsed.get_meas_rsrp(), rsrp, "incorrect rsrp");
|
||||
assert_eq!(parsed.get_meas_rssi(), rssi, "incorrect rssi");
|
||||
assert_eq!(parsed.get_meas_rsrq(), rsrq, "incorrect rsrq");
|
||||
}
|
||||
}
|
||||
|
||||
// Adapted from scat's TestDiagLteLogParser::test_parse_lte_ml1_ncell_meas,
|
||||
// but edited to print full-precision floats
|
||||
#[test]
|
||||
fn test_ncell_meas() {
|
||||
ncell_meas_case(
|
||||
"040100009C1847008348E44DDEA44C00CAB4CC32B6D8420300000000FF773301FF77330122020100",
|
||||
4,
|
||||
6300,
|
||||
vec![
|
||||
(131, -102.125, -75.75, -17.3125),
|
||||
]
|
||||
);
|
||||
ncell_meas_case(
|
||||
"05010000160d0000480000006cea413bb4433b00b4f3cc33cf3c130200000000ffefc00fffefc00f45081600",
|
||||
5,
|
||||
3350,
|
||||
vec![
|
||||
(108, -120.75, -94.6875, -17.0625),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
//! Diag LogBody serialization/deserialization
|
||||
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use deku::prelude::*;
|
||||
|
||||
pub mod measurement;
|
||||
pub mod rrc;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
#[deku(ctx = "log_type: u16, hdr_len: u16", id = "log_type")]
|
||||
pub enum LogBody {
|
||||
#[deku(id = "0x412f")]
|
||||
WcdmaSignallingMessage {
|
||||
channel_type: u8,
|
||||
radio_bearer: u8,
|
||||
length: u16,
|
||||
#[deku(count = "length")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0x512f")]
|
||||
GsmRrSignallingMessage {
|
||||
channel_type: u8,
|
||||
message_type: u8,
|
||||
length: u8,
|
||||
#[deku(count = "length")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0x5226")]
|
||||
GprsMacSignallingMessage {
|
||||
channel_type: u8,
|
||||
message_type: u8,
|
||||
length: u8,
|
||||
#[deku(count = "length")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0xb0c0")]
|
||||
LteRrcOtaMessage {
|
||||
ext_header_version: u8,
|
||||
#[deku(ctx = "*ext_header_version")]
|
||||
packet: rrc::LteRrcOtaPacket,
|
||||
},
|
||||
// the four NAS command opcodes refer to:
|
||||
// * 0xb0e2: plain ESM NAS message (incoming)
|
||||
// * 0xb0e3: plain ESM NAS message (outgoing)
|
||||
// * 0xb0ec: plain EMM NAS message (incoming)
|
||||
// * 0xb0ed: plain EMM NAS message (outgoing)
|
||||
#[deku(id_pat = "0xb0e2 | 0xb0e3 | 0xb0ec | 0xb0ed")]
|
||||
Nas4GMessage {
|
||||
#[deku(skip, default = "log_type")]
|
||||
log_type: u16,
|
||||
#[deku(ctx = "*log_type")]
|
||||
direction: Nas4GMessageDirection,
|
||||
ext_header_version: u8,
|
||||
rrc_rel: u8,
|
||||
rrc_version_minor: u8,
|
||||
rrc_version_major: u8,
|
||||
// message length = hdr_len - (sizeof(ext_header_version) + sizeof(rrc_rel) + sizeof(rrc_version_minor) + sizeof(rrc_version_major))
|
||||
#[deku(count = "hdr_len.saturating_sub(4)")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0x11eb")]
|
||||
IpTraffic {
|
||||
// is this right?? based on https://github.com/P1sec/QCSuper/blob/81dbaeee15ec7747e899daa8e3495e27cdcc1264/src/modules/pcap_dump.py#L378
|
||||
#[deku(count = "hdr_len.saturating_sub(8)")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0x713a")]
|
||||
UmtsNasOtaMessage {
|
||||
is_uplink: u8,
|
||||
length: u32,
|
||||
#[deku(count = "length")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0xb821")]
|
||||
NrRrcOtaMessage {
|
||||
#[deku(count = "hdr_len")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0xb17f")]
|
||||
LteMl1ServingCellMeasurementAndEvaluation {
|
||||
data: measurement::serving_cell::MeasurementAndEvaluation,
|
||||
},
|
||||
#[deku(id = "0xb180")]
|
||||
LteMl1NeighborCellsMeasurements {
|
||||
data: measurement::neighbor_cells::Measurements,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
#[deku(ctx = "log_type: u16", id = "log_type")]
|
||||
pub enum Nas4GMessageDirection {
|
||||
// * 0xb0e2: plain ESM NAS message (incoming)
|
||||
// * 0xb0e3: plain ESM NAS message (outgoing)
|
||||
// * 0xb0ec: plain EMM NAS message (incoming)
|
||||
// * 0xb0ed: plain EMM NAS message (outgoing)
|
||||
#[deku(id_pat = "0xb0e2 | 0xb0ec")]
|
||||
Downlink,
|
||||
#[deku(id_pat = "0xb0e3 | 0xb0ed")]
|
||||
Uplink,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
#[deku(endian = "little")]
|
||||
pub struct Timestamp {
|
||||
pub ts: u64,
|
||||
}
|
||||
|
||||
impl Timestamp {
|
||||
pub fn to_datetime(&self) -> DateTime<FixedOffset> {
|
||||
// Upper 48 bits: epoch at 1980-01-06 00:00:00, incremented by 1 for 1/800s
|
||||
// Lower 16 bits: time since last 1/800s tick in 1/32 chip units
|
||||
let ts_upper = self.ts >> 16;
|
||||
let ts_lower = self.ts & 0xffff;
|
||||
let epoch = chrono::DateTime::parse_from_rfc3339("1980-01-06T00:00:00-00:00").unwrap();
|
||||
let mut delta_seconds = ts_upper as f64 * 1.25;
|
||||
delta_seconds += ts_lower as f64 / 40960.0;
|
||||
let ts_delta = chrono::Duration::milliseconds(delta_seconds as i64);
|
||||
epoch + ts_delta
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::diag::Message;
|
||||
|
||||
#[test]
|
||||
fn test_logs() {
|
||||
let data = vec![
|
||||
16, 0, 38, 0, 38, 0, 192, 176, 26, 165, 245, 135, 118, 35, 2, 1, 20, 14, 48, 0, 160, 0,
|
||||
2, 8, 0, 0, 217, 15, 5, 0, 0, 0, 0, 7, 0, 64, 1, 238, 173, 213, 77, 208,
|
||||
];
|
||||
let msg = Message::from_bytes((&data, 0)).unwrap().1;
|
||||
assert_eq!(
|
||||
msg,
|
||||
Message::Log {
|
||||
pending_msgs: 0,
|
||||
outer_length: 38,
|
||||
inner_length: 38,
|
||||
log_type: 0xb0c0,
|
||||
timestamp: Timestamp {
|
||||
ts: 72659535985485082
|
||||
},
|
||||
body: LogBody::LteRrcOtaMessage {
|
||||
ext_header_version: 20,
|
||||
packet: rrc::LteRrcOtaPacket::V8 {
|
||||
rrc_rel_maj: 14,
|
||||
rrc_rel_min: 48,
|
||||
bearer_id: 0,
|
||||
phy_cell_id: 160,
|
||||
earfcn: 2050,
|
||||
sfn_subfn: 4057,
|
||||
pdu_num: 5,
|
||||
sib_mask: 0,
|
||||
len: 7,
|
||||
packet: vec![0x40, 0x1, 0xee, 0xad, 0xd5, 0x4d, 0xd0],
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fuzz_crash_inner_length_underflow() {
|
||||
// Regression test: inner_length < 12 previously caused panic.
|
||||
// Fixed by using saturating_sub in Message::Log body length calculation.
|
||||
let fuzz_data = b"\x10\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
let _ = Message::from_bytes((fuzz_data, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fuzz_crash_nas_hdr_len_underflow() {
|
||||
// Regression test for two things:
|
||||
// - hdr_len < 4 previously caused panic in Nas4GMessage.
|
||||
// - Upgrading to deku 0.20 caused incorrect parsing behavior (double-read of discriminant)
|
||||
let nas_msg =
|
||||
b"\x10\x00\x14\x00\x02\x00\xe2\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00";
|
||||
|
||||
let ((rest, _), msg) = Message::from_bytes((nas_msg, 0)).unwrap();
|
||||
|
||||
assert_eq!(rest.len(), 0);
|
||||
assert!(
|
||||
matches!(
|
||||
msg,
|
||||
Message::Log {
|
||||
log_type: 0xb0e2,
|
||||
body: LogBody::Nas4GMessage {
|
||||
direction: Nas4GMessageDirection::Downlink,
|
||||
..
|
||||
},
|
||||
..
|
||||
}
|
||||
),
|
||||
"Unexpected message: {:?}",
|
||||
msg
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fuzz_crash_ip_traffic_hdr_len_underflow() {
|
||||
// Regression test: hdr_len < 8 previously caused panic in IpTraffic.
|
||||
// Fixed by using saturating_sub for msg length calculation.
|
||||
let ip_msg = b"\x10\x00\x14\x00\x02\x00\xeb\x11\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00";
|
||||
let _ = Message::from_bytes((ip_msg, 0));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
//! Diag LTE RRC serialization/deserialization
|
||||
|
||||
use deku::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
#[deku(ctx = "ext_header_version: u8", id = "ext_header_version")]
|
||||
pub enum LteRrcOtaPacket {
|
||||
#[deku(id_pat = "0..=4")]
|
||||
V0 {
|
||||
rrc_rel_maj: u8,
|
||||
rrc_rel_min: u8,
|
||||
bearer_id: u8,
|
||||
phy_cell_id: u16,
|
||||
earfcn: u16,
|
||||
sfn_subfn: u16,
|
||||
pdu_num: u8,
|
||||
len: u16,
|
||||
#[deku(count = "len")]
|
||||
packet: Vec<u8>,
|
||||
},
|
||||
#[deku(id_pat = "5..=7")]
|
||||
V5 {
|
||||
rrc_rel_maj: u8,
|
||||
rrc_rel_min: u8,
|
||||
bearer_id: u8,
|
||||
phy_cell_id: u16,
|
||||
earfcn: u16,
|
||||
sfn_subfn: u16,
|
||||
pdu_num: u8,
|
||||
sib_mask: u32,
|
||||
len: u16,
|
||||
#[deku(count = "len")]
|
||||
packet: Vec<u8>,
|
||||
},
|
||||
#[deku(id_pat = "8..=24")]
|
||||
V8 {
|
||||
rrc_rel_maj: u8,
|
||||
rrc_rel_min: u8,
|
||||
bearer_id: u8,
|
||||
phy_cell_id: u16,
|
||||
earfcn: u32,
|
||||
sfn_subfn: u16,
|
||||
pdu_num: u8,
|
||||
sib_mask: u32,
|
||||
len: u16,
|
||||
#[deku(count = "len")]
|
||||
packet: Vec<u8>,
|
||||
},
|
||||
#[deku(id_pat = "25..")]
|
||||
V25 {
|
||||
rrc_rel_maj: u8,
|
||||
rrc_rel_min: u8,
|
||||
nr_rrc_rel_maj: u8,
|
||||
nr_rrc_rel_min: u8,
|
||||
bearer_id: u8,
|
||||
phy_cell_id: u16,
|
||||
earfcn: u32,
|
||||
sfn_subfn: u16,
|
||||
pdu_num: u8,
|
||||
sib_mask: u32,
|
||||
len: u16,
|
||||
#[deku(count = "len")]
|
||||
packet: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
impl LteRrcOtaPacket {
|
||||
fn get_sfn_subfn(&self) -> u16 {
|
||||
match self {
|
||||
LteRrcOtaPacket::V0 { sfn_subfn, .. } => *sfn_subfn,
|
||||
LteRrcOtaPacket::V5 { sfn_subfn, .. } => *sfn_subfn,
|
||||
LteRrcOtaPacket::V8 { sfn_subfn, .. } => *sfn_subfn,
|
||||
LteRrcOtaPacket::V25 { sfn_subfn, .. } => *sfn_subfn,
|
||||
}
|
||||
}
|
||||
pub fn get_sfn(&self) -> u32 {
|
||||
self.get_sfn_subfn() as u32 >> 4
|
||||
}
|
||||
|
||||
pub fn get_subfn(&self) -> u8 {
|
||||
(self.get_sfn_subfn() & 0xf) as u8
|
||||
}
|
||||
|
||||
pub fn get_pdu_num(&self) -> u8 {
|
||||
match self {
|
||||
LteRrcOtaPacket::V0 { pdu_num, .. } => *pdu_num,
|
||||
LteRrcOtaPacket::V5 { pdu_num, .. } => *pdu_num,
|
||||
LteRrcOtaPacket::V8 { pdu_num, .. } => *pdu_num,
|
||||
LteRrcOtaPacket::V25 { pdu_num, .. } => *pdu_num,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_earfcn(&self) -> u32 {
|
||||
match self {
|
||||
LteRrcOtaPacket::V0 { earfcn, .. } => *earfcn as u32,
|
||||
LteRrcOtaPacket::V5 { earfcn, .. } => *earfcn as u32,
|
||||
LteRrcOtaPacket::V8 { earfcn, .. } => *earfcn,
|
||||
LteRrcOtaPacket::V25 { earfcn, .. } => *earfcn,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take_payload(self) -> Vec<u8> {
|
||||
match self {
|
||||
LteRrcOtaPacket::V0 { packet, .. } => packet,
|
||||
LteRrcOtaPacket::V5 { packet, .. } => packet,
|
||||
LteRrcOtaPacket::V8 { packet, .. } => packet,
|
||||
LteRrcOtaPacket::V25 { packet, .. } => packet,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
//! Diag protocol serialization/deserialization
|
||||
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use crc::{Algorithm, Crc};
|
||||
use deku::prelude::*;
|
||||
|
||||
@@ -8,6 +7,10 @@ use crate::hdlc::{self, hdlc_decapsulate};
|
||||
use log::warn;
|
||||
use thiserror::Error;
|
||||
|
||||
pub mod diaglog;
|
||||
|
||||
use diaglog::{LogBody, Timestamp};
|
||||
|
||||
pub const MESSAGE_TERMINATOR: u8 = 0x7e;
|
||||
pub const MESSAGE_ESCAPE_CHAR: u8 = 0x7d;
|
||||
|
||||
@@ -152,218 +155,6 @@ pub enum Message {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
#[deku(ctx = "log_type: u16, hdr_len: u16", id = "log_type")]
|
||||
pub enum LogBody {
|
||||
#[deku(id = "0x412f")]
|
||||
WcdmaSignallingMessage {
|
||||
channel_type: u8,
|
||||
radio_bearer: u8,
|
||||
length: u16,
|
||||
#[deku(count = "length")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0x512f")]
|
||||
GsmRrSignallingMessage {
|
||||
channel_type: u8,
|
||||
message_type: u8,
|
||||
length: u8,
|
||||
#[deku(count = "length")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0x5226")]
|
||||
GprsMacSignallingMessage {
|
||||
channel_type: u8,
|
||||
message_type: u8,
|
||||
length: u8,
|
||||
#[deku(count = "length")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0xb0c0")]
|
||||
LteRrcOtaMessage {
|
||||
ext_header_version: u8,
|
||||
#[deku(ctx = "*ext_header_version")]
|
||||
packet: LteRrcOtaPacket,
|
||||
},
|
||||
// the four NAS command opcodes refer to:
|
||||
// * 0xb0e2: plain ESM NAS message (incoming)
|
||||
// * 0xb0e3: plain ESM NAS message (outgoing)
|
||||
// * 0xb0ec: plain EMM NAS message (incoming)
|
||||
// * 0xb0ed: plain EMM NAS message (outgoing)
|
||||
#[deku(id_pat = "0xb0e2 | 0xb0e3 | 0xb0ec | 0xb0ed")]
|
||||
Nas4GMessage {
|
||||
#[deku(skip, default = "log_type")]
|
||||
log_type: u16,
|
||||
#[deku(ctx = "*log_type")]
|
||||
direction: Nas4GMessageDirection,
|
||||
ext_header_version: u8,
|
||||
rrc_rel: u8,
|
||||
rrc_version_minor: u8,
|
||||
rrc_version_major: u8,
|
||||
// message length = hdr_len - (sizeof(ext_header_version) + sizeof(rrc_rel) + sizeof(rrc_version_minor) + sizeof(rrc_version_major))
|
||||
#[deku(count = "hdr_len.saturating_sub(4)")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0x11eb")]
|
||||
IpTraffic {
|
||||
// is this right?? based on https://github.com/P1sec/QCSuper/blob/81dbaeee15ec7747e899daa8e3495e27cdcc1264/src/modules/pcap_dump.py#L378
|
||||
#[deku(count = "hdr_len.saturating_sub(8)")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0x713a")]
|
||||
UmtsNasOtaMessage {
|
||||
is_uplink: u8,
|
||||
length: u32,
|
||||
#[deku(count = "length")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
#[deku(id = "0xb821")]
|
||||
NrRrcOtaMessage {
|
||||
#[deku(count = "hdr_len")]
|
||||
msg: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
#[deku(ctx = "log_type: u16", id = "log_type")]
|
||||
pub enum Nas4GMessageDirection {
|
||||
// * 0xb0e2: plain ESM NAS message (incoming)
|
||||
// * 0xb0e3: plain ESM NAS message (outgoing)
|
||||
// * 0xb0ec: plain EMM NAS message (incoming)
|
||||
// * 0xb0ed: plain EMM NAS message (outgoing)
|
||||
#[deku(id_pat = "0xb0e2 | 0xb0ec")]
|
||||
Downlink,
|
||||
#[deku(id_pat = "0xb0e3 | 0xb0ed")]
|
||||
Uplink,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
#[deku(ctx = "ext_header_version: u8", id = "ext_header_version")]
|
||||
pub enum LteRrcOtaPacket {
|
||||
#[deku(id_pat = "0..=4")]
|
||||
V0 {
|
||||
rrc_rel_maj: u8,
|
||||
rrc_rel_min: u8,
|
||||
bearer_id: u8,
|
||||
phy_cell_id: u16,
|
||||
earfcn: u16,
|
||||
sfn_subfn: u16,
|
||||
pdu_num: u8,
|
||||
len: u16,
|
||||
#[deku(count = "len")]
|
||||
packet: Vec<u8>,
|
||||
},
|
||||
#[deku(id_pat = "5..=7")]
|
||||
V5 {
|
||||
rrc_rel_maj: u8,
|
||||
rrc_rel_min: u8,
|
||||
bearer_id: u8,
|
||||
phy_cell_id: u16,
|
||||
earfcn: u16,
|
||||
sfn_subfn: u16,
|
||||
pdu_num: u8,
|
||||
sib_mask: u32,
|
||||
len: u16,
|
||||
#[deku(count = "len")]
|
||||
packet: Vec<u8>,
|
||||
},
|
||||
#[deku(id_pat = "8..=24")]
|
||||
V8 {
|
||||
rrc_rel_maj: u8,
|
||||
rrc_rel_min: u8,
|
||||
bearer_id: u8,
|
||||
phy_cell_id: u16,
|
||||
earfcn: u32,
|
||||
sfn_subfn: u16,
|
||||
pdu_num: u8,
|
||||
sib_mask: u32,
|
||||
len: u16,
|
||||
#[deku(count = "len")]
|
||||
packet: Vec<u8>,
|
||||
},
|
||||
#[deku(id_pat = "25..")]
|
||||
V25 {
|
||||
rrc_rel_maj: u8,
|
||||
rrc_rel_min: u8,
|
||||
nr_rrc_rel_maj: u8,
|
||||
nr_rrc_rel_min: u8,
|
||||
bearer_id: u8,
|
||||
phy_cell_id: u16,
|
||||
earfcn: u32,
|
||||
sfn_subfn: u16,
|
||||
pdu_num: u8,
|
||||
sib_mask: u32,
|
||||
len: u16,
|
||||
#[deku(count = "len")]
|
||||
packet: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
impl LteRrcOtaPacket {
|
||||
fn get_sfn_subfn(&self) -> u16 {
|
||||
match self {
|
||||
LteRrcOtaPacket::V0 { sfn_subfn, .. } => *sfn_subfn,
|
||||
LteRrcOtaPacket::V5 { sfn_subfn, .. } => *sfn_subfn,
|
||||
LteRrcOtaPacket::V8 { sfn_subfn, .. } => *sfn_subfn,
|
||||
LteRrcOtaPacket::V25 { sfn_subfn, .. } => *sfn_subfn,
|
||||
}
|
||||
}
|
||||
pub fn get_sfn(&self) -> u32 {
|
||||
self.get_sfn_subfn() as u32 >> 4
|
||||
}
|
||||
|
||||
pub fn get_subfn(&self) -> u8 {
|
||||
(self.get_sfn_subfn() & 0xf) as u8
|
||||
}
|
||||
|
||||
pub fn get_pdu_num(&self) -> u8 {
|
||||
match self {
|
||||
LteRrcOtaPacket::V0 { pdu_num, .. } => *pdu_num,
|
||||
LteRrcOtaPacket::V5 { pdu_num, .. } => *pdu_num,
|
||||
LteRrcOtaPacket::V8 { pdu_num, .. } => *pdu_num,
|
||||
LteRrcOtaPacket::V25 { pdu_num, .. } => *pdu_num,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_earfcn(&self) -> u32 {
|
||||
match self {
|
||||
LteRrcOtaPacket::V0 { earfcn, .. } => *earfcn as u32,
|
||||
LteRrcOtaPacket::V5 { earfcn, .. } => *earfcn as u32,
|
||||
LteRrcOtaPacket::V8 { earfcn, .. } => *earfcn,
|
||||
LteRrcOtaPacket::V25 { earfcn, .. } => *earfcn,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take_payload(self) -> Vec<u8> {
|
||||
match self {
|
||||
LteRrcOtaPacket::V0 { packet, .. } => packet,
|
||||
LteRrcOtaPacket::V5 { packet, .. } => packet,
|
||||
LteRrcOtaPacket::V8 { packet, .. } => packet,
|
||||
LteRrcOtaPacket::V25 { packet, .. } => packet,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
#[deku(endian = "little")]
|
||||
pub struct Timestamp {
|
||||
pub ts: u64,
|
||||
}
|
||||
|
||||
impl Timestamp {
|
||||
pub fn to_datetime(&self) -> DateTime<FixedOffset> {
|
||||
// Upper 48 bits: epoch at 1980-01-06 00:00:00, incremented by 1 for 1/800s
|
||||
// Lower 16 bits: time since last 1/800s tick in 1/32 chip units
|
||||
let ts_upper = self.ts >> 16;
|
||||
let ts_lower = self.ts & 0xffff;
|
||||
let epoch = chrono::DateTime::parse_from_rfc3339("1980-01-06T00:00:00-00:00").unwrap();
|
||||
let mut delta_seconds = ts_upper as f64 * 1.25;
|
||||
delta_seconds += ts_lower as f64 / 40960.0;
|
||||
let ts_delta = chrono::Duration::milliseconds(delta_seconds as i64);
|
||||
epoch + ts_delta
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
#[deku(ctx = "opcode: u32, subopcode: u32", id = "opcode")]
|
||||
pub enum ResponsePayload {
|
||||
@@ -478,42 +269,6 @@ mod test {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_logs() {
|
||||
let data = vec![
|
||||
16, 0, 38, 0, 38, 0, 192, 176, 26, 165, 245, 135, 118, 35, 2, 1, 20, 14, 48, 0, 160, 0,
|
||||
2, 8, 0, 0, 217, 15, 5, 0, 0, 0, 0, 7, 0, 64, 1, 238, 173, 213, 77, 208,
|
||||
];
|
||||
let msg = Message::from_bytes((&data, 0)).unwrap().1;
|
||||
assert_eq!(
|
||||
msg,
|
||||
Message::Log {
|
||||
pending_msgs: 0,
|
||||
outer_length: 38,
|
||||
inner_length: 38,
|
||||
log_type: 0xb0c0,
|
||||
timestamp: Timestamp {
|
||||
ts: 72659535985485082
|
||||
},
|
||||
body: LogBody::LteRrcOtaMessage {
|
||||
ext_header_version: 20,
|
||||
packet: LteRrcOtaPacket::V8 {
|
||||
rrc_rel_maj: 14,
|
||||
rrc_rel_min: 48,
|
||||
bearer_id: 0,
|
||||
phy_cell_id: 160,
|
||||
earfcn: 2050,
|
||||
sfn_subfn: 4057,
|
||||
pdu_num: 5,
|
||||
sib_mask: 0,
|
||||
len: 7,
|
||||
packet: vec![0x40, 0x1, 0xee, 0xad, 0xd5, 0x4d, 0xd0],
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
fn make_container(data_type: DataType, message: HdlcEncapsulatedMessage) -> MessagesContainer {
|
||||
MessagesContainer {
|
||||
data_type,
|
||||
@@ -537,7 +292,7 @@ mod test {
|
||||
},
|
||||
body: LogBody::LteRrcOtaMessage {
|
||||
ext_header_version: 20,
|
||||
packet: LteRrcOtaPacket::V8 {
|
||||
packet: diaglog::rrc::LteRrcOtaPacket::V8 {
|
||||
rrc_rel_maj: 14,
|
||||
rrc_rel_min: 48,
|
||||
bearer_id: 0,
|
||||
@@ -619,50 +374,6 @@ mod test {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fuzz_crash_inner_length_underflow() {
|
||||
// Regression test: inner_length < 12 previously caused panic.
|
||||
// Fixed by using saturating_sub in Message::Log body length calculation.
|
||||
let fuzz_data = b"\x10\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
let _ = Message::from_bytes((fuzz_data, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fuzz_crash_nas_hdr_len_underflow() {
|
||||
// Regression test for two things:
|
||||
// - hdr_len < 4 previously caused panic in Nas4GMessage.
|
||||
// - Upgrading to deku 0.20 caused incorrect parsing behavior (double-read of discriminant)
|
||||
let nas_msg =
|
||||
b"\x10\x00\x14\x00\x02\x00\xe2\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00";
|
||||
|
||||
let ((rest, _), msg) = Message::from_bytes((nas_msg, 0)).unwrap();
|
||||
|
||||
assert_eq!(rest.len(), 0);
|
||||
assert!(
|
||||
matches!(
|
||||
msg,
|
||||
Message::Log {
|
||||
log_type: 0xb0e2,
|
||||
body: LogBody::Nas4GMessage {
|
||||
direction: Nas4GMessageDirection::Downlink,
|
||||
..
|
||||
},
|
||||
..
|
||||
}
|
||||
),
|
||||
"Unexpected message: {:?}",
|
||||
msg
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fuzz_crash_ip_traffic_hdr_len_underflow() {
|
||||
// Regression test: hdr_len < 8 previously caused panic in IpTraffic.
|
||||
// Fixed by using saturating_sub for msg length calculation.
|
||||
let ip_msg = b"\x10\x00\x14\x00\x02\x00\xeb\x11\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00";
|
||||
let _ = Message::from_bytes((ip_msg, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fuzz_crash_response_opcode_parsing() {
|
||||
// Regression test: Upgrading to deku 0.20 caused incorrect parsing of Response messages.
|
||||
@@ -40,7 +40,7 @@ pub enum DiagDeviceError {
|
||||
ParseMessagesContainerError(deku::DekuError),
|
||||
}
|
||||
|
||||
pub const LOG_CODES_FOR_RAW_PACKET_LOGGING: [u32; 11] = [
|
||||
pub const LOG_CODES_FOR_RAW_PACKET_LOGGING: [u32; 14] = [
|
||||
// Layer 2:
|
||||
log_codes::LOG_GPRS_MAC_SIGNALLING_MESSAGE_C, // 0x5226
|
||||
// Layer 3:
|
||||
@@ -56,6 +56,10 @@ pub const LOG_CODES_FOR_RAW_PACKET_LOGGING: [u32; 11] = [
|
||||
log_codes::LOG_LTE_NAS_EMM_OTA_OUT_MSG_LOG_C, // 0xb0ed
|
||||
// User IP traffic:
|
||||
log_codes::LOG_DATA_PROTOCOL_LOGGING_C, // 0x11eb
|
||||
// Statistics
|
||||
log_codes::LOG_LTE_ML1_SERVING_CELL_MEAS_RESP_AND_EVAL, // 0xb17f
|
||||
log_codes::LOG_LTE_ML1_SERVING_CELL_MEAS_RESPONSE, // 0xb193
|
||||
log_codes::LOG_LTE_ML1_NEIGHBOR_MEAS, // 0xb180
|
||||
];
|
||||
|
||||
const BUFFER_LEN: usize = 1024 * 1024 * 10;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::diag::*;
|
||||
use crate::gsmtap::*;
|
||||
use crate::diag::Message;
|
||||
use crate::diag::diaglog::{Timestamp, LogBody, Nas4GMessageDirection};
|
||||
use crate::gsmtap::{GsmtapHeader, GsmtapMessage, GsmtapType, LteNasSubtype, LteRrcSubtype};
|
||||
|
||||
use log::error;
|
||||
use log::debug;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@@ -153,7 +154,7 @@ fn log_to_gsmtap(value: LogBody) -> Result<Option<GsmtapMessage>, GsmtapParserEr
|
||||
}))
|
||||
}
|
||||
_ => {
|
||||
error!("gsmtap_sink: ignoring unhandled log type: {value:?}");
|
||||
debug!("gsmtap_sink: ignoring unhandled log type: {value:?}");
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,3 +103,7 @@ pub const WCDMA_SIGNALLING_MESSAGE: u32 = 0x412f;
|
||||
pub const LOG_DATA_PROTOCOL_LOGGING_C: u32 = 0x11eb;
|
||||
|
||||
pub const LOG_UMTS_NAS_OTA_MESSAGE_LOG_PACKET_C: u32 = 0x713a;
|
||||
|
||||
pub const LOG_LTE_ML1_SERVING_CELL_MEAS_RESP_AND_EVAL: u32 = 0xb17f;
|
||||
pub const LOG_LTE_ML1_SERVING_CELL_MEAS_RESPONSE: u32 = 0xb193;
|
||||
pub const LOG_LTE_ML1_NEIGHBOR_MEAS: u32 = 0xb180;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
//! Parse QMDL files and create a pcap file.
|
||||
//! Creates a plausible IP header and [GSMtap](https://osmocom.org/projects/baseband/wiki/GSMTAP) header and then puts the rest of the data under that for wireshark to parse.
|
||||
use crate::diag::Timestamp;
|
||||
use crate::diag::diaglog::Timestamp;
|
||||
use crate::gsmtap::GsmtapMessage;
|
||||
|
||||
use chrono::prelude::*;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use deku::prelude::*;
|
||||
use rayhunter::{
|
||||
diag::{LogBody, LteRrcOtaPacket, Message, Timestamp},
|
||||
diag::Message,
|
||||
diag::diaglog::{LogBody, rrc::LteRrcOtaPacket, Timestamp},
|
||||
gsmtap_parser,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Sets Rayhunter package versions in preparation for a release.
|
||||
#
|
||||
# Usage: ./scripts/set-versions.sh VERSION_NUM
|
||||
# Example: ./scripts/set-versions.sh 0.12.3
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Error: Missing required version number argument."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SED_COMMAND="s/^version = \".*\"/version = \"$1\"/"
|
||||
TOML_FILES=(*/Cargo.toml installer-gui/src-tauri/Cargo.toml)
|
||||
|
||||
echo "Updating Cargo.toml files"
|
||||
if sed --version > /dev/null 2>&1; then
|
||||
# we have GNU sed
|
||||
sed -i -E "$SED_COMMAND" "${TOML_FILES[@]}"
|
||||
else
|
||||
# we have macOS/BSD sed
|
||||
sed -i "" -E "$SED_COMMAND" "${TOML_FILES[@]}"
|
||||
fi
|
||||
|
||||
echo "Updating Cargo.lock"
|
||||
cargo update --workspace
|
||||
Reference in New Issue
Block a user