Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / 用C实现截获网络数据包

1.  把网卡置于混杂模式。2.  捕获数据包。3.  分析数据包。 注:下面的源代码取至Chad  Renfro的 < <  Basic  Packet-Sniffer  Construction  from  the  Ground  Up> > 一文中 
/************************Tcp_sniff_2.c********************/ 
1.#include   
2.#include   
3.#include 
4.#include 
5.#include 
6.#include 
7.#include   
8.#include 
9.#include  "headers.h " 
     
#define  INTERFACE  "eth0 " 
     
/*Prototype  area*/ 
     
10.int  Open_Raw_Socket(void);  
11.int  Set_Promisc(char  *interface,  int  sock);  
12.int  main()  {   
13.int  sock,  bytes_recieved,  fromlen;  
14.char  buffer[65535]; 
15.struct  sockaddr_in  from;  
16.struct  ip  *ip; 
17.struct  tcp  *tcp;   
18.sock  =  Open_Raw_Socket(); 
19.  Set_Promisc(INTERFACE,  sock); 
     
20.  while(1) 
22.  { 
23.  fromlen  =  sizeof  from; 
24.  bytes_recieved  =  recvfrom(sock,  buffer,  sizeof  buffer,  0,  (struct  sockaddr  *)&from,  &fromlen); 
25.  printf( " Bytes  received  :::  %5d ",bytes_recieved); 
26.  printf( "Source  address  :::  %s ",inet_ntoa(from.sin_addr)); 
27.  ip  =  (struct  ip  *)buffer; 
/*See  if  this  is  a  TCP  packet*/ 
28.  if(ip-> ip_protocol  ==  6)  { 
29.  printf( "IP  header  length  :::  %d ",ip-> ip_length); 
30.  printf( "Protocol  :::  %d ",ip-> ip_protocol); 
31.  tcp  =  (struct  tcp  *)(buffer  +  (4*ip-> ip_length)); 
32.  printf( "Source  port  :::  %d ",ntohs(tcp-> tcp_source_port)); 
33.  printf( "Dest  port  :::  %d ",ntohs(tcp-> tcp_dest_port)); 
34.  } 
     
35.  } 
36.} 
37.int  Open_Raw_Socket()  {  
38.  int  sock; 
39.  if((sock  =  socket(AF_INET,  SOCK_RAW,  IPPROTO_TCP))  <  0)  { 
/*Then  the  socket  was  not  created  properly  and  must  die*/ 
40.  perror( "The  raw  socket  was  not  created "); 
41.  exit(0); 
42.  };  
43.  return(sock);  
44.  } 
     
45.int  Set_Promisc(char  *interface,  int  sock  )  {   
46.  struct  ifreq  ifr;     
47.  strncpy(ifr.ifr_name,  interface,strnlen(interface)+1); 
48.  if((ioctl(sock,  SIOCGIFFLAGS,  &ifr)  ==  -1))  {  
/*Could  not  retrieve  flags  for  the  interface*/ 
49.  perror( "Could  not  retrive  flags  for  the  interface "); 
50.  exit(0); 
51.  }  
52.  printf( "The  interface  is  :::  %s ",  interface);  
53.  perror( "Retrieved  flags  from  interface  successfully "); 
54.  ifr.ifr_flags  |=  IFF_PROMISC;   
55.  if  (ioctl  (sock,  SIOCSIFFLAGS,  &ifr)  ==  -1  )  {   
/*Could  not  set  the  flags  on  the  interface  */   
56.  perror( "Could  not  set  the  PROMISC  flag: "); 
57.  exit(0);    
58.  } 
59.  printf( "Setting  interface  :::  %s  :::  to  promisc ",  interface); 
60.  return(0); 
61.  } 
     
/***********************EOF**********************************/ 上面这段程序中有很详细的注解,不过我想还是有必要说一说,首先第10行--int  Open_Raw_Socket(void); 是我们的自定义函数,具体内容如下: 37.int  Open_Raw_Socket()  {  
38.  int  sock; 
39.  if((sock  =  socket(AF_INET,  SOCK_RAW,  IPPROTO_TCP))  <  0)  { 
/*Then  the  socket  was  not  created  properly  and  must  die*/ 
40.  perror( "The  raw  socket  was  not  created "); 
41.  exit(0); 
42.  };  
43.  return(sock);  
44.  } 
               第39行  if((sock  =  socket(AF_INET,  SOCK_RAW,  IPPROTO_TCP))  <  0)  { 这里我们调用了socket函数,使创建了了一个原始套接口,使之收到TCP/IP信息包。  接下来第11行-int  Set_Promisc(char  *interface,  int  sock),这也是我们的自定义函数,目的是把网卡置于混杂模式,具体内容如下: 
45.int  Set_Promisc(char  *interface,  int  sock  )  {   
46.  struct  ifreq  ifr;     
47.  strncpy(ifr.ifr_name,  interface,strnlen(interface)+1); 
48.  if((ioctl(sock,  SIOCGIFFLAGS,  &ifr)  ==  -1))  {  
/*Could  not  retrieve  flags  for  the  interface*/ 
49.  perror( "Could  not  retrive  flags  for  the  interface "); 
50.  exit(0); 
51.  }  
52.  printf( "The  interface  is  :::  %s ",  interface);  
53.  perror( "Retrieved  flags  from  interface  successfully "); 
54.  ifr.ifr_flags  |=  IFF_PROMISC;   
55.  if  (ioctl  (sock,  SIOCSIFFLAGS,  &ifr)  ==  -1  )  {   
/*Could  not  set  the  flags  on  the  interface  */   
56.  perror( "Could  not  set  the  PROMISC  flag: "); 
57.  exit(0);    
58.  } 
59.  printf( "Setting  interface  :::  %s  :::  to  promisc ",  interface); 
60.  return(0); 
61.  }  首先  struct  ifreq  ifr;  定一了一个ifrreg的结构ifr,接下来  strncpy(ifr.ifr_name,  interface,strnlen(interface)+1);,就是把我们网络设备的名字填充到ifr结构中,在这里  #define  INTERFACE  "eth0 "  ,让我们再往下看,ioctl(sock,  SIOCGIFFLAGS,  &ifr),SIOCGIFFLAGS请求表示需要获取接口标志,现在到了第54行,在我们成功的获取接口标志后把他设置成混杂模式,ifr.ifr_flags  |=  IFF_PROMISC;ioctl  (sock,  SIOCSIFFLAGS,  &ifr)。OK,现在我们所说的第一步已经完成--------把网卡置于混杂模式。 更多详情见请继续阅读下一页的精彩内容: http://www.linuxidc.com/Linux/2013-11/92548p2.htm