I'm trying to read the link-layer packets received by my wifi-card using golang. The program I wrote compiles successfully and runs without any errors, but it seems to be stuck trying to read from the socket (syscall.Recvfrom(fd, data, 0
- At this point to be precise).
What am i doing wrong?
PS: wlx34e894f77905
is the name of my wifi device.
My function which tries to read the packets:
func readFromSocket() {
fd, error := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, syscall.ETH_P_ALL)
if error != nil {
syscall.Close(fd)
panic(error)
}
err := syscall.BindToDevice(fd, "wlx34e894f77905")
if err != nil {
syscall.Close(fd)
panic(err)
}
data := make([]byte, 1024)
for {
syscall.Recvfrom(fd, data, 0)
fmt.Println(data)
}
}
netstat -r
output:
default _gateway 0.0.0.0 UG 0 0 0 wlx34e894f77905
link-local 0.0.0.0 255.255.0.0 U 0 0 0 wlx34e894f77905
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-3d5c8c113e89
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 wlx34e894f77905
s_addr = inet_addr("9.1.2.3"); int rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); Show activity on this post. In bind_using_iface_ip , to bind to any port 0 should be passed. And also if the fd is raw socket then need to pass port as 0 .
An application must use recvfrom to read datagrams from a raw socket. Before you can receive packets on a raw socket, you must bind the socket to the IP address of the interface on which you want to receive packets.
A raw socket is a type of socket that allows access to the underlying transport provider. This topic focuses only on raw sockets and the IPv4 and IPv6 protocols. This is because most other protocols with the exception of ATM do not support raw sockets.
RAW-sockets are an additional type of Internet socket available in addition to the well known DATAGRAM- and STREAM-sockets. They do allow the user to see and manipulate the information used for transmitting the data instead of hiding these details, like it is the case with the usually used STREAM- or DATAGRAM sockets.
Linux offers the capability of raw sockets which allows you to directly create an raw L3/L2 packet bypassing the protocol headers normally generated by OS socket.
Now, with raw sockets, because network-level IP packets do not have a notion of “port”, all packets coming in over the server’s network device can be read. Applications that open raw sockets have to do the work of filtering out packets that are not relevant themselves, by parsing the TCP headers.
Go doesn’t directly support raw sockets through the net package, however, syscalls are available through the syscall package There are two options here: run the program as root 1, or to grant the capability to the executable using setcap:
When the application reads data from that socket, they will only see data that was sent to that particular port. Now, with raw sockets, because network-level IP packets do not have a notion of “port”, all packets coming in over the server’s network device can be read.
like c/c++ code:
sock_raw=socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
so, golang is:
syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, htons(syscall.ETH_P_ALL))
htons(syscall.ETH_P_ALL) => 0x0300 (little endian)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With