/* Copyright (c) 2002 Gianni Tedesco * Released under the terms of the GNU GPL version 2 * mmap() packet socket based packet sniffer */ #ifndef __linux__ #error "Are you loco? This is Linux only!" #endif #include #include #include #define __USE_XOPEN #include #include #include #include /* for the glibc version number */ #if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1 #include #include /* the L2 protocols */ #else #include #include #include /* The L2 protocols */ #endif #include #include #include #include char *names[]={ "<", /* incoming */ "B", /* broadcast */ "M", /* multicast */ "P", /* promisc */ ">", /* outgoing */ }; int fd=-1; char *map; struct tpacket_req req; struct iovec *ring; void sigproc(int sig) { struct tpacket_stats st; int len=sizeof(st); if (!getsockopt(fd,SOL_PACKET,PACKET_STATISTICS,(char *)&st,&len)) { fprintf(stderr, "recieved %u packets, dropped %u\n", st.tp_packets, st.tp_drops); } if ( map ) munmap(map, req.tp_block_size * req.tp_block_nr); if ( fd>=0 ) close(fd); if ( ring ) free(ring); exit(0); } int main ( int argc, char **argv ) { struct pollfd pfd; struct sockaddr_ll addr; int i; signal(SIGINT, sigproc); /* Open the packet socket */ if ( (fd=socket(PF_PACKET, SOCK_DGRAM, 0))<0 ) { perror("socket()"); return 1; } /* Setup the fd for mmap() ring buffer */ req.tp_block_size=4096; req.tp_frame_size=1024; req.tp_block_nr=64; req.tp_frame_nr=4*64; if ( (setsockopt(fd, SOL_PACKET, PACKET_RX_RING, (char *)&req, sizeof(req))) != 0 ) { perror("setsockopt()"); close(fd); return 1; }; /* mmap() the sucker */ map=mmap(NULL, req.tp_block_size * req.tp_block_nr, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, fd, 0); if ( map==MAP_FAILED ) { perror("mmap()"); close(fd); return 1; } /* Setup our ringbuffer */ ring=malloc(req.tp_frame_nr * sizeof(struct iovec)); for(i=0; itp_mac; printf("%u.%.6u: if%u %s %u bytes\n", h->tp_sec, h->tp_usec, sll->sll_ifindex, names[sll->sll_pkttype], h->tp_len); /* tell the kernel this packet is done with */ h->tp_status=0; mb(); /* memory barrier */ i=(i==req.tp_frame_nr-1) ? 0 : i+1; } /* Sleep when nothings happening */ pfd.fd=fd; pfd.events=POLLIN|POLLERR; pfd.revents=0; poll(&pfd, 1, -1); } return 0; }