11use pyo3:: prelude:: * ;
22use pyo3:: types:: { PyBytes , PyDict , PyList } ;
3- use pnet:: datalink:: { self , Channel :: Ethernet } ;
4- use pnet:: packet:: ethernet:: { EtherTypes , EthernetPacket } ;
5- use pnet:: packet:: ipv4:: Ipv4Packet ;
3+ use pnet:: datalink:: { self , Channel :: Ethernet , MacAddr } ;
4+ use pnet:: packet:: ethernet:: { MutableEthernetPacket , EtherTypes , EthernetPacket } ;
5+ use pnet:: packet:: ip:: IpNextHeaderProtocols ;
6+ use pnet:: packet:: ipv4:: { MutableIpv4Packet , Ipv4Packet } ;
7+ use pnet:: packet:: udp:: { MutableUdpPacket , UdpPacket } ;
68use pnet:: packet:: tcp:: TcpPacket ;
7- use pnet:: packet:: udp:: UdpPacket ;
89use pnet:: packet:: Packet ;
9- use pnet:: packet:: ip:: IpNextHeaderProtocols ;
10+ use std:: net:: Ipv4Addr ;
11+ use std:: str:: FromStr ;
12+
13+
14+
15+
16+
1017
1118#[ pyclass]
1219struct DataLinkInterface {
@@ -20,6 +27,7 @@ impl DataLinkInterface {
2027 DataLinkInterface { interface_name }
2128 }
2229
30+
2331 #[ pyo3( signature = (
2432 num_packets,
2533 * ,
@@ -177,12 +185,45 @@ impl DataLinkInterface {
177185 Ok ( py_packets. into ( ) )
178186 }
179187
180- #[ pyo3( signature = ( packet , num_packets= None ) ) ]
188+ #[ pyo3( signature = ( payload , src_mac , src_ip , src_port , dst_mac , dst_ip , dst_port ) ) ]
181189 fn transmit_packet (
182190 & self ,
183- packet : & [ u8 ] ,
184- num_packets : Option < usize > ,
191+ payload : & [ u8 ] ,
192+ src_mac : & str ,
193+ src_ip : & str ,
194+ src_port : u16 ,
195+ dst_mac : & str ,
196+ dst_ip : & str ,
197+ dst_port : u16 ,
185198 ) -> PyResult < ( ) > {
199+ // Parse IP addresses
200+ let src_ip: Ipv4Addr = src_ip. parse ( ) . map_err ( |e| {
201+ PyErr :: new :: < pyo3:: exceptions:: PyValueError , _ > ( format ! (
202+ "Invalid source IP address: {}" ,
203+ e
204+ ) )
205+ } ) ?;
206+ let dst_ip: Ipv4Addr = dst_ip. parse ( ) . map_err ( |e| {
207+ PyErr :: new :: < pyo3:: exceptions:: PyValueError , _ > ( format ! (
208+ "Invalid destination IP address: {}" ,
209+ e
210+ ) )
211+ } ) ?;
212+
213+ // Parse MAC addresses
214+ let src_mac = MacAddr :: from_str ( src_mac) . map_err ( |e| {
215+ PyErr :: new :: < pyo3:: exceptions:: PyValueError , _ > ( format ! (
216+ "Invalid source MAC address: {}" ,
217+ e
218+ ) )
219+ } ) ?;
220+ let dst_mac = MacAddr :: from_str ( dst_mac) . map_err ( |e| {
221+ PyErr :: new :: < pyo3:: exceptions:: PyValueError , _ > ( format ! (
222+ "Invalid destination MAC address: {}" ,
223+ e
224+ ) )
225+ } ) ?;
226+
186227 // Find the network interface
187228 let interface = {
188229 if cfg ! ( target_os = "windows" ) {
@@ -202,9 +243,69 @@ impl DataLinkInterface {
202243 ) )
203244 } ) ?;
204245
246+ // Create a new UDP packet
247+ let mut udp_buffer = vec ! [ 0u8 ; MutableUdpPacket :: minimum_packet_size( ) + payload. len( ) ] ;
248+ let mut udp_packet = MutableUdpPacket :: new ( & mut udp_buffer) . ok_or_else ( || {
249+ PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( "Failed to create UDP packet" )
250+ } ) ?;
251+
252+ udp_packet. set_source ( src_port) ;
253+ udp_packet. set_destination ( dst_port) ;
254+ udp_packet. set_length ( ( MutableUdpPacket :: minimum_packet_size ( ) + payload. len ( ) ) as u16 ) ;
255+ udp_packet. set_payload ( payload) ;
256+
257+ // Calculate UDP checksum
258+ let checksum = pnet:: packet:: udp:: ipv4_checksum (
259+ & udp_packet. to_immutable ( ) ,
260+ & src_ip,
261+ & dst_ip,
262+ ) ;
263+ udp_packet. set_checksum ( checksum) ;
264+
265+ // Create a new IPv4 packet
266+ let mut ip_buffer = vec ! [
267+ 0u8 ;
268+ MutableIpv4Packet :: minimum_packet_size( ) + udp_packet. packet( ) . len( )
269+ ] ;
270+ let mut ip_packet = MutableIpv4Packet :: new ( & mut ip_buffer) . ok_or_else ( || {
271+ PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( "Failed to create IPv4 packet" )
272+ } ) ?;
273+
274+ ip_packet. set_version ( 4 ) ;
275+ ip_packet. set_header_length ( 5 ) ;
276+ ip_packet. set_total_length (
277+ ( MutableIpv4Packet :: minimum_packet_size ( ) + udp_packet. packet ( ) . len ( ) ) as u16 ,
278+ ) ;
279+ ip_packet. set_ttl ( 64 ) ;
280+ ip_packet. set_next_level_protocol ( IpNextHeaderProtocols :: Udp ) ;
281+ ip_packet. set_source ( src_ip) ;
282+ ip_packet. set_destination ( dst_ip) ;
283+ ip_packet. set_payload ( udp_packet. packet ( ) ) ;
284+
285+ // Calculate IPv4 checksum
286+ let checksum = pnet:: packet:: ipv4:: checksum ( & ip_packet. to_immutable ( ) ) ;
287+ ip_packet. set_checksum ( checksum) ;
288+
289+ // Create a new Ethernet packet
290+ let mut ethernet_buffer = vec ! [
291+ 0u8 ;
292+ MutableEthernetPacket :: minimum_packet_size( ) + ip_packet. packet( ) . len( )
293+ ] ;
294+ let mut ethernet_packet =
295+ MutableEthernetPacket :: new ( & mut ethernet_buffer) . ok_or_else ( || {
296+ PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > (
297+ "Failed to create Ethernet packet" ,
298+ )
299+ } ) ?;
300+
301+ ethernet_packet. set_destination ( dst_mac) ;
302+ ethernet_packet. set_source ( src_mac) ;
303+ ethernet_packet. set_ethertype ( pnet:: packet:: ethernet:: EtherTypes :: Ipv4 ) ;
304+ ethernet_packet. set_payload ( ip_packet. packet ( ) ) ;
305+
205306 // Create a channel to send on
206- let ( mut tx, _ ) = match datalink:: channel ( & interface, Default :: default ( ) ) {
207- Ok ( Ethernet ( tx, _rx) ) => ( tx , _rx ) ,
307+ let mut tx = match datalink:: channel ( & interface, Default :: default ( ) ) {
308+ Ok ( Ethernet ( tx, _rx) ) => tx ,
208309 Ok ( _) => {
209310 return Err ( PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > (
210311 "Unhandled channel type" ,
@@ -218,35 +319,17 @@ impl DataLinkInterface {
218319 }
219320 } ;
220321
221- let packet_bytes = packet;
222-
223- let packet_size = packet_bytes. len ( ) ;
224-
225- let num_packets = num_packets. unwrap_or ( 1 ) ;
226- let num_packets = if num_packets < 1 { 1 } else { num_packets } ;
227-
228- for _ in 0 ..num_packets {
229- let send_result = tx. build_and_send ( 1 , packet_size, & mut |new_packet : & mut [ u8 ] | {
230- new_packet. copy_from_slice ( packet_bytes) ;
231- } ) ;
232-
233- match send_result {
234- Some ( Ok ( ( ) ) ) => {
235- // Packet sent successfully
236- }
237- Some ( Err ( e) ) => {
238- return Err ( PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( format ! (
239- "Failed to send packet: {}" ,
240- e
241- ) ) ) ;
242- }
243- None => {
244- return Err ( PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > (
245- "DataLinkSender has been closed" ,
246- ) ) ;
247- }
248- }
249- }
322+ // Send the packet
323+ tx. send_to ( ethernet_packet. packet ( ) , None )
324+ . ok_or_else ( || {
325+ PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( "Failed to send packet" )
326+ } ) ?
327+ . map_err ( |e| {
328+ PyErr :: new :: < pyo3:: exceptions:: PyRuntimeError , _ > ( format ! (
329+ "Failed to send packet: {}" ,
330+ e
331+ ) )
332+ } ) ?;
250333
251334 Ok ( ( ) )
252335 }
0 commit comments