current state
This commit is contained in:
1 parent
92d3e3370b
commit
27aa972fe6
5 files changed
+230
-9
No files matched your search
Generated
+10
@@ -50,6 +50,7 @@ dependencies = [
|
||||
"pnet",
|
||||
"pnet_transport",
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -291,6 +292,15 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_bytes"
|
||||
version = "0.11.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.144"
|
||||
|
||||
@@ -21,6 +21,7 @@ nix = { version = "0.25.0", features = ["net", "socket", "time"] }
|
||||
pnet = "0.31.0"
|
||||
pnet_transport = "0.31.0"
|
||||
serde = { version = "1.0.144", features = ["derive"] }
|
||||
serde_bytes = "0.11"
|
||||
|
||||
[patch.crates-io]
|
||||
nix = { path = "../nix" }
|
||||
+12
-8
@@ -1,5 +1,3 @@
|
||||
extern crate core;
|
||||
|
||||
mod cake;
|
||||
mod config;
|
||||
mod netlink;
|
||||
@@ -13,8 +11,8 @@ use std::{process, thread, time};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::netlink::{find_interface, find_qdisc, get_interface_stats, set_qdisc_rate};
|
||||
use crate::pinger::Pinger;
|
||||
use crate::pinger_icmp::PingerICMPEcho;
|
||||
use crate::pinger::{PingListener, PingSender, Pinger};
|
||||
use crate::pinger_icmp::{PingerICMPEcho, PingerICMPEchoListener, PingerICMPEchoSender};
|
||||
use crate::pinger_icmp_ts::PingerICMPTimestamps;
|
||||
|
||||
#[macro_export]
|
||||
@@ -43,18 +41,24 @@ fn main() {
|
||||
|
||||
get_interface_stats(config.upload_interface.as_str()).unwrap();
|
||||
|
||||
let mut pinger_receiver =
|
||||
/*let mut pinger_receiver =
|
||||
PingerICMPTimestamps::new((process::id() & 0xFFFF) as u16, reflectors.clone());
|
||||
let mut pinger_sender =
|
||||
PingerICMPTimestamps::new((process::id() & 0xFFFF) as u16, reflectors.clone());
|
||||
PingerICMPTimestamps::new((process::id() & 0xFFFF) as u16, reflectors.clone());*/
|
||||
|
||||
let mut pinger_receiver =
|
||||
PingerICMPEchoListener::new((process::id() & 0xFFF) as u16, reflectors.clone());
|
||||
|
||||
let mut pinger_sender =
|
||||
PingerICMPEchoSender::new((process::id() & 0xFFF) as u16, reflectors.clone());
|
||||
|
||||
let receiver_handle = thread::Builder::new()
|
||||
.name("receiver".to_string())
|
||||
.spawn(move || pinger_receiver.receive_loop())
|
||||
.spawn(move || pinger_receiver.listen())
|
||||
.unwrap();
|
||||
let sender_handle = thread::Builder::new()
|
||||
.name("sender".to_string())
|
||||
.spawn(move || pinger_sender.sender_loop())
|
||||
.spawn(move || pinger_sender.send())
|
||||
.unwrap();
|
||||
|
||||
let threads = vec![receiver_handle, sender_handle];
|
||||
|
||||
+102
-1
@@ -1,5 +1,106 @@
|
||||
use nix::sys::socket::{
|
||||
recvfrom, sendto, socket, AddressFamily, MsgFlags, SockFlag, SockProtocol, SockType,
|
||||
SockaddrIn, SockaddrIn6, SockaddrLike,
|
||||
};
|
||||
use std::error::Error;
|
||||
use std::net::IpAddr;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
||||
use std::str::FromStr;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
pub trait PingListener {
|
||||
fn new(id: u16, reflectors: Vec<IpAddr>) -> Self;
|
||||
|
||||
fn get_id(&self) -> u16;
|
||||
fn get_reflectors(&self) -> Vec<IpAddr>;
|
||||
|
||||
fn listen(&mut self) {
|
||||
let socket = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Raw,
|
||||
SockFlag::empty(), /* value */
|
||||
SockProtocol::ICMP,
|
||||
)
|
||||
.expect("Couldn't open socket");
|
||||
|
||||
loop {
|
||||
let mut v: Vec<u8> = vec![0; 128];
|
||||
let buf = v.as_mut_slice();
|
||||
|
||||
let (size, sender) = match recvfrom::<SockaddrIn>(socket, buf) {
|
||||
Ok(val) => val,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
let (rtt, down_time, up_time) = match Self::parse_packet(buf, size) {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
println!("Shit went to hell: {}", e.to_string());
|
||||
continue;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_packet(buf: &[u8], len: usize) -> Result<(i64, i64, i64), Box<dyn Error>>;
|
||||
}
|
||||
|
||||
pub trait PingSender {
|
||||
fn new(id: u16, reflectors: Vec<IpAddr>) -> Self;
|
||||
|
||||
fn get_id(&self) -> u16;
|
||||
fn get_reflectors(&self) -> Vec<IpAddr>;
|
||||
|
||||
fn send(&mut self) {
|
||||
let socket = socket(
|
||||
AddressFamily::Inet,
|
||||
SockType::Raw,
|
||||
SockFlag::empty(), /* value */
|
||||
SockProtocol::ICMP,
|
||||
)
|
||||
.expect("Couldn't open socket");
|
||||
|
||||
let mut seq: u16 = 0;
|
||||
let tick_duration_ms: u16 = 500;
|
||||
let sleep_duration = Duration::from_millis(tick_duration_ms as u64);
|
||||
|
||||
loop {
|
||||
let reflectors = Self::get_reflectors(self);
|
||||
|
||||
for reflector in reflectors.iter() {
|
||||
let addr: Box<dyn SockaddrLike>;
|
||||
|
||||
match reflector.is_ipv4() {
|
||||
true => {
|
||||
let ip4 = Ipv4Addr::from_str(&*reflector.to_string()).unwrap();
|
||||
let sock4 = SocketAddrV4::new(ip4, 0);
|
||||
addr = Box::new(SockaddrIn::from(sock4));
|
||||
}
|
||||
false => {
|
||||
let ip6 = Ipv6Addr::from_str(&*reflector.to_string()).unwrap();
|
||||
let sock6 = SocketAddrV6::new(ip6, 0, 0, 0);
|
||||
addr = Box::new(SockaddrIn6::from(sock6));
|
||||
}
|
||||
}
|
||||
|
||||
let buf_v = self.craft_packet(seq);
|
||||
let buf = buf_v.as_slice();
|
||||
|
||||
sendto(socket, buf, addr.as_ref(), MsgFlags::empty()).expect("Couldn't send ping");
|
||||
}
|
||||
|
||||
thread::sleep(sleep_duration);
|
||||
|
||||
seq += 1;
|
||||
|
||||
if seq >= u16::MAX {
|
||||
seq = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn craft_packet(&self, seq: u16) -> Vec<u8>;
|
||||
}
|
||||
|
||||
pub trait Pinger {
|
||||
fn new(id: u16, reflectors: Vec<IpAddr>) -> Self;
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
use bincode::{deserialize, serialize};
|
||||
use std::error::Error;
|
||||
use std::net::IpAddr;
|
||||
use std::{thread, time};
|
||||
|
||||
use crate::pinger::{PingListener, PingSender};
|
||||
use crate::Pinger;
|
||||
use byteorder::*;
|
||||
use neli::err::NlError;
|
||||
use nix::sys::time::TimeValLike;
|
||||
use nix::time::{clock_gettime, ClockId};
|
||||
use pnet::packet::icmp::IcmpTypes::EchoReply;
|
||||
@@ -12,6 +15,19 @@ use pnet::packet::*;
|
||||
use pnet_transport::TransportChannelType::Layer4;
|
||||
use pnet_transport::TransportProtocol::Ipv4;
|
||||
use pnet_transport::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Default, Debug)]
|
||||
//#[repr(C)]
|
||||
pub struct ICMPEcho {
|
||||
type_: u8,
|
||||
code: u8,
|
||||
checksum: u16,
|
||||
identifier: u16,
|
||||
sequence: u16,
|
||||
#[serde(with = "serde_bytes")]
|
||||
payload: Vec<u8>,
|
||||
}
|
||||
|
||||
pub struct PingerICMPEcho {
|
||||
id: u16,
|
||||
@@ -20,6 +36,33 @@ pub struct PingerICMPEcho {
|
||||
tx: TransportSender,
|
||||
}
|
||||
|
||||
pub struct PingerICMPEchoListener {
|
||||
id: u16,
|
||||
reflectors: Vec<IpAddr>,
|
||||
}
|
||||
|
||||
pub struct PingerICMPEchoSender {
|
||||
id: u16,
|
||||
reflectors: Vec<IpAddr>,
|
||||
}
|
||||
|
||||
fn calculate_checksum(buffer: &mut [u8]) -> u16 {
|
||||
let mut sum = 0u32;
|
||||
for word in buffer.chunks(2) {
|
||||
let mut part = u16::from(word[0]) << 8;
|
||||
if word.len() > 1 {
|
||||
part += u16::from(word[1]);
|
||||
}
|
||||
sum = sum.wrapping_add(u32::from(part));
|
||||
}
|
||||
|
||||
while (sum >> 16) > 0 {
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
}
|
||||
|
||||
!sum as u16
|
||||
}
|
||||
|
||||
impl Pinger for PingerICMPEcho {
|
||||
fn new(id: u16, reflectors: Vec<IpAddr>) -> Self {
|
||||
let protocol = Layer4(Ipv4(IpNextHeaderProtocols::Icmp));
|
||||
@@ -121,3 +164,65 @@ impl Pinger for PingerICMPEcho {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl PingListener for PingerICMPEchoListener {
|
||||
fn new(id: u16, reflectors: Vec<IpAddr>) -> Self {
|
||||
PingerICMPEchoListener { id, reflectors }
|
||||
}
|
||||
|
||||
fn get_id(&self) -> u16 {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn get_reflectors(&self) -> Vec<IpAddr> {
|
||||
self.reflectors.clone()
|
||||
}
|
||||
|
||||
fn parse_packet(buf: &[u8], len: usize) -> Result<(i64, i64, i64), Box<dyn Error>> {
|
||||
if len != 44 {
|
||||
println!("len: {}", len);
|
||||
return Err(Box::new(NlError::msg("Wrong length")));
|
||||
}
|
||||
|
||||
let hdr: ICMPEcho = deserialize(buf).expect("Failed to parse ICMP packet");
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PingSender for PingerICMPEchoSender {
|
||||
fn new(id: u16, reflectors: Vec<IpAddr>) -> Self {
|
||||
PingerICMPEchoSender { id, reflectors }
|
||||
}
|
||||
|
||||
fn get_id(&self) -> u16 {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn get_reflectors(&self) -> Vec<IpAddr> {
|
||||
self.reflectors.clone()
|
||||
}
|
||||
|
||||
fn craft_packet(&self, seq: u16) -> Vec<u8> {
|
||||
let time = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap();
|
||||
let time_u64: u64 = time.num_milliseconds() as u64;
|
||||
|
||||
let mut hdr = ICMPEcho {
|
||||
type_: 8,
|
||||
code: 0,
|
||||
checksum: 0,
|
||||
identifier: self.get_id(),
|
||||
sequence: seq,
|
||||
payload: time_u64.to_ne_bytes().to_vec(),
|
||||
};
|
||||
|
||||
println!("id: {}", hdr.identifier);
|
||||
println!("seq: {}", hdr.sequence);
|
||||
|
||||
let mut tmp_buf_v = serialize(&hdr).unwrap();
|
||||
let mut tmp_buf = tmp_buf_v.as_mut_slice();
|
||||
hdr.checksum = calculate_checksum(tmp_buf).to_be();
|
||||
|
||||
serialize(&hdr).unwrap()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user