极速论坛's Archiver

niuboy 发表于 2009-8-19 23:38

一个用PF_PACKET写的抓包程序sniffer

[code]/*
* capture.c
*
* gcc   -W   -Wall   -Wno-unused   -ggdb   -o   capture   capture.c
*
*/

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <net/if.h>
#include <features.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>
   
#include <signal.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>

#define N 30
#define in
#define out
#define RET_OK 1

#define IP_PROTOCOL_TCP    0x06
#define IP_PROTOCOL_UDP 0x11

#define OFFSET_DMAC    0
#define OFFSET_SMAC    6
#define OFFSET_ETHER    12
#define OFFSET_IP_PROT    23
#define OFFSET_SIP    26
#define OFFSET_DIP    30
#define OFFSET_SPORT    34
#define OFFSET_DPORT    36


#define DEFAULT_DEVICE_NAME "eth0"
/* #define DEFAULT_RECORD_FILENAME "packet.dat" */
   
typedef unsigned   char   uchar;
   
int RecordFile;
int Packet;
int PacketCount   =   0;
/* char *RecordFileName   =   DEFAULT_RECORD_FILENAME; */
char *DeviceName   =   DEFAULT_DEVICE_NAME;
short int DefaultFlag;
struct ifreq ifr;
/**********from handle***************************************************/
typedef enum __ETHER_TYPE {
    ETHER_IP = 0,       /* 0x0800 */
    ETHER_ARP,        /* 0x0806 */
    ETHER_PPP,        /* 0x880b */
    ETHER_MPLS_U,        /* 0x8847 */
    ETHER_MPLS_M,        /* 0x8848 */
    ETHER_PPPOE_DIS,    /* 0x8863 */
    ETHER_PPPOE_SESS,    /* 0x8864 */
    ETHER_EAPOL,        /* 0x888e */
    ETHER_LWAPP,        /* 0x88bb */
    ETHER_MAX         /* 0xffff */
}ETHER_TYPE_T;

uchar* Ether_Type_Desc[] = { \
    "IP", \
    "ARP", \
    "PPP", \
    "MPLS_UNICAST", \
    "MPLS_MULTICAST", \
    "PPPOE_DISCOVERY", \
    "PPPOE_SESSION", \
    "EAPOL", \
    "LWAPP", \
    "Unknown" \
};

typedef enum __IP_PROT_TYPE {
    IP_PROT_TCP = 0,     /* 0x06 */
    IP_PROT_UDP,        /* 0x11 */
    IP_PROT_MAX,        /* 0xFF */
}IP_PROT_TYPE_T;

uchar* Ip_Protocol_Desc[] = { \
    "TCP", \
    "UDP", \
    "Unknown" \
};

typedef enum __UDP_PORT_TYPE {
    UDP_PORT_CAPWAP_C = 0,    /* 0x2fbf */
    UDP_PORT_CAPWAP_D,    /* 0x2fbe */
    UDP_PORT_DNS,        /* 0x35 */
    UDP_PORT_DHCPS,        /* 0x43 */
    UDP_PORT_DHCPC,        /* 0x44 */   
    UDP_PORT_MAX
}UDP_PORT_TYPE_T;

uchar* Udp_Port_Desc[] = { \
    "capwap control", \
    "capwap data", \
    "dns", \
    "dhcp server", \
    "dhcp client", \
    "Unknown" \
};

typedef enum __TCP_PORT_TYPE {
    TCP_PORT_FTP_C = 0,     /* 0x15 */
    TCP_PORT_FTP_D,        /* 0x16 */
    TCP_PORT_TELNET,    /* 0x17 */
    TCP_PORT_SMTP,        /* 0x19 */
    TCP_PORT_HTTP,        /* 0x50 */
    TCP_PORT_MAX
}TCP_PORT_TYPE_T;

