• libpcap编程实例


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <pcap.h> 
      4 #include <errno.h>
      5 #include <sys/socket.h>
      6 #include <netinet/in.h>
      7 #include <arpa/inet.h>
      8 
      9 int main(int argc, char **argv)
     10 {
     11   char *dev;
     12   char *net;
     13   char *mask;
     14   int ret;  
     15   char errbuf[PCAP_ERRBUF_SIZE];
     16   bpf_u_int32 netp;
     17   bpf_u_int32 maskp;
     18   struct in_addr addr;
     19 
     20  
     21   dev = pcap_lookupdev(errbuf);
     22 
     23  
     24   if(dev == NULL)
     25   {
     26    printf("%s
    ",errbuf);
     27    exit(1);
     28   }
     29 
     30  
     31   printf("DEV: %s
    ",dev);
     32 
     33  
     34   ret = pcap_lookupnet(dev,&netp,&maskp,errbuf);
     35 
     36   if(ret == -1)
     37   {
     38    printf("%s
    ",errbuf);
     39    exit(1);
     40   }
     41 
     42  
     43   addr.s_addr = netp;
     44   net = inet_ntoa(addr);
     45 
     46   if(net == NULL)
     47   {
     48     perror("inet_ntoa");
     49     exit(1);
     50   }
     51 
     52   printf("NET: %s
    ",net);
     53 
     54  
     55   addr.s_addr = maskp;
     56   mask = inet_ntoa(addr);
     57  
     58   if(mask == NULL)
     59   {
     60     perror("inet_ntoa");
     61     exit(1);
     62   }
     63  
     64   printf("MASK: %s
    ",mask);
     65 
     66   return 0;
     67 }
     68 然后gcc -o pcap_1 pcap_1.c -lpcap(一定要-lpcap参数)
     69 编译ok~,执行./pcap_1,可以看到:
     70 DEV: eth0
     71 NET: 192.168.12.0
     72 MASK: 255.255.255.0
     73 好了,第一个pcap程序出炉了。。。。。
     74  
     75 但是(当然有但是了,要不然我后面写啥),上面那个程序除了向我们展现pcap_lookupdev和pcap_lookupnet之外什么都没有干,好,我们接着来,动手编写我们的第一个抓包程序。
     76  
     77 #include <stdio.h>
     78 #include <stdlib.h>
     79 #include <pcap.h>
     80 #include <errno.h>
     81 #include <sys/socket.h>
     82 #include <netinet/in.h>
     83 #include <arpa/inet.h>
     84 #include <netinet/if_ether.h>
     85 
     86 int main(int argc, char **argv)
     87 {
     88     int i;
     89     char *dev;
     90     char errbuf[PCAP_ERRBUF_SIZE];
     91     pcap_t* descr;      
     92     const u_char *packet;
     93     struct pcap_pkthdr hdr;    
     94     struct ether_header *eptr; 
     95 
     96     u_char *ptr;
     97 
     98    
     99     dev = pcap_lookupdev(errbuf);
    100 
    101     if(dev == NULL)
    102     {
    103         printf("%s
    ",errbuf);
    104         exit(1);
    105     }
    106 
    107     printf("DEV: %s
    ",dev);
    108 
    109    
    110 
    111     descr = pcap_open_live(dev,BUFSIZ,0,-1,errbuf);
    112 
    113     if(descr == NULL)
    114     {
    115         printf("pcap_open_live(): %s
    ",errbuf);
    116         exit(1);
    117     }
    118 
    119 
    120    
    121 
    122     packet = pcap_next(descr,&hdr);
    123 
    124     if(packet == NULL)
    125     {
    126         printf("Didn't grab packet
    ");
    127         exit(1);
    128     }
    129 
    130    
    131 
    132     printf("Grabbed packet of length %d
    ",hdr.len);
    133     printf("Recieved at ..... %s
    ",ctime((const time_t*)&hdr.ts.tv_sec));
    134     printf("Ethernet address length is %d
    ",ETHER_HDR_LEN);
    135 
    136    
    137     eptr = (struct ether_header *) packet;
    138 
    139    
    140     if (ntohs (eptr->ether_type) == ETHERTYPE_IP)
    141     {
    142         printf("Ethernet type hex:%x dec:%d is an IP packet
    ",
    143                 ntohs(eptr->ether_type),
    144                 ntohs(eptr->ether_type));
    145     }else  if (ntohs (eptr->ether_type) == ETHERTYPE_ARP)
    146     {
    147         printf("Ethernet type hex:%x dec:%d is an ARP packet
    ",
    148                 ntohs(eptr->ether_type),
    149                 ntohs(eptr->ether_type));
    150     }else {
    151         printf("Ethernet type %x not IP", ntohs(eptr->ether_type));
    152         exit(1);
    153     }
    154 
    155    
    156     ptr = eptr->ether_dhost;
    157     i = ETHER_ADDR_LEN;
    158     printf(" Destination Address:  ");
    159     do{
    160         printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++);
    161     }while(--i>0);
    162     printf("
    ");
    163 
    164     ptr = eptr->ether_shost;
    165     i = ETHER_ADDR_LEN;
    166     printf(" Source Address:  ");
    167     do{
    168         printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++);
    169     }while(--i>0);
    170     printf("
    ");
    171 
    172     return 0;
    173 }
    174 
    175 好了,编译运行!
    176 [root@norman libpcap]# ./pcap_2
    177 DEV: eth0
    178 Grabbed packet of length 76
    179 Recieved at time..... Mon Mar 12 22:23:29 2001
    180 
    181 Ethernet address length is 14
    182 Ethernet type hex:800 dec:2048 is an IP packet
    183 Destination Address:   0:20:78:d1:e8:1
    184 Source Address:   0:a0:cc:56:c2:91
    185 [root@pepe libpcap]#
    186  
    187 可能有人等了半天都没有一个包过来,有个好办法,再开一个控制台,ping一下某个网站,比如google~~,呵呵
    188 马上就有反应了~~
    189  
    190 这个程序是一个老外写的,大家看看注释应该没有问题吧~
    191 但是大家也发现了一个问题,就是上面的程序只能捕捉一个包,要不停的捕捉包怎么办,用循环??libpcap提供了一个更好的方法:
    192 int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
    193 这个函数能够不停的捕捉以太网的包,cnt就是捕捉的次数,callback是处理函数,这个处理函数怎么写,看看pcap_3.c就知道了。user参数是干什么的?不要问我,我也不知道。
    194  
    195 #include <pcap.h>
    196 #include <stdio.h>
    197 #include <stdlib.h>
    198 #include <errno.h>
    199 #include <sys/socket.h>
    200 #include <netinet/in.h>
    201 #include <arpa/inet.h>
    202 #include <netinet/if_ether.h>
    203 
    204 
    205 void my_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char*
    206         packet)
    207 {
    208     static int count = 1;
    209     fprintf(stdout,"%d, ",count);
    210     if(count == 4)
    211         fprintf(stdout,"Come on baby sayyy you love me!!! ");
    212     if(count == 7)
    213         fprintf(stdout,"Tiiimmmeesss!! ");
    214     fflush(stdout);
    215     count++;
    216 }
    217 
    218 int main(int argc,char **argv)
    219 {
    220     int i;
    221     char *dev;
    222     char errbuf[PCAP_ERRBUF_SIZE];
    223     pcap_t* descr;
    224     const u_char *packet;
    225     struct pcap_pkthdr hdr;    
    226     struct ether_header *eptr; 
    227 
    228     if(argc != 2){ fprintf(stdout,"Usage: %s numpackets
    ",argv[0]);return 0;}
    229 
    230    
    231     dev = pcap_lookupdev(errbuf);
    232     if(dev == NULL)
    233     { printf("%s
    ",errbuf); exit(1); }
    234    
    235     descr = pcap_open_live(dev,BUFSIZ,0,-1,errbuf);
    236     if(descr == NULL)
    237     { printf("pcap_open_live(): %s
    ",errbuf); exit(1); }
    238 
    239    
    240    
    241     pcap_loop(descr,atoi(argv[1]),my_callback,NULL);
    242 
    243     fprintf(stdout,"
    Done processing packets... wheew!
    ");
    244     return 0;
    245 }
    246  
    247 运行./pcap_3 7
    248 1, 2, 3, 4, Come on baby sayyy you love me!!! 5, 6, 7, Tiiimmmeesss!! 
    249 Done processing packets... wheew!
    250  
    251 pcap_loop确实很好用,但是如果没有包包过来,只有干等在那里,pcap_dispatch就含有一个超时的功能,下面是man里面的一段话:
    252 pcap_dispatch() is used to collect and process packets. cnt specifies the maximum number of packets to process before returning. A cnt of -1 processes all the packets received in one buffer. A cnt of 0 processes all packets until an error occurs, EOF is reached, or the read times out (when doing live reads and a non-zero read timeout is specified). callback specifies a routine to be called with three arguments: a u_char pointer which is passed in from pcap_dispatch(), a pointer to the pcap_pkthdr struct (which precede the actual network headers and data), and a u_char pointer to the packet data. The number of packets read is returned. Zero is returned when EOF is reached in a ``savefile.'' A return of -1 indicates an error in which case pcap_perror() or pcap_geterr() may be used to display the error text. 
    253  
    254 另外的问题是,我们可能对抓取的包包太多而很头痛,可能很多都不是我们感兴趣的包,别急,pcap_compile和pcap_setfilter能帮我们解决问题。
    255  
    256 #include <pcap.h>
    257 #include <stdio.h>
    258 #include <stdlib.h>
    259 #include <errno.h>
    260 #include <sys/socket.h>
    261 #include <netinet/in.h>
    262 #include <arpa/inet.h>
    263 #include <netinet/if_ether.h>
    264 
    265 
    266 void my_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char*
    267         packet)
    268 {
    269     static int count = 1;
    270     fprintf(stdout,"%d, ",count);
    271     fflush(stdout);
    272     count++;
    273 }
    274 
    275 int main(int argc,char **argv)
    276 {
    277     int i;
    278     char *dev;
    279     char errbuf[PCAP_ERRBUF_SIZE];
    280     pcap_t* descr;
    281     const u_char *packet;
    282     struct pcap_pkthdr hdr;    
    283     struct ether_header *eptr; 
    284     struct bpf_program fp;     
    285     bpf_u_int32 maskp;         
    286     bpf_u_int32 netp;          
    287 
    288 
    289     if(argc != 2){ fprintf(stdout,"Usage: %s "filter program"
    "
    290             ,argv[0]);return 0;}
    291 
    292    
    293     dev = pcap_lookupdev(errbuf);
    294     if(dev == NULL)
    295     { fprintf(stderr,"%s
    ",errbuf); exit(1); }
    296 
    297    
    298     pcap_lookupnet(dev,&netp,&maskp,errbuf);
    299 
    300    
    301     descr = pcap_open_live(dev,BUFSIZ,1,-1,errbuf);
    302     if(descr == NULL)
    303     { printf("pcap_open_live(): %s
    ",errbuf); exit(1); }
    304 
    305    
    306     if(pcap_compile(descr,&fp,argv[1],0,netp) == -1)
    307     { fprintf(stderr,"Error calling pcap_compile
    "); exit(1); }
    308 
    309    
    310     if(pcap_setfilter(descr,&fp) == -1)
    311     { fprintf(stderr,"Error setting filter
    "); exit(1); }
    312 
    313    
    314     pcap_loop(descr,-1,my_callback,NULL);
    315 
    316     return 0;
    317 }
    318 
    319 运行./pcap_4.c "host www.google.com" 
    320 然后在另外一个控制台下面ping www.baidu.com
    321 哈哈
    322 没有反应吧
    323 接着再ping www.google.com
    324 就看到1, 2, 3, 4, 5, 6,
    325 ok
    326 you got it!!
    View Code
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <pcap.h> 
      4 #include <errno.h>
      5 #include <sys/socket.h>
      6 #include <netinet/in.h>
      7 #include <arpa/inet.h>
      8 
      9 int main(int argc, char **argv)
     10 {
     11   char *dev;
     12   char *net;
     13   char *mask;
     14   int ret;  
     15   char errbuf[PCAP_ERRBUF_SIZE];
     16   bpf_u_int32 netp;
     17   bpf_u_int32 maskp;
     18   struct in_addr addr;
     19 
     20  
     21   dev = pcap_lookupdev(errbuf);
     22 
     23  
     24   if(dev == NULL)
     25   {
     26    printf("%s
    ",errbuf);
     27    exit(1);
     28   }
     29 
     30  
     31   printf("DEV: %s
    ",dev);
     32 
     33  
     34   ret = pcap_lookupnet(dev,&netp,&maskp,errbuf);
     35 
     36   if(ret == -1)
     37   {
     38    printf("%s
    ",errbuf);
     39    exit(1);
     40   }
     41 
     42  
     43   addr.s_addr = netp;
     44   net = inet_ntoa(addr);
     45 
     46   if(net == NULL)
     47   {
     48     perror("inet_ntoa");
     49     exit(1);
     50   }
     51 
     52   printf("NET: %s
    ",net);
     53 
     54  
     55   addr.s_addr = maskp;
     56   mask = inet_ntoa(addr);
     57  
     58   if(mask == NULL)
     59   {
     60     perror("inet_ntoa");
     61     exit(1);
     62   }
     63  
     64   printf("MASK: %s
    ",mask);
     65 
     66   return 0;
     67 }
     68 然后gcc -o pcap_1 pcap_1.c -lpcap(一定要-lpcap参数)
     69 编译ok~,执行./pcap_1,可以看到:
     70 DEV: eth0
     71 NET: 192.168.12.0
     72 MASK: 255.255.255.0
     73 好了,第一个pcap程序出炉了。。。。。
     74  
     75 但是(当然有但是了,要不然我后面写啥),上面那个程序除了向我们展现pcap_lookupdev和pcap_lookupnet之外什么都没有干,好,我们接着来,动手编写我们的第一个抓包程序。
     76  
     77 #include <stdio.h>
     78 #include <stdlib.h>
     79 #include <pcap.h>
     80 #include <errno.h>
     81 #include <sys/socket.h>
     82 #include <netinet/in.h>
     83 #include <arpa/inet.h>
     84 #include <netinet/if_ether.h>
     85 
     86 int main(int argc, char **argv)
     87 {
     88     int i;
     89     char *dev;
     90     char errbuf[PCAP_ERRBUF_SIZE];
     91     pcap_t* descr;      
     92     const u_char *packet;
     93     struct pcap_pkthdr hdr;    
     94     struct ether_header *eptr; 
     95 
     96     u_char *ptr;
     97 
     98    
     99     dev = pcap_lookupdev(errbuf);
    100 
    101     if(dev == NULL)
    102     {
    103         printf("%s
    ",errbuf);
    104         exit(1);
    105     }
    106 
    107     printf("DEV: %s
    ",dev);
    108 
    109    
    110 
    111     descr = pcap_open_live(dev,BUFSIZ,1,0,errbuf);
    112 
    113     if(descr == NULL)
    114     {
    115         printf("pcap_open_live(): %s
    ",errbuf);
    116         exit(1);
    117     }
    118 
    119 
    120    
    121 
    122     packet = pcap_next(descr,&hdr);
    123 
    124     if(packet == NULL)
    125     {
    126         printf("Didn't grab packet
    ");
    127         exit(1);
    128     }
    129 
    130    
    131 
    132     printf("Grabbed packet of length %d
    ",hdr.len);
    133     printf("Recieved at ..... %s
    ",ctime((const time_t*)&hdr.ts.tv_sec));
    134     printf("Ethernet address length is %d
    ",ETHER_HDR_LEN);
    135 
    136    
    137     eptr = (struct ether_header *) packet;
    138 
    139    
    140     if (ntohs (eptr->ether_type) == ETHERTYPE_IP)
    141     {
    142         printf("Ethernet type hex:%x dec:%d is an IP packet
    ",
    143                 ntohs(eptr->ether_type),
    144                 ntohs(eptr->ether_type));
    145     }else  if (ntohs (eptr->ether_type) == ETHERTYPE_ARP)
    146     {
    147         printf("Ethernet type hex:%x dec:%d is an ARP packet
    ",
    148                 ntohs(eptr->ether_type),
    149                 ntohs(eptr->ether_type));
    150     }else {
    151         printf("Ethernet type %x not IP", ntohs(eptr->ether_type));
    152         exit(1);
    153     }
    154 
    155    
    156     ptr = eptr->ether_dhost;
    157     i = ETHER_ADDR_LEN;
    158     printf(" Destination Address:  ");
    159     do{
    160         printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++);
    161     }while(--i>0);
    162     printf("
    ");
    163 
    164     ptr = eptr->ether_shost;
    165     i = ETHER_ADDR_LEN;
    166     printf(" Source Address:  ");
    167     do{
    168         printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++);
    169     }while(--i>0);
    170     printf("
    ");
    171 
    172     return 0;
    173 }
    174 
    175 好了,编译运行!
    176 [root@norman libpcap]# ./pcap_2
    177 DEV: eth0
    178 Grabbed packet of length 76
    179 Recieved at time..... Mon Mar 12 22:23:29 2001
    180 
    181 Ethernet address length is 14
    182 Ethernet type hex:800 dec:2048 is an IP packet
    183 Destination Address:   0:20:78:d1:e8:1
    184 Source Address:   0:a0:cc:56:c2:91
    185 [root@pepe libpcap]#
    186  
    187 可能有人等了半天都没有一个包过来,有个好办法,再开一个控制台,ping一下某个网站,比如google~~,呵呵
    188 马上就有反应了~~
    189  
    190 这个程序是一个老外写的,大家看看注释应该没有问题吧~
    191 但是大家也发现了一个问题,就是上面的程序只能捕捉一个包,要不停的捕捉包怎么办,用循环??libpcap提供了一个更好的方法:
    192 int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
    193 这个函数能够不停的捕捉以太网的包,cnt就是捕捉的次数,callback是处理函数,这个处理函数怎么写,看看pcap_3.c就知道了。user参数是干什么的?不要问我,我也不知道。
    194  
    195 #include <pcap.h>
    196 #include <stdio.h>
    197 #include <stdlib.h>
    198 #include <errno.h>
    199 #include <sys/socket.h>
    200 #include <netinet/in.h>
    201 #include <arpa/inet.h>
    202 #include <netinet/if_ether.h>
    203 
    204 
    205 void my_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char*
    206         packet)
    207 {
    208     static int count = 1;
    209     fprintf(stdout,"%d, ",count);
    210     if(count == 4)
    211         fprintf(stdout,"Come on baby sayyy you love me!!! ");
    212     if(count == 7)
    213         fprintf(stdout,"Tiiimmmeesss!! ");
    214     fflush(stdout);
    215     count++;
    216 }
    217 
    218 int main(int argc,char **argv)
    219 {
    220     int i;
    221     char *dev;
    222     char errbuf[PCAP_ERRBUF_SIZE];
    223     pcap_t* descr;
    224     const u_char *packet;
    225     struct pcap_pkthdr hdr;    
    226     struct ether_header *eptr; 
    227 
    228     if(argc != 2){ fprintf(stdout,"Usage: %s numpackets
    ",argv[0]);return 0;}
    229 
    230    
    231     dev = pcap_lookupdev(errbuf);
    232     if(dev == NULL)
    233     { printf("%s
    ",errbuf); exit(1); }
    234    
    235     descr = pcap_open_live(dev,BUFSIZ,0,-1,errbuf);
    236     if(descr == NULL)
    237     { printf("pcap_open_live(): %s
    ",errbuf); exit(1); }
    238 
    239    
    240    
    241     pcap_loop(descr,atoi(argv[1]),my_callback,NULL);
    242 
    243     fprintf(stdout,"
    Done processing packets... wheew!
    ");
    244     return 0;
    245 }
    246  
    247 运行./pcap_3 7
    248 1, 2, 3, 4, Come on baby sayyy you love me!!! 5, 6, 7, Tiiimmmeesss!! 
    249 Done processing packets... wheew!
    250  
    251 pcap_loop确实很好用,但是如果没有包包过来,只有干等在那里,pcap_dispatch就含有一个超时的功能,下面是man里面的一段话:
    252 pcap_dispatch() is used to collect and process packets. cnt specifies the maximum number of packets to process before returning. A cnt of -1 processes all the packets received in one buffer. A cnt of 0 processes all packets until an error occurs, EOF is reached, or the read times out (when doing live reads and a non-zero read timeout is specified). callback specifies a routine to be called with three arguments: a u_char pointer which is passed in from pcap_dispatch(), a pointer to the pcap_pkthdr struct (which precede the actual network headers and data), and a u_char pointer to the packet data. The number of packets read is returned. Zero is returned when EOF is reached in a ``savefile.'' A return of -1 indicates an error in which case pcap_perror() or pcap_geterr() may be used to display the error text. 
    253  
    254 另外的问题是,我们可能对抓取的包包太多而很头痛,可能很多都不是我们感兴趣的包,别急,pcap_compile和pcap_setfilter能帮我们解决问题。
    255  
    256 #include <pcap.h>
    257 #include <stdio.h>
    258 #include <stdlib.h>
    259 #include <errno.h>
    260 #include <sys/socket.h>
    261 #include <netinet/in.h>
    262 #include <arpa/inet.h>
    263 #include <netinet/if_ether.h>
    264 
    265 
    266 void my_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char*
    267         packet)
    268 {
    269     static int count = 1;
    270     fprintf(stdout,"%d, ",count);
    271     fflush(stdout);
    272     count++;
    273 }
    274 
    275 int main(int argc,char **argv)
    276 {
    277     int i;
    278     char *dev;
    279     char errbuf[PCAP_ERRBUF_SIZE];
    280     pcap_t* descr;
    281     const u_char *packet;
    282     struct pcap_pkthdr hdr;    
    283     struct ether_header *eptr; 
    284     struct bpf_program fp;     
    285     bpf_u_int32 maskp;         
    286     bpf_u_int32 netp;          
    287 
    288 
    289     if(argc != 2){ fprintf(stdout,"Usage: %s "filter program"
    "
    290             ,argv[0]);return 0;}
    291 
    292    
    293     dev = pcap_lookupdev(errbuf);
    294     if(dev == NULL)
    295     { fprintf(stderr,"%s
    ",errbuf); exit(1); }
    296 
    297    
    298     pcap_lookupnet(dev,&netp,&maskp,errbuf);
    299 
    300    
    301     descr = pcap_open_live(dev,BUFSIZ,1,-1,errbuf);
    302     if(descr == NULL)
    303     { printf("pcap_open_live(): %s
    ",errbuf); exit(1); }
    304 
    305    
    306     if(pcap_compile(descr,&fp,argv[1],0,netp) == -1)
    307     { fprintf(stderr,"Error calling pcap_compile
    "); exit(1); }
    308 
    309    
    310     if(pcap_setfilter(descr,&fp) == -1)
    311     { fprintf(stderr,"Error setting filter
    "); exit(1); }
    312 
    313    
    314     pcap_loop(descr,-1,my_callback,NULL);
    315 
    316     return 0;
    317 }
    318 
    319 运行./pcap_4.c "host www.google.com" 
    320 然后在另外一个控制台下面ping www.baidu.com
    321 哈哈
    322 没有反应吧
    323 接着再ping www.google.com
    324 就看到1, 2, 3, 4, 5, 6,
    325 ok
    326 you got it!!
  • 相关阅读:
    PHP 反射 ReflectionClass
    go-字符串生成数据库字段
    grpc类型
    ubuntu安装zookeeper集群
    ubuntu安装JDK
    zookeeper分布式读写锁
    golang利用gob序列化struct对象保存到本地(转载)
    golang手动管理内存(转载)
    类json格式字符串打印
    研二寒假---关于Qt&CV曲线算法问题
  • 原文地址:https://www.cnblogs.com/meihao1989/p/4210623.html
Copyright © 2020-2023  润新知