/* An example packet sniffer for Linux 2.4 Version 3.0 By j00n1x (c) 2003 This packet sniffer allows a bind to a specific network device before sniffing. Also sets promiscuous mode to sniff all traffic reaching that network device. Now can read and decode ethernet frames! This program requires superuser (root). Note: It uses pf_packet/sock_dgram. */ #define DEVICE "eth0" // standard C include files #include #include #include // unix header files #include // for write(), close() // BSD socket header files #include #include // resolver header files #include #include // hostname to ip address conversion functions #include // raw packet files - IP #include // pf_packet files #include #include #include #include // netdevice(7) #include #include void dump_packet(char *buf, int len) { int i; for (i = 0; i < len; i++) { printf("%02X ", (int) (buf[i] & 0xff)); } printf("\n\n"); } void dump_eth_header(struct ethhdr *ethh) { int i; for (i = 0; i < ETH_ALEN; i++) { printf("%02X:", (int) (ethh->h_source[i] & 0xff)); } printf(" -> "); for (i = 0; i < ETH_ALEN; i++) { printf("%02X:", (int) (ethh->h_dest[i] & 0xff)); } printf("\n"); } void dump_ip_header(struct iphdr *iph) { struct sockaddr_in to; char source[1024], dest[1024]; // source/dest ip address struct protoent *pent; char protocol[1024]; char *p; // convert our data into strings, so we can // print them out 'nicely' to.sin_addr.s_addr = iph->saddr; p = inet_ntoa(to.sin_addr); strcpy(source, p); to.sin_addr.s_addr = iph->daddr; p = inet_ntoa(to.sin_addr); strcpy(dest, p); pent = getprotobynumber(iph->protocol); if (!pent) { perror("getprotobynumber"); strcpy(protocol, ""); } else { strcpy(protocol, pent->p_name); } // print out details printf("%s -> %s\n", source, dest); printf("version: %d\t", iph->version); printf("ihl: %d\t", iph->ihl); printf("tos: %d\t", iph->tos); printf("tot_len: %d\t", ntohs(iph->tot_len)); printf("id: %d\t", ntohs(iph->id)); printf("frag_off: %d\n", ntohs(iph->frag_off)); printf("ttl: %d\t", iph->ttl); if (pent) printf("protocol: %d (%s)\t", iph->protocol, protocol); else printf("protocol: %d\t", iph->protocol); printf("check: %d\t", ntohs(iph->check)); printf("\n\n"); } int main(int argc, char **argv) { int fd; char buf[1024*64]; struct iphdr *iph; struct sockaddr_ll eth; struct ifreq ifr; struct packet_mreq pmreq; struct ethhdr *ethh; fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (fd < 0) { perror("socket"); exit(1); } // find DEVICE's ifindex -- man 7 netdevice strcpy(ifr.ifr_name, DEVICE); if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl"); exit(1); } printf("ifindex: %d\n", ifr.ifr_ifindex); // bind to DEVICE, using bind() - man 7 packet memset(ð, 0, sizeof(eth)); eth.sll_family = AF_PACKET; eth.sll_protocol = htons(ETH_P_ALL); eth.sll_ifindex = ifr.ifr_ifindex; eth.sll_hatype = ARPHRD_VOID; eth.sll_pkttype = PACKET_HOST; // eth.sll_pkttype = PACKET_OUTGOING; // doesn't seem to work eth.sll_halen = 0; if (bind(fd, (struct sockaddr *) ð, sizeof(eth)) < 0) { perror("bind"); exit(1); } // set promiscuous mode - man 7 packet pmreq.mr_ifindex = ifr.ifr_ifindex; pmreq.mr_type = PACKET_MR_PROMISC; pmreq.mr_alen = 0; if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &pmreq, sizeof(pmreq)) < 0) { perror("setsockopt"); exit(1); } // main loop while (1) { memset(buf, 0, sizeof(buf)); if (recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL) < 0) { perror("recvfrom"); } // setup pointers to point inside buffer ethh = (void *) buf; iph = (void *) buf + sizeof(struct ethhdr); if (ethh->h_proto == htons(ETH_P_IP)) { dump_eth_header(ethh); dump_ip_header(iph); } // dump_packet(buf, 100); } close(fd); return 0; }