extern crate pnet; use std::env; use std::io::{self, Write}; use std::net::{AddrParseError, IpAddr, Ipv4Addr}; use std::process; use pnet::datalink::{Channel, MacAddr, NetworkInterface}; use pnet::packet::arp::{ArpHardwareTypes, ArpOperations, ArpPacket, MutableArpPacket}; use pnet::packet::ethernet::EtherTypes; use pnet::packet::ethernet::MutableEthernetPacket; use pnet::packet::{MutablePacket, Packet}; fn get_mac_through_arp(interface: NetworkInterface, target_ip: Ipv4Addr) -> MacAddr { let source_ip = interface .ips .iter() .find(|ip| ip.is_ipv4()) .map(|ip| match ip.ip() { IpAddr::V4(ip) => ip, _ => unreachable!(), }) .unwrap(); let (mut sender, mut receiver) = match pnet::datalink::channel(&interface, Default::default()) { Ok(Channel::Ethernet(tx, rx)) => (tx, rx), Ok(_) => panic!("Unknown channel type"), Err(e) => panic!("Error happened {}", e), }; let mut ethernet_buffer = [0u8; 42]; let mut ethernet_packet = MutableEthernetPacket::new(&mut ethernet_buffer).unwrap(); ethernet_packet.set_destination(MacAddr::broadcast()); ethernet_packet.set_source(interface.mac.unwrap()); ethernet_packet.set_ethertype(EtherTypes::Arp); let mut arp_buffer = [0u8; 28]; let mut arp_packet = MutableArpPacket::new(&mut arp_buffer).unwrap(); arp_packet.set_hardware_type(ArpHardwareTypes::Ethernet); arp_packet.set_protocol_type(EtherTypes::Ipv4); arp_packet.set_hw_addr_len(6); arp_packet.set_proto_addr_len(4); arp_packet.set_operation(ArpOperations::Request); arp_packet.set_sender_hw_addr(interface.mac.unwrap()); arp_packet.set_sender_proto_addr(source_ip); arp_packet.set_target_hw_addr(MacAddr::zero()); arp_packet.set_target_proto_addr(target_ip); ethernet_packet.set_payload(arp_packet.packet_mut()); sender .send_to(ethernet_packet.packet(), None) .unwrap() .unwrap(); println!("Sent ARP request"); loop { let buf = receiver.next().unwrap(); let arp = ArpPacket::new(&buf[MutableEthernetPacket::minimum_packet_size()..]).unwrap(); if arp.get_sender_proto_addr() == target_ip && arp.get_target_hw_addr() == interface.mac.unwrap() { println!("Received reply"); return arp.get_sender_hw_addr(); } } // unreachable } fn main() { let mut args = env::args().skip(1); let iface_name = match args.next() { Some(n) => n, None => { writeln!( io::stderr(), "USAGE: arp_packet " ) .unwrap(); process::exit(1); } }; let target_ip: Result = match args.next() { Some(n) => n.parse(), None => { writeln!( io::stderr(), "USAGE: arp_packet " ) .unwrap(); process::exit(1); } }; let interfaces = pnet::datalink::interfaces(); let interface = interfaces .into_iter() .find(|iface| iface.name == iface_name) .unwrap(); let _source_mac = interface.mac.unwrap(); let target_mac = get_mac_through_arp(interface, target_ip.unwrap()); println!("Target MAC address: {}", target_mac); }