#include "pcap.h"
#include "mysniffer.h"
#include "decode.h"/* 以太贞 头定义 */
typedef struct Ether_HEADER
{
    u_char ether_dst[6];
    u_char ether_src[6];
    u_short ether_type;}Ether_HEADER;/* 4 BIT的IP头定义 */
typedef struct IP_ADDRESS
{
u_char byte1;
u_char byte2;
u_char byte3;
u_char byte4;
}IP_ADDRESS;/* IPv4 头的定义 */
typedef struct IP_HEADER
{
u_char ver_ihl;   // 4 bit的版本信息 + 4 bits的头长
u_char tos;       // TOS类型 
u_short tlen;     // 总长度
u_short identification; // Identification
u_short flags_fo;   // Flags (3 bits) + Fragment offset (13 bits)
u_char ttl;       // 生存期
u_char proto;     // 后面的协议信息
u_short crc;       // 校验和
IP_ADDRESS saddr;   // 源IP
IP_ADDRESS daddr;   // 目的IP
u_int   op_pad;     // Option + Padding
}IP_HEADER;/* UDP header*/
typedef struct UDP_HEADER
{
u_short sport;     // Source port
u_short dport;     // Destination port
u_short len;       // Datagram length
u_short crc;       // Checksum
}UDP_HEADER;/* TCP header*/
typedef   struct  TCP_HEADER //定义TCP首部   
{   
u_short sport; //16位源端口   
u_short dport; //16位目的端口   
u_int seq; //32位序列号   
u_int ack; //32位确认号   
u_char lenres; //4位首部长度/6位保留字   
u_char flag; //6位标志位   
u_short win; //16位窗口大小   
u_short sum; //16位校验和   
u_short urp; //16位紧急数据偏移量   
}TCP_HEADER; typedef struct PACKET
{    
    Ether_HEADER *eh;            
    IP_HEADER *iph;   
    TCP_HEADER *tcph;
UDP_HEADER *udph;   

    u_char *data; /* packet payload pointer */
    u_short  dsize; /* packet payload size */    char timesec[16]; /* time(秒) */ 
int timeusec; /* time(毫秒)*/ }PACKET;main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
u_int netmask;
char packet_filter[] = "ip and ( tcp or udp)";//and (port 80 or 8080 or 21 or 25 or 110
struct bpf_program fcode; /* Retrieve the device list */
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
  fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
  exit(1);
} /* Print the list */
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 WinPcap 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;
} /* Jump to the selected adapter */
for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); /* Open the adapter */
if ( (adhandle= pcap_open_live(d->name, // name of the device
65536,   // portion of the packet to capture. 
// 65536 grants that the whole packet will be captured on all the MACs.
1,     // promiscuous mode
1000,   // read timeout
errbuf   // error buffer
) ) == NULL)
{
  fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n");
  /* Free the device list */
  pcap_freealldevs(alldevs);
  return -1;
} /* Check the link layer. We support only Ethernet for simplicity. */
if(pcap_datalink(adhandle) != DLT_EN10MB)
{
  fprintf(stderr,"\nThis program works only on Ethernet networks.\n");
  /* Free the device list */
  pcap_freealldevs(alldevs);
  return -1;
} if(d->addresses != NULL)
  /* Retrieve the mask of the first address of the interface */
  netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
  /* If the interface is without addresses we suppose to be in a C class network */
  netmask=0xffffff; 
//compile the filter
if(pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 ){
  fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
  /* Free the device list */
  pcap_freealldevs(alldevs);
  return -1;
} //set the filter
if(pcap_setfilter(adhandle, &fcode)<0){
  fprintf(stderr,"\nError setting the filter.\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); /* start the capture */
pcap_loop(adhandle, 0, packet_handler, NULL); return 0;
}/* Callback function invoked by libpcap for every incoming packet */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
struct tm *ltime;
char timestr[16];
PACKET *p; u_int ip_len;
u_short sport,dport; /* convert the timestamp to readable format */
ltime=localtime(&header->ts.tv_sec);
strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); /* print timestamp and length of the packet */
printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec, header->len);
     //得到以太贞头部
p->eh = (Ether_HEADER *)pkt_data;//运行到此处时出问题,请关注 /* 找到IP头部 */
p->iph = (IP_HEADER *)(pkt_data + 14); //14为以太头的长度 //得到ip头的长度
ip_len = (p->iph->ver_ihl & 0xf) * 4; //判断上层协议是tcp或udp,之后在得到相应的头部
switch( p->iph->proto )
{
case 6:
p->udph = (UDP_HEADER *) ((u_char*)p->iph + ip_len);
return; case 17:
p->tcph = (TCP_HEADER *) ((u_char*)p->iph + ip_len);
return; default:
printf("neither tcp nor udp protocl");
return;
}
/* 将端口信息从网络型转变为主机顺序 */
switch( p->iph->proto )
{
case 6:
sport = ntohs( p->tcph->sport );
dport = ntohs( p->tcph->dport );
return; case 17:
sport = ntohs( p->udph->sport );
dport = ntohs( p->udph->dport );
return; default:
sport = dport = 0;
return;
}
/* print ip addresses and udp ports */
printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n",
  p->iph->saddr.byte1,
  p->iph->saddr.byte2,
  p->iph->saddr.byte3,
  p->iph->saddr.byte4,
  sport,
  p->iph->daddr.byte1,
  p->iph->daddr.byte2,
  p->iph->daddr.byte3,
  p->iph->daddr.byte4,
  dport);
printf("[%u]",p->iph->proto);
}

解决方案 »

  1.   

    出错报告:
    运行到  p->eh = (Ether_HEADER *)pkt_data;  时
    eh  cxx0030:error:expression cannot be evaluated //调试时的错误信息
      

  2.   

    Ether_HEADER *eh;
    eh=(Ether_HEADER *)pkt_data;
      

  3.   

    1、void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
    你在这个函数里面使用的抓包存储u_char指针,最好先定义好,并初始化好!!!
    2、准备把包头以太头部数据保存入eh最好这么写:
    u_char tmpbuf[100];
    memset(tmpbuf,0,sizeof(tmpbuf));
    memcpy(tmpbuf,pkt_data,sizeof(Ether_HEADER));
    p->eh=tmpbuf;