Added readme, the whole project

This commit is contained in:
Ishan Jain 2023-11-07 03:33:39 +05:30
commit 2f1966a098
Signed by: ishan
GPG Key ID: 0506DB2A1CC75C27
7 changed files with 812 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

538
Cargo.lock generated Normal file
View File

@ -0,0 +1,538 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "futures"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]]
name = "futures-executor"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
[[package]]
name = "futures-macro"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
[[package]]
name = "futures-task"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
[[package]]
name = "futures-util"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "gimli"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
[[package]]
name = "hermit-abi"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
[[package]]
name = "libc"
version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "memchr"
version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "miniz_oxide"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
dependencies = [
"libc",
"wasi",
"windows-sys",
]
[[package]]
name = "netlink-packet-core"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4"
dependencies = [
"anyhow",
"byteorder",
"netlink-packet-utils",
]
[[package]]
name = "netlink-packet-route"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66"
dependencies = [
"anyhow",
"bitflags",
"byteorder",
"libc",
"netlink-packet-core",
"netlink-packet-utils",
]
[[package]]
name = "netlink-packet-utils"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34"
dependencies = [
"anyhow",
"byteorder",
"paste",
"thiserror",
]
[[package]]
name = "netlink-proto"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "842c6770fc4bb33dd902f41829c61ef872b8e38de1405aa0b938b27b8fba12c3"
dependencies = [
"bytes",
"futures",
"log",
"netlink-packet-core",
"netlink-sys",
"thiserror",
"tokio",
]
[[package]]
name = "netlink-sys"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411"
dependencies = [
"bytes",
"futures",
"libc",
"log",
"tokio",
]
[[package]]
name = "nix"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
dependencies = [
"bitflags",
"cfg-if",
"libc",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "object"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "pin-project-lite"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro2"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rdns-ipv6"
version = "0.1.0"
dependencies = [
"futures",
"netlink-packet-route",
"rtnetlink",
"tokio",
]
[[package]]
name = "rtnetlink"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0"
dependencies = [
"futures",
"log",
"netlink-packet-core",
"netlink-packet-route",
"netlink-packet-utils",
"netlink-proto",
"netlink-sys",
"nix",
"thiserror",
"tokio",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "socket2"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "syn"
version = "2.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio"
version = "1.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"pin-project-lite",
"socket2",
"tokio-macros",
"windows-sys",
]
[[package]]
name = "tokio-macros"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"

10
Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "rdns-ipv6"
version = "0.1.0"
edition = "2021"
[dependencies]
futures = "0.3.29"
netlink-packet-route = "0.17.1"
rtnetlink = "0.13.1"
tokio = { version = "1.33.0", features = ["macros", "rt-multi-thread"] }

37
README.md Normal file
View File

@ -0,0 +1,37 @@
# rdns-ipv6
In dual stack networks, This project can help in rdns resolution of IPv6 addresses by reusing hostname from DHCPv4 leases for that client.
It works like this,
1. Read IPv6 neighbours on the machine.
2. Identify hostname for this IPv6 client by trying to find a IPv4 lease for this MAC address
3. Update `/etc/hosts` with a list of IPv4 and IPv6 records.
There should be `unbound` or some other DNS resolver running on the machine to read `/etc/hosts` and respond to PTR queries and queries in your local search domain.
This program does not handle any aspect related to that.
This program exits after modifying `/etc/hosts`. It can be used with systemd to run at some interval.
```
# /etc/systemd/system/rdns-ipv6.timer
[Unit]
Description=rdns-ipv6
[Timer]
OnUnitActiveSec=10s
OnBootSec=10s
[Install]
WantedBy=timers.target
#/etc/systemd/system/rdns-ipv6.Service
[Unit]
Description=RDNS for IPv6
[Service]
Type=oneshot
ExecStart=/config/rdns-ipv6
```

119
src/hosts.rs Normal file
View File

@ -0,0 +1,119 @@
use crate::neighbour::Record as NeighbourRecord;
use std::{
fs::{File, OpenOptions},
io::{Read, Write},
net::{IpAddr, Ipv6Addr},
};
pub struct HostsFile {
host_file_path: String,
records: Vec<Record>,
}
#[derive(Debug)]
struct Record {
address: IpAddr,
hostname: String,
}
pub const HOST_FILE_PATH: &str = "/etc/hosts";
impl HostsFile {
pub fn new(path: &str) -> Result<Self, String> {
let mut file = File::open(path).map_err(|e| e.to_string())?;
let mut buf = vec![];
file.read_to_end(&mut buf).map_err(|e| e.to_string())?;
Ok(Self {
records: HostsFile::parse(&buf)?,
host_file_path: path.to_string(),
})
}
fn parse(data: &[u8]) -> Result<Vec<Record>, String> {
let mut output = vec![];
for line in data.split(|&x| x == b'\n') {
let s = String::from_utf8_lossy(line);
let s = s.trim();
if s.starts_with('#') {
continue;
}
if let Some((address, hostname)) = s.split_once(' ') {
output.push(Record {
address: address.parse::<IpAddr>().map_err(|e| e.to_string())?,
hostname: hostname.to_string(),
});
}
}
Ok(output)
}
pub fn retain_ipv4_only(&mut self) {
self.records.retain(|x| {
x.address.is_ipv4()
|| ["fe00::0", "ff00::0", "ff02::1", "ff02::2"]
.map(|x| x.parse::<Ipv6Addr>().unwrap())
.map(IpAddr::V6)
.contains(&x.address)
});
}
pub fn add_ipv6_clients(
&mut self,
ipv6_neigh: Vec<NeighbourRecord>,
ipv4_neigh: Vec<NeighbourRecord>,
) {
for neighbour in ipv6_neigh {
// Lookup address from ipv4 neigh
let ipv4_neighbour = if let Some(v) = ipv4_neigh.iter().find(|x| x.lla == neighbour.lla)
{
v
} else {
continue;
};
let hostname = if let Some(v) = self
.records
.iter()
.find(|x| x.address == ipv4_neighbour.address)
{
v.hostname.clone()
} else {
continue;
};
self.records.push(Record {
address: neighbour.address,
hostname,
});
}
}
pub fn flush(self) -> Result<(), String> {
let mut output = vec![];
for record in self.records {
output.push(format!("{} {}", record.address, record.hostname));
}
let mut f = OpenOptions::new()
.read(false)
.write(true)
.create(true)
.append(false)
.truncate(true)
.open(self.host_file_path)
.map_err(|e| e.to_string())?;
f.write_all(output.join("\n").as_bytes())
.map_err(|e| e.to_string())?;
println!("{}", output.join("\n"));
f.flush().map_err(|e| e.to_string())
}
}

31
src/main.rs Normal file
View File

@ -0,0 +1,31 @@
#![allow(clippy::erasing_op)]
#![allow(clippy::identity_op)]
#![allow(clippy::eq_op)]
use crate::hosts::HostsFile;
use rtnetlink::{new_connection, IpVersion};
mod hosts;
mod neighbour;
#[tokio::main]
async fn main() -> Result<(), String> {
run().await.expect("error occured");
Ok(())
}
async fn run() -> Result<(), String> {
let (conn, handle, _) = new_connection().unwrap();
tokio::spawn(conn);
let ipv4_neigh = neighbour::fetch_reachable_neighbours(handle.clone(), IpVersion::V4).await?;
let ipv6_neigh = neighbour::fetch_reachable_neighbours(handle, IpVersion::V6).await?;
let mut hosts = HostsFile::new(hosts::HOST_FILE_PATH)?;
hosts.retain_ipv4_only();
hosts.add_ipv6_clients(ipv6_neigh, ipv4_neigh);
hosts.flush()
}

76
src/neighbour.rs Normal file
View File

@ -0,0 +1,76 @@
use futures::TryStreamExt;
use netlink_packet_route::rtnl::neighbour::nlas::Nla;
use rtnetlink::{Handle, IpVersion, NeighbourHandle};
use std::net::{IpAddr, Ipv6Addr};
#[derive(Debug)]
pub struct Record {
pub lla: u64,
pub address: IpAddr,
}
impl Default for Record {
fn default() -> Self {
Self {
lla: 0,
address: IpAddr::from([0, 0, 0, 0]),
}
}
}
pub async fn fetch_reachable_neighbours(
handle: Handle,
version: IpVersion,
) -> Result<Vec<Record>, String> {
let mut output = vec![];
let nh = NeighbourHandle::new(handle);
let mut resp = nh.get().set_family(version.clone()).execute();
while let Some(resp) = resp.try_next().await.map_err(|e| e.to_string())? {
let record: Record = resp.nlas.into_iter().fold(Default::default(), |mut r, x| {
match x {
Nla::LinkLocalAddress(d) if !d.is_empty() => r.lla = to_u64(&d),
Nla::Destination(d) => {
r.address = match version {
IpVersion::V4 => IpAddr::from([d[0], d[1], d[2], d[3]]),
IpVersion::V6 => IpAddr::V6(Ipv6Addr::from(to_u128(&d))),
};
}
_ => (),
};
r
});
if record.lla != 0 {
output.push(record);
}
}
Ok(output)
}
#[inline]
const fn to_u64(v: &[u8]) -> u64 {
let mut out = 0;
out |= (v[5] as u64) << ((5 - 5) * 8);
out |= (v[4] as u64) << ((5 - 4) * 8);
out |= (v[3] as u64) << ((5 - 3) * 8);
out |= (v[2] as u64) << ((5 - 2) * 8);
out |= (v[1] as u64) << ((5 - 1) * 8);
out |= (v[0] as u64) << ((5 - 0) * 8);
out
}
fn to_u128(v: &[u8]) -> u128 {
let mut out = 0;
let l = v.len() - 1;
for (i, x) in v.iter().enumerate() {
out |= (*x as u128) << ((l - i) * 8);
}
out
}