#include #include #include #include #include #include #include #include #include #include #include #include #include int main(void) { // Create a packet socket errno = 0; int packet_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (packet_socket == -1) { err(1, "socket"); } // Find the index of the network interface struct ifreq ifr; strncpy(ifr.ifr_name, "wlan0", IFNAMSIZ); errno = 0; if (ioctl(packet_socket, SIOCGIFINDEX, &ifr) == -1) { err(1, "ioctl"); } // Bind to the network interface struct sockaddr_ll sll; sll.sll_family = AF_PACKET; sll.sll_protocol = htons(ETH_P_ALL); sll.sll_ifindex = ifr.ifr_ifindex; errno = 0; if (bind(packet_socket, (const struct sockaddr*)&sll, sizeof(sll)) == -1) { err(1, "bind"); } for(;;) { unsigned char frame[1522]; // 1522 is the largest a 802.3 frame can be errno = 0; ssize_t frame_length = recv(packet_socket, frame, sizeof(frame), MSG_TRUNC); if (frame_length == -1) { err(1, "recv"); } // Extract EtherType / length field // 012345 012345 01 // dest source ^^ // It is stored in the network byte order, that is, high byte 1st if (frame_length < 14) { errx(1, "Very weird frame of only %zdB???", frame_length); } uint16_t ethertype = (frame[12] << 8) | frame[13]; const char *ethertype_meaning = NULL; if (ethertype <= 1500) { ethertype_meaning = "packet length"; } else if (ethertype < 0x0600) { ethertype_meaning = "undefined"; } else if (ethertype == 0x0800) { ethertype_meaning = "IPv4"; } else if (ethertype == 0x0806) { ethertype_meaning = "ARP"; } else if (ethertype == 0x86dd) { ethertype_meaning = "IPv6"; } errno = 0; if (ethertype_meaning == NULL) { if (printf("ethertype: %02x%02x, length: %zd\n", ethertype >> 8, ethertype & 0xff, frame_length) == -1) { err(1, "printf"); } } else { if (printf("ethertype: %02x%02x (%s), length: %zd\n", ethertype >> 8, ethertype & 0xff, ethertype_meaning, frame_length) == -1) { err(1, "printf"); } } } return 0; }