Chinaunix首页 | 论坛 | 博客
  • 博客访问: 340008
  • 博文数量: 73
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1293
  • 用 户 组: 普通用户
  • 注册时间: 2013-03-07 11:17
个人简介

爱运动,爱看书,爱生活!

文章分类

全部博文(73)

文章存档

2014年(7)

2013年(66)

分类: LINUX

2013-08-12 18:57:53

1.能抓取ether、IP、TCP、UDP数据报相关信息。
2.少数几个参数没有转换成日常生活中经常使用的。
3.虽然本人不太喜欢一个文件200多行代码,但为了结构清晰,并未分开
4.3.具体就不介绍了,源代码基本上,每一个变量和函数都已经注释清楚

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <arpa/inet.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <pcap/pcap.h>
  7. #include <netinet/if_ether.h>

  8. //各协议端口,用于后续的判断
  9. #define IP 2048
  10. #define TCP 6
  11. #define ICMP 1
  12. #define UDP 17

  13. #define BUFSIZE 200


  14. //Mac头部,总长度14字节
  15. typedef struct ether_hdr
  16. {
  17.     unsigned char dstmac[6]; //目标mac地址
  18.     unsigned char srcmac[6]; //源mac地址
  19.     unsigned short eth_type; //以太网类型
  20.     char data[0];//数据
  21. }ether_hdr;

  22. //IP头部,总长度20字节
  23. typedef struct ip_hdr

  24. {

  25.     #if LITTLE_ENDIAN
  26.     unsigned char ihl:4; //首部长度
  27.     unsigned char version:4; //版本
  28.     #else
  29.     unsigned char version:4; //版本
  30.     unsigned char ihl:4; //首部长度
  31.     #endif
  32.     unsigned char tos; //服务类型
  33.     unsigned short tot_len; //总长度
  34.     unsigned short id; //标志
  35.     unsigned short frag_off; //分片偏移
  36.     unsigned char ttl; //生存时间
  37.     unsigned char protocol; //协议
  38.     unsigned short chk_sum; //检验和
  39.     struct in_addr srcaddr; //源IP地址
  40.     struct in_addr dstaddr; //目的IP地址
  41.     char data[0];//数据
  42. }ip_hdr;

  43. //TCP头部,总长度20字节
  44. typedef struct tcp_hdr

  45. {
  46.     unsigned short src_port; //源端口号
  47.     unsigned short dst_port; //目的端口号
  48.     unsigned int seq_no; //序列号
  49.     unsigned int ack_no; //确认号
  50.     #if LITTLE_ENDIAN
  51.     unsigned char reserved_1:4; //保留6位中的4位首部长度
  52.     unsigned char thl:4; //tcp头部长度
  53.     unsigned char flag:6; //6位标志
  54.     unsigned char reseverd_2:2; //保留6位中的2位
  55.     #else
  56.     unsigned char thl:4; //tcp头部长度
  57.     unsigned char reserved_1:4; //保留6位中的4位首部长度
  58.     unsigned char reseverd_2:2; //保留6位中的2位
  59.     unsigned char flag:6; //6位标志
  60.     #endif
  61.     unsigned short wnd_size; //16位窗口大小
  62.     unsigned short chk_sum; //16位TCP检验和
  63.     unsigned short urgt_p; //16为紧急指针
  64. //    char data[0];
  65. }tcp_hdr;

  66. //UDP头部,总长度8字节
  67. typedef struct udp_hdr
  68. {
  69.     unsigned short src_port; //远端口号
  70.     unsigned short dst_port; //目的端口号
  71.     unsigned short uhl; //udp头部长度
  72.     unsigned short chk_sum; //16位udp检验和

  73. }udp_hdr;

  74. //ICMP头部,总长度4字节
  75. typedef struct icmp_hdr

  76. {
  77.     unsigned char icmp_type; //类型
  78.     unsigned char code; //代码
  79.     unsigned short chk_sum; //16位检验和
  80. }icmp_hdr;

  81. //pcap_loop的回调函数,用于处理捕获的数据包
  82.  void handle(u_char * user,//pcap_loop最后一个参数
  83.         const struct pcap_pkthdr *hp, //获取数据报报头大小
  84.              const u_char * packet); //获取到的数据报

  85. //net_host用于转换设备号和地址掩码的格式
  86. void net_host(int m);
  87. //主函数,编程模型
  88.  main()
  89. {
  90.     char *dev=NULL;//存储当前可用的网络设备名字
  91.     char errbuf[PCAP_ERRBUF_SIZE];//存放错误信息的缓冲
  92.     pcap_t *hDC;//打开的监听设备句柄
  93.     int net;//设备号
  94.     int mask;//地址掩码
  95.     int time_out=100;//延时
  96.     int r;
  97.     struct bpf_program fp;

  98.     //1.获取当前可用的网络设备
  99.     dev=pcap_lookupdev(errbuf);
  100.     if(dev==NULL){
  101.         printf("::%s\n",errbuf);
  102.         exit(-1);
  103.     }
  104.     //2.获取可用设备的设备号和地址掩码
  105.     r=pcap_lookupnet(dev, &net, &mask,errbuf);
  106.     if(r==-1){
  107.         printf("::%s\n",errbuf);
  108.         exit(-1);
  109.     }
  110.     //3打开设备
  111.     hDC=pcap_open_live(dev, //设备名
  112.                             BUFSIZE,//获取数据报的最大大小
  113.          0,// 是否使用混杂模式
  114.                             100,//延时时间
  115.                             errbuf);//错误信息
  116.     if(hDC==NULL){
  117.         printf("::%s\n",errbuf);
  118.     }
  119.     //打印设备、网络号和地址掩码
  120.     printf("*****************************************\n");
  121.     printf("****网络设备名:%s\n",dev);
  122.     printf("****网络号:");
  123.     net_host(net);
  124.     printf("****地址掩码:");
  125.     net_host(mask);
  126.     printf("*****************************************\n");
  127.     printf("*******************************************\n");

  128.     //4设置规则编译
  129.     r= pcap_compile(hDC,&fp,//规则返回结构体
  130.                    NULL,//规则,可以指定为相应的协议,tcp,udp等,NULL表示全部数据报
  131.                         1,//优化
  132.                         mask);

  133.     if(r==-1){
  134.         printf("::%s\n",pcap_geterr(hDC));
  135.         exit(-1);
  136.     }
  137.     //5处理
  138.     r=pcap_loop(hDC,
  139.      0,//表示处理的最大数据报大小,0 -1表示处理所有数据
  140.                     handle,//受到数据后的回调函数
  141.                     NULL);//传递给回调函数的第一个参数
  142.     if(r==-1){
  143.         printf("::loop error\n");
  144.         exit(-1);
  145.     }
  146.     

  147. }

  148. //格式转换函数

  149. void net_host(int m)
  150. {
  151.     int one, two, three, four;
  152.     one = m;
  153.     one = one >> 24;
  154.     two = m;
  155.     two = two >> 16;
  156.     two = two & 0xff;
  157.     three =m;
  158.     three = three >> 8;
  159.     three = three & 0xff;
  160.     four = m;
  161.     four = four & 0xff;
  162.     printf ("%u.%u.%u.%u\n", four, three, two, one);
  163. }
  164. //数据处理函数
  165. void handle(u_char *user, //pcap_loop的最后一个参数
  166.                 const struct pcap_pkthdr *h,//获取数据报报头大小
  167.             const u_char *packet)//获取到的数据包
  168. {
  169.     ether_hdr *ether;
  170.     ip_hdr *ip;
  171.     int i;
  172.     ether=(ether_hdr*)packet;

  173.     printf("___________________________________________________________\n");
  174.     printf("ether 数据报信息:\n");
  175.     printf("目的MAC:");
  176.     for(i=0;i<6;i++)
  177.     {
  178.         if((ether->dstmac[i])<16)
  179.         printf("0");//以空格分离
  180.         printf("%x",ether->dstmac[i]);
  181.     
  182.     }

  183.     printf("\n");

  184.     printf("源MAC:");
  185.     for(i=0;i<6;i++)
  186.     {
  187.         if((ether->srcmac[i])<16)
  188.         printf("0");//以空格分离
  189.         printf("%x",ether->srcmac[i]);
  190.     }
  191.     printf("\n");

  192.     printf("_________________________________________________________\n");

  193.     if(ntohs(ether->eth_type)==IP)//以太网采用IP数据报
  194.     {
  195.         ip=(ip_hdr*)ether->data;
  196.         struct in_addr srcdr;//
  197.         srcdr=ip->srcaddr;
  198.         struct in_addr dstdr;
  199.         dstdr=ip->dstaddr;
  200.         printf("###################################################\n");
  201.         printf("IP数据信息:\n");
  202.         printf("版本:%x\n",ip->version);
  203.         printf("首部长度:%x\n",ip->ihl);
  204.         printf("服务类型:%x\n",ip->tos);
  205.         printf("总长度:%u\n",ip->tot_len);
  206.         
  207.         printf("标志:%u\n",ip->id);
  208.         printf("分片偏移:%u\n",ip->frag_off);
  209.         printf("生存时间:%x\n",ip->ttl);
  210.         printf("协议:%x\n",ip->protocol);
  211.         printf("检验和:%x\n",ip->chk_sum);     
  212.         printf("源IP地址:%s\n",inet_ntoa(srcdr));
  213.         printf("目的IP地址:%s\n",inet_ntoa(dstdr));
  214.         printf("###################################################\n");
  215.         if(ip->protocol==TCP)//IP数据报上层传输协议是TCP
  216.         {
  217.             tcp_hdr *tcp=(tcp_hdr *)ip->data;
  218.             printf("==================================================\n");
  219.             printf("TCP数据报信息:\n");
  220.             printf("源端口:%u\n",tcp->src_port);
  221.             printf("目的端口:%u\n",tcp->dst_port);
  222.             printf("序列号:%d\n",tcp->seq_no);
  223.             printf("确认号:%d\n",tcp->ack_no);
  224.             printf("tcp头部长度:%x\n",tcp->thl);
  225.             printf("6位标志:%x\n" ,tcp->flag);
  226.             printf("窗口大小:%x\n",tcp->wnd_size);
  227.             printf("检验和:%x\n",tcp->chk_sum); //16位TCP检验和
  228.             printf("紧急指针:%x\n",tcp->urgt_p); //16为紧急指针
  229.             printf("==================================================\n");
  230.                     
  231.         }
  232.         if(ip->protocol==UDP)
  233.         {
  234.             udp_hdr *udp=(udp_hdr*)ip->data;
  235.             printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");    
  236.             printf("UDP数据报信息:\n");
  237.             printf("远端口号:%u\n",udp->src_port);
  238.             printf("目的端口号:%u\n",udp->dst_port);
  239.             printf("udp头部长度:%u\n",udp->uhl);
  240.             printf("16位udp检验和:%u\n",udp->chk_sum);
  241.             printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");        
  242.         
  243.         }
  244.     }
  245.     
  246. }



阅读(2247) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~