uchar* Tcp_Port_Desc[] = { \
    "ftp control", \
    "ftp data", \
    "telnet", \
    "smtp", \
    "http", \
    "Unknown" \
};
int decap(in void * packet,in int totalBytes)
{
    uchar cur;
    uchar cByte;
    ETHER_TYPE_T eType;
    IP_PROT_TYPE_T iType;
    UDP_PORT_TYPE_T uType;
    TCP_PORT_TYPE_T tType;
    int protocol;
    int number = 0;
   
    printf("%-12s:","DST MAC");
    while(number<totalBytes)
    {
        cur = ((uchar*) packet)[number];

        if(number<6)
        {   
            printf("%02x%s", \
                    cur, \
                    number<5?":":"");
            number++;
        }
        else if(number<12)   
        {
            if(number==6)
                printf("\n%-12s:","SRC MAC");
            printf("%02x%s", \
                    cur, \
                    number<11?":":"");
            number++;
        }
        else if(number==12)
        {
            char tmp =((char*) packet)[number+1];

            if(cur==0x08 && tmp == 0x00) eType = ETHER_IP;
            else if (cur==0x08 && tmp == 0x06) eType = ETHER_ARP;
            else eType = ETHER_MAX;
            number += 2;
            printf("\n%-12s:[%s][0x%02x%02x]","ETH TYPE",Ether_Type_Desc[eType],cur,tmp);        
        }
        else
        {
        switch(eType)
        {
        case ETHER_IP:
            if(number==OFFSET_IP_PROT)   
            {
                protocol = (int)cur;
                switch(protocol)
                {
                case 0x06:
                    iType = IP_PROT_TCP;
                    break;
                case 0x11:
                    iType = IP_PROT_UDP;
                    break;
                default:
                    iType = IP_PROT_MAX;
                }
                printf("\n%-12s:[%s][%d]"," IP PROT",Ip_Protocol_Desc[iType],protocol);
            }
            else if(number>=OFFSET_SIP && number<OFFSET_DIP)
            {            
                if(number==OFFSET_SIP)
                    printf("\n%-12s:","SRC IP");
                printf("%d%s", \
                    cur,(number<OFFSET_DIP-1)?".":"");
            }
            else if(number>=OFFSET_DIP && number<OFFSET_DIP+4)
            {
                if(number==OFFSET_DIP)
                    printf("\n%-12s:","DST IP");
                printf("%d%s", \
                    cur,(number<OFFSET_DIP+3)?".":"");
            }
            else if(number>=OFFSET_SPORT && number<OFFSET_DPORT)
            {
                switch(iType)
                {
                case IP_PROT_TCP:
                    number += 1;
                    cByte = ((uchar*)packet)[number];

                    if(0x00==cur&&0x15==cByte) tType = TCP_PORT_FTP_C;
                    else if(0x00==cur&&0x16==cByte) tType = TCP_PORT_FTP_D;
                    else if(0x00==cur&&0x17==cByte) tType = TCP_PORT_TELNET;
                    else if(0x00==cur&&0x50==cByte) tType = TCP_PORT_HTTP;
                    else tType = TCP_PORT_MAX;

                    printf("\n%-12s:[%s][0x%02x%02x]","SRC PORT", \
                        (tType==TCP_PORT_MAX)? "???" : Tcp_Port_Desc[tType],cur,cByte);
                    number += 1;
                    cur = ((uchar*)packet)[number];
                    number += 1;
                    cByte = ((uchar*)packet)[number];
                    
                    if(0x00==cur&&0x15==cByte) tType = TCP_PORT_FTP_C;
                    else if(0x00==cur&&0x16==cByte) tType = TCP_PORT_FTP_D;
                    else if(0x00==cur&&0x17==cByte) tType = TCP_PORT_TELNET;
                    else if(0x00==cur&&0x50==cByte) tType = TCP_PORT_HTTP;
                    else tType = TCP_PORT_MAX;
                    
                    printf("\n%-12s:[%s][0x%02x%02x]","DST PORT", \
                        (tType==TCP_PORT_MAX) ? "???" : Tcp_Port_Desc[tType],cur,cByte);
                    break;
                case IP_PROT_UDP:
                    number += 1;
                    cByte = ((uchar*)packet)[number];

                    if(0x00==cur&&0x35==cByte) uType = UDP_PORT_DNS;
                    else if(0x00==cur&&0x43==cByte) uType = UDP_PORT_DHCPS;
                    else if(0x00==cur&&0x44==cByte) uType = UDP_PORT_DHCPC;
                    else tType = UDP_PORT_MAX;

                    printf("\n%-12s:[%s][0x%02x%02x]","SRC PORT", \
                        uType==UDP_PORT_MAX?"???":Udp_Port_Desc[uType],cur,cByte);
                    
                    number += 1;
                    cur = ((uchar*)packet)[number];
                    number += 1;
                    cByte = ((uchar*)packet)[number];
                    
                    if(0x00==cur&&0x35==cByte) uType = UDP_PORT_DNS;
                    else if(0x00==cur&&0x43==cByte) uType = UDP_PORT_DHCPS;
                    else if(0x00==cur&&0x44==cByte) uType = UDP_PORT_DHCPC;
                    else uType = UDP_PORT_MAX;
                    
                    printf("\n%-12s:[%s][0x%02x%02x]","DST PORT", \
                        uType==UDP_PORT_MAX?"???":Udp_Port_Desc[uType],cur,cByte);
                    break;
                default:
                    ;
                }
            }
            else {}
        break;
   
        case ETHER_ARP:
        break;

        case ETHER_MAX:
        break;

        default:
         break;   
        }
            number++;
        }   
    }
    return RET_OK;
}
/*****************************************************************************/
   
