Help with custom packets over raw sockets

Hi,

I’m trying to write some custom packets (That I have already created and verified they are valid) to the network, I have tried using both tap interfaces and raw sockets.

I created the raw socket following this thread Linux raw socket, I can read packets from this io, but when I try to write packets to it they don’t seem to make it onto the network (I am observing with wireshark if that makes a difference) - Can anybody provide me with some insight on why this isn’t working? It currently blocking the progression of my dissertation project…

Thanks.

I have resolved this, and figure I will leave my solution here for the next person.

Firstly we create the socket:

function get_socket()::IOStream
    #fd = ccall(:socket, Cint, (Cint, Cint, Cint), AF_PACKET, SOCK_RAW, hton(IPPROTO_RAW))
    fd = ccall(:socket, Cint, (Cint, Cint, Cint), Int32(17), Int32(3), 0xff00)
    if fd == -1
        @error "Failed to open socket" errno=Base.Libc.errno()
    end
    return fdio(fd)
end

Then in order to send data we need to use the sendto() function sendto(2), and to do that across a connectionless socket (like a raw socket) you’ll need to create a sockaddr_ll struct:

struct Sockaddr_ll
    sll_family::Cushort
    sll_protocol::Cushort
    sll_ifindex::Cint
    sll_hatype::Cushort
    sll_pkttype::Cuchar
    sll_halen::Cuchar
    sll_addr::NTuple{6, Cuchar}
end

and the sendto ccall too:

    bytes = ccall(:sendto, Cint, (Cint, Ptr{UInt8}, Csize_t, Cint, Ptr{Sockaddr_ll}, Cint), sockfd, packet, length(packet), 0, Ref(sockaddr_ll), sizeof(sockaddr_ll))

where sockfd is the output of get_socket(), packet is a Vector{UInt8}.

In my implementation I have hard-coded the values of Sockaddr_ll (other than interface and addr):

    function Sockaddr_ll(;
        sll_family::Cushort=hton(UInt16(3)),#hton(AF_PACKET),
        sll_protocol::Cushort=hton(0x0800),#hton(ETH_P_IP),
        sll_ifindex::Cint, # Interface id here
        sll_hatype::Cushort=hton(Cushort(1)),#hton(ARPHRD_ETHER),
        sll_pkttype::Cuchar=Cuchar(0), # This field doesn't matter for sending packets
        sll_halen::Cuchar=Cuchar(6),#ETH_ALEN,
        sll_addr::NTuple{6, Cuchar} # Mac address here
    )
        new(sll_family, sll_protocol, sll_ifindex, sll_hatype, sll_pkttype, sll_halen, sll_addr)
    end

You can use the if_nametoindex function from c to get the interface name.