1 | #include <machine/rtems-bsd-user-space.h> |
---|
2 | |
---|
3 | /* |
---|
4 | * Copyright (c) 1993, 1994, 1995, 1996, 1997 |
---|
5 | * The Regents of the University of California. All rights reserved. |
---|
6 | * |
---|
7 | * Redistribution and use in source and binary forms, with or without |
---|
8 | * modification, are permitted provided that: (1) source code distributions |
---|
9 | * retain the above copyright notice and this paragraph in its entirety, (2) |
---|
10 | * distributions including binary code include the above copyright notice and |
---|
11 | * this paragraph in its entirety in the documentation or other materials |
---|
12 | * provided with the distribution, and (3) all advertising materials mentioning |
---|
13 | * features or use of this software display the following acknowledgement: |
---|
14 | * ``This product includes software developed by the University of California, |
---|
15 | * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of |
---|
16 | * the University nor the names of its contributors may be used to endorse |
---|
17 | * or promote products derived from this software without specific prior |
---|
18 | * written permission. |
---|
19 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED |
---|
20 | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
---|
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
---|
22 | * |
---|
23 | * sf-pcap-ng.c - pcap-ng-file-format-specific code from savefile.c |
---|
24 | */ |
---|
25 | |
---|
26 | #ifndef lint |
---|
27 | static const char rcsid[] _U_ = |
---|
28 | "@(#) $Header$ (LBL)"; |
---|
29 | #endif |
---|
30 | |
---|
31 | #ifdef HAVE_CONFIG_H |
---|
32 | #include "config.h" |
---|
33 | #endif |
---|
34 | |
---|
35 | #ifdef _WIN32 |
---|
36 | #include <pcap-stdinc.h> |
---|
37 | #else /* _WIN32 */ |
---|
38 | #if HAVE_INTTYPES_H |
---|
39 | #include <inttypes.h> |
---|
40 | #elif HAVE_STDINT_H |
---|
41 | #include <stdint.h> |
---|
42 | #endif |
---|
43 | #ifdef HAVE_SYS_BITYPES_H |
---|
44 | #include <sys/bitypes.h> |
---|
45 | #endif |
---|
46 | #include <sys/types.h> |
---|
47 | #endif /* _WIN32 */ |
---|
48 | |
---|
49 | #include <errno.h> |
---|
50 | #include <memory.h> |
---|
51 | #include <stdio.h> |
---|
52 | #include <stdlib.h> |
---|
53 | #include <string.h> |
---|
54 | |
---|
55 | #include "pcap-int.h" |
---|
56 | |
---|
57 | #include "pcap-common.h" |
---|
58 | |
---|
59 | #ifdef HAVE_OS_PROTO_H |
---|
60 | #include "os-proto.h" |
---|
61 | #endif |
---|
62 | |
---|
63 | #include "sf-pcap-ng.h" |
---|
64 | |
---|
65 | /* |
---|
66 | * Block types. |
---|
67 | */ |
---|
68 | |
---|
69 | /* |
---|
70 | * Common part at the beginning of all blocks. |
---|
71 | */ |
---|
72 | struct block_header { |
---|
73 | bpf_u_int32 block_type; |
---|
74 | bpf_u_int32 total_length; |
---|
75 | }; |
---|
76 | |
---|
77 | /* |
---|
78 | * Common trailer at the end of all blocks. |
---|
79 | */ |
---|
80 | struct block_trailer { |
---|
81 | bpf_u_int32 total_length; |
---|
82 | }; |
---|
83 | |
---|
84 | /* |
---|
85 | * Common options. |
---|
86 | */ |
---|
87 | #define OPT_ENDOFOPT 0 /* end of options */ |
---|
88 | #define OPT_COMMENT 1 /* comment string */ |
---|
89 | |
---|
90 | /* |
---|
91 | * Option header. |
---|
92 | */ |
---|
93 | struct option_header { |
---|
94 | u_short option_code; |
---|
95 | u_short option_length; |
---|
96 | }; |
---|
97 | |
---|
98 | /* |
---|
99 | * Structures for the part of each block type following the common |
---|
100 | * part. |
---|
101 | */ |
---|
102 | |
---|
103 | /* |
---|
104 | * Section Header Block. |
---|
105 | */ |
---|
106 | #define BT_SHB 0x0A0D0D0A |
---|
107 | |
---|
108 | struct section_header_block { |
---|
109 | bpf_u_int32 byte_order_magic; |
---|
110 | u_short major_version; |
---|
111 | u_short minor_version; |
---|
112 | u_int64_t section_length; |
---|
113 | /* followed by options and trailer */ |
---|
114 | }; |
---|
115 | |
---|
116 | /* |
---|
117 | * Byte-order magic value. |
---|
118 | */ |
---|
119 | #define BYTE_ORDER_MAGIC 0x1A2B3C4D |
---|
120 | |
---|
121 | /* |
---|
122 | * Current version number. If major_version isn't PCAP_NG_VERSION_MAJOR, |
---|
123 | * that means that this code can't read the file. |
---|
124 | */ |
---|
125 | #define PCAP_NG_VERSION_MAJOR 1 |
---|
126 | #define PCAP_NG_VERSION_MINOR 0 |
---|
127 | |
---|
128 | /* |
---|
129 | * Interface Description Block. |
---|
130 | */ |
---|
131 | #define BT_IDB 0x00000001 |
---|
132 | |
---|
133 | struct interface_description_block { |
---|
134 | u_short linktype; |
---|
135 | u_short reserved; |
---|
136 | bpf_u_int32 snaplen; |
---|
137 | /* followed by options and trailer */ |
---|
138 | }; |
---|
139 | |
---|
140 | /* |
---|
141 | * Options in the IDB. |
---|
142 | */ |
---|
143 | #define IF_NAME 2 /* interface name string */ |
---|
144 | #define IF_DESCRIPTION 3 /* interface description string */ |
---|
145 | #define IF_IPV4ADDR 4 /* interface's IPv4 address and netmask */ |
---|
146 | #define IF_IPV6ADDR 5 /* interface's IPv6 address and prefix length */ |
---|
147 | #define IF_MACADDR 6 /* interface's MAC address */ |
---|
148 | #define IF_EUIADDR 7 /* interface's EUI address */ |
---|
149 | #define IF_SPEED 8 /* interface's speed, in bits/s */ |
---|
150 | #define IF_TSRESOL 9 /* interface's time stamp resolution */ |
---|
151 | #define IF_TZONE 10 /* interface's time zone */ |
---|
152 | #define IF_FILTER 11 /* filter used when capturing on interface */ |
---|
153 | #define IF_OS 12 /* string OS on which capture on this interface was done */ |
---|
154 | #define IF_FCSLEN 13 /* FCS length for this interface */ |
---|
155 | #define IF_TSOFFSET 14 /* time stamp offset for this interface */ |
---|
156 | |
---|
157 | /* |
---|
158 | * Enhanced Packet Block. |
---|
159 | */ |
---|
160 | #define BT_EPB 0x00000006 |
---|
161 | |
---|
162 | struct enhanced_packet_block { |
---|
163 | bpf_u_int32 interface_id; |
---|
164 | bpf_u_int32 timestamp_high; |
---|
165 | bpf_u_int32 timestamp_low; |
---|
166 | bpf_u_int32 caplen; |
---|
167 | bpf_u_int32 len; |
---|
168 | /* followed by packet data, options, and trailer */ |
---|
169 | }; |
---|
170 | |
---|
171 | /* |
---|
172 | * Simple Packet Block. |
---|
173 | */ |
---|
174 | #define BT_SPB 0x00000003 |
---|
175 | |
---|
176 | struct simple_packet_block { |
---|
177 | bpf_u_int32 len; |
---|
178 | /* followed by packet data and trailer */ |
---|
179 | }; |
---|
180 | |
---|
181 | /* |
---|
182 | * Packet Block. |
---|
183 | */ |
---|
184 | #define BT_PB 0x00000002 |
---|
185 | |
---|
186 | struct packet_block { |
---|
187 | u_short interface_id; |
---|
188 | u_short drops_count; |
---|
189 | bpf_u_int32 timestamp_high; |
---|
190 | bpf_u_int32 timestamp_low; |
---|
191 | bpf_u_int32 caplen; |
---|
192 | bpf_u_int32 len; |
---|
193 | /* followed by packet data, options, and trailer */ |
---|
194 | }; |
---|
195 | |
---|
196 | /* |
---|
197 | * Block cursor - used when processing the contents of a block. |
---|
198 | * Contains a pointer into the data being processed and a count |
---|
199 | * of bytes remaining in the block. |
---|
200 | */ |
---|
201 | struct block_cursor { |
---|
202 | u_char *data; |
---|
203 | size_t data_remaining; |
---|
204 | bpf_u_int32 block_type; |
---|
205 | }; |
---|
206 | |
---|
207 | typedef enum { |
---|
208 | PASS_THROUGH, |
---|
209 | SCALE_UP_DEC, |
---|
210 | SCALE_DOWN_DEC, |
---|
211 | SCALE_UP_BIN, |
---|
212 | SCALE_DOWN_BIN |
---|
213 | } tstamp_scale_type_t; |
---|
214 | |
---|
215 | /* |
---|
216 | * Per-interface information. |
---|
217 | */ |
---|
218 | struct pcap_ng_if { |
---|
219 | u_int tsresol; /* time stamp resolution */ |
---|
220 | tstamp_scale_type_t scale_type; /* how to scale */ |
---|
221 | u_int scale_factor; /* time stamp scale factor for power-of-10 tsresol */ |
---|
222 | u_int64_t tsoffset; /* time stamp offset */ |
---|
223 | }; |
---|
224 | |
---|
225 | struct pcap_ng_sf { |
---|
226 | u_int user_tsresol; /* time stamp resolution requested by the user */ |
---|
227 | bpf_u_int32 ifcount; /* number of interfaces seen in this capture */ |
---|
228 | bpf_u_int32 ifaces_size; /* size of array below */ |
---|
229 | struct pcap_ng_if *ifaces; /* array of interface information */ |
---|
230 | }; |
---|
231 | |
---|
232 | static void pcap_ng_cleanup(pcap_t *p); |
---|
233 | static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, |
---|
234 | u_char **data); |
---|
235 | |
---|
236 | static int |
---|
237 | read_bytes(FILE *fp, void *buf, size_t bytes_to_read, int fail_on_eof, |
---|
238 | char *errbuf) |
---|
239 | { |
---|
240 | size_t amt_read; |
---|
241 | |
---|
242 | amt_read = fread(buf, 1, bytes_to_read, fp); |
---|
243 | if (amt_read != bytes_to_read) { |
---|
244 | if (ferror(fp)) { |
---|
245 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
246 | "error reading dump file: %s", |
---|
247 | pcap_strerror(errno)); |
---|
248 | } else { |
---|
249 | if (amt_read == 0 && !fail_on_eof) |
---|
250 | return (0); /* EOF */ |
---|
251 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
252 | "truncated dump file; tried to read %lu bytes, only got %lu", |
---|
253 | (unsigned long)bytes_to_read, |
---|
254 | (unsigned long)amt_read); |
---|
255 | } |
---|
256 | return (-1); |
---|
257 | } |
---|
258 | return (1); |
---|
259 | } |
---|
260 | |
---|
261 | static int |
---|
262 | read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf) |
---|
263 | { |
---|
264 | int status; |
---|
265 | struct block_header bhdr; |
---|
266 | u_char *bdata; |
---|
267 | size_t data_remaining; |
---|
268 | |
---|
269 | status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf); |
---|
270 | if (status <= 0) |
---|
271 | return (status); /* error or EOF */ |
---|
272 | |
---|
273 | if (p->swapped) { |
---|
274 | bhdr.block_type = SWAPLONG(bhdr.block_type); |
---|
275 | bhdr.total_length = SWAPLONG(bhdr.total_length); |
---|
276 | } |
---|
277 | |
---|
278 | /* |
---|
279 | * Is this block "too big"? |
---|
280 | * |
---|
281 | * We choose 16MB as "too big", for now, so that we handle |
---|
282 | * "reasonably" large buffers but don't chew up all the |
---|
283 | * memory if we read a malformed file. |
---|
284 | */ |
---|
285 | if (bhdr.total_length > 16*1024*1024) { |
---|
286 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
287 | "pcap-ng block size %u > maximum %u", |
---|
288 | bhdr.total_length, 16*1024*1024); |
---|
289 | return (-1); |
---|
290 | } |
---|
291 | |
---|
292 | /* |
---|
293 | * Is this block "too small" - i.e., is it shorter than a block |
---|
294 | * header plus a block trailer? |
---|
295 | */ |
---|
296 | if (bhdr.total_length < sizeof(struct block_header) + |
---|
297 | sizeof(struct block_trailer)) { |
---|
298 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
299 | "block in pcap-ng dump file has a length of %u < %lu", |
---|
300 | bhdr.total_length, |
---|
301 | (unsigned long)(sizeof(struct block_header) + sizeof(struct block_trailer))); |
---|
302 | return (-1); |
---|
303 | } |
---|
304 | |
---|
305 | /* |
---|
306 | * Is the buffer big enough? |
---|
307 | */ |
---|
308 | if (p->bufsize < bhdr.total_length) { |
---|
309 | /* |
---|
310 | * No - make it big enough. |
---|
311 | */ |
---|
312 | void *bigger_buffer; |
---|
313 | |
---|
314 | bigger_buffer = realloc(p->buffer, bhdr.total_length); |
---|
315 | if (bigger_buffer == NULL) { |
---|
316 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory"); |
---|
317 | return (-1); |
---|
318 | } |
---|
319 | p->buffer = bigger_buffer; |
---|
320 | } |
---|
321 | |
---|
322 | /* |
---|
323 | * Copy the stuff we've read to the buffer, and read the rest |
---|
324 | * of the block. |
---|
325 | */ |
---|
326 | memcpy(p->buffer, &bhdr, sizeof(bhdr)); |
---|
327 | bdata = (u_char *)p->buffer + sizeof(bhdr); |
---|
328 | data_remaining = bhdr.total_length - sizeof(bhdr); |
---|
329 | if (read_bytes(fp, bdata, data_remaining, 1, errbuf) == -1) |
---|
330 | return (-1); |
---|
331 | |
---|
332 | /* |
---|
333 | * Initialize the cursor. |
---|
334 | */ |
---|
335 | cursor->data = bdata; |
---|
336 | cursor->data_remaining = data_remaining - sizeof(struct block_trailer); |
---|
337 | cursor->block_type = bhdr.block_type; |
---|
338 | return (1); |
---|
339 | } |
---|
340 | |
---|
341 | static void * |
---|
342 | get_from_block_data(struct block_cursor *cursor, size_t chunk_size, |
---|
343 | char *errbuf) |
---|
344 | { |
---|
345 | void *data; |
---|
346 | |
---|
347 | /* |
---|
348 | * Make sure we have the specified amount of data remaining in |
---|
349 | * the block data. |
---|
350 | */ |
---|
351 | if (cursor->data_remaining < chunk_size) { |
---|
352 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
353 | "block of type %u in pcap-ng dump file is too short", |
---|
354 | cursor->block_type); |
---|
355 | return (NULL); |
---|
356 | } |
---|
357 | |
---|
358 | /* |
---|
359 | * Return the current pointer, and skip past the chunk. |
---|
360 | */ |
---|
361 | data = cursor->data; |
---|
362 | cursor->data += chunk_size; |
---|
363 | cursor->data_remaining -= chunk_size; |
---|
364 | return (data); |
---|
365 | } |
---|
366 | |
---|
367 | static struct option_header * |
---|
368 | get_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf) |
---|
369 | { |
---|
370 | struct option_header *opthdr; |
---|
371 | |
---|
372 | opthdr = get_from_block_data(cursor, sizeof(*opthdr), errbuf); |
---|
373 | if (opthdr == NULL) { |
---|
374 | /* |
---|
375 | * Option header is cut short. |
---|
376 | */ |
---|
377 | return (NULL); |
---|
378 | } |
---|
379 | |
---|
380 | /* |
---|
381 | * Byte-swap it if necessary. |
---|
382 | */ |
---|
383 | if (p->swapped) { |
---|
384 | opthdr->option_code = SWAPSHORT(opthdr->option_code); |
---|
385 | opthdr->option_length = SWAPSHORT(opthdr->option_length); |
---|
386 | } |
---|
387 | |
---|
388 | return (opthdr); |
---|
389 | } |
---|
390 | |
---|
391 | static void * |
---|
392 | get_optvalue_from_block_data(struct block_cursor *cursor, |
---|
393 | struct option_header *opthdr, char *errbuf) |
---|
394 | { |
---|
395 | size_t padded_option_len; |
---|
396 | void *optvalue; |
---|
397 | |
---|
398 | /* Pad option length to 4-byte boundary */ |
---|
399 | padded_option_len = opthdr->option_length; |
---|
400 | padded_option_len = ((padded_option_len + 3)/4)*4; |
---|
401 | |
---|
402 | optvalue = get_from_block_data(cursor, padded_option_len, errbuf); |
---|
403 | if (optvalue == NULL) { |
---|
404 | /* |
---|
405 | * Option value is cut short. |
---|
406 | */ |
---|
407 | return (NULL); |
---|
408 | } |
---|
409 | |
---|
410 | return (optvalue); |
---|
411 | } |
---|
412 | |
---|
413 | static int |
---|
414 | process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol, |
---|
415 | u_int64_t *tsoffset, int *is_binary, char *errbuf) |
---|
416 | { |
---|
417 | struct option_header *opthdr; |
---|
418 | void *optvalue; |
---|
419 | int saw_tsresol, saw_tsoffset; |
---|
420 | u_char tsresol_opt; |
---|
421 | u_int i; |
---|
422 | |
---|
423 | saw_tsresol = 0; |
---|
424 | saw_tsoffset = 0; |
---|
425 | while (cursor->data_remaining != 0) { |
---|
426 | /* |
---|
427 | * Get the option header. |
---|
428 | */ |
---|
429 | opthdr = get_opthdr_from_block_data(p, cursor, errbuf); |
---|
430 | if (opthdr == NULL) { |
---|
431 | /* |
---|
432 | * Option header is cut short. |
---|
433 | */ |
---|
434 | return (-1); |
---|
435 | } |
---|
436 | |
---|
437 | /* |
---|
438 | * Get option value. |
---|
439 | */ |
---|
440 | optvalue = get_optvalue_from_block_data(cursor, opthdr, |
---|
441 | errbuf); |
---|
442 | if (optvalue == NULL) { |
---|
443 | /* |
---|
444 | * Option value is cut short. |
---|
445 | */ |
---|
446 | return (-1); |
---|
447 | } |
---|
448 | |
---|
449 | switch (opthdr->option_code) { |
---|
450 | |
---|
451 | case OPT_ENDOFOPT: |
---|
452 | if (opthdr->option_length != 0) { |
---|
453 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
454 | "Interface Description Block has opt_endofopt option with length %u != 0", |
---|
455 | opthdr->option_length); |
---|
456 | return (-1); |
---|
457 | } |
---|
458 | goto done; |
---|
459 | |
---|
460 | case IF_TSRESOL: |
---|
461 | if (opthdr->option_length != 1) { |
---|
462 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
463 | "Interface Description Block has if_tsresol option with length %u != 1", |
---|
464 | opthdr->option_length); |
---|
465 | return (-1); |
---|
466 | } |
---|
467 | if (saw_tsresol) { |
---|
468 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
469 | "Interface Description Block has more than one if_tsresol option"); |
---|
470 | return (-1); |
---|
471 | } |
---|
472 | saw_tsresol = 1; |
---|
473 | memcpy(&tsresol_opt, optvalue, sizeof(tsresol_opt)); |
---|
474 | if (tsresol_opt & 0x80) { |
---|
475 | /* |
---|
476 | * Resolution is negative power of 2. |
---|
477 | */ |
---|
478 | *is_binary = 1; |
---|
479 | *tsresol = 1 << (tsresol_opt & 0x7F); |
---|
480 | } else { |
---|
481 | /* |
---|
482 | * Resolution is negative power of 10. |
---|
483 | */ |
---|
484 | *is_binary = 0; |
---|
485 | *tsresol = 1; |
---|
486 | for (i = 0; i < tsresol_opt; i++) |
---|
487 | *tsresol *= 10; |
---|
488 | } |
---|
489 | if (*tsresol == 0) { |
---|
490 | /* |
---|
491 | * Resolution is too high. |
---|
492 | */ |
---|
493 | if (tsresol_opt & 0x80) { |
---|
494 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
495 | "Interface Description Block if_tsresol option resolution 2^-%u is too high", |
---|
496 | tsresol_opt & 0x7F); |
---|
497 | } else { |
---|
498 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
499 | "Interface Description Block if_tsresol option resolution 10^-%u is too high", |
---|
500 | tsresol_opt); |
---|
501 | } |
---|
502 | return (-1); |
---|
503 | } |
---|
504 | break; |
---|
505 | |
---|
506 | case IF_TSOFFSET: |
---|
507 | if (opthdr->option_length != 8) { |
---|
508 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
509 | "Interface Description Block has if_tsoffset option with length %u != 8", |
---|
510 | opthdr->option_length); |
---|
511 | return (-1); |
---|
512 | } |
---|
513 | if (saw_tsoffset) { |
---|
514 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
515 | "Interface Description Block has more than one if_tsoffset option"); |
---|
516 | return (-1); |
---|
517 | } |
---|
518 | saw_tsoffset = 1; |
---|
519 | memcpy(tsoffset, optvalue, sizeof(*tsoffset)); |
---|
520 | if (p->swapped) |
---|
521 | *tsoffset = SWAPLL(*tsoffset); |
---|
522 | break; |
---|
523 | |
---|
524 | default: |
---|
525 | break; |
---|
526 | } |
---|
527 | } |
---|
528 | |
---|
529 | done: |
---|
530 | return (0); |
---|
531 | } |
---|
532 | |
---|
533 | static int |
---|
534 | add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf) |
---|
535 | { |
---|
536 | struct pcap_ng_sf *ps; |
---|
537 | u_int tsresol; |
---|
538 | u_int64_t tsoffset; |
---|
539 | int is_binary; |
---|
540 | |
---|
541 | ps = p->priv; |
---|
542 | |
---|
543 | /* |
---|
544 | * Count this interface. |
---|
545 | */ |
---|
546 | ps->ifcount++; |
---|
547 | |
---|
548 | /* |
---|
549 | * Grow the array of per-interface information as necessary. |
---|
550 | */ |
---|
551 | if (ps->ifcount > ps->ifaces_size) { |
---|
552 | /* |
---|
553 | * We need to grow the array. |
---|
554 | */ |
---|
555 | bpf_u_int32 new_ifaces_size; |
---|
556 | struct pcap_ng_if *new_ifaces; |
---|
557 | |
---|
558 | if (ps->ifaces_size == 0) { |
---|
559 | /* |
---|
560 | * It's currently empty. |
---|
561 | * |
---|
562 | * (The Clang static analyzer doesn't do enough, |
---|
563 | * err, umm, dataflow *analysis* to realize that |
---|
564 | * ps->ifaces_size == 0 if ps->ifaces == NULL, |
---|
565 | * and so complains about a possible zero argument |
---|
566 | * to realloc(), so we check for the former |
---|
567 | * condition to shut it up. |
---|
568 | * |
---|
569 | * However, it doesn't complain that one of the |
---|
570 | * multiplications below could overflow, which is |
---|
571 | * a real, albeit extremely unlikely, problem (you'd |
---|
572 | * need a pcap-ng file with tens of millions of |
---|
573 | * interfaces).) |
---|
574 | */ |
---|
575 | new_ifaces_size = 1; |
---|
576 | new_ifaces = malloc(sizeof (struct pcap_ng_if)); |
---|
577 | } else { |
---|
578 | /* |
---|
579 | * It's not currently empty; double its size. |
---|
580 | * (Perhaps overkill once we have a lot of interfaces.) |
---|
581 | * |
---|
582 | * Check for overflow if we double it. |
---|
583 | */ |
---|
584 | if (ps->ifaces_size * 2 < ps->ifaces_size) { |
---|
585 | /* |
---|
586 | * The maximum number of interfaces before |
---|
587 | * ps->ifaces_size overflows is the largest |
---|
588 | * possible 32-bit power of 2, as we do |
---|
589 | * size doubling. |
---|
590 | */ |
---|
591 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
592 | "more than %u interfaces in the file", |
---|
593 | 0x80000000U); |
---|
594 | return (0); |
---|
595 | } |
---|
596 | |
---|
597 | /* |
---|
598 | * ps->ifaces_size * 2 doesn't overflow, so it's |
---|
599 | * safe to multiply. |
---|
600 | */ |
---|
601 | new_ifaces_size = ps->ifaces_size * 2; |
---|
602 | |
---|
603 | /* |
---|
604 | * Now make sure that's not so big that it overflows |
---|
605 | * if we multiply by sizeof (struct pcap_ng_if). |
---|
606 | * |
---|
607 | * That can happen on 32-bit platforms, with a 32-bit |
---|
608 | * size_t; it shouldn't happen on 64-bit platforms, |
---|
609 | * with a 64-bit size_t, as new_ifaces_size is |
---|
610 | * 32 bits. |
---|
611 | */ |
---|
612 | if (new_ifaces_size * sizeof (struct pcap_ng_if) < new_ifaces_size) { |
---|
613 | /* |
---|
614 | * As this fails only with 32-bit size_t, |
---|
615 | * the multiplication was 32x32->32, and |
---|
616 | * the largest 32-bit value that can safely |
---|
617 | * be multiplied by sizeof (struct pcap_ng_if) |
---|
618 | * without overflow is the largest 32-bit |
---|
619 | * (unsigned) value divided by |
---|
620 | * sizeof (struct pcap_ng_if). |
---|
621 | */ |
---|
622 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
623 | "more than %u interfaces in the file", |
---|
624 | 0xFFFFFFFFU / ((u_int)sizeof (struct pcap_ng_if))); |
---|
625 | return (0); |
---|
626 | } |
---|
627 | new_ifaces = realloc(ps->ifaces, new_ifaces_size * sizeof (struct pcap_ng_if)); |
---|
628 | } |
---|
629 | if (new_ifaces == NULL) { |
---|
630 | /* |
---|
631 | * We ran out of memory. |
---|
632 | * Give up. |
---|
633 | */ |
---|
634 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
635 | "out of memory for per-interface information (%u interfaces)", |
---|
636 | ps->ifcount); |
---|
637 | return (0); |
---|
638 | } |
---|
639 | ps->ifaces_size = new_ifaces_size; |
---|
640 | ps->ifaces = new_ifaces; |
---|
641 | } |
---|
642 | |
---|
643 | /* |
---|
644 | * Set the default time stamp resolution and offset. |
---|
645 | */ |
---|
646 | tsresol = 1000000; /* microsecond resolution */ |
---|
647 | is_binary = 0; /* which is a power of 10 */ |
---|
648 | tsoffset = 0; /* absolute timestamps */ |
---|
649 | |
---|
650 | /* |
---|
651 | * Now look for various time stamp options, so we know |
---|
652 | * how to interpret the time stamps for this interface. |
---|
653 | */ |
---|
654 | if (process_idb_options(p, cursor, &tsresol, &tsoffset, &is_binary, |
---|
655 | errbuf) == -1) |
---|
656 | return (0); |
---|
657 | |
---|
658 | ps->ifaces[ps->ifcount - 1].tsresol = tsresol; |
---|
659 | ps->ifaces[ps->ifcount - 1].tsoffset = tsoffset; |
---|
660 | |
---|
661 | /* |
---|
662 | * Determine whether we're scaling up or down or not |
---|
663 | * at all for this interface. |
---|
664 | */ |
---|
665 | if (tsresol == ps->user_tsresol) { |
---|
666 | /* |
---|
667 | * The resolution is the resolution the user wants, |
---|
668 | * so we don't have to do scaling. |
---|
669 | */ |
---|
670 | ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH; |
---|
671 | } else if (tsresol > ps->user_tsresol) { |
---|
672 | /* |
---|
673 | * The resolution is greater than what the user wants, |
---|
674 | * so we have to scale the timestamps down. |
---|
675 | */ |
---|
676 | if (is_binary) |
---|
677 | ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_BIN; |
---|
678 | else { |
---|
679 | /* |
---|
680 | * Calculate the scale factor. |
---|
681 | */ |
---|
682 | ps->ifaces[ps->ifcount - 1].scale_factor = tsresol/ps->user_tsresol; |
---|
683 | ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_DEC; |
---|
684 | } |
---|
685 | } else { |
---|
686 | /* |
---|
687 | * The resolution is less than what the user wants, |
---|
688 | * so we have to scale the timestamps up. |
---|
689 | */ |
---|
690 | if (is_binary) |
---|
691 | ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_BIN; |
---|
692 | else { |
---|
693 | /* |
---|
694 | * Calculate the scale factor. |
---|
695 | */ |
---|
696 | ps->ifaces[ps->ifcount - 1].scale_factor = ps->user_tsresol/tsresol; |
---|
697 | ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_DEC; |
---|
698 | } |
---|
699 | } |
---|
700 | return (1); |
---|
701 | } |
---|
702 | |
---|
703 | /* |
---|
704 | * Check whether this is a pcap-ng savefile and, if it is, extract the |
---|
705 | * relevant information from the header. |
---|
706 | */ |
---|
707 | pcap_t * |
---|
708 | pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, |
---|
709 | int *err) |
---|
710 | { |
---|
711 | size_t amt_read; |
---|
712 | bpf_u_int32 total_length; |
---|
713 | bpf_u_int32 byte_order_magic; |
---|
714 | struct block_header *bhdrp; |
---|
715 | struct section_header_block *shbp; |
---|
716 | pcap_t *p; |
---|
717 | int swapped = 0; |
---|
718 | struct pcap_ng_sf *ps; |
---|
719 | int status; |
---|
720 | struct block_cursor cursor; |
---|
721 | struct interface_description_block *idbp; |
---|
722 | |
---|
723 | /* |
---|
724 | * Assume no read errors. |
---|
725 | */ |
---|
726 | *err = 0; |
---|
727 | |
---|
728 | /* |
---|
729 | * Check whether the first 4 bytes of the file are the block |
---|
730 | * type for a pcap-ng savefile. |
---|
731 | */ |
---|
732 | if (magic != BT_SHB) { |
---|
733 | /* |
---|
734 | * XXX - check whether this looks like what the block |
---|
735 | * type would be after being munged by mapping between |
---|
736 | * UN*X and DOS/Windows text file format and, if it |
---|
737 | * does, look for the byte-order magic number in |
---|
738 | * the appropriate place and, if we find it, report |
---|
739 | * this as possibly being a pcap-ng file transferred |
---|
740 | * between UN*X and Windows in text file format? |
---|
741 | */ |
---|
742 | return (NULL); /* nope */ |
---|
743 | } |
---|
744 | |
---|
745 | /* |
---|
746 | * OK, they are. However, that's just \n\r\r\n, so it could, |
---|
747 | * conceivably, be an ordinary text file. |
---|
748 | * |
---|
749 | * It could not, however, conceivably be any other type of |
---|
750 | * capture file, so we can read the rest of the putative |
---|
751 | * Section Header Block; put the block type in the common |
---|
752 | * header, read the rest of the common header and the |
---|
753 | * fixed-length portion of the SHB, and look for the byte-order |
---|
754 | * magic value. |
---|
755 | */ |
---|
756 | amt_read = fread(&total_length, 1, sizeof(total_length), fp); |
---|
757 | if (amt_read < sizeof(total_length)) { |
---|
758 | if (ferror(fp)) { |
---|
759 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
760 | "error reading dump file: %s", |
---|
761 | pcap_strerror(errno)); |
---|
762 | *err = 1; |
---|
763 | return (NULL); /* fail */ |
---|
764 | } |
---|
765 | |
---|
766 | /* |
---|
767 | * Possibly a weird short text file, so just say |
---|
768 | * "not pcap-ng". |
---|
769 | */ |
---|
770 | return (NULL); |
---|
771 | } |
---|
772 | amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp); |
---|
773 | if (amt_read < sizeof(byte_order_magic)) { |
---|
774 | if (ferror(fp)) { |
---|
775 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
776 | "error reading dump file: %s", |
---|
777 | pcap_strerror(errno)); |
---|
778 | *err = 1; |
---|
779 | return (NULL); /* fail */ |
---|
780 | } |
---|
781 | |
---|
782 | /* |
---|
783 | * Possibly a weird short text file, so just say |
---|
784 | * "not pcap-ng". |
---|
785 | */ |
---|
786 | return (NULL); |
---|
787 | } |
---|
788 | if (byte_order_magic != BYTE_ORDER_MAGIC) { |
---|
789 | byte_order_magic = SWAPLONG(byte_order_magic); |
---|
790 | if (byte_order_magic != BYTE_ORDER_MAGIC) { |
---|
791 | /* |
---|
792 | * Not a pcap-ng file. |
---|
793 | */ |
---|
794 | return (NULL); |
---|
795 | } |
---|
796 | swapped = 1; |
---|
797 | total_length = SWAPLONG(total_length); |
---|
798 | } |
---|
799 | |
---|
800 | /* |
---|
801 | * Check the sanity of the total length. |
---|
802 | */ |
---|
803 | if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)) { |
---|
804 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
805 | "Section Header Block in pcap-ng dump file has a length of %u < %lu", |
---|
806 | total_length, |
---|
807 | (unsigned long)(sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer))); |
---|
808 | *err = 1; |
---|
809 | return (NULL); |
---|
810 | } |
---|
811 | |
---|
812 | /* |
---|
813 | * OK, this is a good pcap-ng file. |
---|
814 | * Allocate a pcap_t for it. |
---|
815 | */ |
---|
816 | p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf)); |
---|
817 | if (p == NULL) { |
---|
818 | /* Allocation failed. */ |
---|
819 | *err = 1; |
---|
820 | return (NULL); |
---|
821 | } |
---|
822 | p->swapped = swapped; |
---|
823 | ps = p->priv; |
---|
824 | |
---|
825 | /* |
---|
826 | * What precision does the user want? |
---|
827 | */ |
---|
828 | switch (precision) { |
---|
829 | |
---|
830 | case PCAP_TSTAMP_PRECISION_MICRO: |
---|
831 | ps->user_tsresol = 1000000; |
---|
832 | break; |
---|
833 | |
---|
834 | case PCAP_TSTAMP_PRECISION_NANO: |
---|
835 | ps->user_tsresol = 1000000000; |
---|
836 | break; |
---|
837 | |
---|
838 | default: |
---|
839 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
840 | "unknown time stamp resolution %u", precision); |
---|
841 | free(p); |
---|
842 | *err = 1; |
---|
843 | return (NULL); |
---|
844 | } |
---|
845 | |
---|
846 | p->opt.tstamp_precision = precision; |
---|
847 | |
---|
848 | /* |
---|
849 | * Allocate a buffer into which to read blocks. We default to |
---|
850 | * the maximum of: |
---|
851 | * |
---|
852 | * the total length of the SHB for which we read the header; |
---|
853 | * |
---|
854 | * 2K, which should be more than large enough for an Enhanced |
---|
855 | * Packet Block containing a full-size Ethernet frame, and |
---|
856 | * leaving room for some options. |
---|
857 | * |
---|
858 | * If we find a bigger block, we reallocate the buffer. |
---|
859 | */ |
---|
860 | p->bufsize = 2048; |
---|
861 | if (p->bufsize < total_length) |
---|
862 | p->bufsize = total_length; |
---|
863 | p->buffer = malloc(p->bufsize); |
---|
864 | if (p->buffer == NULL) { |
---|
865 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory"); |
---|
866 | free(p); |
---|
867 | *err = 1; |
---|
868 | return (NULL); |
---|
869 | } |
---|
870 | |
---|
871 | /* |
---|
872 | * Copy the stuff we've read to the buffer, and read the rest |
---|
873 | * of the SHB. |
---|
874 | */ |
---|
875 | bhdrp = (struct block_header *)p->buffer; |
---|
876 | shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header)); |
---|
877 | bhdrp->block_type = magic; |
---|
878 | bhdrp->total_length = total_length; |
---|
879 | shbp->byte_order_magic = byte_order_magic; |
---|
880 | if (read_bytes(fp, |
---|
881 | (u_char *)p->buffer + (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)), |
---|
882 | total_length - (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)), |
---|
883 | 1, errbuf) == -1) |
---|
884 | goto fail; |
---|
885 | |
---|
886 | if (p->swapped) { |
---|
887 | /* |
---|
888 | * Byte-swap the fields we've read. |
---|
889 | */ |
---|
890 | shbp->major_version = SWAPSHORT(shbp->major_version); |
---|
891 | shbp->minor_version = SWAPSHORT(shbp->minor_version); |
---|
892 | |
---|
893 | /* |
---|
894 | * XXX - we don't care about the section length. |
---|
895 | */ |
---|
896 | } |
---|
897 | /* currently only SHB version 1.0 is supported */ |
---|
898 | if (! (shbp->major_version == PCAP_NG_VERSION_MAJOR && |
---|
899 | shbp->minor_version == PCAP_NG_VERSION_MINOR)) { |
---|
900 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
901 | "unsupported pcap-ng savefile version %u.%u", |
---|
902 | shbp->major_version, shbp->minor_version); |
---|
903 | goto fail; |
---|
904 | } |
---|
905 | p->version_major = shbp->major_version; |
---|
906 | p->version_minor = shbp->minor_version; |
---|
907 | |
---|
908 | /* |
---|
909 | * Save the time stamp resolution the user requested. |
---|
910 | */ |
---|
911 | p->opt.tstamp_precision = precision; |
---|
912 | |
---|
913 | /* |
---|
914 | * Now start looking for an Interface Description Block. |
---|
915 | */ |
---|
916 | for (;;) { |
---|
917 | /* |
---|
918 | * Read the next block. |
---|
919 | */ |
---|
920 | status = read_block(fp, p, &cursor, errbuf); |
---|
921 | if (status == 0) { |
---|
922 | /* EOF - no IDB in this file */ |
---|
923 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
924 | "the capture file has no Interface Description Blocks"); |
---|
925 | goto fail; |
---|
926 | } |
---|
927 | if (status == -1) |
---|
928 | goto fail; /* error */ |
---|
929 | switch (cursor.block_type) { |
---|
930 | |
---|
931 | case BT_IDB: |
---|
932 | /* |
---|
933 | * Get a pointer to the fixed-length portion of the |
---|
934 | * IDB. |
---|
935 | */ |
---|
936 | idbp = get_from_block_data(&cursor, sizeof(*idbp), |
---|
937 | errbuf); |
---|
938 | if (idbp == NULL) |
---|
939 | goto fail; /* error */ |
---|
940 | |
---|
941 | /* |
---|
942 | * Byte-swap it if necessary. |
---|
943 | */ |
---|
944 | if (p->swapped) { |
---|
945 | idbp->linktype = SWAPSHORT(idbp->linktype); |
---|
946 | idbp->snaplen = SWAPLONG(idbp->snaplen); |
---|
947 | } |
---|
948 | |
---|
949 | /* |
---|
950 | * Interface capture length sanity check |
---|
951 | */ |
---|
952 | if (idbp->snaplen > MAXIMUM_SNAPLEN) { |
---|
953 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
954 | "invalid interface capture length %u, " |
---|
955 | "bigger than maximum of %u", |
---|
956 | idbp->snaplen, MAXIMUM_SNAPLEN); |
---|
957 | goto fail; |
---|
958 | } |
---|
959 | |
---|
960 | /* |
---|
961 | * Try to add this interface. |
---|
962 | */ |
---|
963 | if (!add_interface(p, &cursor, errbuf)) |
---|
964 | goto fail; |
---|
965 | |
---|
966 | goto done; |
---|
967 | |
---|
968 | case BT_EPB: |
---|
969 | case BT_SPB: |
---|
970 | case BT_PB: |
---|
971 | /* |
---|
972 | * Saw a packet before we saw any IDBs. That's |
---|
973 | * not valid, as we don't know what link-layer |
---|
974 | * encapsulation the packet has. |
---|
975 | */ |
---|
976 | pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, |
---|
977 | "the capture file has a packet block before any Interface Description Blocks"); |
---|
978 | goto fail; |
---|
979 | |
---|
980 | default: |
---|
981 | /* |
---|
982 | * Just ignore it. |
---|
983 | */ |
---|
984 | break; |
---|
985 | } |
---|
986 | } |
---|
987 | |
---|
988 | done: |
---|
989 | p->tzoff = 0; /* XXX - not used in pcap */ |
---|
990 | p->snapshot = idbp->snaplen; |
---|
991 | p->linktype = linktype_to_dlt(idbp->linktype); |
---|
992 | p->linktype_ext = 0; |
---|
993 | |
---|
994 | p->next_packet_op = pcap_ng_next_packet; |
---|
995 | p->cleanup_op = pcap_ng_cleanup; |
---|
996 | |
---|
997 | return (p); |
---|
998 | |
---|
999 | fail: |
---|
1000 | free(ps->ifaces); |
---|
1001 | free(p->buffer); |
---|
1002 | free(p); |
---|
1003 | *err = 1; |
---|
1004 | return (NULL); |
---|
1005 | } |
---|
1006 | |
---|
1007 | static void |
---|
1008 | pcap_ng_cleanup(pcap_t *p) |
---|
1009 | { |
---|
1010 | struct pcap_ng_sf *ps = p->priv; |
---|
1011 | |
---|
1012 | free(ps->ifaces); |
---|
1013 | sf_cleanup(p); |
---|
1014 | } |
---|
1015 | |
---|
1016 | /* |
---|
1017 | * Read and return the next packet from the savefile. Return the header |
---|
1018 | * in hdr and a pointer to the contents in data. Return 0 on success, 1 |
---|
1019 | * if there were no more packets, and -1 on an error. |
---|
1020 | */ |
---|
1021 | static int |
---|
1022 | pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) |
---|
1023 | { |
---|
1024 | struct pcap_ng_sf *ps = p->priv; |
---|
1025 | struct block_cursor cursor; |
---|
1026 | int status; |
---|
1027 | struct enhanced_packet_block *epbp; |
---|
1028 | struct simple_packet_block *spbp; |
---|
1029 | struct packet_block *pbp; |
---|
1030 | bpf_u_int32 interface_id = 0xFFFFFFFF; |
---|
1031 | struct interface_description_block *idbp; |
---|
1032 | struct section_header_block *shbp; |
---|
1033 | FILE *fp = p->rfile; |
---|
1034 | u_int64_t t, sec, frac; |
---|
1035 | |
---|
1036 | /* |
---|
1037 | * Look for an Enhanced Packet Block, a Simple Packet Block, |
---|
1038 | * or a Packet Block. |
---|
1039 | */ |
---|
1040 | for (;;) { |
---|
1041 | /* |
---|
1042 | * Read the block type and length; those are common |
---|
1043 | * to all blocks. |
---|
1044 | */ |
---|
1045 | status = read_block(fp, p, &cursor, p->errbuf); |
---|
1046 | if (status == 0) |
---|
1047 | return (1); /* EOF */ |
---|
1048 | if (status == -1) |
---|
1049 | return (-1); /* error */ |
---|
1050 | switch (cursor.block_type) { |
---|
1051 | |
---|
1052 | case BT_EPB: |
---|
1053 | /* |
---|
1054 | * Get a pointer to the fixed-length portion of the |
---|
1055 | * EPB. |
---|
1056 | */ |
---|
1057 | epbp = get_from_block_data(&cursor, sizeof(*epbp), |
---|
1058 | p->errbuf); |
---|
1059 | if (epbp == NULL) |
---|
1060 | return (-1); /* error */ |
---|
1061 | |
---|
1062 | /* |
---|
1063 | * Byte-swap it if necessary. |
---|
1064 | */ |
---|
1065 | if (p->swapped) { |
---|
1066 | /* these were written in opposite byte order */ |
---|
1067 | interface_id = SWAPLONG(epbp->interface_id); |
---|
1068 | hdr->caplen = SWAPLONG(epbp->caplen); |
---|
1069 | hdr->len = SWAPLONG(epbp->len); |
---|
1070 | t = ((u_int64_t)SWAPLONG(epbp->timestamp_high)) << 32 | |
---|
1071 | SWAPLONG(epbp->timestamp_low); |
---|
1072 | } else { |
---|
1073 | interface_id = epbp->interface_id; |
---|
1074 | hdr->caplen = epbp->caplen; |
---|
1075 | hdr->len = epbp->len; |
---|
1076 | t = ((u_int64_t)epbp->timestamp_high) << 32 | |
---|
1077 | epbp->timestamp_low; |
---|
1078 | } |
---|
1079 | goto found; |
---|
1080 | |
---|
1081 | case BT_SPB: |
---|
1082 | /* |
---|
1083 | * Get a pointer to the fixed-length portion of the |
---|
1084 | * SPB. |
---|
1085 | */ |
---|
1086 | spbp = get_from_block_data(&cursor, sizeof(*spbp), |
---|
1087 | p->errbuf); |
---|
1088 | if (spbp == NULL) |
---|
1089 | return (-1); /* error */ |
---|
1090 | |
---|
1091 | /* |
---|
1092 | * SPB packets are assumed to have arrived on |
---|
1093 | * the first interface. |
---|
1094 | */ |
---|
1095 | interface_id = 0; |
---|
1096 | |
---|
1097 | /* |
---|
1098 | * Byte-swap it if necessary. |
---|
1099 | */ |
---|
1100 | if (p->swapped) { |
---|
1101 | /* these were written in opposite byte order */ |
---|
1102 | hdr->len = SWAPLONG(spbp->len); |
---|
1103 | } else |
---|
1104 | hdr->len = spbp->len; |
---|
1105 | |
---|
1106 | /* |
---|
1107 | * The SPB doesn't give the captured length; |
---|
1108 | * it's the minimum of the snapshot length |
---|
1109 | * and the packet length. |
---|
1110 | */ |
---|
1111 | hdr->caplen = hdr->len; |
---|
1112 | if (hdr->caplen > (bpf_u_int32)p->snapshot) |
---|
1113 | hdr->caplen = p->snapshot; |
---|
1114 | t = 0; /* no time stamps */ |
---|
1115 | goto found; |
---|
1116 | |
---|
1117 | case BT_PB: |
---|
1118 | /* |
---|
1119 | * Get a pointer to the fixed-length portion of the |
---|
1120 | * PB. |
---|
1121 | */ |
---|
1122 | pbp = get_from_block_data(&cursor, sizeof(*pbp), |
---|
1123 | p->errbuf); |
---|
1124 | if (pbp == NULL) |
---|
1125 | return (-1); /* error */ |
---|
1126 | |
---|
1127 | /* |
---|
1128 | * Byte-swap it if necessary. |
---|
1129 | */ |
---|
1130 | if (p->swapped) { |
---|
1131 | /* these were written in opposite byte order */ |
---|
1132 | interface_id = SWAPSHORT(pbp->interface_id); |
---|
1133 | hdr->caplen = SWAPLONG(pbp->caplen); |
---|
1134 | hdr->len = SWAPLONG(pbp->len); |
---|
1135 | t = ((u_int64_t)SWAPLONG(pbp->timestamp_high)) << 32 | |
---|
1136 | SWAPLONG(pbp->timestamp_low); |
---|
1137 | } else { |
---|
1138 | interface_id = pbp->interface_id; |
---|
1139 | hdr->caplen = pbp->caplen; |
---|
1140 | hdr->len = pbp->len; |
---|
1141 | t = ((u_int64_t)pbp->timestamp_high) << 32 | |
---|
1142 | pbp->timestamp_low; |
---|
1143 | } |
---|
1144 | goto found; |
---|
1145 | |
---|
1146 | case BT_IDB: |
---|
1147 | /* |
---|
1148 | * Interface Description Block. Get a pointer |
---|
1149 | * to its fixed-length portion. |
---|
1150 | */ |
---|
1151 | idbp = get_from_block_data(&cursor, sizeof(*idbp), |
---|
1152 | p->errbuf); |
---|
1153 | if (idbp == NULL) |
---|
1154 | return (-1); /* error */ |
---|
1155 | |
---|
1156 | /* |
---|
1157 | * Byte-swap it if necessary. |
---|
1158 | */ |
---|
1159 | if (p->swapped) { |
---|
1160 | idbp->linktype = SWAPSHORT(idbp->linktype); |
---|
1161 | idbp->snaplen = SWAPLONG(idbp->snaplen); |
---|
1162 | } |
---|
1163 | |
---|
1164 | /* |
---|
1165 | * If the link-layer type or snapshot length |
---|
1166 | * differ from the ones for the first IDB we |
---|
1167 | * saw, quit. |
---|
1168 | * |
---|
1169 | * XXX - just discard packets from those |
---|
1170 | * interfaces? |
---|
1171 | */ |
---|
1172 | if (p->linktype != idbp->linktype) { |
---|
1173 | pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, |
---|
1174 | "an interface has a type %u different from the type of the first interface", |
---|
1175 | idbp->linktype); |
---|
1176 | return (-1); |
---|
1177 | } |
---|
1178 | if ((bpf_u_int32)p->snapshot != idbp->snaplen) { |
---|
1179 | pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, |
---|
1180 | "an interface has a snapshot length %u different from the type of the first interface", |
---|
1181 | idbp->snaplen); |
---|
1182 | return (-1); |
---|
1183 | } |
---|
1184 | |
---|
1185 | /* |
---|
1186 | * Try to add this interface. |
---|
1187 | */ |
---|
1188 | if (!add_interface(p, &cursor, p->errbuf)) |
---|
1189 | return (-1); |
---|
1190 | break; |
---|
1191 | |
---|
1192 | case BT_SHB: |
---|
1193 | /* |
---|
1194 | * Section Header Block. Get a pointer |
---|
1195 | * to its fixed-length portion. |
---|
1196 | */ |
---|
1197 | shbp = get_from_block_data(&cursor, sizeof(*shbp), |
---|
1198 | p->errbuf); |
---|
1199 | if (shbp == NULL) |
---|
1200 | return (-1); /* error */ |
---|
1201 | |
---|
1202 | /* |
---|
1203 | * Assume the byte order of this section is |
---|
1204 | * the same as that of the previous section. |
---|
1205 | * We'll check for that later. |
---|
1206 | */ |
---|
1207 | if (p->swapped) { |
---|
1208 | shbp->byte_order_magic = |
---|
1209 | SWAPLONG(shbp->byte_order_magic); |
---|
1210 | shbp->major_version = |
---|
1211 | SWAPSHORT(shbp->major_version); |
---|
1212 | } |
---|
1213 | |
---|
1214 | /* |
---|
1215 | * Make sure the byte order doesn't change; |
---|
1216 | * pcap_is_swapped() shouldn't change its |
---|
1217 | * return value in the middle of reading a capture. |
---|
1218 | */ |
---|
1219 | switch (shbp->byte_order_magic) { |
---|
1220 | |
---|
1221 | case BYTE_ORDER_MAGIC: |
---|
1222 | /* |
---|
1223 | * OK. |
---|
1224 | */ |
---|
1225 | break; |
---|
1226 | |
---|
1227 | case SWAPLONG(BYTE_ORDER_MAGIC): |
---|
1228 | /* |
---|
1229 | * Byte order changes. |
---|
1230 | */ |
---|
1231 | pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, |
---|
1232 | "the file has sections with different byte orders"); |
---|
1233 | return (-1); |
---|
1234 | |
---|
1235 | default: |
---|
1236 | /* |
---|
1237 | * Not a valid SHB. |
---|
1238 | */ |
---|
1239 | pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, |
---|
1240 | "the file has a section with a bad byte order magic field"); |
---|
1241 | return (-1); |
---|
1242 | } |
---|
1243 | |
---|
1244 | /* |
---|
1245 | * Make sure the major version is the version |
---|
1246 | * we handle. |
---|
1247 | */ |
---|
1248 | if (shbp->major_version != PCAP_NG_VERSION_MAJOR) { |
---|
1249 | pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, |
---|
1250 | "unknown pcap-ng savefile major version number %u", |
---|
1251 | shbp->major_version); |
---|
1252 | return (-1); |
---|
1253 | } |
---|
1254 | |
---|
1255 | /* |
---|
1256 | * Reset the interface count; this section should |
---|
1257 | * have its own set of IDBs. If any of them |
---|
1258 | * don't have the same interface type, snapshot |
---|
1259 | * length, or resolution as the first interface |
---|
1260 | * we saw, we'll fail. (And if we don't see |
---|
1261 | * any IDBs, we'll fail when we see a packet |
---|
1262 | * block.) |
---|
1263 | */ |
---|
1264 | ps->ifcount = 0; |
---|
1265 | break; |
---|
1266 | |
---|
1267 | default: |
---|
1268 | /* |
---|
1269 | * Not a packet block, IDB, or SHB; ignore it. |
---|
1270 | */ |
---|
1271 | break; |
---|
1272 | } |
---|
1273 | } |
---|
1274 | |
---|
1275 | found: |
---|
1276 | /* |
---|
1277 | * Is the interface ID an interface we know? |
---|
1278 | */ |
---|
1279 | if (interface_id >= ps->ifcount) { |
---|
1280 | /* |
---|
1281 | * Yes. Fail. |
---|
1282 | */ |
---|
1283 | pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, |
---|
1284 | "a packet arrived on interface %u, but there's no Interface Description Block for that interface", |
---|
1285 | interface_id); |
---|
1286 | return (-1); |
---|
1287 | } |
---|
1288 | |
---|
1289 | /* |
---|
1290 | * Convert the time stamp to seconds and fractions of a second, |
---|
1291 | * with the fractions being in units of the file-supplied resolution. |
---|
1292 | */ |
---|
1293 | sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset; |
---|
1294 | frac = t % ps->ifaces[interface_id].tsresol; |
---|
1295 | |
---|
1296 | /* |
---|
1297 | * Convert the fractions from units of the file-supplied resolution |
---|
1298 | * to units of the user-requested resolution. |
---|
1299 | */ |
---|
1300 | switch (ps->ifaces[interface_id].scale_type) { |
---|
1301 | |
---|
1302 | case PASS_THROUGH: |
---|
1303 | /* |
---|
1304 | * The interface resolution is what the user wants, |
---|
1305 | * so we're done. |
---|
1306 | */ |
---|
1307 | break; |
---|
1308 | |
---|
1309 | case SCALE_UP_DEC: |
---|
1310 | /* |
---|
1311 | * The interface resolution is less than what the user |
---|
1312 | * wants; scale the fractional part up to the units of |
---|
1313 | * the resolution the user requested by multiplying by |
---|
1314 | * the quotient of the user-requested resolution and the |
---|
1315 | * file-supplied resolution. |
---|
1316 | * |
---|
1317 | * Those resolutions are both powers of 10, and the user- |
---|
1318 | * requested resolution is greater than the file-supplied |
---|
1319 | * resolution, so the quotient in question is an integer. |
---|
1320 | * We've calculated that quotient already, so we just |
---|
1321 | * multiply by it. |
---|
1322 | */ |
---|
1323 | frac *= ps->ifaces[interface_id].scale_factor; |
---|
1324 | break; |
---|
1325 | |
---|
1326 | case SCALE_UP_BIN: |
---|
1327 | /* |
---|
1328 | * The interface resolution is less than what the user |
---|
1329 | * wants; scale the fractional part up to the units of |
---|
1330 | * the resolution the user requested by multiplying by |
---|
1331 | * the quotient of the user-requested resolution and the |
---|
1332 | * file-supplied resolution. |
---|
1333 | * |
---|
1334 | * The file-supplied resolution is a power of 2, so the |
---|
1335 | * quotient is not an integer, so, in order to do this |
---|
1336 | * entirely with integer arithmetic, we multiply by the |
---|
1337 | * user-requested resolution and divide by the file- |
---|
1338 | * supplied resolution. |
---|
1339 | * |
---|
1340 | * XXX - Is there something clever we could do here, |
---|
1341 | * given that we know that the file-supplied resolution |
---|
1342 | * is a power of 2? Doing a multiplication followed by |
---|
1343 | * a division runs the risk of overflowing, and involves |
---|
1344 | * two non-simple arithmetic operations. |
---|
1345 | */ |
---|
1346 | frac *= ps->user_tsresol; |
---|
1347 | frac /= ps->ifaces[interface_id].tsresol; |
---|
1348 | break; |
---|
1349 | |
---|
1350 | case SCALE_DOWN_DEC: |
---|
1351 | /* |
---|
1352 | * The interface resolution is greater than what the user |
---|
1353 | * wants; scale the fractional part up to the units of |
---|
1354 | * the resolution the user requested by multiplying by |
---|
1355 | * the quotient of the user-requested resolution and the |
---|
1356 | * file-supplied resolution. |
---|
1357 | * |
---|
1358 | * Those resolutions are both powers of 10, and the user- |
---|
1359 | * requested resolution is less than the file-supplied |
---|
1360 | * resolution, so the quotient in question isn't an |
---|
1361 | * integer, but its reciprocal is, and we can just divide |
---|
1362 | * by the reciprocal of the quotient. We've calculated |
---|
1363 | * the reciprocal of that quotient already, so we must |
---|
1364 | * divide by it. |
---|
1365 | */ |
---|
1366 | frac /= ps->ifaces[interface_id].scale_factor; |
---|
1367 | break; |
---|
1368 | |
---|
1369 | |
---|
1370 | case SCALE_DOWN_BIN: |
---|
1371 | /* |
---|
1372 | * The interface resolution is greater than what the user |
---|
1373 | * wants; convert the fractional part to units of the |
---|
1374 | * resolution the user requested by multiplying by the |
---|
1375 | * quotient of the user-requested resolution and the |
---|
1376 | * file-supplied resolution. We do that by multiplying |
---|
1377 | * by the user-requested resolution and dividing by the |
---|
1378 | * file-supplied resolution, as the quotient might not |
---|
1379 | * fit in an integer. |
---|
1380 | * |
---|
1381 | * The file-supplied resolution is a power of 2, so the |
---|
1382 | * quotient is not an integer, and neither is its |
---|
1383 | * reciprocal, so, in order to do this entirely with |
---|
1384 | * integer arithmetic, we multiply by the user-requested |
---|
1385 | * resolution and divide by the file-supplied resolution. |
---|
1386 | * |
---|
1387 | * XXX - Is there something clever we could do here, |
---|
1388 | * given that we know that the file-supplied resolution |
---|
1389 | * is a power of 2? Doing a multiplication followed by |
---|
1390 | * a division runs the risk of overflowing, and involves |
---|
1391 | * two non-simple arithmetic operations. |
---|
1392 | */ |
---|
1393 | frac *= ps->user_tsresol; |
---|
1394 | frac /= ps->ifaces[interface_id].tsresol; |
---|
1395 | break; |
---|
1396 | } |
---|
1397 | #ifdef _WIN32 |
---|
1398 | /* |
---|
1399 | * tv_sec and tv_used in the Windows struct timeval are both |
---|
1400 | * longs. |
---|
1401 | */ |
---|
1402 | hdr->ts.tv_sec = (long)sec; |
---|
1403 | hdr->ts.tv_usec = (long)frac; |
---|
1404 | #else |
---|
1405 | /* |
---|
1406 | * tv_sec in the UN*X struct timeval is a time_t; tv_usec is |
---|
1407 | * suseconds_t in UN*Xes that work the way the current Single |
---|
1408 | * UNIX Standard specify - but not all older UN*Xes necessarily |
---|
1409 | * support that type, so just cast to int. |
---|
1410 | */ |
---|
1411 | hdr->ts.tv_sec = (time_t)sec; |
---|
1412 | hdr->ts.tv_usec = (int)frac; |
---|
1413 | #endif |
---|
1414 | |
---|
1415 | /* |
---|
1416 | * Get a pointer to the packet data. |
---|
1417 | */ |
---|
1418 | *data = get_from_block_data(&cursor, hdr->caplen, p->errbuf); |
---|
1419 | if (*data == NULL) |
---|
1420 | return (-1); |
---|
1421 | |
---|
1422 | if (p->swapped) |
---|
1423 | swap_pseudo_headers(p->linktype, hdr, *data); |
---|
1424 | |
---|
1425 | return (0); |
---|
1426 | } |
---|