1 /*
2 * PCAP capture file reader
3 * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "utils/includes.h"
10 #include <pcap.h>
11
12 #include "utils/common.h"
13 #include "wlantest.h"
14
15
write_pcap_with_radiotap(struct wlantest * wt,const u8 * data,size_t data_len)16 static void write_pcap_with_radiotap(struct wlantest *wt,
17 const u8 *data, size_t data_len)
18 {
19 struct pcap_pkthdr h;
20 u8 rtap[] = {
21 0x00 /* rev */,
22 0x00 /* pad */,
23 0x0a, 0x00, /* header len */
24 0x02, 0x00, 0x00, 0x00, /* present flags */
25 0x00, /* flags */
26 0x00 /* pad */
27 };
28 u8 *buf;
29 size_t len;
30
31 if (wt->assume_fcs)
32 rtap[8] |= 0x10;
33
34 os_memset(&h, 0, sizeof(h));
35 h.ts = wt->write_pcap_time;
36 len = sizeof(rtap) + data_len;
37 buf = os_malloc(len);
38 if (buf == NULL)
39 return;
40 os_memcpy(buf, rtap, sizeof(rtap));
41 os_memcpy(buf + sizeof(rtap), data, data_len);
42 h.caplen = len;
43 h.len = len;
44 pcap_dump(wt->write_pcap_dumper, &h, buf);
45 os_free(buf);
46 }
47
48
read_cap_file(struct wlantest * wt,const char * fname)49 int read_cap_file(struct wlantest *wt, const char *fname)
50 {
51 char errbuf[PCAP_ERRBUF_SIZE];
52 pcap_t *pcap;
53 unsigned int count = 0;
54 struct pcap_pkthdr *hdr;
55 const u_char *data;
56 int res;
57 int dlt;
58
59 pcap = pcap_open_offline(fname, errbuf);
60 if (pcap == NULL) {
61 wpa_printf(MSG_ERROR, "Failed to read pcap file '%s': %s",
62 fname, errbuf);
63 return -1;
64 }
65 dlt = pcap_datalink(pcap);
66 if (dlt != DLT_IEEE802_11_RADIO && dlt != DLT_PRISM_HEADER &&
67 dlt != DLT_IEEE802_11) {
68 wpa_printf(MSG_ERROR, "Unsupported pcap datalink type: %d",
69 dlt);
70 pcap_close(pcap);
71 return -1;
72 }
73 wpa_printf(MSG_DEBUG, "pcap datalink type: %d", dlt);
74
75 for (;;) {
76 clear_notes(wt);
77 os_free(wt->decrypted);
78 wt->decrypted = NULL;
79
80 res = pcap_next_ex(pcap, &hdr, &data);
81 if (res == -2)
82 break; /* No more packets */
83 if (res == -1) {
84 wpa_printf(MSG_INFO, "pcap_next_ex failure: %s",
85 pcap_geterr(pcap));
86 break;
87 }
88 if (res != 1) {
89 wpa_printf(MSG_INFO, "Unexpected pcap_next_ex return "
90 "value %d", res);
91 break;
92 }
93
94 /* Packet was read without problems */
95 wt->frame_num++;
96 wpa_printf(MSG_EXCESSIVE, "pcap hdr: ts=%d.%06d "
97 "len=%u/%u",
98 (int) hdr->ts.tv_sec, (int) hdr->ts.tv_usec,
99 hdr->caplen, hdr->len);
100 if (wt->write_pcap_dumper) {
101 wt->write_pcap_time = hdr->ts;
102 if (dlt == DLT_IEEE802_11)
103 write_pcap_with_radiotap(wt, data, hdr->caplen);
104 else
105 pcap_dump(wt->write_pcap_dumper, hdr, data);
106 if (wt->pcap_no_buffer)
107 pcap_dump_flush(wt->write_pcap_dumper);
108 }
109 if (hdr->caplen < hdr->len) {
110 add_note(wt, MSG_DEBUG, "pcap: Dropped incomplete "
111 "frame (%u/%u captured)",
112 hdr->caplen, hdr->len);
113 write_pcapng_write_read(wt, dlt, hdr, data);
114 continue;
115 }
116 count++;
117 switch (dlt) {
118 case DLT_IEEE802_11_RADIO:
119 wlantest_process(wt, data, hdr->caplen);
120 break;
121 case DLT_PRISM_HEADER:
122 wlantest_process_prism(wt, data, hdr->caplen);
123 break;
124 case DLT_IEEE802_11:
125 wlantest_process_80211(wt, data, hdr->caplen);
126 break;
127 }
128 write_pcapng_write_read(wt, dlt, hdr, data);
129 }
130
131 pcap_close(pcap);
132
133 wpa_printf(MSG_DEBUG, "Read %s: %u packets", fname, count);
134
135 return 0;
136 }
137
138
read_wired_cap_file(struct wlantest * wt,const char * fname)139 int read_wired_cap_file(struct wlantest *wt, const char *fname)
140 {
141 char errbuf[PCAP_ERRBUF_SIZE];
142 pcap_t *pcap;
143 unsigned int count = 0;
144 struct pcap_pkthdr *hdr;
145 const u_char *data;
146 int res;
147
148 pcap = pcap_open_offline(fname, errbuf);
149 if (pcap == NULL) {
150 wpa_printf(MSG_ERROR, "Failed to read pcap file '%s': %s",
151 fname, errbuf);
152 return -1;
153 }
154
155 for (;;) {
156 res = pcap_next_ex(pcap, &hdr, &data);
157 if (res == -2)
158 break; /* No more packets */
159 if (res == -1) {
160 wpa_printf(MSG_INFO, "pcap_next_ex failure: %s",
161 pcap_geterr(pcap));
162 break;
163 }
164 if (res != 1) {
165 wpa_printf(MSG_INFO, "Unexpected pcap_next_ex return "
166 "value %d", res);
167 break;
168 }
169
170 /* Packet was read without problems */
171 wpa_printf(MSG_EXCESSIVE, "pcap hdr: ts=%d.%06d "
172 "len=%u/%u",
173 (int) hdr->ts.tv_sec, (int) hdr->ts.tv_usec,
174 hdr->caplen, hdr->len);
175 if (hdr->caplen < hdr->len) {
176 wpa_printf(MSG_DEBUG, "pcap: Dropped incomplete frame "
177 "(%u/%u captured)",
178 hdr->caplen, hdr->len);
179 continue;
180 }
181 count++;
182 wlantest_process_wired(wt, data, hdr->caplen);
183 }
184
185 pcap_close(pcap);
186
187 wpa_printf(MSG_DEBUG, "Read %s: %u packets", fname, count);
188
189 return 0;
190 }
191