首页 > 代码库 > libpcap编程实例

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\n",errbuf); 27    exit(1); 28   } 29  30   31   printf("DEV: %s\n",dev); 32  33   34   ret = pcap_lookupnet(dev,&netp,&maskp,errbuf); 35  36   if(ret == -1) 37   { 38    printf("%s\n",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\n",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\n",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\n",errbuf);104         exit(1);105     }106 107     printf("DEV: %s\n",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\n",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\n");127         exit(1);128     }129 130    131 132     printf("Grabbed packet of length %d\n",hdr.len);133     printf("Recieved at ..... %s\n",ctime((const time_t*)&hdr.ts.tv_sec));134     printf("Ethernet address length is %d\n",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\n",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\n",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("\n");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("\n");171 172     return 0;173 }174 175 好了,编译运行!176 [root@norman libpcap]# ./pcap_2177 DEV: eth0178 Grabbed packet of length 76179 Recieved at time..... Mon Mar 12 22:23:29 2001180 181 Ethernet address length is 14182 Ethernet type hex:800 dec:2048 is an IP packet183 Destination Address:   0:20:78:d1:e8:1184 Source Address:   0:a0:cc:56:c2:91185 [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\n",argv[0]);return 0;}229 230    231     dev = pcap_lookupdev(errbuf);232     if(dev == NULL)233     { printf("%s\n",errbuf); exit(1); }234    235     descr = pcap_open_live(dev,BUFSIZ,0,-1,errbuf);236     if(descr == NULL)237     { printf("pcap_open_live(): %s\n",errbuf); exit(1); }238 239    240    241     pcap_loop(descr,atoi(argv[1]),my_callback,NULL);242 243     fprintf(stdout,"\nDone processing packets... wheew!\n");244     return 0;245 }246  247 运行./pcap_3 7248 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\"\n"290             ,argv[0]);return 0;}291 292    293     dev = pcap_lookupdev(errbuf);294     if(dev == NULL)295     { fprintf(stderr,"%s\n",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\n",errbuf); exit(1); }304 305    306     if(pcap_compile(descr,&fp,argv[1],0,netp) == -1)307     { fprintf(stderr,"Error calling pcap_compile\n"); exit(1); }308 309    310     if(pcap_setfilter(descr,&fp) == -1)311     { fprintf(stderr,"Error setting filter\n"); 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.com321 哈哈322 没有反应吧323 接着再ping www.google.com324 就看到1, 2, 3, 4, 5, 6,325 ok326 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\n",errbuf); 27    exit(1); 28   } 29  30   31   printf("DEV: %s\n",dev); 32  33   34   ret = pcap_lookupnet(dev,&netp,&maskp,errbuf); 35  36   if(ret == -1) 37   { 38    printf("%s\n",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\n",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\n",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\n",errbuf);104         exit(1);105     }106 107     printf("DEV: %s\n",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\n",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\n");127         exit(1);128     }129 130    131 132     printf("Grabbed packet of length %d\n",hdr.len);133     printf("Recieved at ..... %s\n",ctime((const time_t*)&hdr.ts.tv_sec));134     printf("Ethernet address length is %d\n",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\n",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\n",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("\n");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("\n");171 172     return 0;173 }174 175 好了,编译运行!176 [root@norman libpcap]# ./pcap_2177 DEV: eth0178 Grabbed packet of length 76179 Recieved at time..... Mon Mar 12 22:23:29 2001180 181 Ethernet address length is 14182 Ethernet type hex:800 dec:2048 is an IP packet183 Destination Address:   0:20:78:d1:e8:1184 Source Address:   0:a0:cc:56:c2:91185 [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\n",argv[0]);return 0;}229 230    231     dev = pcap_lookupdev(errbuf);232     if(dev == NULL)233     { printf("%s\n",errbuf); exit(1); }234    235     descr = pcap_open_live(dev,BUFSIZ,0,-1,errbuf);236     if(descr == NULL)237     { printf("pcap_open_live(): %s\n",errbuf); exit(1); }238 239    240    241     pcap_loop(descr,atoi(argv[1]),my_callback,NULL);242 243     fprintf(stdout,"\nDone processing packets... wheew!\n");244     return 0;245 }246  247 运行./pcap_3 7248 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\"\n"290             ,argv[0]);return 0;}291 292    293     dev = pcap_lookupdev(errbuf);294     if(dev == NULL)295     { fprintf(stderr,"%s\n",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\n",errbuf); exit(1); }304 305    306     if(pcap_compile(descr,&fp,argv[1],0,netp) == -1)307     { fprintf(stderr,"Error calling pcap_compile\n"); exit(1); }308 309    310     if(pcap_setfilter(descr,&fp) == -1)311     { fprintf(stderr,"Error setting filter\n"); 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.com321 哈哈322 没有反应吧323 接着再ping www.google.com324 就看到1, 2, 3, 4, 5, 6,325 ok326 you got it!!

 

libpcap编程实例