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_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\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 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\"\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.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\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,1,0,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_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\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 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\"\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.com
321 哈哈
322 没有反应吧
323 接着再ping www.google.com
324 就看到1, 2, 3, 4, 5, 6,
325 ok
326 you got it!!

 

posted @ 2015-01-08 13:01  婷婷玉立的成长之家  阅读(1207)  评论(0编辑  收藏  举报