SoFunction
Updated on 2024-11-19

python to send layer 2 packets (link layer frames) using raw sockets

Transmitter code:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import socket
import struct

raw_socket = (socket.PF_PACKET, socket.SOCK_RAW, (0x1234))
raw_socket.bind(("eth0", 0))
packet = ("!6s6sH", "\xff\xff\xff\xff\xff\xff", "\xaa\xaa\xaa\xaa\xaa\xaa", 0x1234)
while True:
 print repr(packet)
 raw_socket.send(packet + "hello,world!")

1. Create a socket using the address family PF_PACKET, type SOCK_RAW, custom type 0x1234, this is exactly the same as the C language. Custom type we can also use 0X0800, this is ETH_P_IP, equivalent to our simulation of ip packet to send, then ip packet header and mac packet header need to fill in our own. Now we use 0x1234, a protocol type other than the system definition.

2. As it is sending Layer 2 packets, our default NIC is not configured for networking, that is, the ping does not work, and it is directly bound to the NIC.

mac package header structure defined in the kernel

struct ethhdr
{
 unsigned char h_dest[6];
 unsigned char h_source[6];
 uint16_t h_proto; //0x1234
};

The first is the destination mac address, the second is the local mac address, and the third is a custom type that must be filled in so that when the other side also cares about this custom type, the protocol stack receives a layer 2 packet to give it to the other side's socket correctly. Through this structure, so the pack is used, "!6s6sH". I'm using a broadcast address send here.
Receiver code:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import socket
import struct

raw_socket = (socket.PF_PACKET,socket.SOCK_RAW,(0x1234))
while True :
 packet = raw_socket.recv(1024)
 data = ("!6s6sH12s", packet)
 print repr(data[0])
 print repr(data[1])
 print repr(data[2])
 print repr(data[3])

This above python using raw sockets to send layer 2 packets (link layer frames) is all I have to share with you, I hope it will give you a reference, and I hope you will support me more.