/* * IPv4 packet sniffer for Linux 2.x * * Copyright (C) 2002 Christophe Devine * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #define ETH_P_ALL 0x0003 #define ETH_P_IP 0x0800 int main( int argc, char *argv[] ) { unsigned char buffer[4096]; unsigned short sport, dport; int raw_sock, buflen, fromlen; struct sockaddr_ll sll, from; struct packet_mreq mr; struct ifreq ifr; struct in_addr src, dst; struct icmphdr *icmp; struct udphdr *udp; struct tcphdr *tcp; struct iphdr *ip; struct tm *lt; time_t tt; /* check the argument */ if( argc != 2 ) { printf( "usage: %s \n", argv[0] ); return( 1 ); } /* create the raw socket */ if( ( raw_sock = socket( PF_PACKET, SOCK_DGRAM, htons( ETH_P_ALL ) ) ) == -1 ) { perror( "socket" ); return( 1 ); } /* find the interface index */ memset( &ifr, 0, sizeof( ifr ) ); strncpy( ifr.ifr_name, argv[1], sizeof( ifr.ifr_name ) ); if( ioctl( raw_sock, SIOCGIFINDEX, &ifr ) == -1 ) { perror( "ioctl(SIOCGIFINDEX)" ); return( 1 ); } /* this raw socket will receive all ethernet packets */ memset( &sll, 0, sizeof( sll ) ); sll.sll_family = AF_PACKET; sll.sll_ifindex = ifr.ifr_ifindex; sll.sll_protocol = htons( ETH_P_ALL ); /* bind the raw socket to the interface */ if( bind( raw_sock, (struct sockaddr *) &sll, sizeof( sll ) ) == -1 ) { perror( "bind" ); return( 1 ); } /* enable promiscuous mode */ memset( &mr, 0, sizeof( mr ) ); mr.mr_ifindex = ifr.ifr_ifindex; mr.mr_type = PACKET_MR_PROMISC; if( setsockopt( raw_sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof( mr ) ) == -1 ) { perror( "setsockopt" ); return( 1 ); } while( 1 ) { /* wait for packets */ fromlen = sizeof( from ); if( ( buflen = recvfrom( raw_sock, buffer, 4096, 0, (struct sockaddr *) &from, &fromlen ) ) == -1 ) { perror( "recvfrom" ); return( 1 ); } /* skip duplicate packets on the loopback interface */ if( ! strcmp( argv[1], "lo" ) && from.sll_pkttype == PACKET_OUTGOING ) { continue; } /* verify the socket family */ if( from.sll_family != AF_PACKET ) { printf( "socket family is %d, should be %d (AF_PACKET)\n", from.sll_protocol, AF_PACKET ); continue; } /* we're only interested in standard IPv4 packets */ if( ntohs( from.sll_protocol ) != ETH_P_IP ) { continue; } /* have a look inside the IP header */ ip = (struct iphdr *) buffer; src.s_addr = ip->saddr; dst.s_addr = ip->daddr; /* print the local time */ tt = time( 0 ); lt = localtime( &tt ); printf( "%02d-%02d %02d:%02d:%02d ", lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec ); switch( ip->protocol ) { case SOL_TCP: printf( " TCP: " ); tcp = (struct tcphdr *) \ ( (void *) ip + sizeof( struct iphdr ) ); /* grab source and destination port */ sport = htons( tcp->source ); dport = htons( tcp->dest ); common: /* and print the most interesting informations */ printf( "%15s : %-5d", inet_ntoa( src ), sport ); printf( " -> " ); printf( "%15s : %-5d", inet_ntoa( dst ), dport ); printf( " %4d\n", buflen ); break; case SOL_UDP: udp = (struct udphdr *) \ ( (void *) ip + sizeof( struct iphdr ) ); printf( " UDP: " ); sport = htons( udp->source ); dport = htons( udp->dest ); goto common; case 1: /* SOL_ICMP */ icmp = (struct icmphdr *) \ ( (void *) ip + sizeof( struct iphdr ) ); printf( "ICMP: " ); sport = icmp->type; dport = icmp->code; goto common; default : printf( "unsupported IP protocol %d\n", ip->protocol ); break; } } return( 0 ); }