]>
Commit | Line | Data |
---|---|---|
a149fcc7 JM |
1 | /* |
2 | * PCAP capture file reader | |
3 | * Copyright (c) 2010, Jouni Malinen <j@w1.fi> | |
4 | * | |
0f3d578e JM |
5 | * This software may be distributed under the terms of the BSD license. |
6 | * See README for more details. | |
a149fcc7 JM |
7 | */ |
8 | ||
9 | #include "utils/includes.h" | |
ef00c780 | 10 | #include <pcap.h> |
a149fcc7 JM |
11 | |
12 | #include "utils/common.h" | |
13 | #include "wlantest.h" | |
14 | ||
15 | ||
0321bcdf JM |
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 | ||
a149fcc7 JM |
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; | |
350132be | 57 | int dlt; |
a149fcc7 JM |
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 | } | |
350132be | 65 | dlt = pcap_datalink(pcap); |
0f3e4f2a JM |
66 | if (dlt != DLT_IEEE802_11_RADIO && dlt != DLT_PRISM_HEADER && |
67 | dlt != DLT_IEEE802_11) { | |
350132be JM |
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); | |
a149fcc7 JM |
74 | |
75 | for (;;) { | |
ba2beacc JM |
76 | clear_notes(wt); |
77 | os_free(wt->decrypted); | |
78 | wt->decrypted = NULL; | |
79 | ||
a149fcc7 JM |
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 | wpa_printf(MSG_EXCESSIVE, "pcap hdr: ts=%d.%06d " | |
96 | "len=%u/%u", | |
97 | (int) hdr->ts.tv_sec, (int) hdr->ts.tv_usec, | |
98 | hdr->caplen, hdr->len); | |
64f45d07 JM |
99 | if (wt->write_pcap_dumper) { |
100 | wt->write_pcap_time = hdr->ts; | |
0321bcdf JM |
101 | if (dlt == DLT_IEEE802_11) |
102 | write_pcap_with_radiotap(wt, data, hdr->caplen); | |
103 | else | |
104 | pcap_dump(wt->write_pcap_dumper, hdr, data); | |
64f45d07 | 105 | } |
a149fcc7 | 106 | if (hdr->caplen < hdr->len) { |
ba2beacc JM |
107 | add_note(wt, MSG_DEBUG, "pcap: Dropped incomplete " |
108 | "frame (%u/%u captured)", | |
109 | hdr->caplen, hdr->len); | |
110 | write_pcapng_write_read(wt, dlt, hdr, data); | |
a149fcc7 JM |
111 | continue; |
112 | } | |
113 | count++; | |
350132be JM |
114 | switch (dlt) { |
115 | case DLT_IEEE802_11_RADIO: | |
116 | wlantest_process(wt, data, hdr->caplen); | |
117 | break; | |
118 | case DLT_PRISM_HEADER: | |
119 | wlantest_process_prism(wt, data, hdr->caplen); | |
120 | break; | |
0f3e4f2a JM |
121 | case DLT_IEEE802_11: |
122 | wlantest_process_80211(wt, data, hdr->caplen); | |
ba2beacc | 123 | break; |
350132be | 124 | } |
ba2beacc | 125 | write_pcapng_write_read(wt, dlt, hdr, data); |
a149fcc7 JM |
126 | } |
127 | ||
128 | pcap_close(pcap); | |
129 | ||
130 | wpa_printf(MSG_DEBUG, "Read %s: %u packets", fname, count); | |
131 | ||
132 | return 0; | |
133 | } | |
3215df77 JM |
134 | |
135 | ||
136 | int read_wired_cap_file(struct wlantest *wt, const char *fname) | |
137 | { | |
138 | char errbuf[PCAP_ERRBUF_SIZE]; | |
139 | pcap_t *pcap; | |
140 | unsigned int count = 0; | |
141 | struct pcap_pkthdr *hdr; | |
142 | const u_char *data; | |
143 | int res; | |
144 | ||
145 | pcap = pcap_open_offline(fname, errbuf); | |
146 | if (pcap == NULL) { | |
147 | wpa_printf(MSG_ERROR, "Failed to read pcap file '%s': %s", | |
148 | fname, errbuf); | |
149 | return -1; | |
150 | } | |
151 | ||
152 | for (;;) { | |
153 | res = pcap_next_ex(pcap, &hdr, &data); | |
154 | if (res == -2) | |
155 | break; /* No more packets */ | |
156 | if (res == -1) { | |
157 | wpa_printf(MSG_INFO, "pcap_next_ex failure: %s", | |
158 | pcap_geterr(pcap)); | |
159 | break; | |
160 | } | |
161 | if (res != 1) { | |
162 | wpa_printf(MSG_INFO, "Unexpected pcap_next_ex return " | |
163 | "value %d", res); | |
164 | break; | |
165 | } | |
166 | ||
167 | /* Packet was read without problems */ | |
168 | wpa_printf(MSG_EXCESSIVE, "pcap hdr: ts=%d.%06d " | |
169 | "len=%u/%u", | |
170 | (int) hdr->ts.tv_sec, (int) hdr->ts.tv_usec, | |
171 | hdr->caplen, hdr->len); | |
172 | if (hdr->caplen < hdr->len) { | |
173 | wpa_printf(MSG_DEBUG, "pcap: Dropped incomplete frame " | |
174 | "(%u/%u captured)", | |
175 | hdr->caplen, hdr->len); | |
176 | continue; | |
177 | } | |
178 | count++; | |
179 | wlantest_process_wired(wt, data, hdr->caplen); | |
180 | } | |
181 | ||
182 | pcap_close(pcap); | |
183 | ||
184 | wpa_printf(MSG_DEBUG, "Read %s: %u packets", fname, count); | |
185 | ||
186 | return 0; | |
187 | } |