Successfully sent ICMP ping packets
This commit is contained in:
parent
7f8187a43e
commit
2b376a2239
@ -2,6 +2,7 @@
|
||||
resolver = "3"
|
||||
members = [
|
||||
"app",
|
||||
"network/icmp",
|
||||
"network/abstract",
|
||||
"network/windows"
|
||||
]
|
||||
|
||||
7
network/icmp/Cargo.toml
Normal file
7
network/icmp/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "bgtu-networks-2-network-icmp"
|
||||
version = "0.0.0"
|
||||
edition = "2024"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
44
network/icmp/src/checksum.rs
Normal file
44
network/icmp/src/checksum.rs
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
pub(crate) struct IPv4ChecksumAccumulator {
|
||||
acc: u32,
|
||||
}
|
||||
|
||||
impl IPv4ChecksumAccumulator {
|
||||
pub fn new() -> Self {
|
||||
return Self { acc: 0 };
|
||||
}
|
||||
|
||||
pub fn add_first_byte(&mut self, b: u8) {
|
||||
self.acc += (b as u32) << 8;
|
||||
}
|
||||
|
||||
pub fn add_second_byte(&mut self, b: u8) {
|
||||
self.acc += b as u32;
|
||||
}
|
||||
|
||||
pub fn add_last_byte(&mut self, b: u8) {
|
||||
self.acc += b as u32;
|
||||
}
|
||||
|
||||
pub fn add_word(&mut self, b: u16) {
|
||||
self.acc += b as u32;
|
||||
}
|
||||
|
||||
pub fn add_trailing_data(&mut self, data: &[u8]) {
|
||||
for i in (0..(data.len() / 2)).into_iter().map(|i| i * 2) {
|
||||
self.add_first_byte(data[i]);
|
||||
self.add_second_byte(data[i + 1]);
|
||||
}
|
||||
if data.len() % 2 != 0 {
|
||||
self.add_last_byte(data[data.len() - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn snapshot(&self) -> u16 {
|
||||
let mut out = self.acc;
|
||||
while out > 0x0000FFFFu32 {
|
||||
out = (out & 0x0000FFFFu32) + (out >> 16);
|
||||
}
|
||||
return !(out as u16);
|
||||
}
|
||||
}
|
||||
23
network/icmp/src/lib.rs
Normal file
23
network/icmp/src/lib.rs
Normal file
@ -0,0 +1,23 @@
|
||||
mod checksum;
|
||||
mod ping;
|
||||
|
||||
use checksum::IPv4ChecksumAccumulator;
|
||||
|
||||
pub use ping::fmt_icmp_echo_req;
|
||||
|
||||
fn hton16(v: u16, b: &mut [u8]) {
|
||||
b[0] = (v >> 8) as u8;
|
||||
b[1] = (v & 0xFF) as u8;
|
||||
}
|
||||
|
||||
fn hton64(v: u64, b: &mut [u8]) {
|
||||
hton16((v >> 48) as u16, b);
|
||||
hton16(((v >> 32) & 0xFFFF) as u16, &mut b[2..4]);
|
||||
hton16(((v >> 16) & 0xFFFF) as u16, &mut b[4..6]);
|
||||
hton16((v & 0xFFFF) as u16, &mut b[6..8]);
|
||||
}
|
||||
|
||||
fn hton128(v: u128, b: &mut [u8]) {
|
||||
hton64((v >> 64) as u64, b);
|
||||
hton64((v & 0xFFFF_FFFF_FFFF_FFFF) as u64, &mut b[8..16]);
|
||||
}
|
||||
19
network/icmp/src/ping.rs
Normal file
19
network/icmp/src/ping.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use crate::checksum::IPv4ChecksumAccumulator;
|
||||
use crate::{hton128, hton16, hton64};
|
||||
|
||||
pub fn fmt_icmp_echo_req(buff: &mut [u8], seq_no: u16, req_id: u64, timestamp: u128) -> usize{
|
||||
buff[0] = 8;
|
||||
buff[1] = 0;
|
||||
hton16(0, &mut buff[4..6]);
|
||||
hton16(seq_no, &mut buff[6..8]);
|
||||
hton64(req_id, &mut buff[8..16]);
|
||||
hton128(timestamp, &mut buff[16..32]);
|
||||
|
||||
let mut checksum = IPv4ChecksumAccumulator::new();
|
||||
checksum.add_first_byte(buff[0]);
|
||||
checksum.add_second_byte(buff[1]);
|
||||
checksum.add_trailing_data(&buff[4..32]);
|
||||
hton16(checksum.snapshot(), &mut buff[2..4]);
|
||||
|
||||
return 32;
|
||||
}
|
||||
@ -8,6 +8,7 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
bgtu-networks-2-network-abstract = { path = "../abstract" }
|
||||
bgtu-networks-2-network-icmp = { path = "../icmp" }
|
||||
|
||||
[dependencies.windows]
|
||||
version = ">=0.41.0, <=0.62.2"
|
||||
|
||||
@ -9,10 +9,13 @@ use std::ffi::c_void;
|
||||
use crate::address::WindowsAddressKnown;
|
||||
use crate::errors::format_windows_err_code;
|
||||
use allocator::Allocator;
|
||||
use bgtu_networks_2_network_abstract::ServersContext;
|
||||
use bgtu_networks_2_network_abstract::{Address, ServersContext};
|
||||
use std::ptr::NonNull;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use windows::Win32::Networking::WinSock::{WSAEACCES, WSA_ERROR};
|
||||
use windows::Win32::System::SystemInformation::GetTickCount;
|
||||
use windows::Win32::System::Threading::SleepEx;
|
||||
use bgtu_networks_2_network_icmp::fmt_icmp_echo_req;
|
||||
|
||||
pub unsafe fn run_eventloop<Ctx: ServersContext<WindowsAddressKnown>>(ctx: *mut Ctx) {
|
||||
let heap = Allocator::new();
|
||||
@ -25,15 +28,17 @@ pub unsafe fn run_eventloop<Ctx: ServersContext<WindowsAddressKnown>>(ctx: *mut
|
||||
ctx,
|
||||
};
|
||||
|
||||
let mut seq_no = 0u16;
|
||||
|
||||
loop {
|
||||
let (id, it) = (*ctx).start_measuring();
|
||||
let (round_id, addrs_it) = (*ctx).start_measuring();
|
||||
|
||||
let mut should_recv_being_enabled = false;
|
||||
for address in it {
|
||||
for address in addrs_it {
|
||||
socket.send(
|
||||
address,
|
||||
|buff| {},
|
||||
|err, _| println!("Otpravlena hujnya: {}", format_windows_err_code(err)),
|
||||
|buff| fmt_icmp_echo_req(buff, seq_no, round_id, get_timestamp()),
|
||||
send_callback,
|
||||
);
|
||||
should_recv_being_enabled = true;
|
||||
}
|
||||
@ -61,6 +66,8 @@ pub unsafe fn run_eventloop<Ctx: ServersContext<WindowsAddressKnown>>(ctx: *mut
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
seq_no = seq_no.wrapping_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,6 +87,13 @@ impl<'s, Ctx: ServersContext<WindowsAddressKnown>> RecvCallback<'_, Ctx> {
|
||||
let this = this_ptr.cast::<Self>().as_ref();
|
||||
this.bind_callback();
|
||||
}
|
||||
|
||||
println!("Received from addr {} data {:02X?}", addr.to_string(), buffer);
|
||||
|
||||
match WSA_ERROR(errcode.cast_signed()) {
|
||||
WSA_ERROR(0) => {}
|
||||
errcode => panic!("Unhandled exception on send: [{}] {}", errcode.0, format_windows_err_code(errcode))
|
||||
}
|
||||
}
|
||||
|
||||
// I <3 borrow checker
|
||||
@ -98,3 +112,19 @@ impl<'s, Ctx: ServersContext<WindowsAddressKnown>> RecvCallback<'_, Ctx> {
|
||||
Self::_bind_callback(self_ptr.cast(), self.sock, Self::_callback_body);
|
||||
}
|
||||
}
|
||||
|
||||
fn send_callback(errcode: u32, addr: WindowsAddressKnown) {
|
||||
match WSA_ERROR(errcode.cast_signed()) {
|
||||
WSAEACCES => panic!("Need admin privileges to send ICMP"), // todo without panic,
|
||||
WSA_ERROR(0) => {}
|
||||
errcode => panic!("Unhandled exception on send: [{}] {}", errcode.0, format_windows_err_code(errcode))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_timestamp() -> u128 {
|
||||
let start = SystemTime::now();
|
||||
let since_the_epoch = start
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("time should go forward");
|
||||
return since_the_epoch.as_millis();
|
||||
}
|
||||
@ -2,19 +2,18 @@ use crate::address::WindowsAddressKnown;
|
||||
use crate::errors::throw_from_windows_err_code;
|
||||
use crate::eventloop::allocator::Allocator;
|
||||
use crate::eventloop::task::IoTask;
|
||||
use bgtu_networks_2_network_abstract::ServersContext;
|
||||
use std::mem::uninitialized;
|
||||
use std::pin::Pin;
|
||||
use std::ptr::NonNull;
|
||||
use std::slice;
|
||||
use windows::Win32::Networking::WinSock::{
|
||||
WSAGetLastError, WSARecvFrom, WSASendTo, WSASocketW, AF_UNSPEC,
|
||||
IPPROTO_ICMP, LPWSAOVERLAPPED_COMPLETION_ROUTINE, SOCKADDR, SOCKADDR_STORAGE, SOCKET,
|
||||
SOCKET_ERROR, SOCK_RAW, WSAEACCES, WSAEADDRNOTAVAIL, WSAEAFNOSUPPORT,
|
||||
AF_UNSPEC, IPPROTO_ICMP, LPWSAOVERLAPPED_COMPLETION_ROUTINE, SOCK_RAW, SOCKADDR,
|
||||
SOCKADDR_STORAGE, SOCKET, SOCKET_ERROR, WSA_FLAG_NO_HANDLE_INHERIT, WSA_FLAG_OVERLAPPED,
|
||||
WSA_IO_PENDING, WSA_OPERATION_ABORTED, WSAEACCES, WSAEADDRNOTAVAIL, WSAEAFNOSUPPORT,
|
||||
WSAECONNRESET, WSAEDESTADDRREQ, WSAEFAULT, WSAEHOSTUNREACH, WSAEINPROGRESS, WSAEINTR,
|
||||
WSAEINVAL, WSAEMSGSIZE, WSAENETDOWN, WSAENETRESET, WSAENETUNREACH, WSAENOBUFS, WSAENOTCONN,
|
||||
WSAENOTSOCK, WSAESHUTDOWN, WSAEWOULDBLOCK, WSANOTINITIALISED, WSA_FLAG_NO_HANDLE_INHERIT, WSA_FLAG_OVERLAPPED,
|
||||
WSA_IO_PENDING, WSA_OPERATION_ABORTED,
|
||||
WSAENOTSOCK, WSAESHUTDOWN, WSAEWOULDBLOCK, WSAGetLastError, WSANOTINITIALISED, WSARecvFrom,
|
||||
WSASendTo, WSASocketW,
|
||||
};
|
||||
use windows::Win32::System::IO::OVERLAPPED;
|
||||
|
||||
@ -78,7 +77,7 @@ impl<'a> WindowsOverlappingIcmpSocket<'a> {
|
||||
pub unsafe fn send(
|
||||
&mut self,
|
||||
addr: WindowsAddressKnown,
|
||||
init_data: impl FnOnce(&mut [u8]),
|
||||
init_data: impl FnOnce(&mut [u8]) -> usize,
|
||||
on_sent: impl FnOnce(u32, WindowsAddressKnown) + 'static,
|
||||
) {
|
||||
let task = self.heap.alloc(|p| {
|
||||
@ -91,7 +90,7 @@ impl<'a> WindowsOverlappingIcmpSocket<'a> {
|
||||
});
|
||||
let task_p = task.get_unchecked_mut();
|
||||
|
||||
init_data(&mut task_p.buff);
|
||||
task_p.buff_d[0].len = init_data(&mut task_p.buff) as u32;
|
||||
|
||||
let result = WSASendTo(
|
||||
self.socket,
|
||||
@ -138,7 +137,6 @@ impl<'a> WindowsOverlappingIcmpSocket<'a> {
|
||||
&self,
|
||||
on_received: impl for<'xx> FnOnce(u32, WindowsAddressKnown, &'xx [u8]) + 'static,
|
||||
) {
|
||||
|
||||
let task = self.heap.alloc(|p| {
|
||||
IoTask::init(
|
||||
p,
|
||||
@ -149,7 +147,6 @@ impl<'a> WindowsOverlappingIcmpSocket<'a> {
|
||||
});
|
||||
let task_p = task.get_unchecked_mut();
|
||||
|
||||
|
||||
task_p._addr_size = size_of::<SOCKADDR_STORAGE>() as i32;
|
||||
task_p._flags = 0;
|
||||
let result = WSARecvFrom(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user