Created
December 8, 2024 19:43
-
-
Save tristan-white/f0712db5aa449dd4c655c1f6163f74bd to your computer and use it in GitHub Desktop.
Simple C program to listen for any incoming packet of any protocol (includes ethernet header; does not strip layer 2).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** This code shows how to create raw socket in C that listens for any | |
| * incoming packet of any protocol. Comments added anywhere someone | |
| * familiar with C socket programming (but not raw sockets) may have | |
| * questions. | |
| * | |
| * Assumes you're already familiar with | |
| * socket programming. For info/intro on socket programming, check out: | |
| * https://beej.us/guide/bgnet/ | |
| * | |
| * Reccomended reading for raw socket programming: | |
| * - man 7 ip | |
| * - man packet | |
| * | |
| * The _DEFAULT_SOURCE macro help vscode's intellisense work properly; | |
| * very handy when working with large struct in network programming. | |
| * See https://stackoverflow.com/questions/74823127/vscode-c-c-intellisense-issue-with-netinet-ip-h | |
| */ | |
| #ifndef _DEFAULT_SOURCE | |
| #define _DEFAULT_SOURCE | |
| #endif // _DEFAULT_SOURCE | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <arpa/inet.h> | |
| #include <netinet/ip.h> | |
| #include <netinet/ether.h> | |
| #include <sys/socket.h> | |
| #include <net/ethernet.h> | |
| #include <netpacket/packet.h> | |
| void print_packet_info(const unsigned char *packet, int packet_len) { | |
| // struct ether_header defined in <netinet/ethernet.h> | |
| struct ether_header *eth_header = (struct ether_header *)packet; | |
| // struct ip defined in <netinet/ip.h> | |
| struct ip *ip_header; // newer version of up struct is the iphdr struct | |
| // Print MAC addresses | |
| printf("Source MAC: %s\n", ether_ntoa((struct ether_addr *)eth_header->ether_shost)); | |
| printf("Destination MAC: %s\n", ether_ntoa((struct ether_addr *)eth_header->ether_dhost)); | |
| // Check if the packet is an IP packet | |
| if (ntohs(eth_header->ether_type) == ETHERTYPE_IP) { | |
| ip_header = (struct ip *)(packet + sizeof(struct ether_header)); | |
| printf("Source IP: %s\n", inet_ntoa(ip_header->ip_src)); | |
| printf("Destination IP: %s\n", inet_ntoa(ip_header->ip_dst)); | |
| } | |
| printf("\n"); | |
| } | |
| int main() { | |
| int sock; | |
| struct sockaddr saddr; | |
| int saddr_len = sizeof(saddr); | |
| unsigned char buffer[65536]; // Buffer to hold the packet | |
| /** Create a raw socket. | |
| * `man packet` has helpful info about these socket() params | |
| * | |
| * AF_PACKET: Specifices socket will be raw. | |
| * SOCK_RAW: Packets are not changed before receipt (eg stripped of | |
| * link layer header). | |
| * ETH_P_ALL: Specifies that all protocols should be received on this | |
| * socket (not just UDP, TCP, etc) | |
| */ | |
| sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); | |
| if (sock < 0) { | |
| perror("Socket creation failed"); | |
| return 1; | |
| } | |
| // Listen for incoming packets | |
| while (1) { | |
| int packet_len = recvfrom(sock, buffer, 65536, 0, &saddr, (socklen_t *)&saddr_len); | |
| if (packet_len < 0) { | |
| perror("Packet receive failed"); | |
| close(sock); | |
| return 1; | |
| } | |
| print_packet_info(buffer, packet_len); | |
| } | |
| // Cleanup | |
| close(sock); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment