There is a raw socket type provided in Network.Socket, but near binding sockets there is a comment "Currently only Unix domain sockets and the Internet families are supported". How can I use raw sockets in haskell?
What I am trying to achieve, as working Python code:
import binascii
import socket
# Create raw socket.
ethType = b'FFFF' # 2 bytes, has to be >= 0x0600. FFFF is "unavailable" by IEEE.
sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
sock.bind( ('lo', int(ethType,16)) )
# Create packet.
srcMac = b'000000000000' # 6 bytes
destMac = b'000000000000' # 6 bytes
header = binascii.a2b_hex( destMac + srcMac + ethType ) # 14 bytes
message = b'Hello, World!'
sock.send(header + message)
# Receive such packets
while True: print (sock.recv(65535))
EDIT1:
In Haskell, I use sock <- socket AF_PACKET Raw 0xFFFF to create a socket, but bindSocket requires a SockAddr as an argument, for which available constructors are
SockAddrInet PortNumber HostAddress
SockAddrInet6 PortNumber FlowInfo HostAddress6 ScopeID
SockAddrUnix String
but none of these seems right.
EDIT2: Thanks to a comment by Yuras I got receiving packets to work:
import Network.Socket
sock <- socket AF_PACKET Raw 0xFFFF
recv sock 0xFFFF
EDIT3: Trying to send a packet from a socket without binding it results in an exception:
sock <- socket AF_PACKET Raw 0xFFFF
send sock "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\255\255"
*** Exception: send: does not exist (No such device or address)
This makes sense, because the kernel would not have any clue on which interface to actually transmit the packet. Is there any way to bind a (raw) socket to an interface in Haskell?
AF_PACKET` is supported, as isSOCK_RAW. Looks like a straight forward translation to me. - Don StewartbindSocket. - Don Stewart