mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-04-30 01:19:58 -07:00
Merge branch 'main' into documentation
This commit is contained in:
@@ -1,11 +1,3 @@
|
||||
[build]
|
||||
target = "armv7-unknown-linux-gnueabihf"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
|
||||
[alias]
|
||||
test_pc = "test --target=x86_64-unknown-linux-gnu"
|
||||
build_pc = "build --target=x86_64-unknown-linux-gnu"
|
||||
|
||||
|
||||
[target.armv7-unknown-linux-gnueabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
|
||||
4
.github/workflows/rust.yml
vendored
4
.github/workflows/rust.yml
vendored
@@ -17,6 +17,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build
|
||||
run: cargo build_pc --verbose
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test_pc --verbose
|
||||
run: cargo test --verbose
|
||||
|
||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"fcntl.h": "c"
|
||||
}
|
||||
}
|
||||
507
Cargo.lock
generated
507
Cargo.lock
generated
@@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.7"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
|
||||
checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
@@ -59,6 +59,98 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1-codecs"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e4ed1fe0647213e739f7ea78f50d3d0f6f9bef7285f6d8672aaca8365decfc3"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1-compiler"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1d056f38f3e98ffe9808e6a482d1527e4ded46e72b3dbe77305f5508e76c5f6"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"clap",
|
||||
"env_logger",
|
||||
"heck",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"topological-sort",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1_codecs_derive"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "394acf8791d3d345ed71e2e820355c9f8ad4202a99b97e59fb7b6595b18f28cd"
|
||||
dependencies = [
|
||||
"asn1-codecs",
|
||||
"bitvec",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.77"
|
||||
@@ -67,7 +159,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
"syn 2.0.50",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -152,12 +244,6 @@ version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "1.0.1"
|
||||
@@ -166,15 +252,16 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
|
||||
dependencies = [
|
||||
"funty",
|
||||
"radium",
|
||||
"serde",
|
||||
"tap",
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.14.0"
|
||||
version = "3.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||
checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
@@ -199,12 +286,9 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.83"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@@ -214,9 +298,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.33"
|
||||
version = "0.4.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb"
|
||||
checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
@@ -224,9 +308,55 @@ dependencies = [
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-targets 0.52.0",
|
||||
"windows-targets 0.52.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim 0.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.50",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.6"
|
||||
@@ -268,7 +398,7 @@ dependencies = [
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"strsim 0.10.0",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
@@ -337,16 +467,6 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@@ -374,6 +494,21 @@ version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.30"
|
||||
@@ -381,6 +516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -389,6 +525,23 @@ version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.30"
|
||||
@@ -397,7 +550,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
"syn 2.0.50",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -418,9 +571,13 @@ version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
@@ -462,10 +619,16 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.4"
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
@@ -521,9 +684,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75"
|
||||
checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
@@ -535,6 +698,7 @@ dependencies = [
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
@@ -556,9 +720,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.59"
|
||||
version = "0.1.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"
|
||||
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
@@ -604,9 +768,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.2"
|
||||
version = "2.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520"
|
||||
checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
@@ -614,12 +778,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.10"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
|
||||
checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix",
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
@@ -631,13 +795,19 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.67"
|
||||
version = "0.3.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
|
||||
checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.153"
|
||||
@@ -656,12 +826,6 @@ dependencies = [
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.11"
|
||||
@@ -708,9 +872,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
@@ -728,9 +892,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
@@ -794,6 +958,21 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pcap-file-tokio"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ee4f08e375f9aabbb17f4c031a2f0af1397835ce8d7909b167ada1dd8b572e6"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"byteorder",
|
||||
"derive-into-owned",
|
||||
"pcap-file",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
@@ -817,7 +996,7 @@ checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
"syn 2.0.50",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -834,9 +1013,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
|
||||
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
@@ -909,10 +1088,14 @@ dependencies = [
|
||||
"crc",
|
||||
"deku",
|
||||
"env_logger",
|
||||
"futures",
|
||||
"futures-core",
|
||||
"libc",
|
||||
"log",
|
||||
"pcap-file",
|
||||
"pcap-file-tokio",
|
||||
"telcom-parser",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -922,6 +1105,7 @@ dependencies = [
|
||||
"axum",
|
||||
"chrono",
|
||||
"env_logger",
|
||||
"futures",
|
||||
"futures-core",
|
||||
"futures-macro",
|
||||
"include_dir",
|
||||
@@ -932,6 +1116,7 @@ dependencies = [
|
||||
"tempdir",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"toml",
|
||||
]
|
||||
@@ -951,7 +1136,7 @@ version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1012,19 +1197,6 @@ version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
@@ -1033,9 +1205,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.16"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
||||
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
@@ -1045,29 +1217,29 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.196"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.196"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
"syn 2.0.50",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.113"
|
||||
version = "1.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
|
||||
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -1152,6 +1324,12 @@ version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
@@ -1165,9 +1343,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.48"
|
||||
version = "2.0.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
||||
checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1186,6 +1364,19 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "telcom-parser"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"asn1-codecs",
|
||||
"asn1-compiler",
|
||||
"asn1_codecs_derive",
|
||||
"bitvec",
|
||||
"log",
|
||||
"serde",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempdir"
|
||||
version = "0.3.7"
|
||||
@@ -1207,22 +1398,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.56"
|
||||
version = "1.0.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
|
||||
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.56"
|
||||
version = "1.0.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
|
||||
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
"syn 2.0.50",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1244,6 +1435,16 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-byteorder"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cf347e8ae1d1ffd16c8aed569172a71bd81098a001d0f4964d476c0097aba4a"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.2.0"
|
||||
@@ -1252,7 +1453,18 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
"syn 2.0.50",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1273,14 +1485,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.9"
|
||||
version = "0.8.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325"
|
||||
checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit 0.21.1",
|
||||
"toml_edit 0.22.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1300,22 +1512,28 @@ checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
"winnow 0.5.40",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.21.1"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
|
||||
checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
"winnow 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "topological-sort"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.4.13"
|
||||
@@ -1379,6 +1597,12 @@ version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
@@ -1399,9 +1623,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.90"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
|
||||
checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
@@ -1409,24 +1633,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.90"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
|
||||
checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
"syn 2.0.50",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.90"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
|
||||
checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -1434,22 +1658,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.90"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
|
||||
checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
"syn 2.0.50",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.90"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
|
||||
checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
@@ -1488,7 +1712,7 @@ version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.0",
|
||||
"windows-targets 0.52.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1506,7 +1730,7 @@ version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.0",
|
||||
"windows-targets 0.52.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1526,17 +1750,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||
checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.0",
|
||||
"windows_aarch64_msvc 0.52.0",
|
||||
"windows_i686_gnu 0.52.0",
|
||||
"windows_i686_msvc 0.52.0",
|
||||
"windows_x86_64_gnu 0.52.0",
|
||||
"windows_x86_64_gnullvm 0.52.0",
|
||||
"windows_x86_64_msvc 0.52.0",
|
||||
"windows_aarch64_gnullvm 0.52.3",
|
||||
"windows_aarch64_msvc 0.52.3",
|
||||
"windows_i686_gnu 0.52.3",
|
||||
"windows_i686_msvc 0.52.3",
|
||||
"windows_x86_64_gnu 0.52.3",
|
||||
"windows_x86_64_gnullvm 0.52.3",
|
||||
"windows_x86_64_msvc 0.52.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1547,9 +1771,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||
checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
@@ -1559,9 +1783,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||
checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
@@ -1571,9 +1795,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||
checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
@@ -1583,9 +1807,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||
checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
@@ -1595,9 +1819,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||
checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
@@ -1607,9 +1831,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||
checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
@@ -1619,15 +1843,24 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.36"
|
||||
version = "0.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "818ce546a11a9986bc24f93d0cdf38a8a1a400f1473ea8c82e59f6e0ffab9249"
|
||||
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a4191c47f15cc3ec71fcb4913cb83d58def65dd3787610213c649283b5ce178"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -1658,5 +1891,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
"syn 2.0.50",
|
||||
]
|
||||
|
||||
@@ -5,5 +5,6 @@ members = [
|
||||
"bin",
|
||||
"serial",
|
||||
"rootshell",
|
||||
"telcom-parser",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
name = "rayhunter"
|
||||
name = "rayhunter-daemon"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
@@ -23,3 +23,5 @@ include_dir = "0.7.3"
|
||||
mime_guess = "2.0.4"
|
||||
tempdir = "0.3.7"
|
||||
chrono = { version = "0.4.31", features = ["serde"] }
|
||||
tokio-stream = "0.1.14"
|
||||
futures = "0.3.30"
|
||||
|
||||
127
bin/src/diag.rs
127
bin/src/diag.rs
@@ -1,110 +1,101 @@
|
||||
use std::pin::pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use axum::extract::State;
|
||||
use axum::http::StatusCode;
|
||||
use rayhunter::diag::DataType;
|
||||
use rayhunter::diag_device::DiagDevice;
|
||||
use rayhunter::diag_reader::DiagReader;
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::sync::mpsc::{Receiver, self};
|
||||
use tokio::sync::mpsc::Receiver;
|
||||
use rayhunter::qmdl::QmdlWriter;
|
||||
use log::{debug, info};
|
||||
use tokio::sync::mpsc::error::TryRecvError;
|
||||
use tokio::task::JoinHandle;
|
||||
use log::{debug, error, info};
|
||||
use tokio::fs::File;
|
||||
use tokio_util::task::TaskTracker;
|
||||
use futures::{StreamExt, TryStreamExt};
|
||||
|
||||
use crate::error::RayhunterError;
|
||||
use crate::qmdl_store::QmdlStore;
|
||||
use crate::server::ServerState;
|
||||
|
||||
pub enum DiagDeviceCtrlMessage {
|
||||
StopRecording,
|
||||
StartRecording(QmdlWriter<std::fs::File>),
|
||||
StartRecording(QmdlWriter<File>),
|
||||
Exit,
|
||||
}
|
||||
|
||||
pub fn run_diag_read_thread(task_tracker: &TaskTracker, mut dev: DiagDevice, mut qmdl_file_rx: Receiver<DiagDeviceCtrlMessage>, qmdl_store_lock: Arc<RwLock<QmdlStore>>) -> JoinHandle<Result<(), RayhunterError>> {
|
||||
// mpsc channel for updating QmdlStore entry filesizes. First usize is the
|
||||
// index, second is the size in bytes
|
||||
let (tx, mut rx) = mpsc::channel::<(usize, usize)>(1);
|
||||
|
||||
// Spawn a thread to monitor the (usize, usize) channel for updates,
|
||||
// triggering QmdlStore updates
|
||||
let qmdl_store_lock_clone = qmdl_store_lock.clone();
|
||||
pub fn run_diag_read_thread(task_tracker: &TaskTracker, mut dev: DiagDevice, mut qmdl_file_rx: Receiver<DiagDeviceCtrlMessage>, qmdl_store_lock: Arc<RwLock<QmdlStore>>) {
|
||||
task_tracker.spawn(async move {
|
||||
while let Some((entry_idx, new_size)) = rx.recv().await {
|
||||
let mut qmdl_store = qmdl_store_lock_clone.write().await;
|
||||
qmdl_store.update_entry_size(entry_idx, new_size).await
|
||||
.expect("failed to update qmdl file size");
|
||||
}
|
||||
info!("QMDL store size updater thread exiting...");
|
||||
});
|
||||
|
||||
// Spawn a thread to drive the DiagDevice reading loop. Since DiagDevice
|
||||
// works via synchronous I/O, we have to spawn a "blocking" thread to avoid
|
||||
// gumming up tokio's event loop.
|
||||
task_tracker.spawn_blocking(move || {
|
||||
let initial_file = qmdl_store_lock.write().await.new_entry().await.expect("failed creating QMDL file entry");
|
||||
let mut qmdl_writer: Option<QmdlWriter<File>> = Some(QmdlWriter::new(initial_file));
|
||||
let mut diag_stream = pin!(dev.as_stream().into_stream());
|
||||
loop {
|
||||
// First check if we've gotten any control meesages
|
||||
match qmdl_file_rx.try_recv() {
|
||||
Ok(DiagDeviceCtrlMessage::StartRecording(qmdl_writer)) => {
|
||||
dev.qmdl_writer = Some(qmdl_writer);
|
||||
},
|
||||
Ok(DiagDeviceCtrlMessage::StopRecording) => dev.qmdl_writer = None,
|
||||
// Disconnected means all the Senders have been dropped, so it's
|
||||
// time to go
|
||||
Ok(DiagDeviceCtrlMessage::Exit) | Err(TryRecvError::Disconnected) => {
|
||||
info!("Diag reader thread exiting...");
|
||||
return Ok(())
|
||||
},
|
||||
// empty just means there's no message for us, so continue as normal
|
||||
Err(TryRecvError::Empty) => {},
|
||||
}
|
||||
|
||||
// remember the QmdlStore current entry index so we can update its size later
|
||||
let qmdl_store_index = qmdl_store_lock.blocking_read().current_entry;
|
||||
|
||||
// TODO: once we're actually doing analysis, we'll wanna use the messages
|
||||
// returned here. Until then, the DiagDevice has already written those messages
|
||||
// to the QMDL file, so we can just ignore them.
|
||||
debug!("reading response from diag device...");
|
||||
let _messages = dev.read_response().map_err(RayhunterError::DiagReadError)?;
|
||||
debug!("got diag response ({} messages)", _messages.len());
|
||||
|
||||
// keep track of how many bytes were written to the QMDL file so we can read
|
||||
// a valid block of data from it in the HTTP server
|
||||
if let Some(qmdl_writer) = dev.qmdl_writer.as_ref() {
|
||||
debug!("total QMDL bytes written: {}, sending update...", qmdl_writer.total_written);
|
||||
let index = qmdl_store_index.expect("DiagDevice had qmdl_writer, but QmdlStore didn't have current entry???");
|
||||
tx.blocking_send((index, qmdl_writer.total_written)).unwrap();
|
||||
debug!("done!");
|
||||
} else {
|
||||
debug!("no qmdl_writer set, continuing...");
|
||||
tokio::select! {
|
||||
msg = qmdl_file_rx.recv() => {
|
||||
match msg {
|
||||
Some(DiagDeviceCtrlMessage::StartRecording(new_writer)) => {
|
||||
qmdl_writer = Some(new_writer);
|
||||
},
|
||||
Some(DiagDeviceCtrlMessage::StopRecording) => qmdl_writer = None,
|
||||
// None means all the Senders have been dropped, so it's
|
||||
// time to go
|
||||
Some(DiagDeviceCtrlMessage::Exit) | None => {
|
||||
info!("Diag reader thread exiting...");
|
||||
return Ok(())
|
||||
},
|
||||
}
|
||||
}
|
||||
maybe_container = diag_stream.next() => {
|
||||
match maybe_container.unwrap() {
|
||||
Ok(container) => {
|
||||
if container.data_type != DataType::UserSpace {
|
||||
debug!("skipping non-userspace diag messages...");
|
||||
continue;
|
||||
}
|
||||
// keep track of how many bytes were written to the QMDL file so we can read
|
||||
// a valid block of data from it in the HTTP server
|
||||
if let Some(writer) = qmdl_writer.as_mut() {
|
||||
writer.write_container(&container).await.expect("failed to write to QMDL writer");
|
||||
debug!("total QMDL bytes written: {}, updating manifest...", writer.total_written);
|
||||
let mut qmdl_store = qmdl_store_lock.write().await;
|
||||
let index = qmdl_store.current_entry.expect("DiagDevice had qmdl_writer, but QmdlStore didn't have current entry???");
|
||||
qmdl_store.update_entry(index, writer.total_written).await
|
||||
.expect("failed to update qmdl file size");
|
||||
debug!("done!");
|
||||
} else {
|
||||
debug!("no qmdl_writer set, continuing...");
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
error!("error reading diag device: {}", err);
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub async fn start_recording(State(state): State<Arc<ServerState>>) -> Result<(StatusCode, String), (StatusCode, String)> {
|
||||
if state.readonly_mode {
|
||||
return Err((StatusCode::FORBIDDEN, format!("server is in readonly mode")));
|
||||
return Err((StatusCode::FORBIDDEN, "server is in readonly mode".to_string()));
|
||||
}
|
||||
let mut qmdl_store = state.qmdl_store_lock.write().await;
|
||||
let qmdl_file = qmdl_store.new_entry().await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("couldn't create new qmdl entry: {}", e)))?;
|
||||
let qmdl_writer = QmdlWriter::new(qmdl_file.into_std().await);
|
||||
let qmdl_writer = QmdlWriter::new(qmdl_file);
|
||||
state.diag_device_ctrl_sender.send(DiagDeviceCtrlMessage::StartRecording(qmdl_writer)).await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("couldn't send stop recording message: {}", e)))?;
|
||||
Ok((StatusCode::ACCEPTED, format!("ok")))
|
||||
Ok((StatusCode::ACCEPTED, "ok".to_string()))
|
||||
}
|
||||
|
||||
pub async fn stop_recording(State(state): State<Arc<ServerState>>) -> Result<(StatusCode, String), (StatusCode, String)> {
|
||||
if state.readonly_mode {
|
||||
return Err((StatusCode::FORBIDDEN, format!("server is in readonly mode")));
|
||||
return Err((StatusCode::FORBIDDEN, "server is in readonly mode".to_string()));
|
||||
}
|
||||
let mut qmdl_store = state.qmdl_store_lock.write().await;
|
||||
qmdl_store.close_current_entry().await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("couldn't close current qmdl entry: {}", e)))?;
|
||||
state.diag_device_ctrl_sender.send(DiagDeviceCtrlMessage::StopRecording).await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("couldn't send stop recording message: {}", e)))?;
|
||||
Ok((StatusCode::ACCEPTED, format!("ok")))
|
||||
Ok((StatusCode::ACCEPTED, "ok".to_string()))
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ pub enum RayhunterError{
|
||||
ConfigFileParsingError(#[from] toml::de::Error),
|
||||
#[error("Diag intialization error: {0}")]
|
||||
DiagInitError(DiagDeviceError),
|
||||
#[error("Diag read error: {0}")]
|
||||
DiagReadError(DiagDeviceError),
|
||||
#[error("Tokio error: {0}")]
|
||||
TokioError(#[from] tokio::io::Error),
|
||||
#[error("QmdlStore error: {0}")]
|
||||
|
||||
@@ -20,7 +20,6 @@ use log::{info, error};
|
||||
use rayhunter::diag_device::DiagDevice;
|
||||
use axum::routing::{get, post};
|
||||
use axum::Router;
|
||||
use rayhunter::qmdl::QmdlWriter;
|
||||
use stats::get_qmdl_manifest;
|
||||
use tokio::sync::mpsc::{self, Sender};
|
||||
use tokio::task::JoinHandle;
|
||||
@@ -127,11 +126,9 @@ async fn main() -> Result<(), RayhunterError> {
|
||||
let qmdl_store_lock = Arc::new(RwLock::new(init_qmdl_store(&config).await?));
|
||||
let (tx, rx) = mpsc::channel::<DiagDeviceCtrlMessage>(1);
|
||||
if !config.readonly_mode {
|
||||
let qmdl_file = qmdl_store_lock.write().await.new_entry().await?;
|
||||
let qmdl_writer = QmdlWriter::new(qmdl_file.into_std().await);
|
||||
let mut dev = DiagDevice::new(Some(qmdl_writer))
|
||||
let mut dev = DiagDevice::new().await
|
||||
.map_err(RayhunterError::DiagInitError)?;
|
||||
dev.config_logs()
|
||||
dev.config_logs().await
|
||||
.map_err(RayhunterError::DiagInitError)?;
|
||||
|
||||
run_diag_read_thread(&task_tracker, dev, rx, qmdl_store_lock.clone());
|
||||
|
||||
113
bin/src/pcap.rs
113
bin/src/pcap.rs
@@ -1,26 +1,24 @@
|
||||
use crate::ServerState;
|
||||
|
||||
use rayhunter::diag::DataType;
|
||||
use rayhunter::gsmtap_parser::GsmtapParser;
|
||||
use rayhunter::pcap::GsmtapPcapWriter;
|
||||
use rayhunter::qmdl::{QmdlReader, QmdlReaderError};
|
||||
use rayhunter::diag_reader::DiagReader;
|
||||
use rayhunter::qmdl::QmdlReader;
|
||||
use axum::body::Body;
|
||||
use axum::http::header::CONTENT_TYPE;
|
||||
use axum::extract::{State, Path};
|
||||
use axum::http::StatusCode;
|
||||
use axum::response::{Response, IntoResponse};
|
||||
use std::io::Write;
|
||||
use std::pin::Pin;
|
||||
use tokio::io::duplex;
|
||||
use tokio_util::io::ReaderStream;
|
||||
use std::{future, pin::pin};
|
||||
use std::sync::Arc;
|
||||
use std::task::{Poll, Context};
|
||||
use futures_core::Stream;
|
||||
use log::error;
|
||||
use tokio::sync::mpsc;
|
||||
use futures::TryStreamExt;
|
||||
|
||||
// Streams a pcap file chunk-by-chunk to the client by reading the QMDL data
|
||||
// written so far. This is done by spawning a blocking thread (a tokio thread
|
||||
// capable of handling blocking operations) which streams chunks of pcap data to
|
||||
// a channel that's piped to the client.
|
||||
// written so far. This is done by spawning a thread which streams chunks of
|
||||
// pcap data to a channel that's piped to the client.
|
||||
pub async fn get_pcap(State(state): State<Arc<ServerState>>, Path(qmdl_name): Path<String>) -> Result<Response, (StatusCode, String)> {
|
||||
let qmdl_store = state.qmdl_store_lock.read().await;
|
||||
let entry = qmdl_store.entry_for_name(&qmdl_name)
|
||||
@@ -31,82 +29,39 @@ pub async fn get_pcap(State(state): State<Arc<ServerState>>, Path(qmdl_name): Pa
|
||||
"QMDL file is empty, try again in a bit!".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let qmdl_file = qmdl_store.open_entry(&entry).await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("{:?}", e)))?
|
||||
.into_std().await;
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("{:?}", e)))?;
|
||||
// the QMDL reader should stop at the last successfully written data chunk
|
||||
// (entry.size_bytes)
|
||||
let mut gsmtap_parser = GsmtapParser::new();
|
||||
let (reader, writer) = duplex(1024);
|
||||
let mut pcap_writer = GsmtapPcapWriter::new(writer).await.unwrap();
|
||||
pcap_writer.write_iface_header().await.unwrap();
|
||||
|
||||
let (tx, rx) = mpsc::channel(1);
|
||||
let channel_reader = ChannelReader { rx };
|
||||
let channel_writer = ChannelWriter { tx };
|
||||
tokio::task::spawn_blocking(move || {
|
||||
// the QMDL reader should stop at the last successfully written data
|
||||
// chunk (qmdl_bytes_written)
|
||||
let mut qmdl_reader = QmdlReader::new(qmdl_file, Some(entry.size_bytes));
|
||||
|
||||
let mut gsmtap_parser = GsmtapParser::new();
|
||||
let mut pcap_writer = GsmtapPcapWriter::new(channel_writer).unwrap();
|
||||
pcap_writer.write_iface_header().unwrap();
|
||||
loop {
|
||||
match qmdl_reader.read_response() {
|
||||
Ok(messages) => {
|
||||
for maybe_msg in messages {
|
||||
match maybe_msg {
|
||||
Ok(msg) => {
|
||||
let maybe_gsmtap_msg = gsmtap_parser.recv_message(msg)
|
||||
.expect("error parsing gsmtap message");
|
||||
if let Some((timestamp, gsmtap_msg)) = maybe_gsmtap_msg {
|
||||
pcap_writer.write_gsmtap_message(gsmtap_msg, timestamp)
|
||||
.expect("error writing pcap packet");
|
||||
}
|
||||
},
|
||||
Err(e) => error!("error parsing message: {:?}", e),
|
||||
tokio::spawn(async move {
|
||||
let mut reader = QmdlReader::new(qmdl_file, Some(entry.size_bytes));
|
||||
let mut messages_stream = pin!(reader.as_stream()
|
||||
.try_filter(|container| future::ready(container.data_type == DataType::UserSpace)));
|
||||
|
||||
while let Some(container) = messages_stream.try_next().await.expect("failed getting QMDL container") {
|
||||
for maybe_msg in container.into_messages() {
|
||||
match maybe_msg {
|
||||
Ok(msg) => {
|
||||
let maybe_gsmtap_msg = gsmtap_parser.recv_message(msg)
|
||||
.expect("error parsing gsmtap message");
|
||||
if let Some((timestamp, gsmtap_msg)) = maybe_gsmtap_msg {
|
||||
pcap_writer.write_gsmtap_message(gsmtap_msg, timestamp).await
|
||||
.expect("error writing pcap packet");
|
||||
}
|
||||
}
|
||||
},
|
||||
// this is expected, and just means we've reached the end of the
|
||||
// safely written QMDL data
|
||||
Err(QmdlReaderError::MaxBytesReached(_)) => break,
|
||||
Err(e) => {
|
||||
error!("error reading qmdl file: {:?}", e);
|
||||
break;
|
||||
},
|
||||
},
|
||||
Err(e) => error!("error parsing message: {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let headers = [(CONTENT_TYPE, "application/vnd.tcpdump.pcap")];
|
||||
let body = Body::from_stream(channel_reader);
|
||||
let body = Body::from_stream(ReaderStream::new(reader));
|
||||
Ok((headers, body).into_response())
|
||||
}
|
||||
|
||||
struct ChannelWriter {
|
||||
tx: mpsc::Sender<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl Write for ChannelWriter {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
self.tx.blocking_send(buf.to_vec())
|
||||
.map_err(|_| std::io::Error::new(std::io::ErrorKind::Other, "channel closed"))?;
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct ChannelReader {
|
||||
rx: mpsc::Receiver<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl Stream for ChannelReader {
|
||||
type Item = Result<Vec<u8>, String>;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
match self.rx.poll_recv(cx) {
|
||||
Poll::Ready(Some(msg)) => Poll::Ready(Some(Ok(msg))),
|
||||
Poll::Ready(None) => Poll::Ready(None),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ pub struct Manifest {
|
||||
pub struct ManifestEntry {
|
||||
pub name: String,
|
||||
pub start_time: DateTime<Local>,
|
||||
pub end_time: Option<DateTime<Local>>,
|
||||
pub last_message_time: Option<DateTime<Local>>,
|
||||
pub size_bytes: usize,
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ impl ManifestEntry {
|
||||
ManifestEntry {
|
||||
name: format!("{}", now.timestamp()),
|
||||
start_time: now,
|
||||
end_time: None,
|
||||
last_message_time: None,
|
||||
size_bytes: 0,
|
||||
}
|
||||
}
|
||||
@@ -128,18 +128,21 @@ impl QmdlStore {
|
||||
.map_err(QmdlStoreError::ReadFileError)
|
||||
}
|
||||
|
||||
// Sets the current entry's end_time, updates the manifest, and unsets the
|
||||
// current entry
|
||||
// Unsets the current entry
|
||||
pub async fn close_current_entry(&mut self) -> Result<(), QmdlStoreError> {
|
||||
let entry_index = self.current_entry.take()
|
||||
.ok_or(QmdlStoreError::NoCurrentEntry)?;
|
||||
self.manifest.entries[entry_index].end_time = Some(Local::now());
|
||||
self.write_manifest().await
|
||||
match self.current_entry {
|
||||
Some(_) => {
|
||||
self.current_entry = None;
|
||||
Ok(())
|
||||
},
|
||||
None => Err(QmdlStoreError::NoCurrentEntry)
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the given entry's size, updating the manifest
|
||||
pub async fn update_entry_size(&mut self, entry_index: usize, size_bytes: usize) -> Result<(), QmdlStoreError> {
|
||||
// Sets the given entry's size and updates the last_message_time to now, updating the manifest
|
||||
pub async fn update_entry(&mut self, entry_index: usize, size_bytes: usize) -> Result<(), QmdlStoreError> {
|
||||
self.manifest.entries[entry_index].size_bytes = size_bytes;
|
||||
self.manifest.entries[entry_index].last_message_time = Some(Local::now());
|
||||
self.write_manifest().await
|
||||
}
|
||||
|
||||
@@ -185,17 +188,15 @@ mod tests {
|
||||
let _ = store.new_entry().await.unwrap();
|
||||
let entry_index = store.current_entry.unwrap();
|
||||
assert_eq!(QmdlStore::read_manifest(dir.path()).await.unwrap(), store.manifest);
|
||||
assert!(store.manifest.entries[entry_index].last_message_time.is_none());
|
||||
|
||||
store.update_entry_size(entry_index, 1000).await.unwrap();
|
||||
store.update_entry(entry_index, 1000).await.unwrap();
|
||||
let entry = store.entry_for_name(&store.manifest.entries[entry_index].name).unwrap();
|
||||
assert!(entry.last_message_time.is_some());
|
||||
assert_eq!(store.manifest.entries[entry_index].size_bytes, 1000);
|
||||
assert_eq!(QmdlStore::read_manifest(dir.path()).await.unwrap(), store.manifest);
|
||||
|
||||
assert!(store.manifest.entries[entry_index].end_time.is_none());
|
||||
store.close_current_entry().await.unwrap();
|
||||
let entry = store.entry_for_name(&store.manifest.entries[entry_index].name).unwrap();
|
||||
assert!(entry.end_time.is_some());
|
||||
assert_eq!(QmdlStore::read_manifest(dir.path()).await.unwrap(), store.manifest);
|
||||
|
||||
assert!(matches!(store.close_current_entry().await, Err(QmdlStoreError::NoCurrentEntry)));
|
||||
}
|
||||
|
||||
|
||||
@@ -103,10 +103,10 @@ pub async fn get_system_stats(State(state): State<Arc<ServerState>>) -> Result<J
|
||||
Ok(stats) => Ok(Json(stats)),
|
||||
Err(err) => {
|
||||
error!("error getting system stats: {}", err);
|
||||
return Err((
|
||||
Err((
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"error getting system stats".to_string()
|
||||
));
|
||||
))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<tr>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Date Started</th>
|
||||
<th scope="col">Date Stopped</th>
|
||||
<th scope="col">Date of Last Message</th>
|
||||
<th scope="col">Size (bytes)</th>
|
||||
<th scope="col">PCAP</th>
|
||||
<th scope="col">QMDL</th>
|
||||
|
||||
@@ -29,7 +29,7 @@ function createEntryRow(entry) {
|
||||
name.scope = 'row';
|
||||
name.innerText = entry.name;
|
||||
row.appendChild(name);
|
||||
for (const key of ['start_time', 'end_time', 'size_bytes']) {
|
||||
for (const key of ['start_time', 'last_message_time', 'size_bytes']) {
|
||||
const td = document.createElement('td');
|
||||
td.innerText = entry[key];
|
||||
row.appendChild(td);
|
||||
@@ -57,10 +57,15 @@ async function getQmdlManifest() {
|
||||
const manifest = JSON.parse(await req('GET', '/api/qmdl-manifest'));
|
||||
if (manifest.current_entry) {
|
||||
manifest.current_entry.start_time = new Date(manifest.current_entry.start_time);
|
||||
if (manifest.current_entry.last_message_time === undefined) {
|
||||
manifest.current_entry.last_message_time = "N/A";
|
||||
} else {
|
||||
manifest.current_entry.last_message_time = new Date(manifest.current_entry.last_message_time);
|
||||
}
|
||||
}
|
||||
for (entry of manifest.entries) {
|
||||
entry.start_time = new Date(entry.start_time);
|
||||
entry.end_time = new Date(entry.end_time);
|
||||
entry.last_message_time = new Date(entry.last_message_time);
|
||||
}
|
||||
// sort them in reverse chronological order
|
||||
manifest.entries.reverse();
|
||||
|
||||
@@ -12,5 +12,9 @@ deku = { version = "0.16.0", features = ["logging"] }
|
||||
env_logger = "0.10.1"
|
||||
libc = "0.2.150"
|
||||
log = "0.4.20"
|
||||
pcap-file = "2.0.0"
|
||||
pcap-file-tokio = "0.1.0"
|
||||
thiserror = "1.0.50"
|
||||
telcom-parser = { path = "../telcom-parser" }
|
||||
tokio = { version = "1.35.1", features = ["full"] }
|
||||
futures-core = "0.3.30"
|
||||
futures = "0.3.30"
|
||||
|
||||
51
lib/src/analysis/analyzer.rs
Normal file
51
lib/src/analysis/analyzer.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use super::information_element::InformationElement;
|
||||
|
||||
/// Qualitative measure of how severe a Warning event type is.
|
||||
/// The levels should break down like this:
|
||||
/// * Low: if combined with a large number of other Warnings, user should investigate
|
||||
/// * Medium: if combined with a few other Warnings, user should investigate
|
||||
/// * High: user should investigate
|
||||
pub enum Severity {
|
||||
Low,
|
||||
Medium,
|
||||
High,
|
||||
}
|
||||
|
||||
/// [QualitativeWarning] events will always be shown to the user in some manner,
|
||||
/// while `Informational` ones may be hidden based on user settings.
|
||||
pub enum EventType {
|
||||
Informational,
|
||||
QualitativeWarning(Severity),
|
||||
}
|
||||
|
||||
/// Events are user-facing signals that can be emitted by an [Analyzer] upon a
|
||||
/// message being received. They can be used to signifiy an IC detection
|
||||
/// warning, or just to display some relevant information to the user.
|
||||
pub struct Event {
|
||||
pub event_type: EventType,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
/// An [Analyzer] represents one type of heuristic for detecting an IMSI Catcher
|
||||
/// (IC). While maintaining some amount of state is useful, be mindful of how
|
||||
/// much memory your [Analyzer] uses at runtime, since rayhunter may run for
|
||||
/// many hours at a time with dozens of [Analyzers](Analyzer) working in parallel.
|
||||
pub trait Analyzer {
|
||||
/// Returns a user-friendly, concise name for your heuristic.
|
||||
fn get_name(&self) -> Cow<str>;
|
||||
|
||||
/// Returns a user-friendly description of what your heuristic looks for,
|
||||
/// the types of [Events](Event) it may return, as well as possible false-positive
|
||||
/// conditions that may trigger an [Event]. If different [Events](Event) have
|
||||
/// different false-positive conditions, consider including them in its
|
||||
/// `message` field.
|
||||
fn get_description(&self) -> Cow<str>;
|
||||
|
||||
/// Analyze a single [InformationElement], possibly returning an [Event] if your
|
||||
/// heuristic deems it relevant. Again, be mindful of any state your
|
||||
/// [Analyzer] updates per message, since it may be run over hundreds or
|
||||
/// thousands of them alongside many other [Analyzers](Analyzer).
|
||||
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event>;
|
||||
}
|
||||
82
lib/src/analysis/information_element.rs
Normal file
82
lib/src/analysis/information_element.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
//! The term "information element" is used by 3GPP to describe "structural
|
||||
//! elements containing single or multiple fields" in 2G/3G/4G/5G. We use
|
||||
//! the term to refer to a structured, fully parsed message in any telcom
|
||||
//! standard.
|
||||
|
||||
use telcom_parser::{decode, lte_rrc};
|
||||
use thiserror::Error;
|
||||
use crate::gsmtap::{GsmtapType, LteRrcSubtype, GsmtapMessage};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum InformationElementError {
|
||||
#[error("Failed decoding")]
|
||||
DecodingError(#[from] telcom_parser::ParsingError),
|
||||
#[error("Unsupported LTE RRC subtype {0:?}")]
|
||||
UnsupportedGsmtapType(GsmtapType),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum InformationElement {
|
||||
GSM,
|
||||
UMTS,
|
||||
LTE(LteInformationElement),
|
||||
FiveG,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum LteInformationElement {
|
||||
DlCcch(lte_rrc::DL_CCCH_Message),
|
||||
DlDcch(lte_rrc::DL_DCCH_Message),
|
||||
UlCcch(lte_rrc::UL_CCCH_Message),
|
||||
UlDcch(lte_rrc::UL_DCCH_Message),
|
||||
BcchBch(lte_rrc::BCCH_BCH_Message),
|
||||
BcchDlSch(lte_rrc::BCCH_DL_SCH_Message),
|
||||
PCCH(lte_rrc::PCCH_Message),
|
||||
MCCH(lte_rrc::MCCH_Message),
|
||||
ScMcch(lte_rrc::SC_MCCH_Message_r13),
|
||||
BcchBchMbms(lte_rrc::BCCH_BCH_Message_MBMS),
|
||||
BcchDlSchBr(lte_rrc::BCCH_DL_SCH_Message_BR),
|
||||
BcchDlSchMbms(lte_rrc::BCCH_DL_SCH_Message_MBMS),
|
||||
SbcchSlBch(lte_rrc::SBCCH_SL_BCH_Message),
|
||||
SbcchSlBchV2x(lte_rrc::SBCCH_SL_BCH_Message_V2X_r14),
|
||||
|
||||
// FIXME: unclear which message these "NB" types map to
|
||||
//DlCcchNb(),
|
||||
//DlDcchNb(),
|
||||
//UlCcchNb(),
|
||||
//UlDcchNb(),
|
||||
//BcchBchNb(),
|
||||
//BcchBchTddNb(),
|
||||
//BcchDlSchNb(),
|
||||
//PcchNb(),
|
||||
//ScMcchNb(),
|
||||
}
|
||||
|
||||
impl TryFrom<&GsmtapMessage> for LteInformationElement {
|
||||
type Error = InformationElementError;
|
||||
|
||||
fn try_from(gsmtap_msg: &GsmtapMessage) -> Result<Self, Self::Error> {
|
||||
if let GsmtapType::LteRrc(lte_rrc_subtype) = gsmtap_msg.header.gsmtap_type {
|
||||
use LteRrcSubtype as L;
|
||||
use LteInformationElement as R;
|
||||
return match lte_rrc_subtype {
|
||||
L::DlCcch => Ok(R::DlCcch(decode(&gsmtap_msg.payload)?)),
|
||||
L::DlDcch => Ok(R::DlDcch(decode(&gsmtap_msg.payload)?)),
|
||||
L::UlCcch => Ok(R::UlCcch(decode(&gsmtap_msg.payload)?)),
|
||||
L::UlDcch => Ok(R::UlDcch(decode(&gsmtap_msg.payload)?)),
|
||||
L::BcchBch => Ok(R::BcchBch(decode(&gsmtap_msg.payload)?)),
|
||||
L::BcchDlSch => Ok(R::BcchDlSch(decode(&gsmtap_msg.payload)?)),
|
||||
L::PCCH => Ok(R::PCCH(decode(&gsmtap_msg.payload)?)),
|
||||
L::MCCH => Ok(R::MCCH(decode(&gsmtap_msg.payload)?)),
|
||||
L::ScMcch => Ok(R::ScMcch(decode(&gsmtap_msg.payload)?)),
|
||||
L::BcchBchMbms => Ok(R::BcchBchMbms(decode(&gsmtap_msg.payload)?)),
|
||||
L::BcchDlSchBr => Ok(R::BcchDlSchBr(decode(&gsmtap_msg.payload)?)),
|
||||
L::BcchDlSchMbms => Ok(R::BcchDlSchMbms(decode(&gsmtap_msg.payload)?)),
|
||||
L::SbcchSlBch => Ok(R::SbcchSlBch(decode(&gsmtap_msg.payload)?)),
|
||||
L::SbcchSlBchV2x => Ok(R::SbcchSlBchV2x(decode(&gsmtap_msg.payload)?)),
|
||||
_ => Err(InformationElementError::UnsupportedGsmtapType(gsmtap_msg.header.gsmtap_type)),
|
||||
};
|
||||
}
|
||||
Err(InformationElementError::UnsupportedGsmtapType(gsmtap_msg.header.gsmtap_type))
|
||||
}
|
||||
}
|
||||
81
lib/src/analysis/lte_downgrade.rs
Normal file
81
lib/src/analysis/lte_downgrade.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use super::analyzer::{Analyzer, Event, EventType, Severity};
|
||||
use super::information_element::{InformationElement, LteInformationElement};
|
||||
use telcom_parser::lte_rrc::{BCCH_DL_SCH_MessageType, BCCH_DL_SCH_MessageType_c1, CellReselectionPriority, SystemInformationBlockType7, SystemInformationCriticalExtensions, SystemInformation_r8_IEsSib_TypeAndInfo, SystemInformation_r8_IEsSib_TypeAndInfo_Entry};
|
||||
|
||||
/// Based on heuristic T7 from Shinjo Park's "Why We Cannot Win".
|
||||
pub struct LteSib7DowngradeAnalyzer {
|
||||
}
|
||||
|
||||
impl LteSib7DowngradeAnalyzer {
|
||||
fn unpack_system_information<'a>(&self, ie: &'a InformationElement) -> Option<&'a SystemInformation_r8_IEsSib_TypeAndInfo> {
|
||||
if let InformationElement::LTE(LteInformationElement::BcchDlSch(bcch_dl_sch_message)) = ie {
|
||||
if let BCCH_DL_SCH_MessageType::C1(BCCH_DL_SCH_MessageType_c1::SystemInformation(system_information)) = &bcch_dl_sch_message.message {
|
||||
if let SystemInformationCriticalExtensions::SystemInformation_r8(sib) = &system_information.critical_extensions {
|
||||
return Some(&sib.sib_type_and_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: keep track of SIB state to compare LTE reselection blocks w/ 2g/3g ones
|
||||
impl Analyzer for LteSib7DowngradeAnalyzer {
|
||||
fn get_name(&self) -> Cow<str> {
|
||||
Cow::from("LTE SIB 7 Downgrade")
|
||||
}
|
||||
|
||||
fn get_description(&self) -> Cow<str> {
|
||||
Cow::from("Tests for LTE cells broadcasting a SIB type 7 which include 2G/3G frequencies with higher priorities.")
|
||||
}
|
||||
|
||||
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<super::analyzer::Event> {
|
||||
let sibs = &self.unpack_system_information(ie)?.0;
|
||||
for sib in sibs {
|
||||
match sib {
|
||||
SystemInformation_r8_IEsSib_TypeAndInfo_Entry::Sib6(sib6) => {
|
||||
if let Some(carrier_info_list) = sib6.carrier_freq_list_utra_fdd.as_ref() {
|
||||
for carrier_info in &carrier_info_list.0 {
|
||||
if let Some(CellReselectionPriority(p)) = carrier_info.cell_reselection_priority {
|
||||
if p == 0 {
|
||||
return Some(Event {
|
||||
event_type: EventType::QualitativeWarning(Severity::High),
|
||||
message: "LTE cell advertised a 3G cell for priority 0 reselection".to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(carrier_info_list) = sib6.carrier_freq_list_utra_tdd.as_ref() {
|
||||
for carrier_info in &carrier_info_list.0 {
|
||||
if let Some(CellReselectionPriority(p)) = carrier_info.cell_reselection_priority {
|
||||
if p == 0 {
|
||||
return Some(Event {
|
||||
event_type: EventType::QualitativeWarning(Severity::High),
|
||||
message: "LTE cell advertised a 3G cell for priority 0 reselection".to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
SystemInformation_r8_IEsSib_TypeAndInfo_Entry::Sib7(SystemInformationBlockType7 { carrier_freqs_info_list: Some(carrier_info_list), .. }) => {
|
||||
for carrier_info in &carrier_info_list.0 {
|
||||
if let Some(CellReselectionPriority(p)) = carrier_info.common_info.cell_reselection_priority {
|
||||
if p == 0 {
|
||||
return Some(Event {
|
||||
event_type: EventType::QualitativeWarning(Severity::High),
|
||||
message: "LTE cell advertised a 2G cell for priority 0 reselection".to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
3
lib/src/analysis/mod.rs
Normal file
3
lib/src/analysis/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod analyzer;
|
||||
pub mod information_element;
|
||||
pub mod lte_downgrade;
|
||||
145
lib/src/diag.rs
145
lib/src/diag.rs
@@ -1,8 +1,13 @@
|
||||
//! Diag protocol serialization/deserialization
|
||||
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use crc::{Algorithm, Crc};
|
||||
use deku::prelude::*;
|
||||
|
||||
use crate::hdlc::{self, hdlc_decapsulate};
|
||||
use log::{warn, error};
|
||||
use thiserror::Error;
|
||||
|
||||
pub const MESSAGE_TERMINATOR: u8 = 0x7e;
|
||||
pub const MESSAGE_ESCAPE_CHAR: u8 = 0x7d;
|
||||
|
||||
@@ -49,6 +54,28 @@ pub enum DataType {
|
||||
Other(u32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Error)]
|
||||
pub enum DiagParsingError {
|
||||
#[error("Failed to parse Message: {0}, data: {1:?}")]
|
||||
MessageParsingError(deku::DekuError, Vec<u8>),
|
||||
#[error("HDLC decapsulation of message failed: {0}, data: {1:?}")]
|
||||
HdlcDecapsulationError(hdlc::HdlcError, Vec<u8>),
|
||||
}
|
||||
|
||||
// this is sorta based on the params qcsuper uses, plus what seems to be used in
|
||||
// https://github.com/fgsect/scat/blob/f1538b397721df3ab8ba12acd26716abcf21f78b/util.py#L47
|
||||
pub const CRC_CCITT_ALG: Algorithm<u16> = Algorithm {
|
||||
poly: 0x1021,
|
||||
init: 0xffff,
|
||||
refin: true,
|
||||
refout: true,
|
||||
width: 16,
|
||||
xorout: 0xffff,
|
||||
check: 0x2189,
|
||||
residue: 0x0000,
|
||||
};
|
||||
|
||||
pub const CRC_CCITT: Crc<u16> = Crc::<u16>::new(&CRC_CCITT_ALG);
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
pub struct MessagesContainer {
|
||||
pub data_type: DataType,
|
||||
@@ -57,6 +84,29 @@ pub struct MessagesContainer {
|
||||
pub messages: Vec<HdlcEncapsulatedMessage>,
|
||||
}
|
||||
|
||||
impl MessagesContainer {
|
||||
pub fn into_messages(self) -> Vec<Result<Message, DiagParsingError>> {
|
||||
let mut result = Vec::new();
|
||||
for msg in self.messages {
|
||||
for sub_msg in msg.data.split_inclusive(|&b| b == MESSAGE_TERMINATOR) {
|
||||
match hdlc_decapsulate(sub_msg, &CRC_CCITT) {
|
||||
Ok(data) => match Message::from_bytes((&data, 0)) {
|
||||
Ok(((leftover_bytes, _), res)) => {
|
||||
if !leftover_bytes.is_empty() {
|
||||
warn!("warning: {} leftover bytes when parsing Message", leftover_bytes.len());
|
||||
}
|
||||
result.push(Ok(res));
|
||||
},
|
||||
Err(e) => result.push(Err(DiagParsingError::MessageParsingError(e, data))),
|
||||
},
|
||||
Err(err) => result.push(Err(DiagParsingError::HdlcDecapsulationError(err, sub_msg.to_vec()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
|
||||
pub struct HdlcEncapsulatedMessage {
|
||||
pub len: u32,
|
||||
@@ -431,4 +481,99 @@ mod test {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
fn make_container(data_type: DataType, message: HdlcEncapsulatedMessage) -> MessagesContainer {
|
||||
MessagesContainer {
|
||||
data_type,
|
||||
num_messages: 1,
|
||||
messages: vec![message],
|
||||
}
|
||||
}
|
||||
|
||||
// this log is based on one captured on a real device -- if it fails to
|
||||
// serialize or deserialize, that's probably a problem with this mock, not
|
||||
// the DiagReader implementation
|
||||
fn get_test_message(payload: &[u8]) -> (HdlcEncapsulatedMessage, Message) {
|
||||
let length_with_payload = 31 + payload.len() as u16;
|
||||
let message = Message::Log {
|
||||
pending_msgs: 0,
|
||||
outer_length: length_with_payload,
|
||||
inner_length: length_with_payload,
|
||||
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: payload.len() as u16,
|
||||
packet: payload.to_vec(),
|
||||
},
|
||||
},
|
||||
};
|
||||
let serialized = message.to_bytes().expect("failed to serialize test message");
|
||||
let encapsulated_data = hdlc::hdlc_encapsulate(&serialized, &CRC_CCITT);
|
||||
let encapsulated = HdlcEncapsulatedMessage {
|
||||
len: encapsulated_data.len() as u32,
|
||||
data: encapsulated_data,
|
||||
};
|
||||
(encapsulated, message)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_containers_with_multiple_messages() {
|
||||
let (encapsulated1, message1) = get_test_message(&[1]);
|
||||
let (encapsulated2, message2) = get_test_message(&[2]);
|
||||
let mut container = make_container(DataType::UserSpace, encapsulated1);
|
||||
container.messages.push(encapsulated2);
|
||||
container.num_messages += 1;
|
||||
assert_eq!(container.into_messages(), vec![Ok(message1), Ok(message2)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_containers_with_concatenated_message() {
|
||||
let (mut encapsulated1, message1) = get_test_message(&[1]);
|
||||
let (encapsulated2, message2) = get_test_message(&[2]);
|
||||
encapsulated1.data.extend(encapsulated2.data);
|
||||
encapsulated1.len += encapsulated2.len;
|
||||
let container = make_container(DataType::UserSpace, encapsulated1);
|
||||
assert_eq!(container.into_messages(), vec![Ok(message1), Ok(message2)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_handles_parsing_errors() {
|
||||
let (encapsulated1, message1) = get_test_message(&[1]);
|
||||
let bad_message = hdlc::hdlc_encapsulate(&[0x01, 0x02, 0x03, 0x04], &CRC_CCITT);
|
||||
let encapsulated2 = HdlcEncapsulatedMessage {
|
||||
len: bad_message.len() as u32,
|
||||
data: bad_message,
|
||||
};
|
||||
let mut container = make_container(DataType::UserSpace, encapsulated1);
|
||||
container.messages.push(encapsulated2);
|
||||
container.num_messages += 1;
|
||||
let result = container.into_messages();
|
||||
assert_eq!(result[0], Ok(message1));
|
||||
assert!(matches!(result[1], Err(DiagParsingError::MessageParsingError(_, _))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_handles_encapsulation_errors() {
|
||||
let (encapsulated1, message1) = get_test_message(&[1]);
|
||||
let bad_encapsulation = HdlcEncapsulatedMessage {
|
||||
len: 4,
|
||||
data: vec![0x01, 0x02, 0x03, 0x04],
|
||||
};
|
||||
let mut container = make_container(DataType::UserSpace, encapsulated1);
|
||||
container.messages.push(bad_encapsulation);
|
||||
container.num_messages += 1;
|
||||
let result = container.into_messages();
|
||||
assert_eq!(result[0], Ok(message1));
|
||||
assert!(matches!(result[1], Err(DiagParsingError::HdlcDecapsulationError(_, _))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use crate::hdlc::hdlc_encapsulate;
|
||||
use crate::diag::{Message, ResponsePayload, Request, LogConfigRequest, LogConfigResponse, build_log_mask_request, RequestContainer, DataType, MessagesContainer};
|
||||
use crate::diag_reader::{DiagReader, CRC_CCITT};
|
||||
use crate::qmdl::QmdlWriter;
|
||||
use crate::diag::{build_log_mask_request, DataType, DiagParsingError, LogConfigRequest, LogConfigResponse, Message, MessagesContainer, Request, RequestContainer, ResponsePayload, CRC_CCITT};
|
||||
use crate::log_codes;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::io::ErrorKind;
|
||||
use std::os::fd::AsRawFd;
|
||||
use futures_core::TryStream;
|
||||
use thiserror::Error;
|
||||
use log::{info, warn, error};
|
||||
use deku::prelude::*;
|
||||
use tokio::fs::File;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
|
||||
pub type DiagResult<T> = Result<T, DiagDeviceError>;
|
||||
|
||||
@@ -20,7 +20,7 @@ pub enum DiagDeviceError {
|
||||
#[error("Failed to read diag device: {0}")]
|
||||
DeviceReadFailed(std::io::Error),
|
||||
#[error("Failed to write diag device: {0}")]
|
||||
DeviceWriteFailed(String),
|
||||
DeviceWriteFailed(std::io::Error),
|
||||
#[error("Nonzero status code {0} for diag request: {1:?}")]
|
||||
RequestFailed(u32, Request),
|
||||
#[error("Didn't receive response for request: {0:?}")]
|
||||
@@ -71,43 +71,17 @@ const DIAG_IOCTL_SWITCH_LOGGING: u64 = 7;
|
||||
|
||||
pub struct DiagDevice {
|
||||
file: File,
|
||||
pub qmdl_writer: Option<QmdlWriter<File>>,
|
||||
fully_initialized: bool,
|
||||
read_buf: Vec<u8>,
|
||||
use_mdm: i32,
|
||||
}
|
||||
|
||||
impl DiagReader for DiagDevice {
|
||||
type Err = DiagDeviceError;
|
||||
|
||||
fn get_next_messages_container(&mut self) -> DiagResult<MessagesContainer> {
|
||||
let mut bytes_read = 0;
|
||||
while bytes_read == 0 {
|
||||
bytes_read = self.file.read(&mut self.read_buf)
|
||||
.map_err(DiagDeviceError::DeviceReadFailed)?;
|
||||
}
|
||||
let ((leftover_bytes, _), container) = MessagesContainer::from_bytes((&self.read_buf[0..bytes_read], 0))
|
||||
.map_err(DiagDeviceError::ParseMessagesContainerError)?;
|
||||
if !leftover_bytes.is_empty() {
|
||||
warn!("warning: {} leftover bytes when parsing MessagesContainer", leftover_bytes.len());
|
||||
}
|
||||
|
||||
if let Some(qmdl_writer) = self.qmdl_writer.as_mut() {
|
||||
if self.fully_initialized {
|
||||
qmdl_writer.write_container(&container)
|
||||
.map_err(DiagDeviceError::QmdlFileWriteError)?;
|
||||
}
|
||||
}
|
||||
Ok(container)
|
||||
}
|
||||
}
|
||||
|
||||
impl DiagDevice {
|
||||
pub fn new(qmdl_writer: Option<QmdlWriter<File>>) -> DiagResult<Self> {
|
||||
let diag_file = std::fs::File::options()
|
||||
pub async fn new() -> 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();
|
||||
|
||||
@@ -117,13 +91,32 @@ impl DiagDevice {
|
||||
Ok(DiagDevice {
|
||||
read_buf: vec![0; BUFFER_LEN],
|
||||
file: diag_file,
|
||||
fully_initialized: false,
|
||||
qmdl_writer,
|
||||
use_mdm,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write_request(&mut self, req: &Request) -> DiagResult<()> {
|
||||
pub fn as_stream(&mut self) -> impl TryStream<Ok = MessagesContainer, Error = DiagDeviceError> + '_ {
|
||||
futures::stream::try_unfold(self, |dev| async {
|
||||
let container = dev.get_next_messages_container().await?;
|
||||
Ok(Some((container, dev)))
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_next_messages_container(&mut self) -> Result<MessagesContainer, DiagDeviceError> {
|
||||
let mut bytes_read = 0;
|
||||
while bytes_read == 0 {
|
||||
bytes_read = self.file.read(&mut self.read_buf).await
|
||||
.map_err(DiagDeviceError::DeviceReadFailed)?;
|
||||
}
|
||||
let ((leftover_bytes, _), container) = MessagesContainer::from_bytes((&self.read_buf[0..bytes_read], 0))
|
||||
.map_err(DiagDeviceError::ParseMessagesContainerError)?;
|
||||
if !leftover_bytes.is_empty() {
|
||||
warn!("warning: {} leftover bytes when parsing MessagesContainer", leftover_bytes.len());
|
||||
}
|
||||
Ok(container)
|
||||
}
|
||||
|
||||
async fn write_request(&mut self, req: &Request) -> DiagResult<()> {
|
||||
let req_bytes = &req.to_bytes().expect("Failed to serialize Request");
|
||||
let buf = RequestContainer {
|
||||
data_type: DataType::UserSpace,
|
||||
@@ -131,23 +124,35 @@ impl DiagDevice {
|
||||
mdm_field: -1,
|
||||
hdlc_encapsulated_request: hdlc_encapsulate(req_bytes, &CRC_CCITT),
|
||||
}.to_bytes().expect("Failed to serialize RequestContainer");
|
||||
unsafe {
|
||||
let fd = self.file.as_raw_fd();
|
||||
let buf_ptr = buf.as_ptr() as *const libc::c_void;
|
||||
let ret = libc::write(fd, buf_ptr, buf.len());
|
||||
if ret < 0 {
|
||||
let msg = format!("write failed with error code {}", ret);
|
||||
return Err(DiagDeviceError::DeviceWriteFailed(msg));
|
||||
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));
|
||||
}
|
||||
}
|
||||
self.file.flush().await
|
||||
.map_err(DiagDeviceError::DeviceWriteFailed)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn retrieve_id_ranges(&mut self) -> DiagResult<[u32; 16]> {
|
||||
let req = Request::LogConfig(LogConfigRequest::RetrieveIdRanges);
|
||||
self.write_request(&req)?;
|
||||
async fn read_response(&mut self) -> DiagResult<Vec<Result<Message, DiagParsingError>>> {
|
||||
loop {
|
||||
let container = self.get_next_messages_container().await?;
|
||||
if container.data_type != DataType::UserSpace {
|
||||
continue;
|
||||
}
|
||||
return Ok(container.into_messages());
|
||||
}
|
||||
}
|
||||
|
||||
for msg in self.read_response()? {
|
||||
async fn retrieve_id_ranges(&mut self) -> DiagResult<[u32; 16]> {
|
||||
let req = Request::LogConfig(LogConfigRequest::RetrieveIdRanges);
|
||||
self.write_request(&req).await?;
|
||||
|
||||
for msg in self.read_response().await? {
|
||||
match msg {
|
||||
Ok(Message::Log { .. }) => info!("skipping log response..."),
|
||||
Ok(Message::Response { payload, status, .. }) => match payload {
|
||||
@@ -166,11 +171,11 @@ impl DiagDevice {
|
||||
Err(DiagDeviceError::NoResponse(req))
|
||||
}
|
||||
|
||||
fn set_log_mask(&mut self, log_type: u32, log_mask_bitsize: u32) -> DiagResult<()> {
|
||||
async fn set_log_mask(&mut self, log_type: u32, log_mask_bitsize: u32) -> DiagResult<()> {
|
||||
let req = build_log_mask_request(log_type, log_mask_bitsize, &LOG_CODES_FOR_RAW_PACKET_LOGGING);
|
||||
self.write_request(&req)?;
|
||||
self.write_request(&req).await?;
|
||||
|
||||
for msg in self.read_response()? {
|
||||
for msg in self.read_response().await? {
|
||||
match msg {
|
||||
Ok(Message::Log { .. }) => info!("skipping log response..."),
|
||||
Ok(Message::Response { payload, status, .. }) => {
|
||||
@@ -188,18 +193,17 @@ impl DiagDevice {
|
||||
Err(DiagDeviceError::NoResponse(req))
|
||||
}
|
||||
|
||||
pub fn config_logs(&mut self) -> DiagResult<()> {
|
||||
pub async fn config_logs(&mut self) -> DiagResult<()> {
|
||||
info!("retrieving diag logging capabilities...");
|
||||
let log_mask_sizes = self.retrieve_id_ranges()?;
|
||||
let log_mask_sizes = self.retrieve_id_ranges().await?;
|
||||
|
||||
for (log_type, &log_mask_bitsize) in log_mask_sizes.iter().enumerate() {
|
||||
if log_mask_bitsize > 0 {
|
||||
self.set_log_mask(log_type as u32, log_mask_bitsize)?;
|
||||
self.set_log_mask(log_type as u32, log_mask_bitsize).await?;
|
||||
info!("enabled logging for log type {}", log_type);
|
||||
}
|
||||
}
|
||||
|
||||
self.fully_initialized = true;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
use crate::diag;
|
||||
use crate::{diag::*, hdlc::hdlc_decapsulate};
|
||||
use crate::hdlc;
|
||||
|
||||
use crc::{Crc, Algorithm};
|
||||
use deku::prelude::*;
|
||||
use log::{info, warn, error};
|
||||
use thiserror::Error;
|
||||
|
||||
// this is sorta based on the params qcsuper uses, plus what seems to be used in
|
||||
// https://github.com/fgsect/scat/blob/f1538b397721df3ab8ba12acd26716abcf21f78b/util.py#L47
|
||||
pub const CRC_CCITT_ALG: Algorithm<u16> = Algorithm {
|
||||
poly: 0x1021,
|
||||
init: 0xffff,
|
||||
refin: true,
|
||||
refout: true,
|
||||
width: 16,
|
||||
xorout: 0xffff,
|
||||
check: 0x2189,
|
||||
residue: 0x0000,
|
||||
};
|
||||
pub const CRC_CCITT: Crc<u16> = Crc::<u16>::new(&CRC_CCITT_ALG);
|
||||
|
||||
#[derive(Debug, PartialEq, Error)]
|
||||
pub enum DiagParsingError {
|
||||
#[error("Failed to parse Message: {0}, data: {1:?}")]
|
||||
MessageParsingError(deku::DekuError, Vec<u8>),
|
||||
#[error("HDLC decapsulation of message failed: {0}, data: {1:?}")]
|
||||
HdlcDecapsulationError(hdlc::HdlcError, Vec<u8>),
|
||||
}
|
||||
|
||||
type MaybeMessage = Result<Message, DiagParsingError>;
|
||||
|
||||
pub trait DiagReader {
|
||||
type Err;
|
||||
|
||||
fn get_next_messages_container(&mut self) -> Result<MessagesContainer, Self::Err>;
|
||||
|
||||
fn read_response(&mut self) -> Result<Vec<MaybeMessage>, Self::Err> {
|
||||
loop {
|
||||
let container = self.get_next_messages_container()?;
|
||||
if container.data_type == DataType::UserSpace {
|
||||
return self.parse_response_container(container);
|
||||
} else {
|
||||
info!("skipping non-userspace message...")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_response_container(&self, container: MessagesContainer) -> Result<Vec<MaybeMessage>, Self::Err> {
|
||||
let mut result = Vec::new();
|
||||
for msg in container.messages {
|
||||
for sub_msg in msg.data.split_inclusive(|&b| b == diag::MESSAGE_TERMINATOR) {
|
||||
match hdlc_decapsulate(sub_msg, &CRC_CCITT) {
|
||||
Ok(data) => match Message::from_bytes((&data, 0)) {
|
||||
Ok(((leftover_bytes, _), res)) => {
|
||||
if !leftover_bytes.is_empty() {
|
||||
warn!("warning: {} leftover bytes when parsing Message", leftover_bytes.len());
|
||||
}
|
||||
result.push(Ok(res));
|
||||
},
|
||||
Err(e) => {
|
||||
result.push(Err(DiagParsingError::MessageParsingError(e, data)));
|
||||
},
|
||||
},
|
||||
Err(err) => {
|
||||
result.push(Err(DiagParsingError::HdlcDecapsulationError(err, sub_msg.to_vec())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
struct MockReader {
|
||||
containers: Vec<MessagesContainer>,
|
||||
}
|
||||
|
||||
impl DiagReader for MockReader {
|
||||
type Err = ();
|
||||
|
||||
fn get_next_messages_container(&mut self) -> Result<MessagesContainer, Self::Err> {
|
||||
Ok(self.containers.remove(0))
|
||||
}
|
||||
}
|
||||
|
||||
fn make_container(data_type: DataType, message: HdlcEncapsulatedMessage) -> MessagesContainer {
|
||||
MessagesContainer {
|
||||
data_type,
|
||||
num_messages: 1,
|
||||
messages: vec![message],
|
||||
}
|
||||
}
|
||||
|
||||
// this log is based on one captured on a real device -- if it fails to
|
||||
// serialize or deserialize, that's probably a problem with this mock, not
|
||||
// the DiagReader implementation
|
||||
fn get_test_message(payload: &[u8]) -> (HdlcEncapsulatedMessage, Message) {
|
||||
let length_with_payload = 31 + payload.len() as u16;
|
||||
let message = Message::Log {
|
||||
pending_msgs: 0,
|
||||
outer_length: length_with_payload,
|
||||
inner_length: length_with_payload,
|
||||
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: payload.len() as u16,
|
||||
packet: payload.to_vec(),
|
||||
},
|
||||
},
|
||||
};
|
||||
let serialized = message.to_bytes().expect("failed to serialize test message");
|
||||
let encapsulated_data = hdlc::hdlc_encapsulate(&serialized, &CRC_CCITT);
|
||||
let encapsulated = HdlcEncapsulatedMessage {
|
||||
len: encapsulated_data.len() as u32,
|
||||
data: encapsulated_data,
|
||||
};
|
||||
(encapsulated, message)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_skipping_nonuser_containers() {
|
||||
let (encapsulated1, message1) = get_test_message(&[1]);
|
||||
let (encapsulated2, _) = get_test_message(&[2]);
|
||||
let (encapsulated3, message3) = get_test_message(&[3]);
|
||||
let mut reader = MockReader {
|
||||
containers: vec![
|
||||
make_container(DataType::UserSpace, encapsulated1),
|
||||
make_container(DataType::Other(0), encapsulated2),
|
||||
make_container(DataType::UserSpace, encapsulated3),
|
||||
],
|
||||
};
|
||||
assert_eq!(reader.read_response(), Ok(vec![Ok(message1)]));
|
||||
assert_eq!(reader.read_response(), Ok(vec![Ok(message3)]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_containers_with_multiple_messages() {
|
||||
let (encapsulated1, message1) = get_test_message(&[1]);
|
||||
let (encapsulated2, message2) = get_test_message(&[2]);
|
||||
let mut container1 = make_container(DataType::UserSpace, encapsulated1);
|
||||
container1.messages.push(encapsulated2);
|
||||
container1.num_messages += 1;
|
||||
let (encapsulated3, message3) = get_test_message(&[3]);
|
||||
let mut reader = MockReader {
|
||||
containers: vec![
|
||||
container1,
|
||||
make_container(DataType::UserSpace, encapsulated3),
|
||||
],
|
||||
};
|
||||
assert_eq!(reader.read_response(), Ok(vec![Ok(message1), Ok(message2)]));
|
||||
assert_eq!(reader.read_response(), Ok(vec![Ok(message3)]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_containers_with_concatenated_message() {
|
||||
let (mut encapsulated1, message1) = get_test_message(&[1]);
|
||||
let (encapsulated2, message2) = get_test_message(&[2]);
|
||||
encapsulated1.data.extend(encapsulated2.data);
|
||||
encapsulated1.len += encapsulated2.len;
|
||||
let (encapsulated3, message3) = get_test_message(&[3]);
|
||||
let mut reader = MockReader {
|
||||
containers: vec![
|
||||
make_container(DataType::UserSpace, encapsulated1),
|
||||
make_container(DataType::UserSpace, encapsulated3),
|
||||
],
|
||||
};
|
||||
assert_eq!(reader.read_response(), Ok(vec![Ok(message1), Ok(message2)]));
|
||||
assert_eq!(reader.read_response(), Ok(vec![Ok(message3)]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_handles_parsing_errors() {
|
||||
let (encapsulated1, message1) = get_test_message(&[1]);
|
||||
let bad_message = hdlc::hdlc_encapsulate(&[0x01, 0x02, 0x03, 0x04], &CRC_CCITT);
|
||||
let encapsulated2 = HdlcEncapsulatedMessage {
|
||||
len: bad_message.len() as u32,
|
||||
data: bad_message,
|
||||
};
|
||||
let mut container = make_container(DataType::UserSpace, encapsulated1);
|
||||
container.messages.push(encapsulated2);
|
||||
container.num_messages += 1;
|
||||
let mut reader = MockReader {
|
||||
containers: vec![container],
|
||||
};
|
||||
let result = reader.read_response().unwrap();
|
||||
assert_eq!(result[0], Ok(message1));
|
||||
assert!(matches!(result[1], Err(DiagParsingError::MessageParsingError(_, _))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_handles_encapsulation_errors() {
|
||||
let (encapsulated1, message1) = get_test_message(&[1]);
|
||||
let bad_encapsulation = HdlcEncapsulatedMessage {
|
||||
len: 4,
|
||||
data: vec![0x01, 0x02, 0x03, 0x04],
|
||||
};
|
||||
let mut container = make_container(DataType::UserSpace, encapsulated1);
|
||||
container.messages.push(bad_encapsulation);
|
||||
container.num_messages += 1;
|
||||
let mut reader = MockReader {
|
||||
containers: vec![container],
|
||||
};
|
||||
let result = reader.read_response().unwrap();
|
||||
assert_eq!(result[0], Ok(message1));
|
||||
assert!(matches!(result[1], Err(DiagParsingError::HdlcDecapsulationError(_, _))));
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ use thiserror::Error;
|
||||
|
||||
use crate::diag::{MESSAGE_ESCAPE_CHAR, MESSAGE_TERMINATOR, ESCAPED_MESSAGE_ESCAPE_CHAR, ESCAPED_MESSAGE_TERMINATOR};
|
||||
|
||||
#[derive(Debug, Error, PartialEq)]
|
||||
#[derive(Debug, Clone, Error, PartialEq)]
|
||||
pub enum HdlcError {
|
||||
#[error("Invalid checksum (expected {0}, got {1})")]
|
||||
InvalidChecksum(u16, u16),
|
||||
@@ -89,7 +89,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_hdlc_encapsulate() {
|
||||
let crc = Crc::<u16>::new(&crate::diag_reader::CRC_CCITT_ALG);
|
||||
let crc = Crc::<u16>::new(&crate::diag::CRC_CCITT_ALG);
|
||||
let data = vec![0x01, 0x02, 0x03, 0x04];
|
||||
let expected = vec![1, 2, 3, 4, 145, 57, 126];
|
||||
let encapsulated = hdlc_encapsulate(&data, &crc);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
pub mod hdlc;
|
||||
pub mod diag;
|
||||
pub mod diag_device;
|
||||
pub mod diag_reader;
|
||||
pub mod qmdl;
|
||||
pub mod log_codes;
|
||||
pub mod gsmtap;
|
||||
pub mod gsmtap_parser;
|
||||
pub mod pcap;
|
||||
pub mod analysis;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Enumerates some releVant diag log codes. Copied from QCSuper
|
||||
//! Enumerates some relevant diag log codes. Copied from QCSuper
|
||||
|
||||
|
||||
// These are 2G-related log types.
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use crate::gsmtap::GsmtapMessage;
|
||||
use crate::diag::Timestamp;
|
||||
|
||||
use std::io::Write;
|
||||
use tokio::io::AsyncWrite;
|
||||
use std::borrow::Cow;
|
||||
use chrono::prelude::*;
|
||||
use deku::prelude::*;
|
||||
use pcap_file::pcapng::blocks::enhanced_packet::EnhancedPacketBlock;
|
||||
use pcap_file::pcapng::blocks::interface_description::InterfaceDescriptionBlock;
|
||||
use pcap_file::pcapng::PcapNgWriter;
|
||||
use pcap_file::PcapError;
|
||||
use pcap_file_tokio::pcapng::blocks::enhanced_packet::EnhancedPacketBlock;
|
||||
use pcap_file_tokio::pcapng::blocks::interface_description::InterfaceDescriptionBlock;
|
||||
use pcap_file_tokio::pcapng::PcapNgWriter;
|
||||
use pcap_file_tokio::PcapError;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
@@ -23,7 +23,7 @@ pub enum GsmtapPcapError {
|
||||
Deku(#[from] DekuError),
|
||||
}
|
||||
|
||||
pub struct GsmtapPcapWriter<T> where T: Write {
|
||||
pub struct GsmtapPcapWriter<T> where T: AsyncWrite {
|
||||
writer: PcapNgWriter<T>,
|
||||
ip_id: u16,
|
||||
}
|
||||
@@ -56,23 +56,23 @@ struct UdpHeader {
|
||||
checksum: u16,
|
||||
}
|
||||
|
||||
impl<T> GsmtapPcapWriter<T> where T: Write {
|
||||
pub fn new(writer: T) -> Result<Self, GsmtapPcapError> {
|
||||
let writer = PcapNgWriter::new(writer)?;
|
||||
impl<T> GsmtapPcapWriter<T> where T: AsyncWrite + Unpin + Send {
|
||||
pub async fn new(writer: T) -> Result<Self, GsmtapPcapError> {
|
||||
let writer = PcapNgWriter::new(writer).await?;
|
||||
Ok(GsmtapPcapWriter { writer, ip_id: 0 })
|
||||
}
|
||||
|
||||
pub fn write_iface_header(&mut self) -> Result<(), GsmtapPcapError> {
|
||||
pub async fn write_iface_header(&mut self) -> Result<(), GsmtapPcapError> {
|
||||
let interface = InterfaceDescriptionBlock {
|
||||
linktype: pcap_file::DataLink::IPV4,
|
||||
linktype: pcap_file_tokio::DataLink::IPV4,
|
||||
snaplen: 0xffff,
|
||||
options: vec![],
|
||||
};
|
||||
self.writer.write_pcapng_block(interface)?;
|
||||
self.writer.write_pcapng_block(interface).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_gsmtap_message(&mut self, msg: GsmtapMessage, timestamp: Timestamp) -> Result<(), GsmtapPcapError> {
|
||||
pub async fn write_gsmtap_message(&mut self, msg: GsmtapMessage, timestamp: Timestamp) -> Result<(), GsmtapPcapError> {
|
||||
let duration = timestamp.to_datetime()
|
||||
.signed_duration_since(DateTime::UNIX_EPOCH)
|
||||
.to_std()?;
|
||||
@@ -113,7 +113,7 @@ impl<T> GsmtapPcapWriter<T> where T: Write {
|
||||
data: Cow::Owned(data),
|
||||
options: vec![],
|
||||
};
|
||||
self.writer.write_pcapng_block(packet)?;
|
||||
self.writer.write_pcapng_block(packet).await?;
|
||||
self.ip_id = self.ip_id.wrapping_add(1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3,19 +3,18 @@
|
||||
//! QmdlReader and QmdlWriter can read and write MessagesContainers to and from
|
||||
//! QMDL files.
|
||||
|
||||
use crate::diag_reader::DiagReader;
|
||||
use crate::diag::{MessagesContainer, MESSAGE_TERMINATOR, HdlcEncapsulatedMessage, DataType};
|
||||
|
||||
use std::io::{Write, BufReader, BufRead, Read};
|
||||
use thiserror::Error;
|
||||
use futures::TryStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt, BufReader, AsyncBufReadExt};
|
||||
use log::error;
|
||||
|
||||
pub struct QmdlWriter<T> where T: Write {
|
||||
pub struct QmdlWriter<T> where T: AsyncWrite + Unpin {
|
||||
writer: T,
|
||||
pub total_written: usize,
|
||||
}
|
||||
|
||||
impl<T> QmdlWriter<T> where T: Write {
|
||||
impl<T> QmdlWriter<T> where T: AsyncWrite + Unpin {
|
||||
pub fn new(writer: T) -> Self {
|
||||
QmdlWriter::new_with_existing_size(writer, 0)
|
||||
}
|
||||
@@ -27,30 +26,22 @@ impl<T> QmdlWriter<T> where T: Write {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_container(&mut self, container: &MessagesContainer) -> std::io::Result<()> {
|
||||
pub async fn write_container(&mut self, container: &MessagesContainer) -> std::io::Result<()> {
|
||||
for msg in &container.messages {
|
||||
self.writer.write_all(&msg.data)?;
|
||||
self.writer.write_all(&msg.data).await?;
|
||||
self.total_written += msg.data.len();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum QmdlReaderError {
|
||||
#[error("IO error: {0}")]
|
||||
IoError(#[from] std::io::Error),
|
||||
#[error("Reached max_bytes count {0}")]
|
||||
MaxBytesReached(usize),
|
||||
}
|
||||
|
||||
pub struct QmdlReader<T> where T: Read {
|
||||
pub struct QmdlReader<T> where T: AsyncRead {
|
||||
reader: BufReader<T>,
|
||||
bytes_read: usize,
|
||||
max_bytes: Option<usize>,
|
||||
}
|
||||
|
||||
impl<T> QmdlReader<T> where T: Read {
|
||||
impl<T> QmdlReader<T> where T: AsyncRead + Unpin {
|
||||
pub fn new(reader: T, max_bytes: Option<usize>) -> Self {
|
||||
QmdlReader {
|
||||
reader: BufReader::new(reader),
|
||||
@@ -58,23 +49,29 @@ impl<T> QmdlReader<T> where T: Read {
|
||||
max_bytes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DiagReader for QmdlReader<T> where T: Read {
|
||||
type Err = QmdlReaderError;
|
||||
pub fn as_stream(&mut self) -> impl TryStream<Ok = MessagesContainer, Error = std::io::Error> + '_ {
|
||||
futures::stream::try_unfold(self, |reader| async {
|
||||
let maybe_container = reader.get_next_messages_container().await?;
|
||||
match maybe_container {
|
||||
Some(container) => Ok(Some((container, reader))),
|
||||
None => Ok(None)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn get_next_messages_container(&mut self) -> Result<MessagesContainer, Self::Err> {
|
||||
async fn get_next_messages_container(&mut self) -> Result<Option<MessagesContainer>, std::io::Error> {
|
||||
if let Some(max_bytes) = self.max_bytes {
|
||||
if self.bytes_read >= max_bytes {
|
||||
if self.bytes_read > max_bytes {
|
||||
error!("warning: {} bytes read, but max_bytes was {}", self.bytes_read, max_bytes);
|
||||
}
|
||||
return Err(QmdlReaderError::MaxBytesReached(max_bytes));
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
|
||||
let mut buf = Vec::new();
|
||||
let bytes_read = self.reader.read_until(MESSAGE_TERMINATOR, &mut buf)?;
|
||||
let bytes_read = self.reader.read_until(MESSAGE_TERMINATOR, &mut buf).await?;
|
||||
self.bytes_read += bytes_read;
|
||||
|
||||
// Since QMDL is just a flat list of messages, we can't actually
|
||||
@@ -82,7 +79,7 @@ impl<T> DiagReader for QmdlReader<T> where T: Read {
|
||||
// read. So we'll just pretend that all containers had exactly one
|
||||
// message. As far as I know, the number of messages per container
|
||||
// doesn't actually affect anything, so this should be fine.
|
||||
Ok(MessagesContainer {
|
||||
Ok(Some(MessagesContainer {
|
||||
data_type: DataType::UserSpace,
|
||||
num_messages: 1,
|
||||
messages: vec![
|
||||
@@ -91,7 +88,7 @@ impl<T> DiagReader for QmdlReader<T> where T: Read {
|
||||
data: buf,
|
||||
},
|
||||
]
|
||||
})
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +97,7 @@ mod test {
|
||||
use std::io::Cursor;
|
||||
|
||||
use crate::hdlc::hdlc_encapsulate;
|
||||
use crate::diag_reader::CRC_CCITT;
|
||||
use crate::diag::CRC_CCITT;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -140,8 +137,8 @@ mod test {
|
||||
]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unbounded_qmdl_reader() {
|
||||
#[tokio::test]
|
||||
async fn test_unbounded_qmdl_reader() {
|
||||
let mut buf = Cursor::new(get_test_message_bytes());
|
||||
let mut reader = QmdlReader::new(&mut buf, None);
|
||||
let expected_messages = get_test_messages();
|
||||
@@ -151,12 +148,12 @@ mod test {
|
||||
num_messages: 1,
|
||||
messages: vec![message],
|
||||
};
|
||||
assert_eq!(expected_container, reader.get_next_messages_container().unwrap());
|
||||
assert_eq!(expected_container, reader.get_next_messages_container().await.unwrap().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bounded_qmdl_reader() {
|
||||
#[tokio::test]
|
||||
async fn test_bounded_qmdl_reader() {
|
||||
let mut buf = Cursor::new(get_test_message_bytes());
|
||||
|
||||
// bound the reader to the first two messages
|
||||
@@ -170,30 +167,30 @@ mod test {
|
||||
num_messages: 1,
|
||||
messages: vec![message],
|
||||
};
|
||||
assert_eq!(expected_container, reader.get_next_messages_container().unwrap());
|
||||
assert_eq!(expected_container, reader.get_next_messages_container().await.unwrap().unwrap());
|
||||
}
|
||||
assert!(matches!(reader.get_next_messages_container(), Err(QmdlReaderError::MaxBytesReached(_))));
|
||||
assert!(matches!(reader.get_next_messages_container().await, Ok(None)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_qmdl_writer() {
|
||||
#[tokio::test]
|
||||
async fn test_qmdl_writer() {
|
||||
let mut buf = Vec::new();
|
||||
let mut writer = QmdlWriter::new(&mut buf);
|
||||
let expected_containers = get_test_containers();
|
||||
for container in &expected_containers {
|
||||
writer.write_container(container).unwrap();
|
||||
writer.write_container(container).await.unwrap();
|
||||
}
|
||||
assert_eq!(writer.total_written, buf.len());
|
||||
assert_eq!(buf, get_test_message_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_writing_and_reading() {
|
||||
#[tokio::test]
|
||||
async fn test_writing_and_reading() {
|
||||
let mut buf = Vec::new();
|
||||
let mut writer = QmdlWriter::new(&mut buf);
|
||||
let expected_containers = get_test_containers();
|
||||
for container in &expected_containers {
|
||||
writer.write_container(container).unwrap();
|
||||
writer.write_container(container).await.unwrap();
|
||||
}
|
||||
|
||||
let limit = Some(buf.len());
|
||||
@@ -205,8 +202,8 @@ mod test {
|
||||
num_messages: 1,
|
||||
messages: vec![message],
|
||||
};
|
||||
assert_eq!(expected_container, reader.get_next_messages_container().unwrap());
|
||||
assert_eq!(expected_container, reader.get_next_messages_container().await.unwrap().unwrap());
|
||||
}
|
||||
assert!(matches!(reader.get_next_messages_container(), Err(QmdlReaderError::MaxBytesReached(_))));
|
||||
assert!(matches!(reader.get_next_messages_container().await, Ok(None)));
|
||||
}
|
||||
}
|
||||
|
||||
7
make.sh
7
make.sh
@@ -1,3 +1,4 @@
|
||||
cargo build --release
|
||||
adb push target/armv7-unknown-linux-gnueabihf/release/rayhunter /data/rayhunter/rayhunter
|
||||
adb shell '/bin/rootshell -c "/etc/init.d/rayhunter_daemon restart"'
|
||||
#!/bin/sh
|
||||
cargo build --release --target="armv7-unknown-linux-gnueabihf" --bin rayhunter-daemon
|
||||
adb push target/armv7-unknown-linux-gnueabihf/release/rayhunter-daemon /data/rayhunter/
|
||||
adb shell '/bin/rootshell -c "/etc/init.d/rayhunter_daemon restart"'
|
||||
|
||||
@@ -6,7 +6,7 @@ case "$1" in
|
||||
start)
|
||||
echo -n "Starting rayhunter: "
|
||||
start-stop-daemon -S -b --make-pidfile --pidfile /tmp/rayhunter.pid \
|
||||
--startas /bin/bash -- -c "exec /data/rayhunter/rayhunter /data/rayhunter/config.toml > /data/rayhunter/rayhunter.log 2>&1"
|
||||
--startas /bin/bash -- -c "exec /data/rayhunter/rayhunter-daemon /data/rayhunter/config.toml > /data/rayhunter/rayhunter.log 2>&1"
|
||||
echo "done"
|
||||
;;
|
||||
stop)
|
||||
|
||||
15
telcom-parser/Cargo.toml
Normal file
15
telcom-parser/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "telcom-parser"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
asn1-compiler = "0.6.1"
|
||||
asn1-codecs = "0.6.1"
|
||||
asn1_codecs_derive = "0.6.1"
|
||||
bitvec = { version = "1.0", features = ["serde"] }
|
||||
log = "0.4"
|
||||
thiserror = "1.0.56"
|
||||
serde = { version = "1.0.196", features = ["derive"] }
|
||||
26
telcom-parser/README.md
Normal file
26
telcom-parser/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Autogenerated telcom packet parsing
|
||||
|
||||
This crate contains [ASN.1](https://en.wikipedia.org/wiki/ASN.1) specs for various telcom message payloads, as well as autogenerated
|
||||
Rust code for parsing these messages. We're using [hampi](https://github.com/ystero-dev/hampi/) as a parser generator, and it seems
|
||||
3GPP protocols are encoded in the unaligned Packed Encoding Rules (or uPER) codec.
|
||||
|
||||
## Generating the parser
|
||||
|
||||
To install the hampi compiler, run:
|
||||
|
||||
```
|
||||
> cargo install asn1-compiler
|
||||
```
|
||||
|
||||
To generate the parser for LTE RRC, run:
|
||||
|
||||
```
|
||||
> hampi-rs-asn1c --codec uper --derive clone --derive partial-eq --derive serialize --module src/lte_rrc.rs -- specs/EUTRA* specs/PC5-RRC-Definitions.asn
|
||||
```
|
||||
|
||||
## Sourcing the ASN.1 files
|
||||
|
||||
3GPP, who develops the standards for 4G (and all the other G's) publishes ASN.1 specs for their protocols in these horrific Microsoft Word docs (e.g. [here](https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=2440)). The ASN.1 blocks are denoted by `--ASN1START` and `--ASN1STOP` text, so extracting them automatically is possible using a script like [hampi's](https://github.com/ystero-dev/hampi/blob/master/examples/specs/parse_spec.py). Instead of doing this ourselves, we just sourced ours from [these](https://obj-sys.com/products/asn1apis/lte_3gpp_apis.php#lte_4g_apis).
|
||||
|
||||
# TODO
|
||||
* implement proof of concept binary using this to parse QMDL, summarize the packets
|
||||
670
telcom-parser/specs/EUTRA-InterNodeDefinitions.asn
Normal file
670
telcom-parser/specs/EUTRA-InterNodeDefinitions.asn
Normal file
@@ -0,0 +1,670 @@
|
||||
-- This file was generated by the Objective Systems ASN1C Compiler
|
||||
-- (http://www.obj-sys.com). Version: 7.7.2, Date: 13-Oct-2023.
|
||||
|
||||
EUTRA-InterNodeDefinitions DEFINITIONS AUTOMATIC TAGS ::= BEGIN
|
||||
|
||||
IMPORTS
|
||||
|
||||
AntennaInfoCommon, AntennaInfoDedicated-v10i0, ARFCN-ValueEUTRA,
|
||||
ARFCN-ValueEUTRA-v9e0, ARFCN-ValueEUTRA-r9, CellIdentity, C-RNTI,
|
||||
DAPS-PowerCoordinationInfo-r16, DL-DCCH-Message, DRB-Identity,
|
||||
DRB-ToReleaseList, DRB-ToReleaseList-r15, FreqBandIndicator-r11,
|
||||
InDeviceCoexIndication-r11, LWA-Config-r13, MasterInformationBlock, maxBands
|
||||
, maxFreq, maxDRB, maxDRBExt-r15, maxDRB-r15, maxSCell-r10, maxSCell-r13,
|
||||
maxServCell-r10, maxServCell-r13, MBMSInterestIndication-r11, MeasConfig,
|
||||
MeasGapConfig, MeasGapConfigPerCC-List-r14, MeasResultForRSSI-r13,
|
||||
MeasResultListWLAN-r13, OtherConfig-r9, PhysCellId, P-Max,
|
||||
PowerCoordinationInfo-r12, SidelinkUEInformation-r12, SL-CommConfig-r12,
|
||||
SL-DiscConfig-r12, SubframeAssignment-r15, RadioResourceConfigDedicated,
|
||||
RadioResourceConfigDedicated-v13c0, RadioResourceConfigDedicated-v1370,
|
||||
RAN-NotificationAreaInfo-r15, RCLWI-Configuration-r13, RSRP-Range,
|
||||
RSRQ-Range, RSRQ-Range-v1250, RS-SINR-Range-r13, SCellToAddModList-r10,
|
||||
SCellToAddModList-v13c0, SCellToAddModListExt-r13,
|
||||
SCellToAddModListExt-v13c0, SCG-ConfigPartSCG-r12, SCG-ConfigPartSCG-v12f0,
|
||||
SCG-ConfigPartSCG-v13c0, SecurityAlgorithmConfig, SCellIndex-r10,
|
||||
SCellIndex-r13, SCellToReleaseList-r10, SCellToReleaseListExt-r13,
|
||||
ServCellIndex-r10, ServCellIndex-r13, ShortMAC-I,
|
||||
MeasResultServFreqListNR-r15, MeasResultSSTD-r13, SL-V2X-ConfigDedicated-r14
|
||||
, SystemInformationBlockType1, SystemInformationBlockType1-v890-IEs,
|
||||
SystemInformationBlockType2, TDM-PatternConfig-r15,
|
||||
UEAssistanceInformation-r11, UECapabilityInformation,
|
||||
UE-CapabilityRAT-ContainerList, UE-RadioPagingInfo-r12,
|
||||
WLANConnectionStatusReport-r13, WLAN-OffloadConfig-r12
|
||||
FROM EUTRA-RRC-Definitions ;
|
||||
|
||||
-- Productions
|
||||
|
||||
Key-eNodeB-Star ::= BIT STRING (SIZE (256))
|
||||
|
||||
HandoverCommand-r8-IEs ::= SEQUENCE {
|
||||
handoverCommandMessage [0] OCTET STRING (CONTAINING DL-DCCH-Message),
|
||||
nonCriticalExtension [1] SEQUENCE {
|
||||
|
||||
} OPTIONAL
|
||||
}
|
||||
|
||||
HandoverCommand ::= SEQUENCE {
|
||||
criticalExtensions [0] EXPLICIT CHOICE {
|
||||
c1 [0] EXPLICIT CHOICE {
|
||||
handoverCommand-r8 [0] HandoverCommand-r8-IEs,
|
||||
spare7 [1] NULL,
|
||||
spare6 [2] NULL,
|
||||
spare5 [3] NULL,
|
||||
spare4 [4] NULL,
|
||||
spare3 [5] NULL,
|
||||
spare2 [6] NULL,
|
||||
spare1 [7] NULL
|
||||
},
|
||||
criticalExtensionsFuture [1] SEQUENCE {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCG-Config-v12i0b-IEs ::= SEQUENCE {
|
||||
scg-RadioConfig-v12i0 [0] SCG-ConfigPartSCG-v12f0 OPTIONAL,
|
||||
nonCriticalExtension [1] SEQUENCE {
|
||||
|
||||
} OPTIONAL
|
||||
}
|
||||
|
||||
SCG-Config-v13c0-IEs ::= SEQUENCE {
|
||||
scg-RadioConfig-v13c0 [0] SCG-ConfigPartSCG-v13c0 OPTIONAL,
|
||||
--Following field is only for late non-critical extensions from REL-13 onwards
|
||||
nonCriticalExtension [1] SEQUENCE {
|
||||
|
||||
} OPTIONAL
|
||||
}
|
||||
|
||||
SCG-Config-v12i0a-IEs ::= SEQUENCE {
|
||||
--Following field is only for late non-critical extensions from REL-12
|
||||
lateNonCriticalExtension [0] OCTET STRING (CONTAINING SCG-Config-v12i0b-IEs)
|
||||
OPTIONAL,
|
||||
nonCriticalExtension [1] SCG-Config-v13c0-IEs OPTIONAL
|
||||
}
|
||||
|
||||
SCG-Config-r12-IEs ::= SEQUENCE {
|
||||
scg-RadioConfig-r12 [0] SCG-ConfigPartSCG-r12 OPTIONAL,
|
||||
nonCriticalExtension [1] SCG-Config-v12i0a-IEs OPTIONAL
|
||||
}
|
||||
|
||||
SCG-Config-r12 ::= SEQUENCE {
|
||||
criticalExtensions [0] EXPLICIT CHOICE {
|
||||
c1 [0] EXPLICIT CHOICE {
|
||||
scg-Config-r12 [0] SCG-Config-r12-IEs,
|
||||
spare7 [1] NULL,
|
||||
spare6 [2] NULL,
|
||||
spare5 [3] NULL,
|
||||
spare4 [4] NULL,
|
||||
spare3 [5] NULL,
|
||||
spare2 [6] NULL,
|
||||
spare1 [7] NULL
|
||||
},
|
||||
criticalExtensionsFuture [1] SEQUENCE {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AS-ConfigNR-r15 ::= SEQUENCE {
|
||||
sourceRB-ConfigNR-r15 [0] OCTET STRING OPTIONAL,
|
||||
sourceRB-ConfigSN-NR-r15 [1] OCTET STRING OPTIONAL,
|
||||
sourceOtherConfigSN-NR-r15 [2] OCTET STRING OPTIONAL
|
||||
}
|
||||
|
||||
AS-Config-v1550 ::= SEQUENCE {
|
||||
tdm-PatternConfig-r15 [0] SEQUENCE {
|
||||
subframeAssignment-r15 [0] SubframeAssignment-r15,
|
||||
harq-Offset-r15 [1] INTEGER (0..9)
|
||||
} OPTIONAL,
|
||||
p-MaxEUTRA-r15 [1] P-Max OPTIONAL
|
||||
}
|
||||
|
||||
AS-ConfigNR-v1570 ::= SEQUENCE {
|
||||
sourceSCG-ConfiguredNR-r15 [0] ENUMERATED { true(0) }
|
||||
}
|
||||
|
||||
AS-ConfigNR-v1620 ::= SEQUENCE {
|
||||
tdm-PatternConfig2-r16 [0] EXPLICIT TDM-PatternConfig-r15
|
||||
}
|
||||
|
||||
AS-Config ::= SEQUENCE {
|
||||
sourceMeasConfig [0] MeasConfig,
|
||||
sourceRadioResourceConfig [1] RadioResourceConfigDedicated,
|
||||
sourceSecurityAlgorithmConfig [2] SecurityAlgorithmConfig,
|
||||
sourceUE-Identity [3] C-RNTI,
|
||||
sourceMasterInformationBlock [4] MasterInformationBlock,
|
||||
sourceSystemInformationBlockType1 [5] SystemInformationBlockType1 (
|
||||
WITH COMPONENTS {..., nonCriticalExtension ABSENT}),
|
||||
sourceSystemInformationBlockType2 [6] SystemInformationBlockType2,
|
||||
antennaInfoCommon [7] AntennaInfoCommon,
|
||||
sourceDl-CarrierFreq [8] ARFCN-ValueEUTRA,
|
||||
...,
|
||||
[[
|
||||
sourceSystemInformationBlockType1Ext [9] OCTET STRING (CONTAINING
|
||||
SystemInformationBlockType1-v890-IEs) OPTIONAL,
|
||||
sourceOtherConfig-r9 [10] OtherConfig-r9
|
||||
]],
|
||||
[[
|
||||
sourceSCellConfigList-r10 [11] SCellToAddModList-r10 OPTIONAL
|
||||
]],
|
||||
[[
|
||||
sourceConfigSCG-r12 [12] SCG-Config-r12 OPTIONAL
|
||||
]],
|
||||
[[
|
||||
as-ConfigNR-r15 [13] AS-ConfigNR-r15 OPTIONAL
|
||||
]],
|
||||
[[
|
||||
as-Config-v1550 [14] AS-Config-v1550 OPTIONAL
|
||||
]],
|
||||
[[
|
||||
as-ConfigNR-v1570 [15] AS-ConfigNR-v1570 OPTIONAL
|
||||
]],
|
||||
[[
|
||||
as-ConfigNR-v1620 [16] AS-ConfigNR-v1620 OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
CandidateCellInfo-r10 ::= SEQUENCE {
|
||||
--cellIdentification
|
||||
physCellId-r10 [0] PhysCellId,
|
||||
dl-CarrierFreq-r10 [1] ARFCN-ValueEUTRA,
|
||||
--available measurement results
|
||||
rsrpResult-r10 [2] RSRP-Range OPTIONAL,
|
||||
rsrqResult-r10 [3] RSRQ-Range OPTIONAL,
|
||||
...,
|
||||
[[
|
||||
dl-CarrierFreq-v1090 [4] ARFCN-ValueEUTRA-v9e0 OPTIONAL
|
||||
]],
|
||||
[[
|
||||
rsrqResult-v1250 [5] RSRQ-Range-v1250 OPTIONAL
|
||||
]],
|
||||
[[
|
||||
rs-sinr-Result-r13 [6] RS-SINR-Range-r13 OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
CandidateCellInfoList-r10 ::= SEQUENCE (SIZE (1..maxFreq)) OF CandidateCellInfo-r10
|
||||
|
||||
RRM-Config ::= SEQUENCE {
|
||||
ue-InactiveTime [0] ENUMERATED { s1(0), s2(1), s3(2), s5(3), s7(4), s10(5),
|
||||
s15(6), s20(7), s25(8), s30(9), s40(10), s50(11), min1(12), min1s20c(13)
|
||||
, min1s40(14), min2(15), min2s30(16), min3(17), min3s30(18), min4(19),
|
||||
min5(20), min6(21), min7(22), min8(23), min9(24), min10(25), min12(26),
|
||||
min14(27), min17(28), min20(29), min24(30), min28(31), min33(32),
|
||||
min38(33), min44(34), min50(35), hr1(36), hr1min30(37), hr2(38),
|
||||
hr2min30(39), hr3(40), hr3min30(41), hr4(42), hr5(43), hr6(44), hr8(45),
|
||||
hr10(46), hr13(47), hr16(48), hr20(49), day1(50), day1hr12(51), day2(52)
|
||||
, day2hr12(53), day3(54), day4(55), day5(56), day7(57), day10(58),
|
||||
day14(59), day19(60), day24(61), day30(62), dayMoreThan30(63) } OPTIONAL,
|
||||
...,
|
||||
[[
|
||||
candidateCellInfoList-r10 [1] CandidateCellInfoList-r10 OPTIONAL
|
||||
]],
|
||||
[[
|
||||
candidateCellInfoListNR-r15 [2] MeasResultServFreqListNR-r15 OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
AdditionalReestabInfo ::= SEQUENCE {
|
||||
cellIdentity [0] CellIdentity,
|
||||
key-eNodeB-Star [1] Key-eNodeB-Star,
|
||||
shortMAC-I [2] ShortMAC-I
|
||||
}
|
||||
|
||||
AdditionalReestabInfoList ::= SEQUENCE (SIZE (1..maxReestabInfo)) OF AdditionalReestabInfo
|
||||
|
||||
ReestablishmentInfo ::= SEQUENCE {
|
||||
sourcePhysCellId [0] PhysCellId,
|
||||
targetCellShortMAC-I [1] ShortMAC-I,
|
||||
additionalReestabInfoList [2] AdditionalReestabInfoList OPTIONAL,
|
||||
...
|
||||
}
|
||||
|
||||
AS-Context ::= SEQUENCE {
|
||||
reestablishmentInfo [0] ReestablishmentInfo OPTIONAL -- Cond HO
|
||||
}
|
||||
|
||||
AS-Config-v10j0 ::= SEQUENCE {
|
||||
antennaInfoDedicatedPCell-v10i0 [0] AntennaInfoDedicated-v10i0 OPTIONAL
|
||||
}
|
||||
|
||||
AS-Config-v13c0 ::= SEQUENCE {
|
||||
radioResourceConfigDedicated-v13c01 [0] RadioResourceConfigDedicated-v1370
|
||||
OPTIONAL,
|
||||
radioResourceConfigDedicated-v13c02 [1] RadioResourceConfigDedicated-v13c0
|
||||
OPTIONAL,
|
||||
sCellToAddModList-v13c0 [2] SCellToAddModList-v13c0 OPTIONAL,
|
||||
sCellToAddModListExt-v13c0 [3] SCellToAddModListExt-v13c0 OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v13c0-IEs ::= SEQUENCE {
|
||||
as-Config-v13c0 [0] AS-Config-v13c0 OPTIONAL,
|
||||
--Following field is only for late non-critical extensions from REL-13
|
||||
nonCriticalExtension [1] SEQUENCE {
|
||||
|
||||
} OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v10x0-IEs ::= SEQUENCE {
|
||||
--Following field is only for late non-critical extensions from REL-10 to REL-12
|
||||
lateNonCriticalExtension [0] OCTET STRING OPTIONAL,
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v13c0-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v10j0-IEs ::= SEQUENCE {
|
||||
as-Config-v10j0 [0] AS-Config-v10j0 OPTIONAL,
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v10x0-IEs OPTIONAL
|
||||
}
|
||||
|
||||
-- Late non-critical extensions:
|
||||
HandoverPreparationInformation-v9j0-IEs ::= SEQUENCE {
|
||||
--Following field is only for pre REL-10 late non-critical extensions
|
||||
lateNonCriticalExtension [0] OCTET STRING OPTIONAL,
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v10j0-IEs OPTIONAL
|
||||
}
|
||||
|
||||
AS-Config-v9e0 ::= SEQUENCE {
|
||||
sourceDl-CarrierFreq-v9e0 [0] ARFCN-ValueEUTRA-v9e0
|
||||
}
|
||||
|
||||
AS-Context-v1130 ::= SEQUENCE {
|
||||
idc-Indication-r11 [0] OCTET STRING (CONTAINING InDeviceCoexIndication-r11)
|
||||
OPTIONAL, -- Cond HO2
|
||||
mbmsInterestIndication-r11 [1] OCTET STRING (CONTAINING
|
||||
MBMSInterestIndication-r11) OPTIONAL, -- Cond HO2
|
||||
ueAssistanceInformation-r11 [2] OCTET STRING (CONTAINING
|
||||
UEAssistanceInformation-r11) OPTIONAL,
|
||||
...,
|
||||
[[
|
||||
sidelinkUEInformation-r12 [3] OCTET STRING (CONTAINING
|
||||
SidelinkUEInformation-r12) OPTIONAL
|
||||
]],
|
||||
[[
|
||||
sourceContextEN-DC-r15 [4] OCTET STRING OPTIONAL
|
||||
]],
|
||||
[[
|
||||
selectedbandCombinationInfoEN-DC-v1540 [5] OCTET STRING OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
AS-Config-v1250 ::= SEQUENCE {
|
||||
sourceWlan-OffloadConfig-r12 [0] WLAN-OffloadConfig-r12 OPTIONAL,
|
||||
sourceSL-CommConfig-r12 [1] SL-CommConfig-r12 OPTIONAL,
|
||||
sourceSL-DiscConfig-r12 [2] SL-DiscConfig-r12 OPTIONAL
|
||||
}
|
||||
|
||||
AS-Config-v1320 ::= SEQUENCE {
|
||||
sourceSCellConfigList-r13 [0] SCellToAddModListExt-r13 OPTIONAL,
|
||||
sourceRCLWI-Configuration-r13 [1] EXPLICIT RCLWI-Configuration-r13 OPTIONAL
|
||||
}
|
||||
|
||||
AS-Context-v1320 ::= SEQUENCE {
|
||||
wlanConnectionStatusReport-r13 [0] OCTET STRING (CONTAINING
|
||||
WLANConnectionStatusReport-r13) OPTIONAL -- Cond HO2
|
||||
}
|
||||
|
||||
AS-Config-v1430 ::= SEQUENCE {
|
||||
sourceSL-V2X-CommConfig-r14 [0] SL-V2X-ConfigDedicated-r14 OPTIONAL,
|
||||
sourceLWA-Config-r14 [1] LWA-Config-r13 OPTIONAL,
|
||||
sourceWLAN-MeasResult-r14 [2] MeasResultListWLAN-r13 OPTIONAL
|
||||
}
|
||||
|
||||
ConfigRestrictInfoDAPS-r16 ::= SEQUENCE {
|
||||
maxSCH-TB-BitsDL-r16 [0] INTEGER (1..100) OPTIONAL, -- Cond HO2
|
||||
maxSCH-TB-BitsUL-r16 [1] INTEGER (1..100) OPTIONAL -- Cond HO2
|
||||
}
|
||||
|
||||
AS-Context-v1610 ::= SEQUENCE {
|
||||
sidelinkUEInformationNR-r16 [0] OCTET STRING OPTIONAL, -- Cond HO3
|
||||
ueAssistanceInformationNR-r16 [1] OCTET STRING OPTIONAL, -- Cond HO3
|
||||
configRestrictInfoDAPS-r16 [2] ConfigRestrictInfoDAPS-r16 OPTIONAL -- Cond HO2
|
||||
}
|
||||
|
||||
AS-Context-v1620 ::= SEQUENCE {
|
||||
ueAssistanceInformationNR-SCG-r16 [0] OCTET STRING OPTIONAL -- Cond HO2
|
||||
}
|
||||
|
||||
ConfigRestrictInfoDAPS-v1630 ::= SEQUENCE {
|
||||
daps-PowerCoordinationInfo-r16 [0] DAPS-PowerCoordinationInfo-r16 OPTIONAL -- Cond HO2
|
||||
}
|
||||
|
||||
AS-Context-v1630 ::= SEQUENCE {
|
||||
configRestrictInfoDAPS-v1630 [0] ConfigRestrictInfoDAPS-v1630 OPTIONAL -- Cond HO2
|
||||
}
|
||||
|
||||
AS-Config-v1700 ::= SEQUENCE {
|
||||
scg-State-r17 [0] ENUMERATED { deactivated(0) } OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v1700-IEs ::= SEQUENCE {
|
||||
as-Config-v1700 [0] AS-Config-v1700 OPTIONAL, --Cond HO5
|
||||
nonCriticalExtension [1] SEQUENCE {
|
||||
|
||||
} OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v1630-IEs ::= SEQUENCE {
|
||||
as-Context-v1630 [0] AS-Context-v1630 OPTIONAL, --Cond HO2
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v1700-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v1620-IEs ::= SEQUENCE {
|
||||
as-Context-v1620 [0] AS-Context-v1620 OPTIONAL, --Cond HO2
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v1630-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v1610-IEs ::= SEQUENCE {
|
||||
as-Context-v1610 [0] AS-Context-v1610 OPTIONAL, --Cond HO5
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v1620-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v1540-IEs ::= SEQUENCE {
|
||||
sourceRB-ConfigIntra5GC-r15 [0] OCTET STRING OPTIONAL, --Cond HO4
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v1610-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v1530-IEs ::= SEQUENCE {
|
||||
ran-NotificationAreaInfo-r15 [0] EXPLICIT RAN-NotificationAreaInfo-r15
|
||||
OPTIONAL,
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v1540-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v1430-IEs ::= SEQUENCE {
|
||||
as-Config-v1430 [0] AS-Config-v1430 OPTIONAL, -- Cond HO2
|
||||
makeBeforeBreakReq-r14 [1] ENUMERATED { true(0) } OPTIONAL, -- Cond HO2
|
||||
nonCriticalExtension [2] HandoverPreparationInformation-v1530-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v1320-IEs ::= SEQUENCE {
|
||||
as-Config-v1320 [0] AS-Config-v1320 OPTIONAL, -- Cond HO2
|
||||
as-Context-v1320 [1] AS-Context-v1320 OPTIONAL, -- Cond HO2
|
||||
nonCriticalExtension [2] HandoverPreparationInformation-v1430-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v1250-IEs ::= SEQUENCE {
|
||||
ue-SupportedEARFCN-r12 [0] ARFCN-ValueEUTRA-r9 OPTIONAL, -- Cond HO3
|
||||
as-Config-v1250 [1] AS-Config-v1250 OPTIONAL, -- Cond HO2
|
||||
nonCriticalExtension [2] HandoverPreparationInformation-v1320-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v1130-IEs ::= SEQUENCE {
|
||||
as-Context-v1130 [0] AS-Context-v1130 OPTIONAL, -- Cond HO2
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v1250-IEs OPTIONAL
|
||||
}
|
||||
|
||||
-- Regular non-critical extensions:
|
||||
HandoverPreparationInformation-v9e0-IEs ::= SEQUENCE {
|
||||
as-Config-v9e0 [0] AS-Config-v9e0 OPTIONAL, -- Cond HO2
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v1130-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v9d0-IEs ::= SEQUENCE {
|
||||
lateNonCriticalExtension [0] OCTET STRING (CONTAINING
|
||||
HandoverPreparationInformation-v9j0-IEs) OPTIONAL,
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v9e0-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-v920-IEs ::= SEQUENCE {
|
||||
ue-ConfigRelease-r9 [0] ENUMERATED { rel9(0), rel10(1), rel11(2), rel12(3),
|
||||
v10j0(4), v11e0(5), v1280(6), rel13(7), ..., rel14(8), rel15(9),
|
||||
rel16(10), rel17(11) } OPTIONAL, -- Cond HO2
|
||||
nonCriticalExtension [1] HandoverPreparationInformation-v9d0-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation-r8-IEs ::= SEQUENCE {
|
||||
ue-RadioAccessCapabilityInfo [0] UE-CapabilityRAT-ContainerList,
|
||||
as-Config [1] AS-Config OPTIONAL, -- Cond HO
|
||||
rrm-Config [2] RRM-Config OPTIONAL,
|
||||
as-Context [3] AS-Context OPTIONAL, -- Cond HO
|
||||
nonCriticalExtension [4] HandoverPreparationInformation-v920-IEs OPTIONAL
|
||||
}
|
||||
|
||||
HandoverPreparationInformation ::= SEQUENCE {
|
||||
criticalExtensions [0] EXPLICIT CHOICE {
|
||||
c1 [0] EXPLICIT CHOICE {
|
||||
handoverPreparationInformation-r8 [0]
|
||||
HandoverPreparationInformation-r8-IEs,
|
||||
spare7 [1] NULL,
|
||||
spare6 [2] NULL,
|
||||
spare5 [3] NULL,
|
||||
spare4 [4] NULL,
|
||||
spare3 [5] NULL,
|
||||
spare2 [6] NULL,
|
||||
spare1 [7] NULL
|
||||
},
|
||||
criticalExtensionsFuture [1] SEQUENCE {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCG-ConfigRestrictInfo-r12 ::= SEQUENCE {
|
||||
maxSCH-TB-BitsDL-r12 [0] INTEGER (1..100),
|
||||
maxSCH-TB-BitsUL-r12 [1] INTEGER (1..100)
|
||||
}
|
||||
|
||||
MeasResultServCellSCG-r12 ::= SEQUENCE {
|
||||
servCellId-r12 [0] ServCellIndex-r10,
|
||||
measResultSCell-r12 [1] SEQUENCE {
|
||||
rsrpResultSCell-r12 [0] RSRP-Range,
|
||||
rsrqResultSCell-r12 [1] RSRQ-Range
|
||||
},
|
||||
...,
|
||||
[[
|
||||
servCellId-r13 [2] ServCellIndex-r13 OPTIONAL,
|
||||
measResultSCell-v1310 [3] SEQUENCE {
|
||||
rs-sinr-ResultSCell-r13 [0] RS-SINR-Range-r13
|
||||
} OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
MeasResultServCellListSCG-r12 ::= SEQUENCE (SIZE (1..maxServCell-r10)) OF
|
||||
MeasResultServCellSCG-r12
|
||||
|
||||
DRB-InfoSCG-r12 ::= SEQUENCE {
|
||||
eps-BearerIdentity-r12 [0] INTEGER (0..15) OPTIONAL, -- Cond DRB-Setup
|
||||
drb-Identity-r12 [1] DRB-Identity,
|
||||
drb-Type-r12 [2] ENUMERATED { split(0), scg(1) } OPTIONAL,
|
||||
...
|
||||
}
|
||||
|
||||
DRB-InfoListSCG-r12 ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-InfoSCG-r12
|
||||
|
||||
Cell-ToAddMod-r12 ::= SEQUENCE {
|
||||
sCellIndex-r12 [0] SCellIndex-r10,
|
||||
cellIdentification-r12 [1] SEQUENCE {
|
||||
physCellId-r12 [0] PhysCellId,
|
||||
dl-CarrierFreq-r12 [1] ARFCN-ValueEUTRA-r9
|
||||
} OPTIONAL, -- Cond SCellAdd
|
||||
measResultCellToAdd-r12 [2] SEQUENCE {
|
||||
rsrpResult-r12 [0] RSRP-Range,
|
||||
rsrqResult-r12 [1] RSRQ-Range
|
||||
} OPTIONAL,
|
||||
...,
|
||||
[[
|
||||
sCellIndex-r13 [3] SCellIndex-r13 OPTIONAL,
|
||||
measResultCellToAdd-v1310 [4] SEQUENCE {
|
||||
rs-sinr-Result-r13 [0] RS-SINR-Range-r13
|
||||
} OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
SCellToAddModListSCG-r12 ::= SEQUENCE (SIZE (1..maxSCell-r10)) OF Cell-ToAddMod-r12
|
||||
|
||||
MeasResultServCellListSCG-Ext-r13 ::= SEQUENCE (SIZE (1..maxServCell-r13)) OF
|
||||
MeasResultServCellSCG-r12
|
||||
|
||||
SCellToAddModListSCG-Ext-r13 ::= SEQUENCE (SIZE (1..maxSCell-r13)) OF Cell-ToAddMod-r12
|
||||
|
||||
MeasResultRSSI-SCG-r13 ::= SEQUENCE {
|
||||
servCellId-r13 [0] ServCellIndex-r13,
|
||||
measResultForRSSI-r13 [1] MeasResultForRSSI-r13
|
||||
}
|
||||
|
||||
MeasResultListRSSI-SCG-r13 ::= SEQUENCE (SIZE (1..maxServCell-r13)) OF MeasResultRSSI-SCG-r13
|
||||
|
||||
DRB-InfoListSCG-r15 ::= SEQUENCE (SIZE (1..maxDRB-r15)) OF DRB-InfoSCG-r12
|
||||
|
||||
SCG-ConfigInfo-v1530-IEs ::= SEQUENCE {
|
||||
drb-ToAddModListSCG-r15 [0] DRB-InfoListSCG-r15 OPTIONAL,
|
||||
drb-ToReleaseListSCG-r15 [1] DRB-ToReleaseList-r15 OPTIONAL,
|
||||
nonCriticalExtension [2] SEQUENCE {
|
||||
|
||||
} OPTIONAL
|
||||
}
|
||||
|
||||
SCG-ConfigInfo-v1430-IEs ::= SEQUENCE {
|
||||
makeBeforeBreakSCG-Req-r14 [0] ENUMERATED { true(0) } OPTIONAL,
|
||||
measGapConfigPerCC-List [1] EXPLICIT MeasGapConfigPerCC-List-r14 OPTIONAL,
|
||||
nonCriticalExtension [2] SCG-ConfigInfo-v1530-IEs OPTIONAL
|
||||
}
|
||||
|
||||
SCG-ConfigInfo-v1330-IEs ::= SEQUENCE {
|
||||
measResultListRSSI-SCG-r13 [0] MeasResultListRSSI-SCG-r13 OPTIONAL,
|
||||
nonCriticalExtension [1] SCG-ConfigInfo-v1430-IEs OPTIONAL
|
||||
}
|
||||
|
||||
SCG-ConfigInfo-v1310-IEs ::= SEQUENCE {
|
||||
measResultSSTD-r13 [0] MeasResultSSTD-r13 OPTIONAL,
|
||||
sCellToAddModListMCG-Ext-r13 [1] SCellToAddModListExt-r13 OPTIONAL,
|
||||
measResultServCellListSCG-Ext-r13 [2] MeasResultServCellListSCG-Ext-r13
|
||||
OPTIONAL,
|
||||
sCellToAddModListSCG-Ext-r13 [3] SCellToAddModListSCG-Ext-r13 OPTIONAL,
|
||||
sCellToReleaseListSCG-Ext-r13 [4] SCellToReleaseListExt-r13 OPTIONAL,
|
||||
nonCriticalExtension [5] SCG-ConfigInfo-v1330-IEs OPTIONAL
|
||||
}
|
||||
|
||||
SCG-ConfigInfo-r12-IEs ::= SEQUENCE {
|
||||
radioResourceConfigDedMCG-r12 [0] RadioResourceConfigDedicated OPTIONAL,
|
||||
sCellToAddModListMCG-r12 [1] SCellToAddModList-r10 OPTIONAL,
|
||||
measGapConfig-r12 [2] EXPLICIT MeasGapConfig OPTIONAL,
|
||||
powerCoordinationInfo-r12 [3] PowerCoordinationInfo-r12 OPTIONAL,
|
||||
scg-RadioConfig-r12 [4] SCG-ConfigPartSCG-r12 OPTIONAL,
|
||||
eutra-CapabilityInfo-r12 [5] OCTET STRING (CONTAINING
|
||||
UECapabilityInformation) OPTIONAL,
|
||||
scg-ConfigRestrictInfo-r12 [6] SCG-ConfigRestrictInfo-r12 OPTIONAL,
|
||||
mbmsInterestIndication-r12 [7] OCTET STRING (CONTAINING
|
||||
MBMSInterestIndication-r11) OPTIONAL,
|
||||
measResultServCellListSCG-r12 [8] MeasResultServCellListSCG-r12 OPTIONAL,
|
||||
drb-ToAddModListSCG-r12 [9] DRB-InfoListSCG-r12 OPTIONAL,
|
||||
drb-ToReleaseListSCG-r12 [10] DRB-ToReleaseList OPTIONAL,
|
||||
sCellToAddModListSCG-r12 [11] SCellToAddModListSCG-r12 OPTIONAL,
|
||||
sCellToReleaseListSCG-r12 [12] SCellToReleaseList-r10 OPTIONAL,
|
||||
p-Max-r12 [13] P-Max OPTIONAL,
|
||||
nonCriticalExtension [14] SCG-ConfigInfo-v1310-IEs OPTIONAL
|
||||
}
|
||||
|
||||
SCG-ConfigInfo-r12 ::= SEQUENCE {
|
||||
criticalExtensions [0] EXPLICIT CHOICE {
|
||||
c1 [0] EXPLICIT CHOICE {
|
||||
scg-ConfigInfo-r12 [0] SCG-ConfigInfo-r12-IEs,
|
||||
spare7 [1] NULL,
|
||||
spare6 [2] NULL,
|
||||
spare5 [3] NULL,
|
||||
spare4 [4] NULL,
|
||||
spare3 [5] NULL,
|
||||
spare2 [6] NULL,
|
||||
spare1 [7] NULL
|
||||
},
|
||||
criticalExtensionsFuture [1] SEQUENCE {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UEPagingCoverageInformation-r13-IEs ::= SEQUENCE {
|
||||
mpdcch-NumRepetition-r13 [0] INTEGER (1..256) OPTIONAL,
|
||||
nonCriticalExtension [1] SEQUENCE {
|
||||
|
||||
} OPTIONAL
|
||||
}
|
||||
|
||||
UEPagingCoverageInformation ::= SEQUENCE {
|
||||
criticalExtensions [0] EXPLICIT CHOICE {
|
||||
c1 [0] EXPLICIT CHOICE {
|
||||
uePagingCoverageInformation-r13 [0]
|
||||
UEPagingCoverageInformation-r13-IEs,
|
||||
spare7 [1] NULL,
|
||||
spare6 [2] NULL,
|
||||
spare5 [3] NULL,
|
||||
spare4 [4] NULL,
|
||||
spare3 [5] NULL,
|
||||
spare2 [6] NULL,
|
||||
spare1 [7] NULL
|
||||
},
|
||||
criticalExtensionsFuture [1] SEQUENCE {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UERadioAccessCapabilityInformation-r8-IEs ::= SEQUENCE {
|
||||
ue-RadioAccessCapabilityInfo [0] OCTET STRING (CONTAINING
|
||||
UECapabilityInformation),
|
||||
nonCriticalExtension [1] SEQUENCE {
|
||||
|
||||
} OPTIONAL
|
||||
}
|
||||
|
||||
UERadioAccessCapabilityInformation ::= SEQUENCE {
|
||||
criticalExtensions [0] EXPLICIT CHOICE {
|
||||
c1 [0] EXPLICIT CHOICE {
|
||||
ueRadioAccessCapabilityInformation-r8 [0]
|
||||
UERadioAccessCapabilityInformation-r8-IEs,
|
||||
spare7 [1] NULL,
|
||||
spare6 [2] NULL,
|
||||
spare5 [3] NULL,
|
||||
spare4 [4] NULL,
|
||||
spare3 [5] NULL,
|
||||
spare2 [6] NULL,
|
||||
spare1 [7] NULL
|
||||
},
|
||||
criticalExtensionsFuture [1] SEQUENCE {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UERadioPagingInformation-v1610-IEs ::= SEQUENCE {
|
||||
accessStratumRelease-r16 [0] ENUMERATED { true(0) } OPTIONAL,
|
||||
nonCriticalExtension [1] SEQUENCE {
|
||||
|
||||
} OPTIONAL
|
||||
}
|
||||
|
||||
UERadioPagingInformation-v1310-IEs ::= SEQUENCE {
|
||||
supportedBandListEUTRAForPaging-r13 [0] SEQUENCE (SIZE (1..maxBands)) OF
|
||||
FreqBandIndicator-r11 OPTIONAL,
|
||||
nonCriticalExtension [1] UERadioPagingInformation-v1610-IEs OPTIONAL
|
||||
}
|
||||
|
||||
UERadioPagingInformation-r12-IEs ::= SEQUENCE {
|
||||
ue-RadioPagingInfo-r12 [0] OCTET STRING (CONTAINING UE-RadioPagingInfo-r12),
|
||||
nonCriticalExtension [1] UERadioPagingInformation-v1310-IEs OPTIONAL
|
||||
}
|
||||
|
||||
UERadioPagingInformation ::= SEQUENCE {
|
||||
criticalExtensions [0] EXPLICIT CHOICE {
|
||||
c1 [0] EXPLICIT CHOICE {
|
||||
ueRadioPagingInformation-r12 [0] UERadioPagingInformation-r12-IEs,
|
||||
spare7 [1] NULL,
|
||||
spare6 [2] NULL,
|
||||
spare5 [3] NULL,
|
||||
spare4 [4] NULL,
|
||||
spare3 [5] NULL,
|
||||
spare2 [6] NULL,
|
||||
spare1 [7] NULL
|
||||
},
|
||||
criticalExtensionsFuture [1] SEQUENCE {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-- Value assignments
|
||||
|
||||
maxReestabInfo INTEGER ::= 32
|
||||
|
||||
|
||||
END
|
||||
18149
telcom-parser/specs/EUTRA-RRC-Definitions.asn
Normal file
18149
telcom-parser/specs/EUTRA-RRC-Definitions.asn
Normal file
File diff suppressed because it is too large
Load Diff
274
telcom-parser/specs/EUTRA-Sidelink-Preconf.asn
Normal file
274
telcom-parser/specs/EUTRA-Sidelink-Preconf.asn
Normal file
@@ -0,0 +1,274 @@
|
||||
-- This file was generated by the Objective Systems ASN1C Compiler
|
||||
-- (http://www.obj-sys.com). Version: 7.7.2, Date: 13-Oct-2023.
|
||||
|
||||
EUTRA-Sidelink-Preconf DEFINITIONS AUTOMATIC TAGS ::= BEGIN
|
||||
|
||||
IMPORTS
|
||||
|
||||
AdditionalSpectrumEmission, AdditionalSpectrumEmission-v10l0,
|
||||
ARFCN-ValueEUTRA-r9, FilterCoefficient, maxCBR-Level-r14, maxCBR-Level-1-r14
|
||||
, maxFreq, maxFreqV2X-r14, maxSL-TxPool-r12, maxSL-CommRxPoolPreconf-v1310,
|
||||
maxSL-CommTxPoolPreconf-v1310, maxSL-DiscRxPoolPreconf-r13,
|
||||
maxSL-DiscTxPoolPreconf-r13, maxSL-V2X-CBRConfig2-r14,
|
||||
maxSL-V2X-CBRConfig2-1-r14, maxSL-V2X-RxPoolPreconf-r14,
|
||||
maxSL-V2X-TxConfig2-r14, maxSL-V2X-TxConfig2-1-r14,
|
||||
maxSL-V2X-TxPoolPreconf-r14, MCS-PSSCH-Range-r15, P-Max,
|
||||
ReselectionInfoRelay-r13, SL-AnchorCarrierFreqList-V2X-r14,
|
||||
SL-CBR-Levels-Config-r14, SL-CBR-PSSCH-TxConfig-r14,
|
||||
SL-CommTxPoolSensingConfig-r14, SL-CP-Len-r12, SL-HoppingConfigComm-r12,
|
||||
SL-NR-AnchorCarrierFreqList-r16, SL-OffsetIndicator-r12,
|
||||
SL-OffsetIndicatorSync-r12, SL-OffsetIndicatorSync-v1430, SL-PeriodComm-r12
|
||||
, RSRP-RangeSL3-r12, SL-MinT2ValueList-r15, SL-PriorityList-r13,
|
||||
SL-TF-ResourceConfig-r12, SL-TRPT-Subset-r12, SL-TxParameters-r12,
|
||||
SL-ZoneConfig-r14, P0-SL-r12, TDD-ConfigSL-r12, SubframeBitmapSL-r14,
|
||||
SL-P2X-ResourceSelectionConfig-r14,
|
||||
SL-RestrictResourceReservationPeriodList-r14, SL-SyncAllowed-r14,
|
||||
SL-OffsetIndicatorSync-r14, SL-Priority-r13,
|
||||
SL-V2X-FreqSelectionConfigList-r15, SL-V2X-PacketDuplicationConfig-r15,
|
||||
SL-V2X-SyncFreqList-r15
|
||||
FROM EUTRA-RRC-Definitions ;
|
||||
|
||||
-- Productions
|
||||
|
||||
Tx-PreconfigIndex-r14 ::= INTEGER (0..maxSL-V2X-TxConfig2-1-r14)
|
||||
|
||||
SL-V2X-TxProfile-r15 ::= ENUMERATED { rel14(0), rel15(1), spare6(2), spare5(3)
|
||||
, spare4(4), spare3(5), spare2(6), spare1(7), ... }
|
||||
|
||||
SL-PreconfigGeneral-r12 ::= SEQUENCE {
|
||||
--PDCP configuration
|
||||
rohc-Profiles-r12 [0] SEQUENCE {
|
||||
profile0x0001-r12 [0] BOOLEAN,
|
||||
profile0x0002-r12 [1] BOOLEAN,
|
||||
profile0x0004-r12 [2] BOOLEAN,
|
||||
profile0x0006-r12 [3] BOOLEAN,
|
||||
profile0x0101-r12 [4] BOOLEAN,
|
||||
profile0x0102-r12 [5] BOOLEAN,
|
||||
profile0x0104-r12 [6] BOOLEAN
|
||||
},
|
||||
--Physical configuration
|
||||
carrierFreq-r12 [1] ARFCN-ValueEUTRA-r9,
|
||||
maxTxPower-r12 [2] P-Max,
|
||||
additionalSpectrumEmission-r12 [3] AdditionalSpectrumEmission,
|
||||
sl-bandwidth-r12 [4] ENUMERATED { n6(0), n15(1), n25(2), n50(3), n75(4),
|
||||
n100(5) },
|
||||
tdd-ConfigSL-r12 [5] TDD-ConfigSL-r12,
|
||||
reserved-r12 [6] BIT STRING (SIZE (19)),
|
||||
...,
|
||||
[[
|
||||
additionalSpectrumEmission-v1440 [7] AdditionalSpectrumEmission-v10l0
|
||||
OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
SL-PreconfigSync-r12 ::= SEQUENCE {
|
||||
syncCP-Len-r12 [0] SL-CP-Len-r12,
|
||||
syncOffsetIndicator1-r12 [1] SL-OffsetIndicatorSync-r12,
|
||||
syncOffsetIndicator2-r12 [2] SL-OffsetIndicatorSync-r12,
|
||||
syncTxParameters-r12 [3] P0-SL-r12,
|
||||
syncTxThreshOoC-r12 [4] RSRP-RangeSL3-r12,
|
||||
filterCoefficient-r12 [5] FilterCoefficient,
|
||||
syncRefMinHyst-r12 [6] ENUMERATED { dB0(0), dB3(1), dB6(2), dB9(3), dB12(4)
|
||||
},
|
||||
syncRefDiffHyst-r12 [7] ENUMERATED { dB0(0), dB3(1), dB6(2), dB9(3), dB12(4)
|
||||
, dBinf(5) },
|
||||
...,
|
||||
[[
|
||||
syncTxPeriodic-r13 [8] ENUMERATED { true(0) } OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
SL-PreconfigCommPool-r12 ::= SEQUENCE {
|
||||
--This IE is same as SL-CommResourcePool with rxParametersNCell absent
|
||||
sc-CP-Len-r12 [0] SL-CP-Len-r12,
|
||||
sc-Period-r12 [1] SL-PeriodComm-r12,
|
||||
sc-TF-ResourceConfig-r12 [2] SL-TF-ResourceConfig-r12,
|
||||
sc-TxParameters-r12 [3] P0-SL-r12,
|
||||
data-CP-Len-r12 [4] SL-CP-Len-r12,
|
||||
data-TF-ResourceConfig-r12 [5] SL-TF-ResourceConfig-r12,
|
||||
dataHoppingConfig-r12 [6] SL-HoppingConfigComm-r12,
|
||||
dataTxParameters-r12 [7] P0-SL-r12,
|
||||
trpt-Subset-r12 [8] SL-TRPT-Subset-r12,
|
||||
...,
|
||||
[[
|
||||
priorityList-r13 [9] SL-PriorityList-r13 OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
SL-PreconfigCommPoolList4-r12 ::= SEQUENCE (SIZE (1..maxSL-TxPool-r12)) OF
|
||||
SL-PreconfigCommPool-r12
|
||||
|
||||
SL-PreconfigCommRxPoolList-r13 ::= SEQUENCE (SIZE (1..maxSL-CommRxPoolPreconf-v1310)) OF
|
||||
SL-PreconfigCommPool-r12
|
||||
|
||||
SL-PreconfigCommTxPoolList-r13 ::= SEQUENCE (SIZE (1..maxSL-CommTxPoolPreconf-v1310)) OF
|
||||
SL-PreconfigCommPool-r12
|
||||
|
||||
SL-PreconfigDiscPool-r13 ::= SEQUENCE {
|
||||
--This IE is same as SL-DiscResourcePool with rxParameters absent
|
||||
cp-Len-r13 [0] SL-CP-Len-r12,
|
||||
discPeriod-r13 [1] ENUMERATED { rf4(0), rf6(1), rf7(2), rf8(3), rf12(4),
|
||||
rf14(5), rf16(6), rf24(7), rf28(8), rf32(9), rf64(10), rf128(11),
|
||||
rf256(12), rf512(13), rf1024(14), spare(15) },
|
||||
numRetx-r13 [2] INTEGER (0..3),
|
||||
numRepetition-r13 [3] INTEGER (1..50),
|
||||
tf-ResourceConfig-r13 [4] SL-TF-ResourceConfig-r12,
|
||||
txParameters-r13 [5] SEQUENCE {
|
||||
txParametersGeneral-r13 [0] P0-SL-r12,
|
||||
txProbability-r13 [1] ENUMERATED { p25(0), p50(1), p75(2), p100(3) }
|
||||
} OPTIONAL,
|
||||
...
|
||||
}
|
||||
|
||||
SL-PreconfigDiscRxPoolList-r13 ::= SEQUENCE (SIZE (1..maxSL-DiscRxPoolPreconf-r13)) OF
|
||||
SL-PreconfigDiscPool-r13
|
||||
|
||||
SL-PreconfigDiscTxPoolList-r13 ::= SEQUENCE (SIZE (1..maxSL-DiscTxPoolPreconf-r13)) OF
|
||||
SL-PreconfigDiscPool-r13
|
||||
|
||||
SL-PreconfigRelay-r13 ::= SEQUENCE {
|
||||
reselectionInfoOoC-r13 [0] ReselectionInfoRelay-r13
|
||||
}
|
||||
|
||||
SL-Preconfiguration-r12 ::= SEQUENCE {
|
||||
preconfigGeneral-r12 [0] SL-PreconfigGeneral-r12,
|
||||
preconfigSync-r12 [1] SL-PreconfigSync-r12,
|
||||
preconfigComm-r12 [2] SL-PreconfigCommPoolList4-r12,
|
||||
...,
|
||||
[[
|
||||
preconfigComm-v1310 [3] SEQUENCE {
|
||||
commRxPoolList-r13 [0] SL-PreconfigCommRxPoolList-r13,
|
||||
commTxPoolList-r13 [1] SL-PreconfigCommTxPoolList-r13 OPTIONAL
|
||||
} OPTIONAL,
|
||||
preconfigDisc-r13 [4] SEQUENCE {
|
||||
discRxPoolList-r13 [0] SL-PreconfigDiscRxPoolList-r13,
|
||||
discTxPoolList-r13 [1] SL-PreconfigDiscTxPoolList-r13 OPTIONAL
|
||||
} OPTIONAL,
|
||||
preconfigRelay-r13 [5] SL-PreconfigRelay-r13 OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
SL-V2X-SyncOffsetIndicators-r14 ::= SEQUENCE {
|
||||
syncOffsetIndicator1-r14 [0] SL-OffsetIndicatorSync-r14,
|
||||
syncOffsetIndicator2-r14 [1] SL-OffsetIndicatorSync-r14,
|
||||
syncOffsetIndicator3-r14 [2] SL-OffsetIndicatorSync-r14 OPTIONAL
|
||||
}
|
||||
|
||||
SL-PreconfigV2X-Sync-r14 ::= SEQUENCE {
|
||||
syncOffsetIndicators-r14 [0] SL-V2X-SyncOffsetIndicators-r14,
|
||||
syncTxParameters-r14 [1] P0-SL-r12,
|
||||
syncTxThreshOoC-r14 [2] RSRP-RangeSL3-r12,
|
||||
filterCoefficient-r14 [3] FilterCoefficient,
|
||||
syncRefMinHyst-r14 [4] ENUMERATED { dB0(0), dB3(1), dB6(2), dB9(3), dB12(4)
|
||||
},
|
||||
syncRefDiffHyst-r14 [5] ENUMERATED { dB0(0), dB3(1), dB6(2), dB9(3), dB12(4)
|
||||
, dBinf(5) },
|
||||
...,
|
||||
[[
|
||||
slss-TxDisabled-r15 [6] ENUMERATED { true(0) } OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
SL-PPPP-TxPreconfigIndex-r14 ::= SEQUENCE {
|
||||
priorityThreshold-r14 [0] SL-Priority-r13,
|
||||
defaultTxConfigIndex-r14 [1] INTEGER (0..maxCBR-Level-1-r14),
|
||||
cbr-ConfigIndex-r14 [2] INTEGER (0..maxSL-V2X-CBRConfig2-1-r14),
|
||||
tx-ConfigIndexList-r14 [3] SEQUENCE (SIZE (1..maxCBR-Level-r14)) OF Tx-PreconfigIndex-r14
|
||||
}
|
||||
|
||||
SL-CBR-PPPP-TxPreconfigList-r14 ::= SEQUENCE (SIZE (1..8)) OF
|
||||
SL-PPPP-TxPreconfigIndex-r14
|
||||
|
||||
SL-PPPP-TxPreconfigIndex-v1530 ::= SEQUENCE {
|
||||
mcs-PSSCH-Range-r15 [0] SEQUENCE (SIZE (1..maxCBR-Level-r14)) OF MCS-PSSCH-Range-r15 OPTIONAL
|
||||
}
|
||||
|
||||
SL-CBR-PPPP-TxPreconfigList-v1530 ::= SEQUENCE (SIZE (1..8)) OF
|
||||
SL-PPPP-TxPreconfigIndex-v1530
|
||||
|
||||
SL-V2X-PreconfigCommPool-r14 ::= SEQUENCE {
|
||||
--This IE is same as SL-CommResourcePoolV2X with rxParametersNCell absent
|
||||
sl-OffsetIndicator-r14 [0] EXPLICIT SL-OffsetIndicator-r12 OPTIONAL,
|
||||
sl-Subframe-r14 [1] EXPLICIT SubframeBitmapSL-r14,
|
||||
adjacencyPSCCH-PSSCH-r14 [2] BOOLEAN,
|
||||
sizeSubchannel-r14 [3] ENUMERATED { n4(0), n5(1), n6(2), n8(3), n9(4),
|
||||
n10(5), n12(6), n15(7), n16(8), n18(9), n20(10), n25(11), n30(12),
|
||||
n48(13), n50(14), n72(15), n75(16), n96(17), n100(18), spare13(19),
|
||||
spare12(20), spare11(21), spare10(22), spare9(23), spare8(24), spare7(25)
|
||||
, spare6(26), spare5(27), spare4(28), spare3(29), spare2(30), spare1(31)
|
||||
},
|
||||
numSubchannel-r14 [4] ENUMERATED { n1(0), n3(1), n5(2), n8(3), n10(4),
|
||||
n15(5), n20(6), spare1(7) },
|
||||
startRB-Subchannel-r14 [5] INTEGER (0..99),
|
||||
startRB-PSCCH-Pool-r14 [6] INTEGER (0..99) OPTIONAL,
|
||||
dataTxParameters-r14 [7] P0-SL-r12,
|
||||
zoneID-r14 [8] INTEGER (0..7) OPTIONAL,
|
||||
threshS-RSSI-CBR-r14 [9] INTEGER (0..45) OPTIONAL,
|
||||
cbr-pssch-TxConfigList-r14 [10] SL-CBR-PPPP-TxPreconfigList-r14 OPTIONAL,
|
||||
resourceSelectionConfigP2X-r14 [11] SL-P2X-ResourceSelectionConfig-r14
|
||||
OPTIONAL,
|
||||
syncAllowed-r14 [12] SL-SyncAllowed-r14 OPTIONAL,
|
||||
restrictResourceReservationPeriod-r14 [13]
|
||||
SL-RestrictResourceReservationPeriodList-r14 OPTIONAL,
|
||||
...,
|
||||
[[
|
||||
sl-MinT2ValueList-r15 [14] SL-MinT2ValueList-r15 OPTIONAL,
|
||||
cbr-pssch-TxConfigList-v1530 [15] SL-CBR-PPPP-TxPreconfigList-v1530
|
||||
OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
SL-PreconfigV2X-RxPoolList-r14 ::= SEQUENCE (SIZE (1..maxSL-V2X-RxPoolPreconf-r14)) OF
|
||||
SL-V2X-PreconfigCommPool-r14
|
||||
|
||||
SL-PreconfigV2X-TxPoolList-r14 ::= SEQUENCE (SIZE (1..maxSL-V2X-TxPoolPreconf-r14)) OF
|
||||
SL-V2X-PreconfigCommPool-r14
|
||||
|
||||
SL-V2X-PreconfigFreqInfo-r14 ::= SEQUENCE {
|
||||
v2x-CommPreconfigGeneral-r14 [0] SL-PreconfigGeneral-r12,
|
||||
v2x-CommPreconfigSync-r14 [1] SL-PreconfigV2X-Sync-r14 OPTIONAL,
|
||||
v2x-CommRxPoolList-r14 [2] SL-PreconfigV2X-RxPoolList-r14,
|
||||
v2x-CommTxPoolList-r14 [3] SL-PreconfigV2X-TxPoolList-r14,
|
||||
p2x-CommTxPoolList-r14 [4] SL-PreconfigV2X-TxPoolList-r14,
|
||||
v2x-ResourceSelectionConfig-r14 [5] SL-CommTxPoolSensingConfig-r14 OPTIONAL,
|
||||
zoneConfig-r14 [6] SL-ZoneConfig-r14 OPTIONAL,
|
||||
syncPriority-r14 [7] ENUMERATED { gnss(0), enb(1) },
|
||||
thresSL-TxPrioritization-r14 [8] SL-Priority-r13 OPTIONAL,
|
||||
offsetDFN-r14 [9] INTEGER (0..1000) OPTIONAL,
|
||||
...,
|
||||
[[
|
||||
v2x-FreqSelectionConfigList-r15 [10] SL-V2X-FreqSelectionConfigList-r15
|
||||
OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
SL-V2X-PreconfigFreqList-r14 ::= SEQUENCE (SIZE (1..maxFreqV2X-r14)) OF
|
||||
SL-V2X-PreconfigFreqInfo-r14
|
||||
|
||||
SL-CBR-PreconfigTxConfigList-r14 ::= SEQUENCE {
|
||||
cbr-RangeCommonConfigList-r14 [0] SEQUENCE (SIZE (1..maxSL-V2X-CBRConfig2-r14)) OF
|
||||
SL-CBR-Levels-Config-r14,
|
||||
sl-CBR-PSSCH-TxConfigList-r14 [1] SEQUENCE (SIZE (1..maxSL-V2X-TxConfig2-r14)) OF
|
||||
SL-CBR-PSSCH-TxConfig-r14
|
||||
}
|
||||
|
||||
SL-V2X-TxProfileList-r15 ::= SEQUENCE (SIZE (1..256)) OF SL-V2X-TxProfile-r15
|
||||
|
||||
SL-V2X-Preconfiguration-r14 ::= SEQUENCE {
|
||||
v2x-PreconfigFreqList-r14 [0] SL-V2X-PreconfigFreqList-r14,
|
||||
anchorCarrierFreqList-r14 [1] SL-AnchorCarrierFreqList-V2X-r14 OPTIONAL,
|
||||
cbr-PreconfigList-r14 [2] SL-CBR-PreconfigTxConfigList-r14 OPTIONAL,
|
||||
...,
|
||||
[[
|
||||
v2x-PacketDuplicationConfig-r15 [3] SL-V2X-PacketDuplicationConfig-r15
|
||||
OPTIONAL,
|
||||
syncFreqList-r15 [4] SL-V2X-SyncFreqList-r15 OPTIONAL,
|
||||
slss-TxMultiFreq-r15 [5] ENUMERATED { true(0) } OPTIONAL,
|
||||
v2x-TxProfileList-r15 [6] SL-V2X-TxProfileList-r15 OPTIONAL
|
||||
]],
|
||||
[[
|
||||
anchorCarrierFreqListNR-r16 [7] SL-NR-AnchorCarrierFreqList-r16 OPTIONAL
|
||||
]]
|
||||
}
|
||||
|
||||
END
|
||||
240
telcom-parser/specs/EUTRA-UE-Variables.asn
Normal file
240
telcom-parser/specs/EUTRA-UE-Variables.asn
Normal file
@@ -0,0 +1,240 @@
|
||||
-- This file was generated by the Objective Systems ASN1C Compiler
|
||||
-- (http://www.obj-sys.com). Version: 7.7.2, Date: 13-Oct-2023.
|
||||
|
||||
EUTRA-UE-Variables DEFINITIONS AUTOMATIC TAGS ::= BEGIN
|
||||
|
||||
IMPORTS
|
||||
|
||||
AbsoluteTimeInfo-r10, AreaConfiguration-r10, AreaConfiguration-v1130,
|
||||
ARFCN-ValueNR-r15, BT-NameList-r15, CarrierFreqGERAN, CellIdentity,
|
||||
CellList-r15, CondReconfigurationToAddModList-r16, ConnEstFailReport-r11,
|
||||
EUTRA-CarrierList-r15, SpeedStateScaleFactors, C-RNTI,
|
||||
LoggedEventTriggerConfig-r17, LoggingDuration-r10, LoggingInterval-r10,
|
||||
LogMeasInfo-r10, MeasCSI-RS-Id-r12, MeasId, MeasId-v1250, MeasIdToAddModList
|
||||
, MeasIdToAddModListExt-r12, MeasIdToAddModList-v1310,
|
||||
MeasIdToAddModListExt-v1310, MeasObjectToAddModList,
|
||||
MeasObjectToAddModList-v9e0, MeasObjectToAddModListExt-r13,
|
||||
MeasResultListExtIdle-r16, MeasResultListIdle-r15, MeasResultListIdleNR-r16
|
||||
, MeasScaleFactor-r12, MobilityStateParameters, NeighCellConfig,
|
||||
NR-CarrierList-r16, PhysCellId, PhysCellIdCDMA2000, PhysCellIdGERAN,
|
||||
PhysCellIdUTRA-FDD, PhysCellIdUTRA-TDD, PLMN-Identity,
|
||||
PLMN-IdentityList3-r11, QuantityConfig, ReportConfigToAddModList,
|
||||
RLF-Report-r9, TargetMBSFN-AreaList-r12, TraceReference-r10,
|
||||
Tx-ResourcePoolMeasList-r14, VisitedCellInfoList-r12, maxCellMeas,
|
||||
maxCSI-RS-Meas-r12, maxMeasId, maxMeasId-r12, maxRS-Index-r15,
|
||||
PhysCellIdNR-r15, RS-IndexNR-r15, UL-DelayConfig-r13, ValidityAreaList-r16,
|
||||
WLAN-CarrierInfo-r13, WLAN-Identifiers-r12, WLAN-Id-List-r13,
|
||||
WLAN-NameList-r15, WLAN-Status-r13, WLAN-Status-v1430,
|
||||
WLAN-SuspendConfig-r14
|
||||
FROM EUTRA-RRC-Definitions ;
|
||||
|
||||
-- Productions
|
||||
|
||||
VarMobilityHistoryReport-r12 ::= VisitedCellInfoList-r12
|
||||
|
||||
VarConditionalReconfiguration ::= SEQUENCE {
|
||||
-- Conditional reconfigurations list
|
||||
condReconfigurationList-r16 [0] CondReconfigurationToAddModList-r16 OPTIONAL
|
||||
}
|
||||
|
||||
VarConnEstFailReport-r11 ::= SEQUENCE {
|
||||
connEstFailReport-r11 [0] ConnEstFailReport-r11,
|
||||
plmn-Identity-r11 [1] PLMN-Identity
|
||||
}
|
||||
|
||||
VarLogMeasConfig-r10 ::= SEQUENCE {
|
||||
areaConfiguration-r10 [0] EXPLICIT AreaConfiguration-r10 OPTIONAL,
|
||||
loggingDuration-r10 [1] LoggingDuration-r10,
|
||||
loggingInterval-r10 [2] LoggingInterval-r10
|
||||
}
|
||||
|
||||
VarLogMeasConfig-r11 ::= SEQUENCE {
|
||||
areaConfiguration-r10 [0] EXPLICIT AreaConfiguration-r10 OPTIONAL,
|
||||
areaConfiguration-v1130 [1] AreaConfiguration-v1130 OPTIONAL,
|
||||
loggingDuration-r10 [2] LoggingDuration-r10,
|
||||
loggingInterval-r10 [3] LoggingInterval-r10
|
||||
}
|
||||
|
||||
VarLogMeasConfig-r12 ::= SEQUENCE {
|
||||
areaConfiguration-r10 [0] EXPLICIT AreaConfiguration-r10 OPTIONAL,
|
||||
areaConfiguration-v1130 [1] AreaConfiguration-v1130 OPTIONAL,
|
||||
loggingDuration-r10 [2] LoggingDuration-r10,
|
||||
loggingInterval-r10 [3] LoggingInterval-r10,
|
||||
targetMBSFN-AreaList-r12 [4] TargetMBSFN-AreaList-r12 OPTIONAL
|
||||
}
|
||||
|
||||
VarLogMeasConfig-r15 ::= SEQUENCE {
|
||||
areaConfiguration-r10 [0] EXPLICIT AreaConfiguration-r10 OPTIONAL,
|
||||
areaConfiguration-v1130 [1] AreaConfiguration-v1130 OPTIONAL,
|
||||
loggingDuration-r10 [2] LoggingDuration-r10,
|
||||
loggingInterval-r10 [3] LoggingInterval-r10,
|
||||
targetMBSFN-AreaList-r12 [4] TargetMBSFN-AreaList-r12 OPTIONAL,
|
||||
bt-NameList-r15 [5] BT-NameList-r15 OPTIONAL,
|
||||
wlan-NameList-r15 [6] WLAN-NameList-r15 OPTIONAL
|
||||
}
|
||||
|
||||
VarLogMeasConfig-r17 ::= SEQUENCE {
|
||||
areaConfiguration-r10 [0] EXPLICIT AreaConfiguration-r10 OPTIONAL,
|
||||
areaConfiguration-v1130 [1] AreaConfiguration-v1130 OPTIONAL,
|
||||
loggingDuration-r10 [2] LoggingDuration-r10,
|
||||
loggingInterval-r10 [3] LoggingInterval-r10,
|
||||
targetMBSFN-AreaList-r12 [4] TargetMBSFN-AreaList-r12 OPTIONAL,
|
||||
bt-NameList-r15 [5] BT-NameList-r15 OPTIONAL,
|
||||
wlan-NameList-r15 [6] WLAN-NameList-r15 OPTIONAL,
|
||||
loggedEventTriggerConfig-r17 [7] LoggedEventTriggerConfig-r17 OPTIONAL,
|
||||
measUncomBarPre-r17 [8] ENUMERATED { true(0) } OPTIONAL
|
||||
}
|
||||
|
||||
LogMeasInfoList2-r10 ::= SEQUENCE (SIZE (1..maxLogMeas-r10)) OF LogMeasInfo-r10
|
||||
|
||||
VarLogMeasReport-r10 ::= SEQUENCE {
|
||||
traceReference-r10 [0] TraceReference-r10,
|
||||
traceRecordingSessionRef-r10 [1] OCTET STRING (SIZE (2)),
|
||||
tce-Id-r10 [2] OCTET STRING (SIZE (1)),
|
||||
plmn-Identity-r10 [3] PLMN-Identity,
|
||||
absoluteTimeInfo-r10 [4] AbsoluteTimeInfo-r10,
|
||||
logMeasInfoList-r10 [5] LogMeasInfoList2-r10
|
||||
}
|
||||
|
||||
VarLogMeasReport-r11 ::= SEQUENCE {
|
||||
traceReference-r10 [0] TraceReference-r10,
|
||||
traceRecordingSessionRef-r10 [1] OCTET STRING (SIZE (2)),
|
||||
tce-Id-r10 [2] OCTET STRING (SIZE (1)),
|
||||
plmn-IdentityList-r11 [3] PLMN-IdentityList3-r11,
|
||||
absoluteTimeInfo-r10 [4] AbsoluteTimeInfo-r10,
|
||||
logMeasInfoList-r10 [5] LogMeasInfoList2-r10
|
||||
}
|
||||
|
||||
VarMeasConfig ::= SEQUENCE {
|
||||
--Measurement identities
|
||||
measIdList [0] MeasIdToAddModList OPTIONAL,
|
||||
measIdListExt-r12 [1] MeasIdToAddModListExt-r12 OPTIONAL,
|
||||
measIdList-v1310 [2] MeasIdToAddModList-v1310 OPTIONAL,
|
||||
measIdListExt-v1310 [3] MeasIdToAddModListExt-v1310 OPTIONAL,
|
||||
--Measurement objects
|
||||
measObjectList [4] MeasObjectToAddModList OPTIONAL,
|
||||
measObjectListExt-r13 [5] MeasObjectToAddModListExt-r13 OPTIONAL,
|
||||
measObjectList-v9i0 [6] MeasObjectToAddModList-v9e0 OPTIONAL,
|
||||
--Reporting configurations
|
||||
reportConfigList [7] ReportConfigToAddModList OPTIONAL,
|
||||
--Other parameters
|
||||
quantityConfig [8] QuantityConfig OPTIONAL,
|
||||
measScaleFactor-r12 [9] MeasScaleFactor-r12 OPTIONAL,
|
||||
s-Measure [10] INTEGER (-140..-44) OPTIONAL,
|
||||
speedStatePars [11] EXPLICIT CHOICE {
|
||||
release [0] NULL,
|
||||
setup [1] SEQUENCE {
|
||||
mobilityStateParameters [0] MobilityStateParameters,
|
||||
timeToTrigger-SF [1] SpeedStateScaleFactors
|
||||
}
|
||||
} OPTIONAL,
|
||||
allowInterruptions-r11 [12] BOOLEAN OPTIONAL
|
||||
}
|
||||
|
||||
VarMeasIdleConfig-r15 ::= SEQUENCE {
|
||||
measIdleCarrierListEUTRA-r15 [0] EUTRA-CarrierList-r15 OPTIONAL,
|
||||
measIdleDuration-r15 [1] ENUMERATED { sec10(0), sec30(1), sec60(2),
|
||||
sec120(3), sec180(4), sec240(5), sec300(6) }
|
||||
}
|
||||
|
||||
VarMeasIdleConfig-r16 ::= SEQUENCE {
|
||||
measIdleCarrierListNR-r16 [0] NR-CarrierList-r16 OPTIONAL,
|
||||
validityAreaList-r16 [1] ValidityAreaList-r16 OPTIONAL
|
||||
}
|
||||
|
||||
VarMeasIdleReport-r15 ::= SEQUENCE {
|
||||
measReportIdle-r15 [0] MeasResultListIdle-r15
|
||||
}
|
||||
|
||||
VarMeasIdleReport-r16 ::= SEQUENCE {
|
||||
measReportIdle-r16 [0] MeasResultListExtIdle-r16 OPTIONAL,
|
||||
measReportIdleNR-r16 [1] MeasResultListIdleNR-r16 OPTIONAL
|
||||
}
|
||||
|
||||
SSB-IndexList-r15 ::= SEQUENCE (SIZE (1..maxRS-Index-r15)) OF RS-IndexNR-r15
|
||||
|
||||
CellsTriggeredList ::= SEQUENCE (SIZE (1..maxCellMeas)) OF CHOICE {
|
||||
physCellIdEUTRA [0] PhysCellId,
|
||||
physCellIdUTRA [1] EXPLICIT CHOICE {
|
||||
fdd [0] PhysCellIdUTRA-FDD,
|
||||
tdd [1] PhysCellIdUTRA-TDD
|
||||
},
|
||||
physCellIdGERAN [2] SEQUENCE {
|
||||
carrierFreq [0] CarrierFreqGERAN,
|
||||
physCellId [1] PhysCellIdGERAN
|
||||
},
|
||||
physCellIdCDMA2000 [3] PhysCellIdCDMA2000,
|
||||
wlan-Identifiers-r13 [4] WLAN-Identifiers-r12,
|
||||
physCellIdNR-r15 [5] SEQUENCE {
|
||||
carrierFreq [0] ARFCN-ValueNR-r15,
|
||||
physCellId [1] PhysCellIdNR-r15,
|
||||
rs-IndexList-r15 [2] SSB-IndexList-r15 OPTIONAL
|
||||
}
|
||||
}
|
||||
|
||||
CSI-RS-TriggeredList-r12 ::= SEQUENCE (SIZE (1..maxCSI-RS-Meas-r12)) OF MeasCSI-RS-Id-r12
|
||||
|
||||
VarMeasReport ::= SEQUENCE {
|
||||
--List of measurement that have been triggered
|
||||
measId [0] MeasId,
|
||||
measId-v1250 [1] MeasId-v1250 OPTIONAL,
|
||||
cellsTriggeredList [2] CellsTriggeredList OPTIONAL,
|
||||
csi-RS-TriggeredList-r12 [3] CSI-RS-TriggeredList-r12 OPTIONAL,
|
||||
poolsTriggeredList-r14 [4] Tx-ResourcePoolMeasList-r14 OPTIONAL,
|
||||
numberOfReportsSent [5] INTEGER
|
||||
}
|
||||
|
||||
VarMeasReportList ::= SEQUENCE (SIZE (1..maxMeasId)) OF VarMeasReport
|
||||
|
||||
VarMeasReportList-r12 ::= SEQUENCE (SIZE (1..maxMeasId-r12)) OF VarMeasReport
|
||||
|
||||
VarPendingRnaUpdate-r15 ::= SEQUENCE {
|
||||
pendingRnaUpdate [0] BOOLEAN OPTIONAL
|
||||
}
|
||||
|
||||
VarRLF-Report-r10 ::= SEQUENCE {
|
||||
rlf-Report-r10 [0] RLF-Report-r9,
|
||||
plmn-Identity-r10 [1] PLMN-Identity
|
||||
}
|
||||
|
||||
VarRLF-Report-r11 ::= SEQUENCE {
|
||||
rlf-Report-r10 [0] RLF-Report-r9,
|
||||
plmn-IdentityList-r11 [1] PLMN-IdentityList3-r11
|
||||
}
|
||||
|
||||
VarShortINACTIVE-MAC-Input-r15 ::= SEQUENCE {
|
||||
cellIdentity-r15 [0] CellIdentity,
|
||||
physCellId-r15 [1] PhysCellId,
|
||||
c-RNTI-r15 [2] C-RNTI
|
||||
}
|
||||
|
||||
VarShortMAC-Input ::= SEQUENCE {
|
||||
cellIdentity [0] CellIdentity,
|
||||
physCellId [1] PhysCellId,
|
||||
c-RNTI [2] C-RNTI
|
||||
}
|
||||
|
||||
VarShortResumeMAC-Input-r13 ::= SEQUENCE {
|
||||
cellIdentity-r13 [0] CellIdentity,
|
||||
physCellId-r13 [1] PhysCellId,
|
||||
c-RNTI-r13 [2] C-RNTI,
|
||||
resumeDiscriminator-r13 [3] BIT STRING (SIZE (1))
|
||||
}
|
||||
|
||||
VarWLAN-MobilityConfig ::= SEQUENCE {
|
||||
wlan-MobilitySet-r13 [0] WLAN-Id-List-r13 OPTIONAL,
|
||||
successReportRequested [1] ENUMERATED { true(0) } OPTIONAL,
|
||||
wlan-SuspendConfig-r14 [2] WLAN-SuspendConfig-r14 OPTIONAL
|
||||
}
|
||||
|
||||
VarWLAN-Status-r13 ::= SEQUENCE {
|
||||
status-r13 [0] WLAN-Status-r13,
|
||||
status-r14 [1] WLAN-Status-v1430 OPTIONAL
|
||||
}
|
||||
|
||||
-- Value assignments
|
||||
|
||||
maxLogMeas-r10 INTEGER ::= 4060
|
||||
|
||||
|
||||
END
|
||||
45
telcom-parser/specs/PC5-RRC-Definitions.asn
Normal file
45
telcom-parser/specs/PC5-RRC-Definitions.asn
Normal file
@@ -0,0 +1,45 @@
|
||||
-- This file was generated by the Objective Systems ASN1C Compiler
|
||||
-- (http://www.obj-sys.com). Version: 7.7.2, Date: 13-Oct-2023.
|
||||
|
||||
PC5-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::= BEGIN
|
||||
|
||||
IMPORTS
|
||||
|
||||
TDD-ConfigSL-r12
|
||||
FROM EUTRA-RRC-Definitions ;
|
||||
|
||||
-- Productions
|
||||
|
||||
MasterInformationBlock-SL ::= SEQUENCE {
|
||||
sl-Bandwidth-r12 [0] ENUMERATED { n6(0), n15(1), n25(2), n50(3), n75(4),
|
||||
n100(5) },
|
||||
tdd-ConfigSL-r12 [1] TDD-ConfigSL-r12,
|
||||
directFrameNumber-r12 [2] BIT STRING (SIZE (10)),
|
||||
directSubframeNumber-r12 [3] INTEGER (0..9),
|
||||
inCoverage-r12 [4] BOOLEAN,
|
||||
reserved-r12 [5] BIT STRING (SIZE (19))
|
||||
}
|
||||
|
||||
SBCCH-SL-BCH-MessageType ::= MasterInformationBlock-SL
|
||||
|
||||
MasterInformationBlock-SL-V2X-r14 ::= SEQUENCE {
|
||||
sl-Bandwidth-r14 [0] ENUMERATED { n6(0), n15(1), n25(2), n50(3), n75(4),
|
||||
n100(5) },
|
||||
tdd-ConfigSL-r14 [1] TDD-ConfigSL-r12,
|
||||
directFrameNumber-r14 [2] BIT STRING (SIZE (10)),
|
||||
directSubframeNumber-r14 [3] INTEGER (0..9),
|
||||
inCoverage-r14 [4] BOOLEAN,
|
||||
reserved-r14 [5] BIT STRING (SIZE (27))
|
||||
}
|
||||
|
||||
SBCCH-SL-BCH-MessageType-V2X-r14 ::= MasterInformationBlock-SL-V2X-r14
|
||||
|
||||
SBCCH-SL-BCH-Message ::= SEQUENCE {
|
||||
message [0] SBCCH-SL-BCH-MessageType
|
||||
}
|
||||
|
||||
SBCCH-SL-BCH-Message-V2X-r14 ::= SEQUENCE {
|
||||
message [0] SBCCH-SL-BCH-MessageType-V2X-r14
|
||||
}
|
||||
|
||||
END
|
||||
18
telcom-parser/src/lib.rs
Normal file
18
telcom-parser/src/lib.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
use asn1_codecs::{uper::UperCodec, PerCodecData, PerCodecError};
|
||||
use thiserror::Error;
|
||||
#[allow(warnings, unused, unreachable_patterns, non_camel_case_types)]
|
||||
pub mod lte_rrc;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ParsingError {
|
||||
#[error("Failed to decode UPER data: {0}")]
|
||||
UperDecodeError(PerCodecError),
|
||||
}
|
||||
|
||||
pub fn decode<T>(data: &[u8]) -> Result<T, ParsingError>
|
||||
where T: UperCodec<Output = T>
|
||||
{
|
||||
let mut asn_data = PerCodecData::from_slice_uper(data);
|
||||
T::uper_decode(&mut asn_data)
|
||||
.map_err(ParsingError::UperDecodeError)
|
||||
}
|
||||
51188
telcom-parser/src/lte_rrc.rs
Normal file
51188
telcom-parser/src/lte_rrc.rs
Normal file
File diff suppressed because one or more lines are too long
17
telcom-parser/tests/lte_rrc_test.rs
Normal file
17
telcom-parser/tests/lte_rrc_test.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use telcom_parser::lte_rrc::BCCH_DL_SCH_Message;
|
||||
use asn1_codecs::{uper::UperCodec, PerCodecData};
|
||||
|
||||
fn hex_to_bin(hex: &str) -> Vec<u8> {
|
||||
(0..hex.len())
|
||||
.step_by(2)
|
||||
.map(|i| u8::from_str_radix(&hex[i..i+2], 16).unwrap())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let data = hex_to_bin("484c469010600018fd1a9207e22103108ac21bdc09802292cdd20000");
|
||||
let mut asn_data = PerCodecData::from_slice_uper(&data);
|
||||
let sib1 = BCCH_DL_SCH_Message::uper_decode(&mut asn_data);
|
||||
dbg!(&sib1);
|
||||
}
|
||||
Reference in New Issue
Block a user