Writing a Custom Network Snooper
How does tcpdump work? You can read the lengthy Open Source program, or you write your own network snooper (a tcpdump, of sorts). The only thing you need to know is how to capture any and all messages for a host. The tool that this section describes helps you write a network snooper that disassembles packets intended for the host. It does not support promiscuous mode, however.
For security (like tcpdump), you need to be root to run a network snooper. The snooper captures all messages destined for your computer. To get all messages, you use the following calls:
sd = socket(PF_INET, SOCK_PACKET, filter); bytes_read = recvfrom(sd, buffer, sizeof(buffer), 0, 0, 0);
Notice the new socket type: SOCK_PACKET. This is a read-only hardware-level socket.
You can use several filters for SOCK_PACKET. The filters tell the IP layer what kinds of packet you want to capture. A few of these filters are
ETH_P_802_3 |
802.3 frames |
ETH_P_AX25 |
AX.25 frames |
ETH_P_ALL |
All frames (be careful!) |
ETH_P_802_2 |
802.2 frames |
The filter to use is ETH_P_ALL. As the note indicates, be careful with this filter, because when you select it, it gives you everything. The resulting call is
sd = socket(PF_INET, SOCK_PACKET, ETH_P_ALL);
After successfully completing the call, each recvfrom() system call you make returns a network frame (a physical network message). The network frame includes the hardware addresses (for example, the ethernet addresses) and header.
The SOCK_PACKET provides access to the hardware-level frames and all associated data from each transmission. With it you can see how the network subsystem constructs the frames.
You can use the IP structure defined at the beginning of this chapter. However, recall that the storage is hardware-dependent, so the bitfields may be in the wrong order. The structure assumes that bit #0 is the first bit in the frame stream.
The program example on the Web site, snooper.c, rearranges the fields to match the actual hardware frame for a little endian processor (Intel-compatible) and GNU compiler. If you have a different processor (even a different compiler), you may have to tweak the structure.