现在的位置: 首页 > 综合 > 正文

IP数据包分析与解析

2013年02月05日 ⁄ 综合 ⁄ 共 8023字 ⁄ 字号 评论关闭

版权信息:

本文来自internet,转载这里供网络编程爱好者学习和研究使用,请尊重作者的劳动成果。未经授权而在商业上使用原作者的文章属侵权行为,后果由使用者自负,本人不承担任何法律责任。

 

IP数据包分析与解析

#include "pcap.h"
#include "stdio.h"
/*下边是以太网的协议格式 */
struct ethernet_header
 { 
 
  u_int8_t ether_dhost[6];  /*目的以太地址*/
 u_int8_t ether_shost[6];  /*源以太网地址*/
 u_int16_t ether_type;  /*以太网类型*/
 };
/*ip地址格式*/
typedef u_int32_t in_addr_t;
//struct in_addr
//{
// in_addr_t s_addr;
//};
struct ip_header
 {
 #ifdef WORKS_BIGENDIAN
  u_int8_t ip_version:4,  /*version:4*/
       ip_header_length:4; /*IP协议首部长度*/
 #else
 u_int8_t ip_header_length:4,
       ip_version:4;
 #endif
 u_int8_t ip_tos;   /*TOS服务质量*/
 u_int16_t ip_length;  /*总长度*/
 u_int16_t ip_id;   /*标识*/
 u_int16_t ip_off;   /*偏移*/
 u_int8_t ip_ttl;   /*生存时间*/
 u_int8_t ip_protocol;  /*协议类型*/
 u_int16_t ip_checksum;  /*校验和*/
        struct in_addr  ip_source_address; /*源IP*/
        struct in_addr  ip_destination_address; /*目的IP*/
 };
/*关于tcp头部的定义*/
struct tcp_header
 { 
  u_int16_t tcp_source_port;
  
  u_int16_t tcp_destination_port;
  
  u_int32_t tcp_acknowledgement;
  
  u_int32_t tcp_ack;
 #ifdef WORDS_BIGENDIAN
  u_int8_t tcp_offset:4 ,
     tcp_reserved:4;
 #else
  u_int8_t tcp_reserved:4,
     tcp_offset:4;
 #endif
  u_int8_t tcp_flags;
  
  u_int16_t tcp_windows;
  
  u_int16_t tcp_checksum;
  
  u_int16_t tcp_urgent_pointer;
};
/*下边实现tcp数据包分析的函数定义tcp_protocol_packet_callback*/
void tcp_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr*
packet_header,const u_char* packet_content)
{
 struct tcp_header *tcp_protocol ;     /*tcp协议变量*/
 u_char flags;    /*标记*/
 int header_length;   /*头长度*/
 u_short source_port;   /*源端口*/
 u_short destination_port;  /*目的端口*/
 u_short windows;   /*窗口大小*/
 u_short urgent_pointer;   /*紧急指针*/
 u_int sequence;   /*序列号*/
 u_int acknowledgement;  /*确认号*/
 u_int16_t   checksum;  /*检验和*/
 tcp_protocol=(struct tcp_header *) (packet_content+14+20);  /*获得tcp首部内容*/
 source_port =ntohs(tcp_protocol->tcp_source_port); /*获得源端口号*/
 destination_port =ntohs(tcp_protocol->tcp_destination_port); /*获得目的端口号*/
 header_length =tcp_protocol->tcp_offset *4;   /*获得首部长度*/
 sequence =ntohl(tcp_protocol->tcp_acknowledgement);     
  /*获得序列号*/
 acknowledgement =ntohl(tcp_protocol->tcp_ack);
 windows = ntohs(tcp_protocol->tcp_windows);
 urgent_pointer = ntohs(tcp_protocol->tcp_urgent_pointer);
 flags = tcp_protocol->tcp_flags;
 checksum =ntohs (tcp_protocol->tcp_checksum);
 printf("***************TCP Protocol (Transprot Layer )***************/n");
 printf("Source Port %d/n",source_port);
 printf("Destination Port %d/n",destination_port);
 
    switch (destination_port)
   {
  case 80:printf("Protocol is http ");break;
  
  case 21:printf("Protocol is ftp");break;
  
  case 23:printf("Protocol is telnet ");break;
  
  case 25:printf("Protocol is smtp");break;
  
  case 110:printf("Protocol is pop3");break;
  default :break;
   }
 

 printf("Sequence Number %u /n",sequence);
 printf("Acknowledgement Number %u /n",acknowledgement);
 printf("Header Length %d /n",header_length);
 printf("Reserved  %d /n",tcp_protocol->tcp_reserved);
 printf("Flags:");
 if (flags & 0x08)  printf("PSH");
 if (flags & 0x10)  printf("ACK");
 
 if (flags & 0x02)  printf("SYN");
 if (flags & 0x20)  printf("URG");
 if (flags & 0x01)  printf("FIN");
 if (flags & 0x04)  printf("RST");
 printf("/n");
 printf("Windows Size :%d /n",windows);
 printf("Checksum :%d/n",checksum);
 printf("Urgent pointer :%d/n",urgent_pointer);
}
/*下边实现IP数据包分析的函数定义ethernet_protocol_packet_callback*/
void ip_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr*
packet_header,const u_char* packet_content)
 {
  struct ip_header *ip_protocol;   /*ip协议变量*/
  u_int  header_length;    /*长度*/
  u_int  offset;     /*偏移*/
  u_char  tos;     /*服务质量*/
  u_int16_t checksum;    /*校验和*/
  ip_protocol=(struct ip_header*) (packet_content+14);
       /*获得ip数据包的内容去掉以太头部*/
 
  checksum=ntohs(ip_protocol->ip_checksum);  /*获得校验和*/
  header_length=ip_protocol->ip_header_length*4; /*获得长度*/
  tos=ip_protocol->ip_tos;    /*获得tos*/
  offset=ntohs(ip_protocol->ip_off);   /*获得偏移量*/
 printf("***************IP Protocol network layer***************/n /n");
 printf("IP Version :%d/n",ip_protocol->ip_version);
 printf("Header length :%d/n",header_length);
 printf("Tos :%d/n",tos);
 printf("Total length:%d/n",ntohs(ip_protocol->ip_length));/*获得总长度*/
 printf("Identification:%d/n",ntohs(ip_protocol->ip_id));  /*获得标识*/
 printf("Offset:%d/n",(offset&0x1fff)*8);    /**/
 printf("TTL:%d/n",ip_protocol->ip_ttl);     /*获得ttl*/ 
 printf("protocol:%d/n",ip_protocol->ip_protocol);         /*获得协议类型*/
 
 printf("Header checksum:%d/n",checksum);
 printf("Source address:%s/n",inet_ntoa(ip_protocol->ip_source_address));          /*
获得源ip地址*/
 printf("Destinastion address :%s/n",inet_ntoa(ip_protocol->ip_destination_address));
/*获得目的ip地址*/
 switch(ip_protocol->ip_protocol)
 {
   case 6 :printf("The Transport Layer Protocol is TCP#####################################/n");
        tcp_protocol_packet_callback(argument,packet_header,packet_content);
       
     break; /*协议类型是6代表TCP*/
   case 17:printf("The Transport Layer Protocol is  UDP/n");break;/*17代表UDP*/
    case 1:printf("The Transport Layer Protocol is ICMP/n");break;/*代表ICMP*/
   case 2:printf("The Transport Layer Protocol is IGMP/n");break;/*代表IGMP*/
  default :break;
 }
 }
