/* An example packet sniffer for Linux 2.4 Version 2.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. 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 int main(int argc, char **argv) { int fd; char buf[1024*64]; struct iphdr *iph; struct sockaddr_in to; char source[1024], dest[1024]; // source/dest ip address char *p; struct protoent *pent; char protocol[1024]; struct sockaddr_ll eth; struct ifreq ifr; struct packet_mreq pmreq; fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); 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_IP); 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); } // setup pointers to point inside buffer iph = (void *) buf; // main loop while (1) { if (recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL) < 0) { perror("recvfrom"); } // 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"); } close(fd); return 0; }