- /* snooper.c 
-  * 
-  * Copyright (c) 2000 Sean Walton and Macmillan Publishers.  Use may be in 
-  * whole or in part in accordance to the General Public License (GPL). 
-  * 
-  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
-  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
-  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
-  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
-  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
-  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
-  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
-  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
-  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
-  * SUCH DAMAGE. 
- */ 
-   
- /*****************************************************************************/ 
- /*** snooper.c                                                             ***/ 
- /***                                                                       ***/ 
- /*** This program captures *all* packets that the network interface sees.  ***/ 
- /*** Be very careful with this tool, because you may see all lot of info.  ***/ 
- /*** Also, it uses the deprecated SOCK_PACKET socket type.  The newer and  ***/ 
- /*** preferred method is with PF_PACKET.                                   ***/ 
- /*****************************************************************************/ 
-   
- #include <stdio.h> 
- #include <sys/socket.h> 
- #include <resolv.h> 
- #include <arpa/inet.h> 
- #include <errno.h> 
- #include <sys/types.h> 
- #include <linux/if_ether.h> 
-   
- #define IP_SIZE    4 
- #define ETH_SIZE  6 
-   
- typedef enum { eETH_ADDR, eIP_ADDR } EAddress; 
-   
- typedef unsigned char uchar; 
-   
- /*--------------------------------------------------------------------*/ 
- /* Ethernet Frame                                                     */ 
- /*                                                                    */ 
- /* This structure defines the fields within the ethernet frame. Since */ 
- /* this programs gets the lowest-level packet, fragmented packets are */ 
- /* not reassembled.  The first few fields contain the MAC addresses   */ 
- /* of the source and destination. Note that this structure is set for */ 
- /* little-endian format.                                              */ 
- /*--------------------------------------------------------------------*/ 
- struct ip_packet { 
-   struct { 
-     uchar dst_eth[ETH_SIZE]; 
-     uchar src_eth[ETH_SIZE]; 
-     uchar __unknwn[2]; 
-   } hw_header;             /* hardware header */ 
-     uint header_len:4;       /* header length in words in 32bit words */ 
-     uint version:4;          /* 4-bit version */ 
-     uint serve_type:8;       /* how to service packet */ 
-     uint packet_len:16;      /* total size of packet in bytes */ 
-     uint ID:16;              /* fragment ID */ 
-     uint frag_offset:13;     /* to help reassembly */ 
-     uint more_frags:1;       /* flag for "more frags to follow" */ 
-     uint dont_frag:1;        /* flag to permit fragmentation */ 
-     uint __reserved:1;       /* always zero */ 
-     uint time_to_live:8;     /* maximum router hop count */ 
-     uint protocol:8;         /* ICMP, UDP, TCP */ 
-     uint hdr_chksum:16;      /* ones-comp. checksum of header */ 
-     uchar IPv4_src[IP_SIZE]; /* IP address of originator */ 
-     uchar IPv4_dst[IP_SIZE]; /* IP address of destination */ 
-     uchar options[0];        /* up to 40 bytes */ 
-     uchar data[0];           /* message data up to 64KB */ 
- }; 
-   
- /*--------------------------------------------------------------------*/ 
- /* dump                                                               */ 
- /*                                                                    */ 
- /* Dump a block of data in hex & ascii.                               */ 
- /*--------------------------------------------------------------------*/ 
- void dump(void* b, int len) 
- {   unsigned char *buf = b; 
-     int i, cnt=0; 
-     char str[17]; 
-     memset(str, 0, 17); 
-     for ( i = 0; i < len; i++ ) 
-     { 
-         if ( cnt % 16 == 0 ) 
-         { 
-             printf("  %s\n%04X: ", str, cnt); 
-             memset(str, 0, 17); 
-         } 
-         if ( buf[cnt] < ' '  ||  buf[cnt] >= 127 ) 
-             str[cnt%16] = '.'; 
-         else 
-             str[cnt%16] = buf[cnt]; 
-         printf("%02X ", buf[cnt++]); 
-     } 
-     printf("  %*s\n\n", 16+(16-len%16)*2, str); 
- } 
-   
- /*--------------------------------------------------------------------*/ 
- /* PrintAddr                                                          */ 
- /*                                                                    */ 
- /* Print the different types of address (MAC or IP).                  */ 
- /*--------------------------------------------------------------------*/ 
- void PrintAddr(char* msg, uchar *addr, EAddress is_ip) 
- {  int i; 
-   static struct { 
-     int len; 
-     char *fmt; 
-     char delim; 
-   } addr_fmt[] = {{ETH_SIZE, "%x", ':'}, {IP_SIZE, "%d", '.'}}; 
-   
-   printf("%s", msg); 
-   for ( i = 0; i < addr_fmt[is_ip].len; i++ ) 
-   { 
-     printf(addr_fmt[is_ip].fmt, addr[i]); 
-     if ( i < addr_fmt[is_ip].len-1 ) 
-       putchar(addr_fmt[is_ip].delim); 
-   } 
- } 
-   
- /*--------------------------------------------------------------------*/ 
- /* GetProtocol                                                        */ 
- /*                                                                    */ 
- /* Convert the protocol value into the alphabetic representation.     */ 
- /*--------------------------------------------------------------------*/ 
- char* GetProtocol(int value) 
- { 
-   switch (value) 
-   { 
-     case IPPROTO_IP: return "IP"; 
-     case IPPROTO_ICMP: return "ICMP"; 
-     case IPPROTO_IGMP: return "IGMP"; 
-     case IPPROTO_IPIP: return "IPIP"; 
-     case IPPROTO_TCP: return "TCP"; 
-     case IPPROTO_EGP: return "EGP"; 
-     case IPPROTO_PUP: return "PUP"; 
-     case IPPROTO_UDP: return "UDP"; 
-     case IPPROTO_IDP: return "IDP"; 
-     case IPPROTO_RSVP: return "RSVP"; 
-     case IPPROTO_GRE: return "GRE"; 
-     case IPPROTO_IPV6: return "IPV6/4"; 
-     case IPPROTO_PIM: return "PIM"; 
-     case IPPROTO_RAW: return "RAW"; 
-     default: return "???"; 
-   } 
- } 
-   
- /*--------------------------------------------------------------------*/ 
- /* DumpPacket                                                         */ 
- /*                                                                    */ 
- /* Display the read packet with data and fields.                      */ 
- /*--------------------------------------------------------------------*/ 
- void DumpPacket(char *buffer, int len) 
- {  struct ip_packet *ip=(void*)buffer; 
-   
-   printf("-------------------------------------------------\n"); 
-   dump(buffer, len); 
-   PrintAddr("Destination EtherID=", ip->hw_header.dst_eth, eETH_ADDR); 
-   PrintAddr(", Source EtherID=", ip->hw_header.src_eth, eETH_ADDR); 
-   printf("\nIPv%d: header-len=%d, type=%d, packet-size=%d, ID=%d\n", 
-     ip->version, ip->header_len*4, ip->serve_type, 
-     ntohs(ip->packet_len), ntohs(ip->ID)); 
-   printf("frag=%c, more=%c, offset=%d, TTL=%d, protocol=%s\n", 
-     (ip->dont_frag? 'N': 'Y'), 
-     (ip->more_frags? 'N': 'Y'), 
-     ip->frag_offset, 
-     ip->time_to_live, GetProtocol(ip->protocol)); 
-   printf("checksum=%d, ", ntohs(ip->hdr_chksum)); 
-   PrintAddr("source=", ip->IPv4_src, eIP_ADDR); 
-   PrintAddr(", destination=", ip->IPv4_dst, eIP_ADDR); 
-   printf("\n"); 
-   fflush(stdout); 
- } 
-   
- void PANIC(char *msg); 
- #define PANIC(msg)  {perror(msg);exit(0);} 
-   
- /*--------------------------------------------------------------------*/ 
- /* main                                                               */ 
- /*                                                                    */ 
- /* Open socket.  Repeatedly read and display records.                 */ 
- /*--------------------------------------------------------------------*/ 
- int main() 
- {   int sd, bytes_read; 
-     char data[1024]; 
-   
-     sd  = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); 
-     if ( sd < 0 ) 
-     PANIC("Snooper socket"); 
-     do 
-   { 
-       bytes_read = recvfrom(sd, data, sizeof(data), 0, 0, 0); 
-         if ( bytes_read > 0 ) 
-       DumpPacket(data, bytes_read); 
-     } 
-   while ( bytes_read > 0 ); 
-     return 0; 
- } 
-   
-