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!!