From e2407b936f8dc958cc8b5fd3c52b35d0d0034abe Mon Sep 17 00:00:00 2001 From: ASM Rizvi Date: Sun, 15 Nov 2020 18:47:31 -0800 Subject: [PATCH 1/9] latency added --- src/main.rs | 9 ++++++++- src/net/mod.rs | 44 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index e4c59a8..5916a25 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,7 @@ extern crate argparse; extern crate time; use std::io::{self, BufRead}; use argparse::{ArgumentParser, Store}; +use std::time::{SystemTime, UNIX_EPOCH}; fn main() { // Read arguments from commandline @@ -57,6 +58,7 @@ fn main() { // Setup socket & (optionally) bind address let sockv4 = net::new_icmpv4_socket().expect("Could not create socket (v4)"); if !saddr.is_empty() { + // println!("Could not send packet:{}", saddr); net::bind_to_ip(sockv4, &saddr).expect("Could not bind socket to source address"); } @@ -69,7 +71,6 @@ fn main() { let mut handle = stdin.lock(); // Create new ICMP-header (IPv4 and IPv6) - let icmp4header = net::ICMP4Header::echo_request(identifier, sequence_number).to_byte_array(); let icmp6header = net::ICMP6Header::echo_request(identifier, sequence_number).to_byte_array(); // Initialize TokenBucketFilter for rate-limiting @@ -79,6 +80,12 @@ fn main() { while handle.read_line(&mut buffer).unwrap() > 0 { // Ratelimit tbf.take(); + + // Finding timestamp + let now = SystemTime::now(); + let since_the_epoch = now.duration_since(UNIX_EPOCH).expect("Time went backwards"); + + let icmp4header = net::ICMP4Header::echo_request(identifier, sequence_number, since_the_epoch.as_secs(), since_the_epoch.subsec_nanos(), buffer.trim()).to_byte_array(); // Send packet let result = net::send_packet(sockv4, sockv6, buffer.trim(), &icmp4header, &icmp6header); diff --git a/src/net/mod.rs b/src/net/mod.rs index 62fd2c6..5639aab 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -101,24 +101,44 @@ pub struct ICMP4Header { pub code: u8, pub checksum: u16, pub header: u32, + pub payload_sec: u64, + pub payload_nanosec: u32, + pub dest_part1: u8, + pub dest_part2: u8, + pub dest_part3: u8, + pub dest_part4: u8, } impl ICMP4Header { - pub fn echo_request(identifier: u16, sequence_number: u16) -> ICMP4Header { + pub fn echo_request(identifier: u16, sequence_number: u16, payload_sec: u64, payload_nanosec: u32, dest_ip: &str) -> ICMP4Header { let header = ((identifier as u32) << 16) | (sequence_number as u32); + + let split = dest_ip.split("."); + let vec: Vec<&str> = split.collect(); + let first_part: u8 = vec[0].parse().unwrap(); + let second_part: u8 = vec[1].parse().unwrap(); + let third_part: u8 = vec[2].parse().unwrap(); + let fourth_part: u8 = vec[3].parse().unwrap(); + let mut icmp4_header = ICMP4Header { icmp_type: 8, code: 0, checksum: 0, header: header, + payload_sec: payload_sec, + payload_nanosec: payload_nanosec, + dest_part1: first_part, + dest_part2: second_part, + dest_part3: third_part, + dest_part4: fourth_part, }; let checksum = ICMP4Header::calc_checksum(&icmp4_header.to_byte_array()); icmp4_header.checksum = checksum; icmp4_header } - pub fn to_byte_array(&self) -> [u8; 8] { - let mut buffer = [0; 8]; + pub fn to_byte_array(&self) -> [u8; 24] { + let mut buffer = [0; 24]; buffer[0] = self.icmp_type; buffer[1] = self.code; buffer[2] = (self.checksum >> 8 & 0xFF) as u8; @@ -127,6 +147,23 @@ impl ICMP4Header { buffer[5] = (self.header >> 16 & 0xFF) as u8; buffer[6] = (self.header >> 8 & 0xFF) as u8; buffer[7] = (self.header & 0xFF) as u8; + buffer[8] = (self.dest_part1 & 0xFF) as u8; + buffer[9] = (self.dest_part2 & 0xFF) as u8; + buffer[10] = (self.dest_part3 & 0xFF) as u8; + buffer[11] = (self.dest_part4 & 0xFF) as u8; + buffer[12] = (self.payload_sec >> 56 & 0xFF) as u8; + buffer[13] = (self.payload_sec >> 48 & 0xFF) as u8; + buffer[14] = (self.payload_sec >> 40 & 0xFF) as u8; + buffer[15] = (self.payload_sec >> 32 & 0xFF) as u8; + buffer[16] = (self.payload_sec >> 24 & 0xFF) as u8; + buffer[17] = (self.payload_sec >> 16 & 0xFF) as u8; + buffer[18] = (self.payload_sec >> 8 & 0xFF) as u8; + buffer[19] = (self.payload_sec & 0xFF) as u8; + buffer[20] = (self.payload_nanosec >> 24 & 0xFF) as u8; + buffer[21] = (self.payload_nanosec >> 16 & 0xFF) as u8; + buffer[22] = (self.payload_nanosec >> 8 & 0xFF) as u8; + buffer[23] = (self.payload_nanosec & 0xFF) as u8; + buffer } @@ -174,6 +211,7 @@ fn to_sockaddr(input: SockAddr) -> Option<*const sockaddr> { pub fn bind_to_ip(handle: i32, ip: &str) -> Result<(), String> { let addr = string_to_sockaddr(ip); + // println!("Bolod:{}", ip); if let Some(addr) = addr { let retval = unsafe { bind(handle, to_sockaddr(addr).unwrap(), 16) }; if retval != 0 { From d5831d2c2db147af687c6e2f426fd9dee96ce7a1 Mon Sep 17 00:00:00 2001 From: ASM Rizvi Date: Sun, 15 Nov 2020 18:52:28 -0800 Subject: [PATCH 2/9] small changes --- src/main.rs | 1 - src/net/mod.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5916a25..aa6237d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -58,7 +58,6 @@ fn main() { // Setup socket & (optionally) bind address let sockv4 = net::new_icmpv4_socket().expect("Could not create socket (v4)"); if !saddr.is_empty() { - // println!("Could not send packet:{}", saddr); net::bind_to_ip(sockv4, &saddr).expect("Could not bind socket to source address"); } diff --git a/src/net/mod.rs b/src/net/mod.rs index 5639aab..b647983 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -211,7 +211,6 @@ fn to_sockaddr(input: SockAddr) -> Option<*const sockaddr> { pub fn bind_to_ip(handle: i32, ip: &str) -> Result<(), String> { let addr = string_to_sockaddr(ip); - // println!("Bolod:{}", ip); if let Some(addr) = addr { let retval = unsafe { bind(handle, to_sockaddr(addr).unwrap(), 16) }; if retval != 0 { From 7848b6d698b44f890695965621b79c465ba80fa3 Mon Sep 17 00:00:00 2001 From: ASM Rizvi Date: Mon, 1 Feb 2021 13:46:26 -0800 Subject: [PATCH 3/9] small changes --- src/net/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/net/mod.rs b/src/net/mod.rs index b647983..8374ecb 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -151,6 +151,7 @@ impl ICMP4Header { buffer[9] = (self.dest_part2 & 0xFF) as u8; buffer[10] = (self.dest_part3 & 0xFF) as u8; buffer[11] = (self.dest_part4 & 0xFF) as u8; + // adding timestamp buffer[12] = (self.payload_sec >> 56 & 0xFF) as u8; buffer[13] = (self.payload_sec >> 48 & 0xFF) as u8; buffer[14] = (self.payload_sec >> 40 & 0xFF) as u8; From c277664942809b6fc525453311fe64c7f6fb5bad Mon Sep 17 00:00:00 2001 From: ASM Rizvi Date: Mon, 1 Feb 2021 14:16:30 -0800 Subject: [PATCH 4/9] updating --- .github/workflows/rust.yml | 32 ++++++++++++++++++ .gitignore | 2 ++ .travis.yml | 27 --------------- Cargo.lock | 59 ++++++++++++++++++--------------- Cargo.toml | 8 +++-- src/main.rs | 3 -- src/net/mod.rs | 68 +++++++++++++++----------------------- 7 files changed, 98 insertions(+), 101 deletions(-) create mode 100644 .github/workflows/rust.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..fbf94d3 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,32 @@ +on: [push, pull_request] + +name: Continuous integration + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - uses: actions-rs/cargo@v1 + with: + command: build + + test: + name: Test Suite + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - uses: actions-rs/cargo@v1 + with: + command: test diff --git a/.gitignore b/.gitignore index b83590a..8697327 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ target src/ips.txt +.idea/ +shell.nix diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8eaf38e..0000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: rust -cache: cargo -sudo: required -services: -- docker -before_install: -- sudo apt-get -qq update -- sudo apt-get install -y libpcap0.8-dev -rust: -- stable -- beta -- nightly -matrix: - allow_failures: - - rust: nightly -after_success: -- test $TRAVIS_RUST_VERSION = stable && docker create --name builder woutifier/rust-musl-builder /bin/bash -c "sudo chown -R rust:rust /home/rust/src; cargo build --release --verbose" && docker cp "${TRAVIS_BUILD_DIR}/." builder:/home/rust/src && docker start -i builder && docker cp builder:/home/rust/src/target/x86_64-unknown-linux-musl/release/pinger $TRAVIS_BUILD_DIR/pinger -deploy: - provider: releases - skip_cleanup: true - api_key: - secure: Ffc4Pz2QWhTTsBprwU8qP6gC9hldNa6IkAq3huZ0pDsr3ssYSJQ+CPAyGcGSiDDkTuGC/5BqW2AcP4SuCSxQUZVcKsftm2aF/bRSjuYB4OOfpf/sbbB8NYnkZMDqXFCLqDsurgDuW/hmWASVrEzbC/Fcl3WfTk42vuv3vFJJ8TIEWIXBC7g5xMGZOt4wY4TLtTmEcTwXklrMtx9EG0OrgTaded03AS9TNE14mqv02K1ImgCjU6LdkJ/oE6CKo42pquR+q3hUdtYwc3j1IoE2/zNodJqnQ9IgdXOhzu2UI/kGj5C3tioDXXHty1KhKSjn8kG9itAHk56QxO0RCsiLSstUgpkKN0ljyPFNsK1ImsFDYBNQ7rErpgPAGevWWLUuUZHwqiN/tGkoTyPS1oxVpCNKRw/OKUiLqhNhjzSOiXmhYvLtOZnqFMz093CkUS70GaB8jqHfBtD5MZk2FJhADqkS4BNohEtKn9bMvf7U+B8z9YlNoB69OCkKX2WH4gztOyDhkTZCCqMvHbxVK61mlge/a9TEF58fNip861mwWO3G5fBMdcXRHlcQjKCbPmLY6Lju3u3Wl8zvUobRmm7dGhC+EAV1ocpa0I+SNGPW4LrBNLd+GYpfRuZ3TO2uPU9OIV6tQLJtoZNaMf9Qh511Vktfq6esW8jXYdOkeXowbyY= - file: $TRAVIS_BUILD_DIR/pinger - on: - condition: $TRAVIS_RUST_VERSION = stable - repo: Woutifier/pinger - tags: true diff --git a/Cargo.lock b/Cargo.lock index d51c3c6..88ea6ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,62 +1,69 @@ -[root] -name = "pinger" -version = "0.1.0" -dependencies = [ - "argparse 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", -] +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "anyhow" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" [[package]] name = "argparse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f8ebf5827e4ac4fd5946560e6a99776ea73b596d80898f357007317a7141e47" [[package]] name = "byteorder" -version = "0.5.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" [[package]] name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ - "winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", + "winapi-build", ] [[package]] name = "libc" -version = "0.2.11" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff" + +[[package]] +name = "pinger" +version = "0.1.0" +dependencies = [ + "anyhow", + "argparse", + "byteorder", + "libc", + "time", +] [[package]] name = "time" version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys", + "libc", + "winapi", ] [[package]] name = "winapi" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3969e500d618a5e974917ddefd0ba152e4bcaae5eb5d9b8c1fbc008e9e28c24e" [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum argparse 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37bb99f5e39ee8b23b6e227f5b8f024207e8616f44aa4b8c76ecd828011667ef" -"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c96061f0c8a2dc27482e394d82e23073569de41d73cd736672ccd3e5c7471bfd" -"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af" -"checksum winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3969e500d618a5e974917ddefd0ba152e4bcaae5eb5d9b8c1fbc008e9e28c24e" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index 304e570..03fc8d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,9 +2,11 @@ name = "pinger" version = "0.1.0" authors = ["Wouter de Vries "] +edition = "2018" [dependencies] -libc = "0.2.11" -argparse = "0.2.1" +libc = "0.2.84" +argparse = "0.2.2" time = "0.1.35" -byteorder = "0.5.3" +byteorder = "1.4.2" +anyhow = "1.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index aa6237d..c903029 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,9 +22,6 @@ mod net; mod tbf; -extern crate libc; -extern crate argparse; -extern crate time; use std::io::{self, BufRead}; use argparse::{ArgumentParser, Store}; use std::time::{SystemTime, UNIX_EPOCH}; diff --git a/src/net/mod.rs b/src/net/mod.rs index 8374ecb..8c7d40c 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -19,20 +19,16 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -extern crate byteorder; -extern crate libc; - -use std::mem; -use std::io::{Error, Cursor}; +use std::str::FromStr; use std::thread::sleep; use std::time::Duration; -use std::net::{Ipv6Addr, IpAddr}; -use std::str::FromStr; +use std::io::{Cursor, Error}; +use std::net::{IpAddr, Ipv6Addr}; -// Use other than std -use libc::{c_int, c_void, socket, sendto, AF_INET, AF_INET6, SOCK_RAW, sockaddr_in, sockaddr_in6, - in_addr, sockaddr, bind}; -use self::byteorder::{ReadBytesExt, LittleEndian}; +use anyhow::{anyhow, Result}; +use byteorder::{LittleEndian, ReadBytesExt}; +use libc::{AF_INET, AF_INET6, bind, c_int, c_void, in_addr, sendto, SOCK_RAW, sockaddr, + sockaddr_in, sockaddr_in6, socket}; // Static values static IPPROTO_ICMP: c_int = 1; @@ -185,41 +181,37 @@ impl ICMP4Header { } } -pub fn new_icmpv4_socket() -> Result { +pub fn new_icmpv4_socket() -> Result { let handle = unsafe { socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) }; if handle == -1 { - return Err(::std::error::Error::description(&Error::last_os_error()).to_string()); + return Err(anyhow!(Error::last_os_error().to_string())); } Ok(handle) } -pub fn new_icmpv6_socket() -> Result { +pub fn new_icmpv6_socket() -> Result { let handle = unsafe { socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) }; if handle == -1 { - return Err(::std::error::Error::description(&Error::last_os_error()).to_string()); + return Err(anyhow!(Error::last_os_error().to_string())); } Ok(handle) } -fn to_sockaddr(input: SockAddr) -> Option<*const sockaddr> { - if let SockAddr::V4(input) = input { - return Some((&input as *const sockaddr_in) as *const sockaddr); - } else if let SockAddr::V6(input) = input { - return Some((&input as *const sockaddr_in6) as *const sockaddr); - } - None -} - -pub fn bind_to_ip(handle: i32, ip: &str) -> Result<(), String> { +pub fn bind_to_ip(handle: i32, ip: &str) -> Result<()> { let addr = string_to_sockaddr(ip); if let Some(addr) = addr { - let retval = unsafe { bind(handle, to_sockaddr(addr).unwrap(), 16) }; + // Cast address from sockaddr_in/sockaddr_in6 to sockaddr + let cast_addr = match &addr { + SockAddr::V4(input) => (input as *const sockaddr_in) as *const sockaddr, + SockAddr::V6(input) => (input as *const sockaddr_in6) as *const sockaddr + }; + let retval = unsafe { bind(handle, cast_addr, 16) }; if retval != 0 { - return Err(::std::error::Error::description(&Error::last_os_error()).to_string()); + return Err(anyhow!(Error::last_os_error())); } return Ok(()); } - Err("Invalid IP-address".to_string()) + Err(anyhow!("Invalid IP-address")) } @@ -227,7 +219,6 @@ fn string_to_sockaddr(ip: &str) -> Option { let dest_ip = IpAddr::from_str(ip); if let Ok(IpAddr::V4(dest_ip)) = dest_ip { let mut ipcursor = Cursor::new(dest_ip.octets()); - //println!("{:?}", ipcursor.read_u32::().unwrap()); let addr = sockaddr_in { sin_family: AF_INET as u16, sin_port: 0, @@ -248,17 +239,10 @@ fn string_to_sockaddr(ip: &str) -> Option { None } -// Todo: this function needs cleaning up fn init_in6_addr(addr: Ipv6Addr) -> libc::in6_addr { - let mut bytes = addr.segments(); - bytes.reverse(); - let mut stuff: [u8; 16] = unsafe { mem::transmute(bytes) }; - stuff.reverse(); - unsafe { - let mut in6addr: libc::in6_addr = mem::uninitialized(); - in6addr.s6_addr = stuff; - return in6addr; - }; + libc::in6_addr { + s6_addr: addr.octets() + } } pub fn send_packet(handlev4: i32, @@ -266,7 +250,7 @@ pub fn send_packet(handlev4: i32, destination: &str, bufferv4: &[u8], bufferv6: &[u8]) - -> Result { + -> Result { let addr = string_to_sockaddr(destination); if let Some(addr) = addr { let mut pktlength = -1; @@ -297,13 +281,13 @@ pub fn send_packet(handlev4: i32, sleep(Duration::from_millis(1)); } else { println!("Error: {}", syserr); - return Err(::std::error::Error::description(&syserr).to_string()); + return Err(anyhow!(syserr)); } } } return Ok(pktlength as u32); } - Err(format!("Invalid IP-Address: {}", destination)) + Err(anyhow!(format!("Invalid IP-Address: {}", destination).to_string())) } #[cfg(test)] From 006bf1cf9c3149b2a609edd59f8055ea6039c02f Mon Sep 17 00:00:00 2001 From: ASM Rizvi Date: Mon, 8 Feb 2021 23:19:22 -0800 Subject: [PATCH 5/9] valid address check - fixing bugs --- src/net/mod.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/net/mod.rs b/src/net/mod.rs index 8c7d40c..ebe4226 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -110,11 +110,19 @@ impl ICMP4Header { let header = ((identifier as u32) << 16) | (sequence_number as u32); let split = dest_ip.split("."); - let vec: Vec<&str> = split.collect(); - let first_part: u8 = vec[0].parse().unwrap(); - let second_part: u8 = vec[1].parse().unwrap(); - let third_part: u8 = vec[2].parse().unwrap(); - let fourth_part: u8 = vec[3].parse().unwrap(); + let vec: Vec<&str> = split.collect(); + + let mut first_part: u8 = 0; + let mut second_part: u8 = 0; + let mut third_part: u8 = 0; + let mut fourth_part: u8 = 0; + + if vec.len() == 4 { + first_part = vec[0].parse().unwrap(); + second_part = vec[1].parse().unwrap(); + third_part = vec[2].parse().unwrap(); + fourth_part = vec[3].parse().unwrap(); + } let mut icmp4_header = ICMP4Header { icmp_type: 8, From 305010b2fb2911aee17fdfb0062b7eaf239cead3 Mon Sep 17 00:00:00 2001 From: ASM Rizvi Date: Fri, 12 Feb 2021 14:27:21 -0800 Subject: [PATCH 6/9] added error msg --- src/net/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/net/mod.rs b/src/net/mod.rs index ebe4226..5d4b95d 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -122,6 +122,8 @@ impl ICMP4Header { second_part = vec[1].parse().unwrap(); third_part = vec[2].parse().unwrap(); fourth_part = vec[3].parse().unwrap(); + } else { + println!("Could not parse ipv4 address for the payload, putting 0.0.0.0: {}", dest_ip); } let mut icmp4_header = ICMP4Header { From 191a6fd4585b5786a0e878e11855ac2d161e95c0 Mon Sep 17 00:00:00 2001 From: ASM Rizvi Date: Fri, 12 Feb 2021 22:43:27 -0800 Subject: [PATCH 7/9] condition check for ipv4 --- src/net/mod.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/net/mod.rs b/src/net/mod.rs index 5d4b95d..4a1fb95 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -108,22 +108,20 @@ pub struct ICMP4Header { impl ICMP4Header { pub fn echo_request(identifier: u16, sequence_number: u16, payload_sec: u64, payload_nanosec: u32, dest_ip: &str) -> ICMP4Header { let header = ((identifier as u32) << 16) | (sequence_number as u32); - - let split = dest_ip.split("."); - let vec: Vec<&str> = split.collect(); - + let mut first_part: u8 = 0; let mut second_part: u8 = 0; let mut third_part: u8 = 0; let mut fourth_part: u8 = 0; - - if vec.len() == 4 { - first_part = vec[0].parse().unwrap(); - second_part = vec[1].parse().unwrap(); - third_part = vec[2].parse().unwrap(); - fourth_part = vec[3].parse().unwrap(); - } else { - println!("Could not parse ipv4 address for the payload, putting 0.0.0.0: {}", dest_ip); + + let ip = IpAddr::from_str(dest_ip); + if let Ok(IpAddr::V4(_ip)) = ip { + let split = dest_ip.split("."); + let vec: Vec<&str> = split.collect(); + first_part = vec[0].parse().expect("Failed parsing ipv4 address"); + second_part = vec[1].parse().expect("Failed parsing ipv4 address"); + third_part = vec[2].parse().expect("Failed parsing ipv4 address"); + fourth_part = vec[3].parse().expect("Failed parsing ipv4 address"); } let mut icmp4_header = ICMP4Header { @@ -138,6 +136,7 @@ impl ICMP4Header { dest_part3: third_part, dest_part4: fourth_part, }; + let checksum = ICMP4Header::calc_checksum(&icmp4_header.to_byte_array()); icmp4_header.checksum = checksum; icmp4_header From e05552a3683fea6736cd60d467df8c8677141f4f Mon Sep 17 00:00:00 2001 From: ASM Rizvi Date: Sun, 9 May 2021 21:22:36 -0700 Subject: [PATCH 8/9] ipv6 added --- src/main.rs | 17 ++++++++++++++--- src/net/mod.rs | 14 +++++++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index c903029..487b6ea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,12 +54,23 @@ fn main() { // Setup socket & (optionally) bind address let sockv4 = net::new_icmpv4_socket().expect("Could not create socket (v4)"); + let sockv6 = net::new_icmpv6_socket().expect("Could not create socket (v6)"); + + //if !saddr.is_empty() { + // net::bind_to_ip(sockv4, &saddr).expect("Could not bind socket to source address"); + //} + if !saddr.is_empty() { - net::bind_to_ip(sockv4, &saddr).expect("Could not bind socket to source address"); + let addr = net::string_to_sockaddr(&saddr); + if let Some(addr) = addr { + if let net::SockAddr::V4(_addr) = addr { + net::bind_to_ip(sockv4, &saddr).expect("Could not bind socket to source address"); + } else if let net::SockAddr::V6(_addr) = addr { + net::bind_to_ip(sockv6, &saddr).expect("Could not bind socket to source address"); + } + } } - let sockv6 = net::new_icmpv6_socket().expect("Could not create socket (v6)"); - // Read from STDIN let mut buffer = String::new(); diff --git a/src/net/mod.rs b/src/net/mod.rs index 4a1fb95..1e11a13 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -34,7 +34,7 @@ use libc::{AF_INET, AF_INET6, bind, c_int, c_void, in_addr, sendto, SOCK_RAW, so static IPPROTO_ICMP: c_int = 1; static IPPROTO_ICMPV6: c_int = 58; -enum SockAddr { +pub enum SockAddr { V4(sockaddr_in), V6(sockaddr_in6), } @@ -214,7 +214,15 @@ pub fn bind_to_ip(handle: i32, ip: &str) -> Result<()> { SockAddr::V4(input) => (input as *const sockaddr_in) as *const sockaddr, SockAddr::V6(input) => (input as *const sockaddr_in6) as *const sockaddr }; - let retval = unsafe { bind(handle, cast_addr, 16) }; + + let mut retval = 0; + if let SockAddr::V4(_addr) = addr { + retval = unsafe { bind(handle, cast_addr, 16) }; + } else if let SockAddr::V6(_addr) = addr { + retval = unsafe { bind(handle, cast_addr, 64) }; + } + + // let retval = unsafe { bind(handle, cast_addr, 16) }; if retval != 0 { return Err(anyhow!(Error::last_os_error())); } @@ -224,7 +232,7 @@ pub fn bind_to_ip(handle: i32, ip: &str) -> Result<()> { } -fn string_to_sockaddr(ip: &str) -> Option { +pub fn string_to_sockaddr(ip: &str) -> Option { let dest_ip = IpAddr::from_str(ip); if let Ok(IpAddr::V4(dest_ip)) = dest_ip { let mut ipcursor = Cursor::new(dest_ip.octets()); From 1fcbfa096b18852e1b265ed53c13caf8313c2c85 Mon Sep 17 00:00:00 2001 From: ASM Rizvi Date: Thu, 27 May 2021 22:43:03 -0700 Subject: [PATCH 9/9] modified for ipv6 --- src/main.rs | 15 +++++++++------ src/net/mod.rs | 42 +++++++++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 17 deletions(-) mode change 100644 => 100755 src/main.rs mode change 100644 => 100755 src/net/mod.rs diff --git a/src/main.rs b/src/main.rs old mode 100644 new mode 100755 index 487b6ea..5452fdc --- a/src/main.rs +++ b/src/main.rs @@ -56,10 +56,6 @@ fn main() { let sockv4 = net::new_icmpv4_socket().expect("Could not create socket (v4)"); let sockv6 = net::new_icmpv6_socket().expect("Could not create socket (v6)"); - //if !saddr.is_empty() { - // net::bind_to_ip(sockv4, &saddr).expect("Could not bind socket to source address"); - //} - if !saddr.is_empty() { let addr = net::string_to_sockaddr(&saddr); if let Some(addr) = addr { @@ -77,8 +73,6 @@ fn main() { let stdin = io::stdin(); let mut handle = stdin.lock(); - // Create new ICMP-header (IPv4 and IPv6) - let icmp6header = net::ICMP6Header::echo_request(identifier, sequence_number).to_byte_array(); // Initialize TokenBucketFilter for rate-limiting let mut tbf = tbf::TokenBucketFilter::new(rate); @@ -91,8 +85,17 @@ fn main() { // Finding timestamp let now = SystemTime::now(); let since_the_epoch = now.duration_since(UNIX_EPOCH).expect("Time went backwards"); + //let addr = string_to_sockaddr(buffer.trim()); + //if let Some(addr) = addr { + // println!("Could send packet"); + //} else { + // println!("Could not send packet"); + //} + + //Err(anyhow!(format!("Invalid IP-Address: {}", buffer.trim()).to_string())) let icmp4header = net::ICMP4Header::echo_request(identifier, sequence_number, since_the_epoch.as_secs(), since_the_epoch.subsec_nanos(), buffer.trim()).to_byte_array(); + let icmp6header = net::ICMP6Header::echo_request(identifier, sequence_number, since_the_epoch.as_secs(), since_the_epoch.subsec_nanos()).to_byte_array(); // Send packet let result = net::send_packet(sockv4, sockv6, buffer.trim(), &icmp4header, &icmp6header); diff --git a/src/net/mod.rs b/src/net/mod.rs old mode 100644 new mode 100755 index 1e11a13..5266eed --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -45,24 +45,28 @@ pub struct ICMP6Header { pub code: u8, pub checksum: u16, pub header: u32, + pub payload_sec: u64, + pub payload_nanosec: u32, } impl ICMP6Header { - pub fn echo_request(identifier: u16, sequence_number: u16) -> ICMP6Header { + pub fn echo_request(identifier: u16, sequence_number: u16, payload_sec: u64, payload_nanosec: u32) -> ICMP6Header { let header = ((identifier as u32) << 16) | (sequence_number as u32); let mut icmp6_header = ICMP6Header { icmp_type: 128, code: 0, checksum: 0, header: header, + payload_sec: payload_sec, + payload_nanosec: payload_nanosec, }; let checksum = ICMP6Header::calc_checksum(&icmp6_header.to_byte_array()); icmp6_header.checksum = checksum; icmp6_header } - pub fn to_byte_array(&self) -> [u8; 8] { - let mut buffer = [0; 8]; + pub fn to_byte_array(&self) -> [u8; 20] { + let mut buffer = [0; 20]; buffer[0] = self.icmp_type; buffer[1] = self.code; buffer[2] = (self.checksum >> 8 & 0xFF) as u8; @@ -71,6 +75,19 @@ impl ICMP6Header { buffer[5] = (self.header >> 16 & 0xFF) as u8; buffer[6] = (self.header >> 8 & 0xFF) as u8; buffer[7] = (self.header & 0xFF) as u8; + // adding timestamp + buffer[8] = (self.payload_sec >> 56 & 0xFF) as u8; + buffer[9] = (self.payload_sec >> 48 & 0xFF) as u8; + buffer[10] = (self.payload_sec >> 40 & 0xFF) as u8; + buffer[11] = (self.payload_sec >> 32 & 0xFF) as u8; + buffer[12] = (self.payload_sec >> 24 & 0xFF) as u8; + buffer[13] = (self.payload_sec >> 16 & 0xFF) as u8; + buffer[14] = (self.payload_sec >> 8 & 0xFF) as u8; + buffer[15] = (self.payload_sec & 0xFF) as u8; + buffer[16] = (self.payload_nanosec >> 24 & 0xFF) as u8; + buffer[17] = (self.payload_nanosec >> 16 & 0xFF) as u8; + buffer[18] = (self.payload_nanosec >> 8 & 0xFF) as u8; + buffer[19] = (self.payload_nanosec & 0xFF) as u8; buffer } @@ -108,22 +125,26 @@ pub struct ICMP4Header { impl ICMP4Header { pub fn echo_request(identifier: u16, sequence_number: u16, payload_sec: u64, payload_nanosec: u32, dest_ip: &str) -> ICMP4Header { let header = ((identifier as u32) << 16) | (sequence_number as u32); - + + //let split = dest_ip.split("."); + //let vec: Vec<&str> = split.collect(); + let mut first_part: u8 = 0; let mut second_part: u8 = 0; let mut third_part: u8 = 0; - let mut fourth_part: u8 = 0; + let mut fourth_part: u8 = 0; - let ip = IpAddr::from_str(dest_ip); - if let Ok(IpAddr::V4(_ip)) = ip { - let split = dest_ip.split("."); - let vec: Vec<&str> = split.collect(); + let ip = IpAddr::from_str(dest_ip); + if let Ok(IpAddr::V4(_ip)) = ip { + let split = dest_ip.split("."); + let vec: Vec<&str> = split.collect(); first_part = vec[0].parse().expect("Failed parsing ipv4 address"); second_part = vec[1].parse().expect("Failed parsing ipv4 address"); third_part = vec[2].parse().expect("Failed parsing ipv4 address"); fourth_part = vec[3].parse().expect("Failed parsing ipv4 address"); } + let mut icmp4_header = ICMP4Header { icmp_type: 8, code: 0, @@ -136,7 +157,6 @@ impl ICMP4Header { dest_part3: third_part, dest_part4: fourth_part, }; - let checksum = ICMP4Header::calc_checksum(&icmp4_header.to_byte_array()); icmp4_header.checksum = checksum; icmp4_header @@ -222,7 +242,7 @@ pub fn bind_to_ip(handle: i32, ip: &str) -> Result<()> { retval = unsafe { bind(handle, cast_addr, 64) }; } - // let retval = unsafe { bind(handle, cast_addr, 16) }; + //let retval = unsafe { bind(handle, cast_addr, 16) }; if retval != 0 { return Err(anyhow!(Error::last_os_error())); }