Files
2023-03-10 23:10:39 -08:00

110 lines
3.2 KiB
Rust

use std::{collections::HashMap, net::Ipv6Addr, thread::sleep, time::Duration, vec};
use image::Rgb;
use pnet::{
packet::{
icmpv6::{self, Icmpv6, Icmpv6Code, Icmpv6Types, MutableIcmpv6Packet},
ip::IpNextHeaderProtocols,
},
transport::{transport_channel, TransportSender},
};
use strfmt::strfmt;
// fdcf:8538:9ad5:3333:XXXX:YYYY:11RR:GGBB
const IPV6_BASE: [u16; 8] = [0xfdcf, 0x8538, 0x9ad5, 0x3333, 0, 0, 0x1100, 0];
const IMAGE_FILENAME: &str = "img/xmsx_{i}.png";
const IMAGE_COUNT: u32 = 8;
const CANVAS_LEFT: u32 = 0;
const CANVAS_TOP: u32 = 128;
fn setup_channel() -> TransportSender {
let (sender, _) = transport_channel(
1024,
pnet::transport::TransportChannelType::Layer4(pnet::transport::TransportProtocol::Ipv6(
IpNextHeaderProtocols::Icmpv6,
)),
)
.unwrap();
return sender;
}
fn ping(sender: &mut TransportSender, dest: Ipv6Addr) {
let mut buf = [0u8; 64];
let mut packet = MutableIcmpv6Packet::new(&mut buf).unwrap();
packet.populate(&Icmpv6 {
icmpv6_type: Icmpv6Types::EchoRequest,
icmpv6_code: Icmpv6Code::new(0),
checksum: 0,
payload: [0u8; 24].to_vec(),
});
packet.set_checksum(icmpv6::checksum(
&packet.to_immutable(),
&Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0),
&dest,
));
let packet = packet.consume_to_immutable();
sender.send_to(packet, std::net::IpAddr::V6(dest)).unwrap();
}
fn ipv6_from_pixel(pixel: Rgb<u8>, x: u32, y: u32) -> Ipv6Addr {
let mut target = IPV6_BASE.clone();
target[4] = u16::try_from(x).unwrap();
target[5] = u16::try_from(y).unwrap();
target[6] = 0x1100 + u16::from(pixel.0[0]);
target[7] = u16::from(pixel.0[1]) * 256 + u16::from(pixel.0[2]);
return Ipv6Addr::from(target);
}
fn ipv6_from_image(filename: &str, left: u32, top: u32) -> Vec<Ipv6Addr> {
let img = image::io::Reader::open(filename).unwrap();
let img = img.decode().unwrap();
let img = img.to_rgb8();
let mut result: Vec<Ipv6Addr> = vec![];
for y in 0..img.height() {
for x in 0..img.width() {
let pixel = img.get_pixel(x, y);
let target = ipv6_from_pixel(*pixel, x + left, y + top);
result.push(target);
}
}
return result;
}
fn ipv6_from_image_series(
filename_format: &str,
num_images: u32,
left: u32,
top: u32,
) -> Vec<Vec<Ipv6Addr>> {
let mut result: Vec<Vec<Ipv6Addr>> = vec![];
for i in 0..num_images {
let mut format_args = HashMap::new();
format_args.insert("i".to_string(), i);
let filename = strfmt(filename_format, &format_args).unwrap();
let targets = ipv6_from_image(&filename, left, top);
result.push(targets);
}
return result;
}
fn main() {
let mut sender = setup_channel();
let series = ipv6_from_image_series(IMAGE_FILENAME, IMAGE_COUNT, CANVAS_LEFT, CANVAS_TOP);
loop {
for (i, targets) in series.iter().enumerate() {
println!("Sending image {i}...");
for target in targets.iter() {
ping(&mut sender, *target);
sleep(Duration::from_micros(10));
}
println!("Sleeping...");
sleep(Duration::from_millis(500));
}
}
}