110 lines
3.2 KiB
Rust
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));
|
|
}
|
|
}
|
|
}
|