void ArgInit(   int   argc,   char   **argv   )
{
}
   
void Shutdown(   int   signum   )
{
    /*fdatasync(   RecordFile   ); */
/*    close(   RecordFile   ); */
    ifr.ifr_flags   =   DefaultFlag;
    ioctl(   Packet,   SIOCSIFFLAGS,   &ifr   );
    close(   Packet   );
    fprintf(   stdout,   "Capture   %d   packets\n",   PacketCount   );
    exit(   0   );
}
   
void AppInit(   void   )
{
/*    RecordFile   =   open(   RecordFileName,   O_RDWR   |   O_CREAT   |   O_TRUNC   );
    if   (   RecordFile   <   0   )
    {   
        fprintf(   stderr,   "can't   open   record   file   :   [%s]\n",   strerror(errno)   );
        exit(   1   );
    }    */
   
    strcpy(   ifr.ifr_name,   DeviceName   );
    /*fchmod(   RecordFile,   0644   );*/
    signal(   SIGINT,   Shutdown   );
    signal(   SIGTERM,   Shutdown   );
}
   
void PacketInit(   void   )
{
    int r,   flag;
   
    Packet   =   socket(   PF_PACKET,   SOCK_RAW,   htons(ETH_P_ALL)   );
    if   (   Packet   <   0   )
    {   
        fprintf(   stderr,   "socket   failed   :   [%s]\n",   strerror(errno)   );
        exit(   1   );
    }
   
    r   =   ioctl(   Packet,   SIOCGIFFLAGS,   &ifr   );
    if   (   r   <   0   )
    {
        fprintf(   stderr,   "ioctl   failed   :   [%s]\n",   strerror(errno)   );
        close(   Packet   );
        exit(   1   );
    }   
   
    DefaultFlag   =   ifr.ifr_flags;
     ifr.ifr_flags   |=   IFF_PROMISC;
    r   =   ioctl(   Packet,   SIOCSIFFLAGS,   &ifr   );
    if   (   r   <   0   )
    {
        fprintf(   stderr,   "ioctl   failed   :   [%s]\n",   strerror(errno)   );
        close(   Packet   );
        exit(   1   );
     }        
}
   
void CaptureLoop(   void   )
{
    int n;
    int t;
/*    int i=N;*/
    uchar buf[2048];
   
    while( 1 )
    {
        t=0;
        n   =   recvfrom(   Packet,   buf,   sizeof(buf),   0,   NULL,   NULL   );
        if   (   n   <=   0   )
        {
            fprintf(   stderr,   "recvfrom   error   :   [%s]\n",   strerror(errno)   );
            break;
        }        
   
     //    write(   RecordFile,   &n,   sizeof(n)   );
//    write(   RecordFile,   buf,   n   );
    while((n-t)>=16)
        {
            int i;
            printf("[");
            for(i=0;i<16;i++)
                printf("%02x ",buf[t+i]);
            printf("]\t[");
            for(i=0;i<16;i++)
            {
                char ch=buf[t+i];
                if(isalnum(ch))
                    printf("%c",ch);
                else
                    printf(".");
            }
            printf("]\n");
            t+=16;
        }

        if(n>t)
        {
            int i=t;
            printf("[");
            while(i<n)
                printf("%02x ",buf[i++]);
            printf("]");
            i=n-t;
            i=16-i;
            while(i--)
                printf("   ");
            printf("\t[");
            i=t;
            while(i<n)
            {
                char ch=buf[i++];
                if(isalnum(ch))
                    printf("%c",ch);
                else
                    printf(".");
            }
            printf("]\n");
        }
        decap(buf,n);
        printf("\n\n");
    }
        PacketCount++;
    /*    i--;*/
   
/*     fprintf(   stdout,   "Capture   %d   packets\n",   PacketCount   );*/
/*    fdatasync(   RecordFile   );*/
/*     close(   RecordFile   ); */
    ifr.ifr_flags   =   DefaultFlag;
    ioctl(   Packet,   SIOCSIFFLAGS,   &ifr   );
    close(   Packet   );
}
   
int main(   int   argc,   char   **argv   )
{
    ArgInit(   argc,   argv   );
    AppInit();
    PacketInit();
    CaptureLoop();
    return   0;
}   [/code]

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.