void ethernet_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr *packet_header,const u_char* packet_content)
 {
 u_short ethernet_type;     /*以太网协议类型*/
 struct ethernet_header *ethernet_protocol;  /*以太网协议变量*/
 u_char *mac_string;
 static int packet_number=1;
 
 printf("*******************************************************************************/n");
 printf("The %d ip packet is captured,/n",packet_number);
 printf("**********ethernet protocol (link Layer)*******************/n");
 ethernet_protocol =(struct ethernet_header *) packet_content;  /*获得一太网协议数据内容*/
 printf("Ethernet type is :/n");
 ethernet_type=ntohs(ethernet_protocol->ether_type);
       /*获得以太网类型*/
  printf("%04x/n",ethernet_type);
  switch(ethernet_type)            /*判断以太网类型的值*/
      {
  case 0x0800 :  printf("The network layer is ip protocol/n");break;
        case 0x0806 :  printf("The network layer is ARP protocol/n");break;
  case 0x8035 :  printf("The network layer is RARP protocol/n");break;
  default: break;
      }
printf("Mac souce address is :/n");
mac_string=ethernet_protocol->ether_shost;
printf("%02x:%02x:%02x:%02x:%02x:%02x:/n",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
/*获得以太网地址*/
 
printf("Mac Destination Address is :/n");
mac_string=ethernet_protocol->ether_dhost;
printf("%02x:%02x:%02x:%02x:%02x:%02x:/n",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
 
/*获得目的端口地址*/
 
  switch (ethernet_type)
 {case 0x0800:   ip_protocol_packet_callback(argument,packet_header,packet_content);break;
  /*如果上层是ip协议,就调用分析ip协议的函数对ip包进行贩治*/ 
  default :break;
        }
 
  packet_number++;
}
 
main()
{
  pcap_if_t  *alldevs;
  pcap_if_t *d;
  int inum=0;
  int i=0;
  pcap_t *adhandle;
  char errbuf[PCAP_ERRBUF_SIZE];
 
  /* 获得网卡的列表 */
  if (pcap_findalldevs(&alldevs, errbuf) == -1)
  {
    fprintf(stderr,"Error in pcap_findalldevs: %s/n", errbuf);
    exit(1);
  }
 
  /* 打印网卡信息 */
  for(d=alldevs; d; d=d->next)
  {
    printf("%d. %s", ++i, d->name);
    if (d->description)
        printf(" (%s)/n", d->description);
    else
        printf(" (No description available)/n");
  }
 
  if(i==0)
  {
    printf("/nNo interfaces found! Make sure LibPcap is installed./n");
    return -1;
  }
 
  printf("Enter the interface number (1-%d):",i);
  scanf("%d", &inum);               //输入要选择打开的网卡号
 
  if(inum < 1 || inum > i) //判断号的合法性
  {
    printf("/nInterface number out of range./n");
    /* Free the device list */
    pcap_freealldevs(alldevs);
    return -1;
  }
 
  /* 找到要选择的网卡结构 */
  for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
 
  /* 打开选择的网卡 */
  if ( (adhandle= pcap_open_live(d->name, /* 设备名称*/
                  65536,   /* portion of the packet to capture.*/
                  /* 65536 grants that the whole packet will be captured on allthe MACs.*/
                  1,       /* 混杂模式*/
                  1000,     /* 读超时为1秒*/
                  errbuf   /* error buffer*/
                  ) ) == NULL)
  {
    fprintf(stderr,"/nUnable to open the adapter. %s is not supported by LibPcap/n");
    /* Free the device list */
    pcap_freealldevs(alldevs);
    return -1;
  }
 
  printf("/nlistening on %s.../n", d->description);
 
  /* At this point, we don't need any more the device list. Free it */
  pcap_freealldevs(alldevs);
 
  /* 开始捕获包 */
  pcap_loop(adhandle, 0, ethernet_protocol_packet_callback, NULL);
 
  return 0;
}

抱歉!评论已关闭.