2 * PCAP capture file writer
3 * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
13 #include "utils/common.h"
15 #include "common/qca-vendor.h"
18 int write_pcap_init(struct wlantest
*wt
, const char *fname
)
20 wt
->write_pcap
= pcap_open_dead(DLT_IEEE802_11_RADIO
, 4000);
21 if (wt
->write_pcap
== NULL
)
23 wt
->write_pcap_dumper
= pcap_dump_open(wt
->write_pcap
, fname
);
24 if (wt
->write_pcap_dumper
== NULL
) {
25 pcap_close(wt
->write_pcap
);
26 wt
->write_pcap
= NULL
;
30 wpa_printf(MSG_DEBUG
, "Writing PCAP dump to '%s'", fname
);
36 void write_pcap_deinit(struct wlantest
*wt
)
38 if (wt
->write_pcap_dumper
) {
39 pcap_dump_close(wt
->write_pcap_dumper
);
40 wt
->write_pcap_dumper
= NULL
;
43 pcap_close(wt
->write_pcap
);
44 wt
->write_pcap
= NULL
;
49 void write_pcap_captured(struct wlantest
*wt
, const u8
*buf
, size_t len
)
53 if (!wt
->write_pcap_dumper
)
56 os_memset(&h
, 0, sizeof(h
));
57 gettimeofday(&wt
->write_pcap_time
, NULL
);
58 h
.ts
= wt
->write_pcap_time
;
61 pcap_dump(wt
->write_pcap_dumper
, &h
, buf
);
62 if (wt
->pcap_no_buffer
)
63 pcap_dump_flush(wt
->write_pcap_dumper
);
67 void write_pcap_decrypted(struct wlantest
*wt
, const u8
*buf1
, size_t len1
,
68 const u8
*buf2
, size_t len2
)
74 0x0e, 0x00, /* header len */
75 0x00, 0x00, 0x00, 0x40, /* present flags */
76 0x00, 0x13, 0x74, QCA_RADIOTAP_VID_WLANTEST
,
82 if (!wt
->write_pcap_dumper
&& !wt
->pcapng
)
85 os_free(wt
->decrypted
);
86 len
= sizeof(rtap
) + len1
+ len2
;
87 wt
->decrypted
= buf
= os_malloc(len
);
90 wt
->decrypted_len
= len
;
91 os_memcpy(buf
, rtap
, sizeof(rtap
));
93 os_memcpy(buf
+ sizeof(rtap
), buf1
, len1
);
94 buf
[sizeof(rtap
) + 1] &= ~0x40; /* Clear Protected flag */
97 os_memcpy(buf
+ sizeof(rtap
) + len1
, buf2
, len2
);
99 if (!wt
->write_pcap_dumper
)
102 os_memset(&h
, 0, sizeof(h
));
103 h
.ts
= wt
->write_pcap_time
;
106 pcap_dump(wt
->write_pcap_dumper
, &h
, buf
);
107 if (wt
->pcap_no_buffer
)
108 pcap_dump_flush(wt
->write_pcap_dumper
);
112 struct pcapng_section_header
{
113 u32 block_type
; /* 0x0a0d0d0a */
115 u32 byte_order_magic
;
119 u32 block_total_len2
;
122 struct pcapng_interface_description
{
123 u32 block_type
; /* 0x00000001 */
128 u32 block_total_len2
;
131 struct pcapng_enhanced_packet
{
132 u32 block_type
; /* 0x00000006 */
139 /* Packet data - aligned to 32 bits */
140 /* Options (variable) */
141 /* Block Total Length copy */
144 #define PCAPNG_BYTE_ORDER_MAGIC 0x1a2b3c4d
145 #define PCAPNG_BLOCK_IFACE_DESC 0x00000001
146 #define PCAPNG_BLOCK_PACKET 0x00000002
147 #define PCAPNG_BLOCK_SIMPLE_PACKET 0x00000003
148 #define PCAPNG_BLOCK_NAME_RESOLUTION 0x00000004
149 #define PCAPNG_BLOCK_INTERFACE_STATISTICS 0x00000005
150 #define PCAPNG_BLOCK_ENHANCED_PACKET 0x00000006
151 #define PCAPNG_BLOCK_SECTION_HEADER 0x0a0d0d0a
153 #define LINKTYPE_IEEE802_11 105
154 #define LINKTYPE_IEEE802_11_RADIO 127
156 #define PAD32(a) ((4 - ((a) & 3)) & 3)
157 #define ALIGN32(a) ((a) + PAD32((a)))
160 int write_pcapng_init(struct wlantest
*wt
, const char *fname
)
162 struct pcapng_section_header hdr
;
163 struct pcapng_interface_description desc
;
165 wt
->pcapng
= fopen(fname
, "wb");
166 if (wt
->pcapng
== NULL
)
169 wpa_printf(MSG_DEBUG
, "Writing PCAPNG dump to '%s'", fname
);
171 os_memset(&hdr
, 0, sizeof(hdr
));
172 hdr
.block_type
= PCAPNG_BLOCK_SECTION_HEADER
;
173 hdr
.block_total_len
= sizeof(hdr
);
174 hdr
.byte_order_magic
= PCAPNG_BYTE_ORDER_MAGIC
;
175 hdr
.major_version
= 1;
176 hdr
.minor_version
= 0;
177 hdr
.section_len
= -1;
178 hdr
.block_total_len2
= hdr
.block_total_len
;
179 fwrite(&hdr
, sizeof(hdr
), 1, wt
->pcapng
);
181 os_memset(&desc
, 0, sizeof(desc
));
182 desc
.block_type
= PCAPNG_BLOCK_IFACE_DESC
;
183 desc
.block_total_len
= sizeof(desc
);
184 desc
.block_total_len2
= desc
.block_total_len
;
185 desc
.link_type
= LINKTYPE_IEEE802_11_RADIO
;
186 desc
.snap_len
= 65535;
187 fwrite(&desc
, sizeof(desc
), 1, wt
->pcapng
);
188 if (wt
->pcap_no_buffer
)
195 void write_pcapng_deinit(struct wlantest
*wt
)
204 static u8
* pcapng_add_comments(struct wlantest
*wt
, u8
*pos
)
212 *((u16
*) pos
) = 1 /* opt_comment */;
214 len
= (u16
*) pos
/* length to be filled in */;
217 for (i
= 0; i
< wt
->num_notes
; i
++) {
218 size_t nlen
= os_strlen(wt
->notes
[i
]);
221 os_memcpy(pos
, wt
->notes
[i
], nlen
);
224 *len
= pos
- (u8
*) len
- 2;
227 *((u16
*) pos
) = 0 /* opt_endofopt */;
236 static void write_pcapng_decrypted(struct wlantest
*wt
)
239 struct pcapng_enhanced_packet
*pkt
;
243 if (!wt
->pcapng
|| wt
->decrypted
== NULL
)
246 add_note(wt
, MSG_EXCESSIVE
, "decrypted version of the previous frame");
248 len
= sizeof(*pkt
) + wt
->decrypted_len
+ 100 + notes_len(wt
, 32);
249 pkt
= os_zalloc(len
);
253 pkt
->block_type
= PCAPNG_BLOCK_ENHANCED_PACKET
;
254 pkt
->interface_id
= 0;
255 pkt
->timestamp_high
= wt
->write_pcapng_time_high
;
256 pkt
->timestamp_low
= wt
->write_pcapng_time_low
;
257 pkt
->captured_len
= wt
->decrypted_len
;
258 pkt
->packet_len
= wt
->decrypted_len
;
260 pos
= (u8
*) (pkt
+ 1);
262 os_memcpy(pos
, wt
->decrypted
, wt
->decrypted_len
);
263 pos
+= ALIGN32(wt
->decrypted_len
);
265 pos
= pcapng_add_comments(wt
, pos
);
267 block_len
= (u32
*) pos
;
269 *block_len
= pkt
->block_total_len
= pos
- (u8
*) pkt
;
271 fwrite(pkt
, pos
- (u8
*) pkt
, 1, wt
->pcapng
);
272 if (wt
->pcap_no_buffer
)
279 void write_pcapng_write_read(struct wlantest
*wt
, int dlt
,
280 struct pcap_pkthdr
*hdr
, const u8
*data
)
282 struct pcapng_enhanced_packet
*pkt
;
286 size_t len
, datalen
= hdr
->caplen
;
290 0x0a, 0x00, /* header len */
291 0x02, 0x00, 0x00, 0x00, /* present flags */
302 len
= sizeof(*pkt
) + hdr
->len
+ 100 + notes_len(wt
, 32) + sizeof(rtap
);
303 pkt
= os_zalloc(len
);
307 pkt
->block_type
= PCAPNG_BLOCK_ENHANCED_PACKET
;
308 pkt
->interface_id
= 0;
309 timestamp
= 1000000 * hdr
->ts
.tv_sec
+ hdr
->ts
.tv_usec
;
310 pkt
->timestamp_high
= timestamp
>> 32;
311 pkt
->timestamp_low
= timestamp
& 0xffffffff;
312 wt
->write_pcapng_time_high
= pkt
->timestamp_high
;
313 wt
->write_pcapng_time_low
= pkt
->timestamp_low
;
314 pkt
->captured_len
= hdr
->caplen
;
315 pkt
->packet_len
= hdr
->len
;
317 pos
= (u8
*) (pkt
+ 1);
320 case DLT_IEEE802_11_RADIO
:
322 case DLT_PRISM_HEADER
:
323 /* remove prism header (could be kept ... lazy) */
324 pkt
->captured_len
-= WPA_GET_LE32(data
+ 4);
325 pkt
->packet_len
-= WPA_GET_LE32(data
+ 4);
326 datalen
-= WPA_GET_LE32(data
+ 4);
327 data
+= WPA_GET_LE32(data
+ 4);
330 pkt
->captured_len
+= sizeof(rtap
);
331 pkt
->packet_len
+= sizeof(rtap
);
332 os_memcpy(pos
, &rtap
, sizeof(rtap
));
339 os_memcpy(pos
, data
, datalen
);
340 pos
+= datalen
+ PAD32(pkt
->captured_len
);
341 pos
= pcapng_add_comments(wt
, pos
);
343 block_len
= (u32
*) pos
;
345 *block_len
= pkt
->block_total_len
= pos
- (u8
*) pkt
;
347 fwrite(pkt
, pos
- (u8
*) pkt
, 1, wt
->pcapng
);
348 if (wt
->pcap_no_buffer
)
353 write_pcapng_decrypted(wt
);
357 void write_pcapng_captured(struct wlantest
*wt
, const u8
*buf
, size_t len
)
359 struct pcap_pkthdr h
;
364 os_memset(&h
, 0, sizeof(h
));
365 gettimeofday(&h
.ts
, NULL
);
368 write_pcapng_write_read(wt
, DLT_IEEE802_11_RADIO
, &h
, buf
);