smb-direct fragmentation
[metze/wireshark/wip.git] / wiretap / pcapng.c
1 /* pcapng.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
8  * File format support for pcap-ng file format
9  * Copyright (c) 2007 by Ulf Lamping <ulf.lamping@web.de>
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 /* File format reference:
27  *   http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
28  * Related Wiki page:
29  *   http://wiki.wireshark.org/Development/PcapNg
30  */
31
32 #include "config.h"
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37
38
39 #include "wtap-int.h"
40 #include <epan/addr_resolv.h>
41 #include "file_wrappers.h"
42 #include "buffer.h"
43 #include "libpcap.h"
44 #include "pcap-common.h"
45 #include "pcap-encap.h"
46 #include "pcapng.h"
47
48 #if 0
49 #define pcapng_debug0(str) g_warning(str)
50 #define pcapng_debug1(str,p1) g_warning(str,p1)
51 #define pcapng_debug2(str,p1,p2) g_warning(str,p1,p2)
52 #define pcapng_debug3(str,p1,p2,p3) g_warning(str,p1,p2,p3)
53 #else
54 #define pcapng_debug0(str)
55 #define pcapng_debug1(str,p1)
56 #define pcapng_debug2(str,p1,p2)
57 #define pcapng_debug3(str,p1,p2,p3)
58 #endif
59
60 static gboolean
61 pcapng_read(wtap *wth, int *err, gchar **err_info,
62     gint64 *data_offset);
63 static gboolean
64 pcapng_seek_read(wtap *wth, gint64 seek_off,
65     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
66 static void
67 pcapng_close(wtap *wth);
68
69
70 /* pcapng: common block header for every block type */
71 typedef struct pcapng_block_header_s {
72         guint32 block_type;
73         guint32 block_total_length;
74         /* x bytes block_body */
75         /* guint32 block_total_length */
76 } pcapng_block_header_t;
77
78 /*
79  * Minimum block size = size of block header + size of block trailer.
80  */
81 #define MIN_BLOCK_SIZE  ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
82
83 /*
84  * In order to keep from trying to allocate large chunks of memory,
85  * which could either fail or, even if it succeeds, chew up so much
86  * address space or memory+backing store as not to leave room for
87  * anything else, we impose an upper limit on the size of blocks
88  * we're willing to handle.
89  *
90  * For now, we pick an arbitrary limit of 16MB (OK, fine, 16MiB, but
91  * don't try saying that on Wikipedia :-) :-) :-)).
92  */
93 #define MAX_BLOCK_SIZE  (16*1024*1024)
94
95 /* pcapng: section header block */
96 typedef struct pcapng_section_header_block_s {
97         /* pcapng_block_header_t */
98         guint32 magic;
99         guint16 version_major;
100         guint16 version_minor;
101         guint64 section_length; /* might be -1 for unknown */
102         /* ... Options ... */
103 } pcapng_section_header_block_t;
104
105 /*
106  * Minimum SHB size = minimum block size + size of fixed length portion of SHB.
107  */
108 #define MIN_SHB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
109
110 /* pcapng: interface description block */
111 typedef struct pcapng_interface_description_block_s {
112         guint16 linktype;
113         guint16 reserved;
114         guint32 snaplen;
115         /* ... Options ... */
116 } pcapng_interface_description_block_t;
117
118 /*
119  * Minimum IDB size = minimum block size + size of fixed length portion of IDB.
120  */
121 #define MIN_IDB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
122
123 /* pcapng: packet block (obsolete) */
124 typedef struct pcapng_packet_block_s {
125         guint16 interface_id;
126         guint16 drops_count;
127         guint32 timestamp_high;
128         guint32 timestamp_low;
129         guint32 captured_len;
130         guint32 packet_len;
131         /* ... Packet Data ... */
132         /* ... Padding ... */
133         /* ... Options ... */
134 } pcapng_packet_block_t;
135
136 /*
137  * Minimum PB size = minimum block size + size of fixed length portion of PB.
138  */
139 #define MIN_PB_SIZE     ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_packet_block_t)))
140
141 /* pcapng: enhanced packet block */
142 typedef struct pcapng_enhanced_packet_block_s {
143         guint32 interface_id;
144         guint32 timestamp_high;
145         guint32 timestamp_low;
146         guint32 captured_len;
147         guint32 packet_len;
148         /* ... Packet Data ... */
149         /* ... Padding ... */
150         /* ... Options ... */
151 } pcapng_enhanced_packet_block_t;
152
153 /*
154  * Minimum EPB size = minimum block size + size of fixed length portion of EPB.
155  */
156 #define MIN_EPB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_enhanced_packet_block_t)))
157
158 /* pcapng: simple packet block */
159 typedef struct pcapng_simple_packet_block_s {
160         guint32 packet_len;
161         /* ... Packet Data ... */
162         /* ... Padding ... */
163 } pcapng_simple_packet_block_t;
164
165 /*
166  * Minimum SPB size = minimum block size + size of fixed length portion of SPB.
167  */
168 #define MIN_SPB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_simple_packet_block_t)))
169
170 /* pcapng: name resolution block */
171 typedef struct pcapng_name_resolution_block_s {
172         guint16 record_type;
173         guint16 record_len;
174         /* ... Record ... */
175 } pcapng_name_resolution_block_t;
176
177 /*
178  * Minimum NRB size = minimum block size + size of smallest NRB record
179  * (there must at least be an "end of records" record).
180  */
181 #define MIN_NRB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
182
183 /* pcapng: interface statistics block */
184 typedef struct pcapng_interface_statistics_block_s {
185         guint32 interface_id;
186         guint32 timestamp_high;
187         guint32 timestamp_low;
188         /* ... Options ... */
189 } pcapng_interface_statistics_block_t;
190
191 /*
192  * Minimum ISB size = minimum block size + size of fixed length portion of ISB.
193  */
194 #define MIN_ISB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_statistics_block_t)))
195
196 /* pcapng: common option header for every option type */
197 typedef struct pcapng_option_header_s {
198         guint16 option_code;
199         guint16 option_length;
200         /* ... x bytes Option Body ... */
201         /* ... Padding ... */
202 } pcapng_option_header_t;
203
204 struct option {
205         guint16 type;
206         guint16 value_length;
207 };
208
209 /* Block types */
210 #define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
211 #define BLOCK_TYPE_PB  0x00000002 /* Packet Block (obsolete) */
212 #define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
213 #define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
214 #define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
215 #define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
216 #define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
217
218 /* Options */
219 #define OPT_EOFOPT        0
220 #define OPT_COMMENT       1
221 #define OPT_SHB_HARDWARE  2
222 #define OPT_SHB_OS        3
223 #define OPT_SHB_USERAPPL  4
224 #define OPT_EPB_FLAGS     2
225 #define OPT_EPB_HASH      3
226 #define OPT_EPB_DROPCOUNT 4
227
228 /* Capture section */
229 #if 0
230 /* Moved to wtap.h */
231 typedef struct wtapng_section_s {
232         /* mandatory */
233         guint64                         section_length;
234         /* options */
235         gchar                           *opt_comment;   /* NULL if not available */
236         gchar                           *shb_hardware;  /* NULL if not available */
237         gchar                           *shb_os;                /* NULL if not available */
238         gchar                           *shb_user_appl; /* NULL if not available */
239 } wtapng_section_t;
240 #endif
241
242 #if 0
243 /* Moved to wtap.h */
244
245 /* Interface Description
246  *
247  * Options:
248  * if_name        2  A UTF-8 string containing the name of the device used to capture data. "eth0" / "\Device\NPF_{AD1CE675-96D0-47C5-ADD0-2504B9126B68}" / ...
249  * if_description 3  A UTF-8 string containing the description of the device used to capture data. "Broadcom NetXtreme" / "First Ethernet Interface" / ...
250  * if_IPv4addr    4  Interface network address and netmask. This option can be repeated multiple times within the same Interface Description Block when multiple IPv4 addresses are assigned to the interface. 192 168 1 1 255 255 255 0
251  * if_IPv6addr    5  Interface network address and prefix length (stored in the last byte). This option can be repeated multiple times within the same Interface Description Block when multiple IPv6 addresses are assigned to the interface. 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in hex) as "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40"
252  * if_MACaddr     6  Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
253  * if_EUIaddr     7  Interface Hardware EUI address (64 bits), if available. TODO: give a good example
254  * if_speed       8  Interface speed (in bps). 100000000 for 100Mbps
255  * if_tsresol     9  Resolution of timestamps. If the Most Significant Bit is equal to zero, the remaining bits indicates the resolution of the timestamp as as a negative power of 10 (e.g. 6 means microsecond resolution, timestamps are the number of microseconds since 1/1/1970). If the Most Significant Bit is equal to one, the remaining bits indicates the resolution as as negative power of 2 (e.g. 10 means 1/1024 of second). If this option is not present, a resolution of 10^-6 is assumed (i.e. timestamps have the same resolution of the standard 'libpcap' timestamps). 6
256  * if_tzone      10  Time zone for GMT support (TODO: specify better). TODO: give a good example
257  * if_filter     11  The filter (e.g. "capture only TCP traffic") used to capture traffic. The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more). More details about this format will be presented in Appendix XXX (TODO). (TODO: better use different options for different fields? e.g. if_filter_pcap, if_filter_bpf, ...) 00 "tcp port 23 and host 10.0.0.5"
258  * if_os         12  A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory))) because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
259  * if_fcslen     13  An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. For link layers whose FCS length can change during time, the Packet Block Flags Word can be used (see Appendix A (Packet Block Flags Word)). 4
260  * if_tsoffset   14  A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps. The time zone of the offset can be specified with the option if_tzone. TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems? 1234
261  */
262
263 typedef struct wtapng_if_descr_s {
264         /* mandatory */
265         guint16                         link_type;
266         guint                           encap;
267         guint32                         snap_len;
268         /* options */
269         gchar                           *opt_comment;   /* NULL if not available */
270         gchar                           *if_name;               /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
271         gchar                           *if_description;/* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
272         /* XXX: if_IPv4addr opt 4  Interface network address and netmask.*/
273         /* XXX: if_IPv6addr opt 5  Interface network address and prefix length (stored in the last byte).*/
274         /* XXX: if_MACaddr  opt 6  Interface Hardware MAC address (48 bits).*/
275         /* XXX: if_EUIaddr  opt 7  Interface Hardware EUI address (64 bits)*/
276         guint64                         if_speed;       /* 0 if unknown, opt 8  Interface speed (in bps). 100000000 for 100Mbps */
277         guint8                          if_tsresol;     /* default is 6 for microsecond resolution, opt 9  Resolution of timestamps.
278                                                                          * If the Most Significant Bit is equal to zero, the remaining bits indicates the resolution of the timestamp as as a negative power of 10
279                                                                          */
280         /* XXX: if_tzone      10  Time zone for GMT support (TODO: specify better). */
281         gchar                           *if_filter;     /* NULL if not available, opt 11  The filter (e.g. "capture only TCP traffic") used to capture traffic.
282                                                                          * The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more).
283                                                                          */
284         gchar                           *if_os;         /* NULL if not available, 12  A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. */
285         gint8                           if_fcslen;      /* -1 if unknown or changes between packets, opt 13  An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. */
286         /* XXX: guint64 if_tsoffset; opt 14  A 64 bits integer value that specifies an offset (in seconds)...*/
287 } wtapng_if_descr_t;
288 #endif
289
290 /* Packets */
291 typedef struct wtapng_packet_s {
292         /* mandatory */
293         guint32                         ts_high;        /* seconds since 1.1.1970 */
294         guint32                         ts_low;         /* fraction of seconds, depends on if_tsresol */
295         guint32                         cap_len;        /* data length in the file */
296         guint32                         packet_len;     /* data length on the wire */
297         guint32                         interface_id;   /* identifier of the interface. */
298         guint16                         drops_count;    /* drops count, only valid for packet block */
299                                                                                 /* 0xffff if information no available */
300         /* pack_hash */
301         /* XXX - put the packet data / pseudo_header here as well? */
302 } wtapng_packet_t;
303
304 /* Simple Packets */
305 typedef struct wtapng_simple_packet_s {
306         /* mandatory */
307         guint32                         cap_len;        /* data length in the file */
308         guint32                         packet_len;     /* data length on the wire */
309         guint32                         pseudo_header_len;
310         int                             wtap_encap;
311         /* XXX - put the packet data / pseudo_header here as well? */
312 } wtapng_simple_packet_t;
313
314 /* Name Resolution */
315 typedef struct wtapng_name_res_s {
316         /* options */
317         gchar                           *opt_comment;   /* NULL if not available */
318         /* XXX */
319 } wtapng_name_res_t;
320
321 #if 0
322 /* Interface Statistics moved to wtap.h*/
323 typedef struct wtapng_if_stats_s {
324         /* mandatory */
325         guint32                         interface_id;
326         guint32                         ts_high;
327         guint32                         ts_low;
328         /* options */
329         gchar                           *opt_comment;   /* NULL if not available */
330         guint64                         isb_starttime;
331         guint64                         isb_endtime;
332         guint64                         isb_ifrecv;
333         guint64                         isb_ifdrop;
334         guint64                         isb_filteraccept;
335         guint64                         isb_osdrop;
336         guint64                         isb_usrdeliv;
337 } wtapng_if_stats_t;
338 #endif
339
340 typedef struct wtapng_block_s {
341         guint32                                 type;           /* block_type as defined by pcapng */
342         union {
343                 wtapng_section_t        section;
344                 wtapng_if_descr_t       if_descr;
345                 wtapng_name_res_t       name_res;
346                 wtapng_if_stats_t       if_stats;
347         } data;
348
349         /*
350          * XXX - currently don't know how to handle these!
351          *
352          * For one thing, when we're reading a block, they must be
353          * writable, i.e. not const, so that we can read into them,
354          * but, when we're writing a block, they can be const, and,
355          * in fact, they sometimes point to const values.
356          */
357         struct wtap_pkthdr *packet_header;
358         Buffer *frame_buffer;
359         int *file_encap;
360 } wtapng_block_t;
361
362 /* Interface data in private struct */
363 typedef struct interface_data_s {
364         int wtap_encap;
365         guint32 snap_len;
366         guint64 time_units_per_second;
367 } interface_data_t;
368
369 typedef struct {
370         gboolean shb_read;                                              /**< Set when first SHB read, second read will fail */
371         gboolean byte_swapped;
372         guint16 version_major;
373         guint16 version_minor;
374         GArray *interface_data;
375         guint number_of_interfaces;
376         gint8 if_fcslen;
377         wtap_new_ipv4_callback_t add_new_ipv4;
378         wtap_new_ipv6_callback_t add_new_ipv6;
379 } pcapng_t;
380
381 static int
382 pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
383                    char *content, guint len, guint to_read,
384                    int *err, gchar **err_info)
385 {
386         int     bytes_read;
387         int     block_read;
388         guint64 file_offset64;
389
390         /* sanity check: don't run past the end of the block */
391         if (to_read < sizeof (*oh)) {
392                 *err = WTAP_ERR_BAD_FILE;
393                 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
394                 return -1;
395         }
396
397         /* read option header */
398         errno = WTAP_ERR_CANT_READ;
399         bytes_read = file_read(oh, sizeof (*oh), fh);
400         if (bytes_read != sizeof (*oh)) {
401                 pcapng_debug0("pcapng_read_option: failed to read option");
402                 *err = file_error(fh, err_info);
403                 if (*err != 0)
404                         return -1;
405                 return 0;
406         }
407         block_read = sizeof (*oh);
408         if (pn->byte_swapped) {
409                 oh->option_code      = GUINT16_SWAP_LE_BE(oh->option_code);
410                 oh->option_length    = GUINT16_SWAP_LE_BE(oh->option_length);
411         }
412
413         /* sanity check: don't run past the end of the block */
414         if (to_read < sizeof (*oh) + oh->option_length) {
415                 *err = WTAP_ERR_BAD_FILE;
416                 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
417                 return -1;
418         }
419
420         /* sanity check: option length */
421         if (oh->option_length > len) {
422                 pcapng_debug2("pcapng_read_option: option_length %u larger than buffer (%u)",
423                               oh->option_length, len);
424                 return 0;
425         }
426
427         /* read option content */
428         errno = WTAP_ERR_CANT_READ;
429         bytes_read = file_read(content, oh->option_length, fh);
430         if (bytes_read != oh->option_length) {
431                 pcapng_debug1("pcapng_read_option: failed to read content of option %u", oh->option_code);
432                 *err = file_error(fh, err_info);
433                 if (*err != 0)
434                         return -1;
435                 return 0;
436         }
437         block_read += oh->option_length;
438
439         /* jump over potential padding bytes at end of option */
440         if ( (oh->option_length % 4) != 0) {
441                 file_offset64 = file_seek(fh, 4 - (oh->option_length % 4), SEEK_CUR, err);
442                 if (file_offset64 <= 0) {
443                         if (*err != 0)
444                                 return -1;
445                         return 0;
446                 }
447                 block_read += 4 - (oh->option_length % 4);
448         }
449
450         return block_read;
451 }
452
453
454 static int
455 pcapng_read_section_header_block(FILE_T fh, gboolean first_block,
456                                  pcapng_block_header_t *bh, pcapng_t *pn,
457                                  wtapng_block_t *wblock, int *err,
458                                  gchar **err_info)
459 {
460         int     bytes_read;
461         guint   block_read;
462         guint to_read, opt_cont_buf_len;
463         pcapng_section_header_block_t shb;
464         pcapng_option_header_t oh;
465         char *option_content = NULL; /* Allocate as large as the options block */
466
467         /*
468          * Is this block long enough to be an SHB?
469          */
470         if (bh->block_total_length < MIN_SHB_SIZE) {
471                 /*
472                  * No.
473                  */
474                 if (first_block)
475                         return 0;       /* probably not a pcap-ng file */
476                 *err = WTAP_ERR_BAD_FILE;
477                 *err_info = g_strdup_printf("pcapng_read_section_header_block: total block length %u of an SHB is less than the minimum SHB size %u",
478                               bh->block_total_length, MIN_SHB_SIZE);
479                 return -1;
480         }
481
482         /* read block content */
483         errno = WTAP_ERR_CANT_READ;
484         bytes_read = file_read(&shb, sizeof shb, fh);
485         if (bytes_read != sizeof shb) {
486                 *err = file_error(fh, err_info);
487                 if (*err == 0) {
488                         if (first_block) {
489                                 /*
490                                  * We're reading this as part of an open,
491                                  * and this block is too short to be
492                                  * an SHB, so the file is too short
493                                  * to be a pcap-ng file.
494                                  */
495                                 return 0;
496                         }
497
498                         /*
499                          * Otherwise, just report this as an error.
500                          */
501                         *err = WTAP_ERR_SHORT_READ;
502                 }
503                 return -1;
504         }
505         block_read = bytes_read;
506
507         /* is the magic number one we expect? */
508         switch (shb.magic) {
509             case(0x1A2B3C4D):
510                 /* this seems pcapng with correct byte order */
511                 pn->byte_swapped                = FALSE;
512                 pn->version_major               = shb.version_major;
513                 pn->version_minor               = shb.version_minor;
514
515                 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
516                                 pn->version_major, pn->version_minor, bh->block_total_length);
517                 break;
518             case(0x4D3C2B1A):
519                 /* this seems pcapng with swapped byte order */
520                 pn->byte_swapped                = TRUE;
521                 pn->version_major               = GUINT16_SWAP_LE_BE(shb.version_major);
522                 pn->version_minor               = GUINT16_SWAP_LE_BE(shb.version_minor);
523
524                 /* tweak the block length to meet current swapping that we know now */
525                 bh->block_total_length  = GUINT32_SWAP_LE_BE(bh->block_total_length);
526
527                 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
528                                 pn->version_major, pn->version_minor, bh->block_total_length);
529                 break;
530             default:
531                 /* Not a "pcapng" magic number we know about. */
532                 if (first_block) {
533                         /* Not a pcap-ng file. */
534                         return 0;
535                 }
536
537                 /* A bad block */
538                 *err = WTAP_ERR_BAD_FILE;
539                 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown byte-order magic number 0x%08x", shb.magic);
540                 return 0;
541         }
542
543         /* OK, at this point we assume it's a pcap-ng file.
544
545            Don't try to allocate memory for a huge number of options, as
546            that might fail and, even if it succeeds, it might not leave
547            any address space or memory+backing store for anything else.
548
549            We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
550            We check for this *after* checking the SHB for its byte
551            order magic number, so that non-pcap-ng files are less
552            likely to be treated as bad pcap-ng files. */
553         if (bh->block_total_length > MAX_BLOCK_SIZE) {
554                 *err = WTAP_ERR_BAD_FILE;
555                 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
556                               bh->block_total_length, MAX_BLOCK_SIZE);
557                 return -1;
558         }
559
560         /* We currently only suport one SHB */
561         if (pn->shb_read == TRUE) {
562                 *err = WTAP_ERR_UNSUPPORTED;
563                 *err_info = g_strdup_printf("pcapng: multiple section header blocks not supported");
564                 return 0;
565         }
566
567         /* we currently only understand SHB V1.0 */
568         if (pn->version_major != 1 || pn->version_minor > 0) {
569                 *err = WTAP_ERR_UNSUPPORTED;
570                 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
571                               pn->version_major, pn->version_minor);
572                 return -1;
573         }
574
575
576         /* 64bit section_length (currently unused) */
577         if (pn->byte_swapped) {
578                 wblock->data.section.section_length = GUINT64_SWAP_LE_BE(shb.section_length);
579         } else {
580                 wblock->data.section.section_length = shb.section_length;
581         }
582
583         /* Option defaults */
584         wblock->data.section.opt_comment        = NULL;
585         wblock->data.section.shb_hardware       = NULL;
586         wblock->data.section.shb_os                     = NULL;
587         wblock->data.section.shb_user_appl      = NULL;
588
589         /* Options */
590         errno = WTAP_ERR_CANT_READ;
591         to_read = bh->block_total_length - MIN_SHB_SIZE;
592
593         /* Allocate enough memory to hold all options */
594         opt_cont_buf_len = to_read;
595         option_content = (char *)g_try_malloc(opt_cont_buf_len);
596         if (opt_cont_buf_len != 0 && option_content == NULL) {
597                 *err = ENOMEM;  /* we assume we're out of memory */
598                 return -1;
599         }
600         pcapng_debug1("pcapng_read_section_header_block: Options %u bytes", to_read);
601         while (to_read != 0) {
602                 /* read option */
603                 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes remaining", to_read);
604                 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
605                 if (bytes_read <= 0) {
606                         pcapng_debug0("pcapng_read_section_header_block: failed to read option");
607                         return bytes_read;
608                 }
609                 block_read += bytes_read;
610                 to_read -= bytes_read;
611
612                 /* handle option content */
613                 switch (oh.option_code) {
614                     case(OPT_EOFOPT):
615                         if (to_read != 0) {
616                                 pcapng_debug1("pcapng_read_section_header_block: %u bytes after opt_endofopt", to_read);
617                         }
618                         /* padding should be ok here, just get out of this */
619                         to_read = 0;
620                         break;
621                     case(OPT_COMMENT):
622                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
623                                 wblock->data.section.opt_comment = g_strndup(option_content, oh.option_length);
624                                 pcapng_debug1("pcapng_read_section_header_block: opt_comment %s", wblock->data.section.opt_comment);
625                         } else {
626                                 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh.option_length);
627                         }
628                         break;
629                     case(OPT_SHB_HARDWARE):
630                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
631                                 wblock->data.section.shb_hardware = g_strndup(option_content, oh.option_length);
632                                 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock->data.section.shb_hardware);
633                         } else {
634                                 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh.option_length);
635                         }
636                         break;
637                     case(OPT_SHB_OS):
638                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
639                                 wblock->data.section.shb_os = g_strndup(option_content, oh.option_length);
640                                 pcapng_debug1("pcapng_read_section_header_block: shb_os %s", wblock->data.section.shb_os);
641                         } else {
642                                 pcapng_debug2("pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u", oh.option_length,to_read);
643                         }
644                         break;
645                     case(OPT_SHB_USERAPPL):
646                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
647                                 wblock->data.section.shb_user_appl = g_strndup(option_content, oh.option_length);
648                                 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl %s", wblock->data.section.shb_user_appl);
649                         } else {
650                                 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl length %u seems strange", oh.option_length);
651                         }
652                         break;
653                     default:
654                         pcapng_debug2("pcapng_read_section_header_block: unknown option %u - ignoring %u bytes",
655                                       oh.option_code, oh.option_length);
656                 }
657         }
658         g_free(option_content);
659
660         return block_read;
661 }
662
663
664 /* "Interface Description Block" */
665 static int
666 pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
667                            wtapng_block_t *wblock, int *err, gchar **err_info)
668 {
669         guint64 time_units_per_second = 1000000; /* default */
670         int     bytes_read;
671         guint   block_read;
672         guint to_read, opt_cont_buf_len;
673         pcapng_interface_description_block_t idb;
674         pcapng_option_header_t oh;
675         char *option_content = NULL; /* Allocate as large as the options block */
676
677         /*
678          * Is this block long enough to be an IDB?
679          */
680         if (bh->block_total_length < MIN_IDB_SIZE) {
681                 /*
682                  * No.
683                  */
684                 *err = WTAP_ERR_BAD_FILE;
685                 *err_info = g_strdup_printf("pcapng_read_if_descr_block: total block length %u of an IDB is less than the minimum IDB size %u",
686                               bh->block_total_length, MIN_IDB_SIZE);
687                 return -1;
688         }
689
690         /* Don't try to allocate memory for a huge number of options, as
691            that might fail and, even if it succeeds, it might not leave
692            any address space or memory+backing store for anything else.
693
694            We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
695            We check for this *after* checking the SHB for its byte
696            order magic number, so that non-pcap-ng files are less
697            likely to be treated as bad pcap-ng files. */
698         if (bh->block_total_length > MAX_BLOCK_SIZE) {
699                 *err = WTAP_ERR_BAD_FILE;
700                 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
701                               bh->block_total_length, MAX_BLOCK_SIZE);
702                 return -1;
703         }
704
705         /* read block content */
706         errno = WTAP_ERR_CANT_READ;
707         bytes_read = file_read(&idb, sizeof idb, fh);
708         if (bytes_read != sizeof idb) {
709                 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
710                 *err = file_error(fh, err_info);
711                 if (*err != 0)
712                         return -1;
713                 return 0;
714         }
715         block_read = bytes_read;
716
717         /* mandatory values */
718         if (pn->byte_swapped) {
719                 wblock->data.if_descr.link_type = GUINT16_SWAP_LE_BE(idb.linktype);
720                 wblock->data.if_descr.snap_len  = GUINT32_SWAP_LE_BE(idb.snaplen);
721         } else {
722                 wblock->data.if_descr.link_type = idb.linktype;
723                 wblock->data.if_descr.snap_len  = idb.snaplen;
724         }
725
726         wblock->data.if_descr.wtap_encap = wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type);
727         wblock->data.if_descr.time_units_per_second = time_units_per_second;
728
729         pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
730                       wblock->data.if_descr.link_type,
731                       wtap_encap_string(wblock->data.if_descr.wtap_encap),
732                       wblock->data.if_descr.snap_len);
733
734         if (wblock->data.if_descr.snap_len > WTAP_MAX_PACKET_SIZE) {
735                 /* This is unrealistic, but text2pcap currently uses 102400.
736                  * We do not use this value, maybe we should check the
737                  * snap_len of the packets against it. For now, only warn.
738                  */
739                 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
740                               wblock->data.if_descr.snap_len);
741                 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
742         }
743
744         /* Option defaults */
745         wblock->data.if_descr.opt_comment = NULL;
746         wblock->data.if_descr.if_name = NULL;
747         wblock->data.if_descr.if_description = NULL;
748         /* XXX: if_IPv4addr */
749         /* XXX: if_IPv6addr */
750         /* XXX: if_MACaddr */
751         /* XXX: if_EUIaddr */
752         wblock->data.if_descr.if_speed = 0;                     /* "unknown" */
753         wblock->data.if_descr.if_tsresol = 6;                   /* default is 6 for microsecond resolution */
754         wblock->data.if_descr.if_filter_str = NULL;
755         wblock->data.if_descr.bpf_filter_len = 0;
756         wblock->data.if_descr.if_filter_bpf_bytes = NULL;
757         wblock->data.if_descr.if_os = NULL;
758         wblock->data.if_descr.if_fcslen = -1;                   /* unknown or changes between packets */
759         /* XXX: guint64 if_tsoffset; */
760
761
762         /* Options */
763         errno = WTAP_ERR_CANT_READ;
764         to_read = bh->block_total_length - MIN_IDB_SIZE;
765
766         /* Allocate enough memory to hold all options */
767         opt_cont_buf_len = to_read;
768         option_content = (char *)g_try_malloc(opt_cont_buf_len);
769         if (opt_cont_buf_len != 0 && option_content == NULL) {
770                 *err = ENOMEM;  /* we assume we're out of memory */
771                 return -1;
772         }
773
774         while (to_read != 0) {
775                 /* read option */
776                 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
777                 if (bytes_read <= 0) {
778                         pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
779                         return bytes_read;
780                 }
781                 block_read += bytes_read;
782                 to_read -= bytes_read;
783
784                 /* handle option content */
785                 switch (oh.option_code) {
786                     case(0): /* opt_endofopt */
787                         if (to_read != 0) {
788                                 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read);
789                         }
790                         /* padding should be ok here, just get out of this */
791                         to_read = 0;
792                         break;
793                     case(1): /* opt_comment */
794                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
795                                 wblock->data.if_descr.opt_comment = g_strndup(option_content, oh.option_length);
796                                 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock->data.if_descr.opt_comment);
797                         } else {
798                                 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh.option_length);
799                         }
800                         break;
801                     case(2): /* if_name */
802                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
803                                 wblock->data.if_descr.if_name = g_strndup(option_content, oh.option_length);
804                                 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock->data.if_descr.if_name);
805                         } else {
806                                 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh.option_length);
807                         }
808                         break;
809                     case(3): /* if_description */
810                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
811                             wblock->data.if_descr.if_description = g_strndup(option_content, oh.option_length);
812                                 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock->data.if_descr.if_description);
813                         } else {
814                                 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
815                         }
816                         break;
817                         /*
818                          * if_IPv4addr    4  Interface network address and netmask. This option can be repeated multiple times within the same Interface Description Block when multiple IPv4 addresses are assigned to the interface. 192 168 1 1 255 255 255 0
819                          * if_IPv6addr    5  Interface network address and prefix length (stored in the last byte). This option can be repeated multiple times within the same Interface Description Block when multiple IPv6 addresses are assigned to the interface. 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in hex) as "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40"
820                          * if_MACaddr     6  Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
821                          * if_EUIaddr     7  Interface Hardware EUI address (64 bits), if available. TODO: give a good example
822                          */
823                     case(8): /* if_speed */
824                         if (oh.option_length == 8) {
825                                 /*  Don't cast a char[] into a guint64--the
826                                  *  char[] may not be aligned correctly.
827                                  */
828                                 memcpy(&wblock->data.if_descr.if_speed, option_content, sizeof(guint64));
829                                 if (pn->byte_swapped)
830                                         wblock->data.if_descr.if_speed = GUINT64_SWAP_LE_BE(wblock->data.if_descr.if_speed);
831                                 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
832                         } else {
833                                     pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
834                         }
835                         break;
836                     case(9): /* if_tsresol */
837                         if (oh.option_length == 1) {
838                                 guint64 base;
839                                 guint64 result;
840                                 guint8 i, exponent, if_tsresol;
841
842                                 if_tsresol = option_content[0];
843                                 if (if_tsresol & 0x80) {
844                                         base = 2;
845                                 } else {
846                                         base = 10;
847                                 }
848                                 exponent = (guint8)(if_tsresol & 0x7f);
849                                 if (((base == 2) && (exponent < 64)) || ((base == 10) && (exponent < 20))) {
850                                         result = 1;
851                                         for (i = 0; i < exponent; i++) {
852                                                 result *= base;
853                                         }
854                                         time_units_per_second = result;
855                                 } else {
856                                         time_units_per_second = G_MAXUINT64;
857                                 }
858                                 if (time_units_per_second > (((guint64)1) << 32)) {
859                                         pcapng_debug0("pcapng_open: time conversion might be inaccurate");
860                                 }
861                                 wblock->data.if_descr.time_units_per_second = time_units_per_second;
862                                 wblock->data.if_descr.if_tsresol = if_tsresol;
863                                 pcapng_debug2("pcapng_read_if_descr_block: if_tsresol %u, units/s %" G_GINT64_MODIFIER "u", wblock->data.if_descr.if_tsresol, wblock->data.if_descr.time_units_per_second);
864                         } else {
865                                 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
866                         }
867                         break;
868                         /*
869                          * if_tzone      10  Time zone for GMT support (TODO: specify better). TODO: give a good example
870                          */
871                     case(11): /* if_filter */
872                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
873                                 /* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string,
874                                  * or BPF bytecode.
875                                  */
876                                 if (option_content[0] == 0) {
877                                         wblock->data.if_descr.if_filter_str = g_strndup(option_content+1, oh.option_length-1);
878                                         pcapng_debug2("pcapng_read_if_descr_block: if_filter_str %s oh.option_length %u", wblock->data.if_descr.if_filter_str, oh.option_length);
879                                 } else if (option_content[0] == 1) {
880                                         wblock->data.if_descr.bpf_filter_len = oh.option_length-1;
881                                         wblock->data.if_descr.if_filter_bpf_bytes = (gchar *)g_malloc(oh.option_length-1);
882                                         memcpy(&wblock->data.if_descr.if_filter_bpf_bytes, option_content+1, oh.option_length-1);
883                                 }
884                         } else {
885                                 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
886                         }
887                         break;
888                     case(12): /* if_os */
889                         /*
890                          * if_os         12  A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
891                          * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory)))
892                          * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
893                          */
894                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
895                             wblock->data.if_descr.if_os = g_strndup(option_content, oh.option_length);
896                                 pcapng_debug1("pcapng_read_if_descr_block: if_os %s", wblock->data.if_descr.if_os);
897                         } else {
898                                 pcapng_debug1("pcapng_read_if_descr_block: if_os length %u seems strange", oh.option_length);
899                         }
900                         break;
901                     case(13): /* if_fcslen */
902                         if (oh.option_length == 1) {
903                                 wblock->data.if_descr.if_fcslen = option_content[0];
904                                 pn->if_fcslen = wblock->data.if_descr.if_fcslen;
905                                 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock->data.if_descr.if_fcslen);
906                                 /* XXX - add sanity check */
907                         } else {
908                                 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
909                         }
910                         break;
911                         /*
912                          * if_tsoffset   14  A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
913                          * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
914                          * The time zone of the offset can be specified with the option if_tzone.
915                          * TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems? 1234
916                          */
917                     default:
918                         pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
919                                       oh.option_code, oh.option_length);
920                 }
921         }
922
923         g_free(option_content);
924
925         if (*wblock->file_encap == WTAP_ENCAP_UNKNOWN) {
926                 *wblock->file_encap = wblock->data.if_descr.wtap_encap;
927         } else {
928                 if (*wblock->file_encap != wblock->data.if_descr.wtap_encap) {
929                         *wblock->file_encap = WTAP_ENCAP_PER_PACKET;
930                 }
931         }
932
933         return block_read;
934 }
935
936
937 static int
938 pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info, gboolean enhanced)
939 {
940         int bytes_read;
941         guint block_read;
942         guint to_read, opt_cont_buf_len;
943         guint64 file_offset64;
944         pcapng_enhanced_packet_block_t epb;
945         pcapng_packet_block_t pb;
946         wtapng_packet_t packet;
947         guint32 block_total_length;
948         guint32 padding;
949         interface_data_t int_data;
950         guint64 ts;
951         pcapng_option_header_t oh;
952         int pseudo_header_len;
953         char *option_content = NULL; /* Allocate as large as the options block */
954         int fcslen;
955
956         /* Don't try to allocate memory for a huge number of options, as
957            that might fail and, even if it succeeds, it might not leave
958            any address space or memory+backing store for anything else.
959
960            We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
961            We check for this *after* checking the SHB for its byte
962            order magic number, so that non-pcap-ng files are less
963            likely to be treated as bad pcap-ng files. */
964         if (bh->block_total_length > MAX_BLOCK_SIZE) {
965                 *err = WTAP_ERR_BAD_FILE;
966                 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
967                               bh->block_total_length, MAX_BLOCK_SIZE);
968                 return -1;
969         }
970
971         /* "(Enhanced) Packet Block" read fixed part */
972         errno = WTAP_ERR_CANT_READ;
973         if (enhanced) {
974                 /*
975                  * Is this block long enough to be an EPB?
976                  */
977                 if (bh->block_total_length < MIN_EPB_SIZE) {
978                         /*
979                          * No.
980                          */
981                         *err = WTAP_ERR_BAD_FILE;
982                         *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of an EPB is less than the minimum EPB size %u",
983                                       bh->block_total_length, MIN_EPB_SIZE);
984                         return -1;
985                 }
986                 bytes_read = file_read(&epb, sizeof epb, fh);
987                 if (bytes_read != sizeof epb) {
988                         pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
989                         *err = file_error(fh, err_info);
990                         return 0;
991                 }
992                 block_read = bytes_read;
993
994                 if (pn->byte_swapped) {
995                         packet.interface_id        = GUINT32_SWAP_LE_BE(epb.interface_id);
996                         packet.drops_count         = -1; /* invalid */
997                         packet.ts_high             = GUINT32_SWAP_LE_BE(epb.timestamp_high);
998                         packet.ts_low              = GUINT32_SWAP_LE_BE(epb.timestamp_low);
999                         packet.cap_len             = GUINT32_SWAP_LE_BE(epb.captured_len);
1000                         packet.packet_len          = GUINT32_SWAP_LE_BE(epb.packet_len);
1001                 } else {
1002                         packet.interface_id        = epb.interface_id;
1003                         packet.drops_count         = -1; /* invalid */
1004                         packet.ts_high             = epb.timestamp_high;
1005                         packet.ts_low              = epb.timestamp_low;
1006                         packet.cap_len             = epb.captured_len;
1007                         packet.packet_len          = epb.packet_len;
1008                 }
1009                 pcapng_debug3("pcapng_read_packet_block: EPB on interface_id %d, cap_len %d, packet_len %d",
1010                               packet.interface_id, packet.cap_len, packet.packet_len);
1011         } else {
1012                 /*
1013                  * Is this block long enough to be a PB?
1014                  */
1015                 if (bh->block_total_length < MIN_PB_SIZE) {
1016                         /*
1017                          * No.
1018                          */
1019                         *err = WTAP_ERR_BAD_FILE;
1020                         *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of a PB is less than the minimum PB size %u",
1021                                       bh->block_total_length, MIN_PB_SIZE);
1022                         return -1;
1023                 }
1024                 bytes_read = file_read(&pb, sizeof pb, fh);
1025                 if (bytes_read != sizeof pb) {
1026                         pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
1027                         *err = file_error(fh, err_info);
1028                         return 0;
1029                 }
1030                 block_read = bytes_read;
1031
1032                 if (pn->byte_swapped) {
1033                         packet.interface_id        = GUINT16_SWAP_LE_BE(pb.interface_id);
1034                         packet.drops_count         = GUINT16_SWAP_LE_BE(pb.drops_count);
1035                         packet.ts_high             = GUINT32_SWAP_LE_BE(pb.timestamp_high);
1036                         packet.ts_low              = GUINT32_SWAP_LE_BE(pb.timestamp_low);
1037                         packet.cap_len             = GUINT32_SWAP_LE_BE(pb.captured_len);
1038                         packet.packet_len          = GUINT32_SWAP_LE_BE(pb.packet_len);
1039                 } else {
1040                         packet.interface_id        = pb.interface_id;
1041                         packet.drops_count         = pb.drops_count;
1042                         packet.ts_high             = pb.timestamp_high;
1043                         packet.ts_low              = pb.timestamp_low;
1044                         packet.cap_len             = pb.captured_len;
1045                         packet.packet_len          = pb.packet_len;
1046                 }
1047                 pcapng_debug3("pcapng_read_packet_block: PB on interface_id %d, cap_len %d, packet_len %d",
1048                               packet.interface_id, packet.cap_len, packet.packet_len);
1049         }
1050
1051         /*
1052          * How much padding is there at the end of the packet data?
1053          */
1054         if ((packet.cap_len % 4) != 0)
1055                 padding = 4 - (packet.cap_len % 4);
1056         else
1057                 padding = 0;
1058
1059         /* add padding bytes to "block total length" */
1060         /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1061         if (bh->block_total_length % 4) {
1062                 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1063         } else {
1064                 block_total_length = bh->block_total_length;
1065         }
1066         pcapng_debug1("pcapng_read_packet_block: block_total_length %d", block_total_length);
1067
1068         /*
1069          * Is this block long enough to hold the packet data?
1070          */
1071         if (enhanced) {
1072                 if (block_total_length <
1073                     MIN_EPB_SIZE + packet.cap_len + padding) {
1074                         /*
1075                          * No.
1076                          */
1077                         *err = WTAP_ERR_BAD_FILE;
1078                         *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of EPB is too small for %u bytes of packet data",
1079                                       block_total_length, packet.cap_len);
1080                         return -1;
1081                 }
1082         } else {
1083                 if (block_total_length <
1084                     MIN_PB_SIZE + packet.cap_len + padding) {
1085                         /*
1086                          * No.
1087                          */
1088                         *err = WTAP_ERR_BAD_FILE;
1089                         *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1090                                       block_total_length, packet.cap_len);
1091                         return -1;
1092                 }
1093         }
1094
1095         if (packet.cap_len > packet.packet_len) {
1096                 *err = WTAP_ERR_BAD_FILE;
1097                 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than packet_len %u",
1098                     packet.cap_len, packet.packet_len);
1099                 return 0;
1100         }
1101         if (packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1102                 *err = WTAP_ERR_BAD_FILE;
1103                 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
1104                     packet.cap_len, WTAP_MAX_PACKET_SIZE);
1105                 return 0;
1106         }
1107         pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
1108                       packet.packet_len,
1109                       packet.cap_len,
1110                       packet.interface_id);
1111
1112         if (packet.interface_id >= pn->number_of_interfaces) {
1113                 *err = WTAP_ERR_BAD_FILE;
1114                 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u",
1115                     packet.interface_id, pn->number_of_interfaces);
1116                 return 0;
1117         }
1118         int_data = g_array_index(pn->interface_data, interface_data_t,
1119             packet.interface_id);
1120
1121         wblock->packet_header->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1122
1123         pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
1124                        int_data.wtap_encap,
1125                        wtap_encap_string(int_data.wtap_encap),
1126                        pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header));
1127         wblock->packet_header->interface_id = packet.interface_id;
1128         wblock->packet_header->pkt_encap = int_data.wtap_encap;
1129
1130         memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1131         pseudo_header_len = pcap_process_pseudo_header(fh,
1132                                                        WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1133                                                        int_data.wtap_encap,
1134                                                        packet.cap_len,
1135                                                        TRUE,
1136                                                        wblock->packet_header,
1137                                                        err,
1138                                                        err_info);
1139         if (pseudo_header_len < 0) {
1140                 return 0;
1141         }
1142         block_read += pseudo_header_len;
1143         if (pseudo_header_len != pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header)) {
1144                 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
1145                               pseudo_header_len);
1146         }
1147         wblock->packet_header->caplen = packet.cap_len - pseudo_header_len;
1148         wblock->packet_header->len = packet.packet_len - pseudo_header_len;
1149
1150         /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
1151         ts = (((guint64)packet.ts_high) << 32) | ((guint64)packet.ts_low);
1152         wblock->packet_header->ts.secs = (time_t)(ts / int_data.time_units_per_second);
1153         wblock->packet_header->ts.nsecs = (int)(((ts % int_data.time_units_per_second) * 1000000000) / int_data.time_units_per_second);
1154
1155         /* "(Enhanced) Packet Block" read capture data */
1156         errno = WTAP_ERR_CANT_READ;
1157         if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1158             packet.cap_len - pseudo_header_len, err, err_info))
1159                 return 0;
1160         block_read += packet.cap_len - pseudo_header_len;
1161
1162         /* jump over potential padding bytes at end of the packet data */
1163         if (padding != 0) {
1164                 file_offset64 = file_seek(fh, padding, SEEK_CUR, err);
1165                 if (file_offset64 <= 0) {
1166                         if (*err != 0)
1167                                 return -1;
1168                         return 0;
1169                 }
1170                 block_read += padding;
1171         }
1172
1173         /* Option defaults */
1174         wblock->packet_header->opt_comment = NULL;
1175         wblock->packet_header->drop_count  = -1;
1176         wblock->packet_header->pack_flags  = 0;
1177
1178         /* FCS length default */
1179         fcslen = pn->if_fcslen;
1180
1181         /* Options
1182          * opt_comment    1
1183          * epb_flags      2
1184          * epb_hash       3
1185          * epb_dropcount  4
1186          */
1187         errno = WTAP_ERR_CANT_READ;
1188         to_read = block_total_length -
1189                   (int)sizeof(pcapng_block_header_t) -
1190                   block_read -    /* fixed and variable part, including padding */
1191                   (int)sizeof(bh->block_total_length);
1192
1193         /* Allocate enough memory to hold all options */
1194         opt_cont_buf_len = to_read;
1195         option_content = (char *)g_try_malloc(opt_cont_buf_len);
1196         if (opt_cont_buf_len != 0 && option_content == NULL) {
1197                 *err = ENOMEM;  /* we assume we're out of memory */
1198                 return -1;
1199         }
1200
1201         while (to_read != 0) {
1202                 /* read option */
1203                 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1204                 if (bytes_read <= 0) {
1205                         pcapng_debug0("pcapng_read_packet_block: failed to read option");
1206                         return bytes_read;
1207                 }
1208                 block_read += bytes_read;
1209                 to_read -= bytes_read;
1210
1211                 /* handle option content */
1212                 switch (oh.option_code) {
1213                     case(OPT_EOFOPT):
1214                         if (to_read != 0) {
1215                                 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
1216                         }
1217                         /* padding should be ok here, just get out of this */
1218                         to_read = 0;
1219                         break;
1220                     case(OPT_COMMENT):
1221                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1222                                 wblock->packet_header->presence_flags |= WTAP_HAS_COMMENTS;
1223                                 wblock->packet_header->opt_comment = g_strndup(option_content, oh.option_length);
1224                                 pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh.option_length, wblock->packet_header->opt_comment);
1225                         } else {
1226                                 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh.option_length);
1227                         }
1228                         break;
1229                     case(OPT_EPB_FLAGS):
1230                         if (oh.option_length == 4) {
1231                                 /*  Don't cast a char[] into a guint32--the
1232                                  *  char[] may not be aligned correctly.
1233                                  */
1234                                 wblock->packet_header->presence_flags |= WTAP_HAS_PACK_FLAGS;
1235                                 memcpy(&wblock->packet_header->pack_flags, option_content, sizeof(guint32));
1236                                 if (pn->byte_swapped)
1237                                         wblock->packet_header->pack_flags = GUINT32_SWAP_LE_BE(wblock->packet_header->pack_flags);
1238                                 if (wblock->packet_header->pack_flags & 0x000001E0) {
1239                                         /* The FCS length is present */
1240                                         fcslen = (wblock->packet_header->pack_flags & 0x000001E0) >> 5;
1241                                 }
1242                                 pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->packet_header->pack_flags);
1243                         } else {
1244                                 pcapng_debug1("pcapng_read_packet_block: pack_flags length %u not 4 as expected", oh.option_length);
1245                         }
1246                         break;
1247                     case(OPT_EPB_HASH):
1248                         pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
1249                                       oh.option_code, oh.option_length);
1250                         break;
1251                     case(OPT_EPB_DROPCOUNT):
1252                         if (oh.option_length == 8) {
1253                                 /*  Don't cast a char[] into a guint32--the
1254                                  *  char[] may not be aligned correctly.
1255                                  */
1256                                 wblock->packet_header->presence_flags |= WTAP_HAS_DROP_COUNT;
1257                                 memcpy(&wblock->packet_header->drop_count, option_content, sizeof(guint64));
1258                                 if (pn->byte_swapped)
1259                                         wblock->packet_header->drop_count = GUINT64_SWAP_LE_BE(wblock->packet_header->drop_count);
1260
1261                                 pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->packet_header->drop_count);
1262                         } else {
1263                                 pcapng_debug1("pcapng_read_packet_block: drop_count length %u not 8 as expected", oh.option_length);
1264                         }
1265                         break;
1266                     default:
1267                         pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
1268                                       oh.option_code, oh.option_length);
1269                 }
1270         }
1271
1272         g_free(option_content);
1273
1274         pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, int_data.wtap_encap,
1275             (union wtap_pseudo_header *)&wblock->packet_header->pseudo_header,
1276             buffer_start_ptr(wblock->frame_buffer),
1277             (int) (packet.cap_len - pseudo_header_len),
1278             pn->byte_swapped, fcslen);
1279         return block_read;
1280 }
1281
1282
1283 static int
1284 pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
1285 {
1286         int bytes_read;
1287         guint block_read;
1288         guint64 file_offset64;
1289         interface_data_t int_data;
1290         pcapng_simple_packet_block_t spb;
1291         wtapng_simple_packet_t simple_packet;
1292         guint32 block_total_length;
1293         guint32 padding;
1294         int pseudo_header_len;
1295
1296         /*
1297          * Is this block long enough to be an SPB?
1298          */
1299         if (bh->block_total_length < MIN_SPB_SIZE) {
1300                 /*
1301                  * No.
1302                  */
1303                 *err = WTAP_ERR_BAD_FILE;
1304                 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: total block length %u of an SPB is less than the minimum SPB size %u",
1305                               bh->block_total_length, MIN_SPB_SIZE);
1306                 return -1;
1307         }
1308
1309         /* Don't try to allocate memory for a huge number of options, as
1310            that might fail and, even if it succeeds, it might not leave
1311            any address space or memory+backing store for anything else.
1312
1313            We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1314            We check for this *after* checking the SHB for its byte
1315            order magic number, so that non-pcap-ng files are less
1316            likely to be treated as bad pcap-ng files. */
1317         if (bh->block_total_length > MAX_BLOCK_SIZE) {
1318                 *err = WTAP_ERR_BAD_FILE;
1319                 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1320                               bh->block_total_length, MAX_BLOCK_SIZE);
1321                 return -1;
1322         }
1323
1324         /* "Simple Packet Block" read fixed part */
1325         errno = WTAP_ERR_CANT_READ;
1326         bytes_read = file_read(&spb, sizeof spb, fh);
1327         if (bytes_read != sizeof spb) {
1328                 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
1329                 *err = file_error(fh, err_info);
1330                 return 0;
1331         }
1332         block_read = bytes_read;
1333
1334         if (0 >= pn->number_of_interfaces) {
1335                 *err = WTAP_ERR_BAD_FILE;
1336                 *err_info = g_strdup_printf("pcapng: SPB appeared before any IDBs");
1337                 return 0;
1338         }
1339         int_data = g_array_index(pn->interface_data, interface_data_t, 0);
1340
1341         if (pn->byte_swapped) {
1342                 simple_packet.packet_len   = GUINT32_SWAP_LE_BE(spb.packet_len);
1343         } else {
1344                 simple_packet.packet_len   = spb.packet_len;
1345         }
1346
1347         /*
1348          * The captured length is not a field in the SPB; it can be
1349          * calculated as the minimum of the snapshot length from the
1350          * IDB and the packet length, as per the pcap-ng spec.
1351          */
1352         simple_packet.cap_len = simple_packet.packet_len;
1353         if (simple_packet.cap_len > int_data.snap_len)
1354                 simple_packet.cap_len = int_data.snap_len;
1355
1356         /*
1357          * How much padding is there at the end of the packet data?
1358          */
1359         if ((simple_packet.cap_len % 4) != 0)
1360                 padding = 4 - (simple_packet.cap_len % 4);
1361         else
1362                 padding = 0;
1363
1364         /* add padding bytes to "block total length" */
1365         /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1366         if (bh->block_total_length % 4) {
1367                 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1368         } else {
1369                 block_total_length = bh->block_total_length;
1370         }
1371         pcapng_debug1("pcapng_read_simple_packet_block: block_total_length %d", block_total_length);
1372
1373         /*
1374          * Is this block long enough to hold the packet data?
1375          */
1376         if (block_total_length < MIN_SPB_SIZE + simple_packet.cap_len + padding) {
1377                 /*
1378                  * No.  That means that the problem is with the packet
1379                  * length; the snapshot length can be bigger than the amount
1380                  * of packet data in the block, as it's a *maximum* length,
1381                  * not a *minimum* length.
1382                  */
1383                 *err = WTAP_ERR_BAD_FILE;
1384                 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1385                               block_total_length, simple_packet.packet_len);
1386                 return -1;
1387         }
1388
1389         if (simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1390                 *err = WTAP_ERR_BAD_FILE;
1391                 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
1392                     simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
1393                 return 0;
1394         }
1395         pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
1396                        simple_packet.packet_len);
1397
1398         pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
1399                       pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header));
1400
1401         /* No time stamp in a simple packet block; no options, either */
1402         wblock->packet_header->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1403         wblock->packet_header->interface_id = 0;
1404         wblock->packet_header->pkt_encap = int_data.wtap_encap;
1405         wblock->packet_header->ts.secs = 0;
1406         wblock->packet_header->ts.nsecs = 0;
1407         wblock->packet_header->interface_id = 0;
1408         wblock->packet_header->opt_comment = NULL;
1409         wblock->packet_header->drop_count = 0;
1410         wblock->packet_header->pack_flags = 0;
1411
1412         memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1413         pseudo_header_len = pcap_process_pseudo_header(fh,
1414                                                        WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1415                                                        int_data.wtap_encap,
1416                                                        simple_packet.cap_len,
1417                                                        TRUE,
1418                                                        wblock->packet_header,
1419                                                        err,
1420                                                        err_info);
1421         if (pseudo_header_len < 0) {
1422                 return 0;
1423         }
1424         wblock->packet_header->caplen = simple_packet.cap_len - pseudo_header_len;
1425         wblock->packet_header->len = simple_packet.packet_len - pseudo_header_len;
1426         block_read += pseudo_header_len;
1427         if (pseudo_header_len != pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header)) {
1428                 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
1429                               pseudo_header_len);
1430         }
1431
1432         memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1433
1434         /* "Simple Packet Block" read capture data */
1435         errno = WTAP_ERR_CANT_READ;
1436         if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1437             simple_packet.cap_len, err, err_info))
1438                 return 0;
1439         block_read += simple_packet.cap_len;
1440
1441         /* jump over potential padding bytes at end of the packet data */
1442         if ((simple_packet.cap_len % 4) != 0) {
1443                 file_offset64 = file_seek(fh, 4 - (simple_packet.cap_len % 4), SEEK_CUR, err);
1444                 if (file_offset64 <= 0) {
1445                         if (*err != 0)
1446                                 return -1;
1447                         return 0;
1448                 }
1449                 block_read += 4 - (simple_packet.cap_len % 4);
1450         }
1451
1452         pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, int_data.wtap_encap,
1453             (union wtap_pseudo_header *)&wblock->packet_header->pseudo_header,
1454             buffer_start_ptr(wblock->frame_buffer),
1455             (int) simple_packet.cap_len,
1456             pn->byte_swapped, pn->if_fcslen);
1457         return block_read;
1458 }
1459
1460 #define NRES_ENDOFRECORD 0
1461 #define NRES_IP4RECORD 1
1462 #define NRES_IP6RECORD 2
1463 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
1464 /* IPv6 + MAXNAMELEN */
1465 #define INITIAL_NRB_REC_SIZE (16 + 64)
1466
1467 /*
1468  * Find the end of the NUL-terminated name the beginning of which is pointed
1469  * to by p; record_len is the number of bytes remaining in the record.
1470  *
1471  * Return the length of the name, including the terminating NUL.
1472  *
1473  * If we don't find a terminating NUL, return -1 and set *err and
1474  * *err_info appropriately.
1475  */
1476 static int
1477 name_resolution_block_find_name_end(const char *p, guint record_len, int *err,
1478     gchar **err_info)
1479 {
1480         int namelen;
1481
1482         namelen = 0;
1483         for (;;) {
1484                 if (record_len == 0) {
1485                         /*
1486                          * We ran out of bytes in the record without
1487                          * finding a NUL.
1488                          */
1489                         *err = WTAP_ERR_BAD_FILE;
1490                         *err_info = g_strdup("pcapng_read_name_resolution_block: NRB record has non-null-terminated host name");
1491                         return -1;
1492                 }
1493                 if (*p == '\0')
1494                         break;  /* that's the terminating NUL */
1495                 p++;
1496                 record_len--;
1497                 namelen++;      /* count this byte */
1498         }
1499
1500         /* Include the NUL in the name length. */
1501         return namelen + 1;
1502 }
1503
1504 static int
1505 pcapng_read_name_resolution_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock _U_,int *err, gchar **err_info)
1506 {
1507         int bytes_read = 0;
1508         int block_read = 0;
1509         int to_read;
1510         guint64 file_offset64;
1511         pcapng_name_resolution_block_t nrb;
1512         Buffer nrb_rec;
1513         guint32 v4_addr;
1514         guint record_len;
1515         char *namep;
1516         int namelen;
1517
1518         /*
1519          * Is this block long enough to be an NRB?
1520          */
1521         if (bh->block_total_length < MIN_NRB_SIZE) {
1522                 /*
1523                  * No.
1524                  */
1525                 *err = WTAP_ERR_BAD_FILE;
1526                 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: total block length %u of an NRB is less than the minimum NRB size %u",
1527                               bh->block_total_length, MIN_NRB_SIZE);
1528                 return -1;
1529         }
1530
1531         /* Don't try to allocate memory for a huge number of options, as
1532            that might fail and, even if it succeeds, it might not leave
1533            any address space or memory+backing store for anything else.
1534
1535            We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1536            We check for this *after* checking the SHB for its byte
1537            order magic number, so that non-pcap-ng files are less
1538            likely to be treated as bad pcap-ng files. */
1539         if (bh->block_total_length > MAX_BLOCK_SIZE) {
1540                 *err = WTAP_ERR_BAD_FILE;
1541                 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1542                               bh->block_total_length, MAX_BLOCK_SIZE);
1543                 return -1;
1544         }
1545
1546         errno = WTAP_ERR_CANT_READ;
1547         to_read = bh->block_total_length - 8 - 4; /* We have read the header adn should not read the final block_total_length */
1548
1549         pcapng_debug1("pcapng_read_name_resolution_block, total %d bytes", bh->block_total_length);
1550
1551         /*
1552          * Start out with a buffer big enough for an IPv6 address and one
1553          * 64-byte name; we'll make the buffer bigger if necessary.
1554          */
1555         buffer_init(&nrb_rec, INITIAL_NRB_REC_SIZE);
1556         while (block_read < to_read) {
1557                 /*
1558                  * There must be at least one record's worth of data
1559                  * here.
1560                  */
1561                 if ((size_t)(to_read - block_read) < sizeof nrb) {
1562                         buffer_free(&nrb_rec);
1563                         *err = WTAP_ERR_BAD_FILE;
1564                         *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record header size %u",
1565                                       to_read - block_read,
1566                                       (guint)sizeof nrb);
1567                         return -1;
1568                 }
1569                 bytes_read = file_read(&nrb, sizeof nrb, fh);
1570                 if (bytes_read != sizeof nrb) {
1571                         buffer_free(&nrb_rec);
1572                         pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
1573                         *err = file_error(fh, err_info);
1574                         return 0;
1575                 }
1576                 block_read += bytes_read;
1577
1578                 if (pn->byte_swapped) {
1579                         nrb.record_type = GUINT16_SWAP_LE_BE(nrb.record_type);
1580                         nrb.record_len  = GUINT16_SWAP_LE_BE(nrb.record_len);
1581                 }
1582
1583                 if (to_read - block_read < nrb.record_len + PADDING4(nrb.record_len)) {
1584                         buffer_free(&nrb_rec);
1585                         *err = WTAP_ERR_BAD_FILE;
1586                         *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record length + padding %u",
1587                                       to_read - block_read,
1588                                       nrb.record_len + PADDING4(nrb.record_len));
1589                         return -1;
1590                 }
1591                 switch (nrb.record_type) {
1592                         case NRES_ENDOFRECORD:
1593                                 /* There shouldn't be any more data */
1594                                 to_read = 0;
1595                                 break;
1596                         case NRES_IP4RECORD:
1597                                 /*
1598                                  * The smallest possible record must have
1599                                  * a 4-byte IPv4 address, hence a minimum
1600                                  * of 4 bytes.
1601                                  *
1602                                  * (The pcap-NG spec really indicates
1603                                  * that it must be at least 5 bytes,
1604                                  * as there must be at least one name,
1605                                  * and it really must be at least 6
1606                                  * bytes, as the name mustn't be null,
1607                                  * but there's no need to fail if there
1608                                  * aren't any names at all, and we
1609                                  * should report a null name as such.)
1610                                  */
1611                                 if (nrb.record_len < 4) {
1612                                         buffer_free(&nrb_rec);
1613                                         *err = WTAP_ERR_BAD_FILE;
1614                                         *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv4 record %u < minimum length 4",
1615                                                       nrb.record_len);
1616                                         return -1;
1617                                 }
1618                                 buffer_assure_space(&nrb_rec, nrb.record_len);
1619                                 bytes_read = file_read(buffer_start_ptr(&nrb_rec),
1620                                     nrb.record_len, fh);
1621                                 if (bytes_read != nrb.record_len) {
1622                                         buffer_free(&nrb_rec);
1623                                         pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
1624                                         *err = file_error(fh, err_info);
1625                                         return 0;
1626                                 }
1627                                 block_read += bytes_read;
1628
1629                                 if (pn->add_new_ipv4) {
1630                                         /*
1631                                          * Scan through all the names in
1632                                          * the record and add them.
1633                                          */
1634                                         memcpy(&v4_addr,
1635                                             buffer_start_ptr(&nrb_rec), 4);
1636                                         if (pn->byte_swapped)
1637                                                 v4_addr = GUINT32_SWAP_LE_BE(v4_addr);
1638                                         for (namep = (char *)buffer_start_ptr(&nrb_rec) + 4, record_len = nrb.record_len - 4;
1639                                             record_len != 0;
1640                                             namep += namelen, record_len -= namelen) {
1641                                                 /*
1642                                                  * Scan forward for a null
1643                                                  * byte.
1644                                                  */
1645                                                 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1646                                                 if (namelen == -1) {
1647                                                         buffer_free(&nrb_rec);
1648                                                         return -1;      /* fail */
1649                                                 }
1650                                                 pn->add_new_ipv4(v4_addr, namep);
1651                                         }
1652                                 }
1653
1654                                 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1655                                 if (file_offset64 <= 0) {
1656                                         buffer_free(&nrb_rec);
1657                                         if (*err != 0)
1658                                                 return -1;
1659                                         return 0;
1660                                 }
1661                                 block_read += PADDING4(nrb.record_len);
1662                                 break;
1663                         case NRES_IP6RECORD:
1664                                 /*
1665                                  * The smallest possible record must have
1666                                  * a 16-byte IPv6 address, hence a minimum
1667                                  * of 16 bytes.
1668                                  *
1669                                  * (The pcap-NG spec really indicates
1670                                  * that it must be at least 17 bytes,
1671                                  * as there must be at least one name,
1672                                  * and it really must be at least 18
1673                                  * bytes, as the name mustn't be null,
1674                                  * but there's no need to fail if there
1675                                  * aren't any names at all, and we
1676                                  * should report a null name as such.)
1677                                  */
1678                                 if (nrb.record_len < 16) {
1679                                         buffer_free(&nrb_rec);
1680                                         *err = WTAP_ERR_BAD_FILE;
1681                                         *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u < minimum length 16",
1682                                                       nrb.record_len);
1683                                         return -1;
1684                                 }
1685                                 if (to_read < nrb.record_len) {
1686                                         buffer_free(&nrb_rec);
1687                                         pcapng_debug0("pcapng_read_name_resolution_block: insufficient data for IPv6 record");
1688                                         return 0;
1689                                 }
1690                                 buffer_assure_space(&nrb_rec, nrb.record_len);
1691                                 bytes_read = file_read(buffer_start_ptr(&nrb_rec),
1692                                     nrb.record_len, fh);
1693                                 if (bytes_read != nrb.record_len) {
1694                                         buffer_free(&nrb_rec);
1695                                         pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv6 record data");
1696                                         *err = file_error(fh, err_info);
1697                                         return 0;
1698                                 }
1699                                 block_read += bytes_read;
1700
1701                                 if (pn->add_new_ipv6) {
1702                                         for (namep = (char *)buffer_start_ptr(&nrb_rec) + 16, record_len = nrb.record_len - 16;
1703                                             record_len != 0;
1704                                             namep += namelen, record_len -= namelen) {
1705                                                 /*
1706                                                  * Scan forward for a null
1707                                                  * byte.
1708                                                  */
1709                                                 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1710                                                 if (namelen == -1) {
1711                                                         buffer_free(&nrb_rec);
1712                                                         return -1;      /* fail */
1713                                                 }
1714                                                 pn->add_new_ipv6(buffer_start_ptr(&nrb_rec),
1715                                                     namep);
1716                                         }
1717                                 }
1718
1719                                 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1720                                 if (file_offset64 <= 0) {
1721                                         buffer_free(&nrb_rec);
1722                                         if (*err != 0)
1723                                                 return -1;
1724                                         return 0;
1725                                 }
1726                                 block_read += PADDING4(nrb.record_len);
1727                                 break;
1728                         default:
1729                                 pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
1730                                 file_offset64 = file_seek(fh, nrb.record_len + PADDING4(nrb.record_len), SEEK_CUR, err);
1731                                 if (file_offset64 <= 0) {
1732                                         buffer_free(&nrb_rec);
1733                                         if (*err != 0)
1734                                                 return -1;
1735                                         return 0;
1736                                 }
1737                                 block_read += nrb.record_len + PADDING4(nrb.record_len);
1738                                 break;
1739                 }
1740         }
1741
1742         buffer_free(&nrb_rec);
1743         return block_read;
1744 }
1745
1746 static int
1747 pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock,int *err, gchar **err_info)
1748 {
1749         int bytes_read;
1750         guint block_read;
1751         guint to_read, opt_cont_buf_len;
1752         pcapng_interface_statistics_block_t isb;
1753         pcapng_option_header_t oh;
1754         char *option_content = NULL; /* Allocate as large as the options block */
1755
1756         /*
1757          * Is this block long enough to be an ISB?
1758          */
1759         if (bh->block_total_length < MIN_ISB_SIZE) {
1760                 /*
1761                  * No.
1762                  */
1763                 *err = WTAP_ERR_BAD_FILE;
1764                 *err_info = g_strdup_printf("pcapng_read_interface_statistics_block: total block length %u is too small (< %u)",
1765                               bh->block_total_length, MIN_ISB_SIZE);
1766                 return -1;
1767         }
1768
1769         /* Don't try to allocate memory for a huge number of options, as
1770            that might fail and, even if it succeeds, it might not leave
1771            any address space or memory+backing store for anything else.
1772
1773            We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1774            We check for this *after* checking the SHB for its byte
1775            order magic number, so that non-pcap-ng files are less
1776            likely to be treated as bad pcap-ng files. */
1777         if (bh->block_total_length > MAX_BLOCK_SIZE) {
1778                 *err = WTAP_ERR_BAD_FILE;
1779                 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1780                               bh->block_total_length, MAX_BLOCK_SIZE);
1781                 return -1;
1782         }
1783
1784         /* "Interface Statistics Block" read fixed part */
1785         errno = WTAP_ERR_CANT_READ;
1786         bytes_read = file_read(&isb, sizeof isb, fh);
1787         if (bytes_read != sizeof isb) {
1788                 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1789                 *err = file_error(fh, err_info);
1790                 return 0;
1791         }
1792         block_read = bytes_read;
1793
1794         if (pn->byte_swapped) {
1795                 wblock->data.if_stats.interface_id = GUINT32_SWAP_LE_BE(isb.interface_id);
1796                 wblock->data.if_stats.ts_high      = GUINT32_SWAP_LE_BE(isb.timestamp_high);
1797                 wblock->data.if_stats.ts_low       = GUINT32_SWAP_LE_BE(isb.timestamp_low);
1798         } else {
1799                 wblock->data.if_stats.interface_id = isb.interface_id;
1800                 wblock->data.if_stats.ts_high      = isb.timestamp_high;
1801                 wblock->data.if_stats.ts_low       = isb.timestamp_low;
1802         }
1803         pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %u", wblock->data.if_stats.interface_id);
1804
1805         /* Option defaults */
1806         wblock->data.if_stats.opt_comment          = NULL;
1807         wblock->data.if_stats.isb_ifrecv           = -1;
1808         wblock->data.if_stats.isb_ifdrop           = -1;
1809         wblock->data.if_stats.isb_filteraccept     = -1;
1810         wblock->data.if_stats.isb_osdrop           = -1;
1811         wblock->data.if_stats.isb_usrdeliv         = -1;
1812
1813         /* Options */
1814         errno = WTAP_ERR_CANT_READ;
1815         to_read = bh->block_total_length -
1816                   (MIN_BLOCK_SIZE + block_read);    /* fixed and variable part, including padding */
1817
1818         /* Allocate enough memory to hold all options */
1819         opt_cont_buf_len = to_read;
1820         option_content = (char *)g_try_malloc(opt_cont_buf_len);
1821         if (opt_cont_buf_len != 0 && option_content == NULL) {
1822                 *err = ENOMEM;  /* we assume we're out of memory */
1823                 return -1;
1824         }
1825
1826         while (to_read != 0) {
1827                 /* read option */
1828                 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1829                 if (bytes_read <= 0) {
1830                         pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
1831                         return bytes_read;
1832                 }
1833                 block_read += bytes_read;
1834                 to_read -= bytes_read;
1835
1836                 /* handle option content */
1837                 switch (oh.option_code) {
1838                     case(0): /* opt_endofopt */
1839                         if (to_read != 0) {
1840                                 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
1841                         }
1842                         /* padding should be ok here, just get out of this */
1843                         to_read = 0;
1844                         break;
1845                     case(1): /* opt_comment */
1846                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1847                                 wblock->data.if_stats.opt_comment = g_strndup(option_content, oh.option_length);
1848                                 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.if_stats.opt_comment);
1849                         } else {
1850                                 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
1851                         }
1852                         break;
1853                     case(2): /* isb_starttime */
1854                         if (oh.option_length == 8) {
1855                                 guint32 high, low;
1856
1857                                 /*  Don't cast a char[] into a guint32--the
1858                                  *  char[] may not be aligned correctly.
1859                                  */
1860                                 memcpy(&high, option_content, sizeof(guint32));
1861                                 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
1862                                 if (pn->byte_swapped) {
1863                                         high = GUINT32_SWAP_LE_BE(high);
1864                                         low = GUINT32_SWAP_LE_BE(low);
1865                                 }
1866                                 wblock->data.if_stats.isb_starttime = (guint64)high;
1867                                 wblock->data.if_stats.isb_starttime <<= 32;
1868                                 wblock->data.if_stats.isb_starttime += (guint64)low;
1869                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_starttime);
1870                         } else {
1871                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1872                         }
1873                         break;
1874                     case(3): /* isb_endtime */
1875                         if (oh.option_length == 8) {
1876                                 guint32 high, low;
1877
1878                                 /*  Don't cast a char[] into a guint32--the
1879                                  *  char[] may not be aligned correctly.
1880                                  */
1881                                 memcpy(&high, option_content, sizeof(guint32));
1882                                 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
1883                                 if (pn->byte_swapped) {
1884                                         high = GUINT32_SWAP_LE_BE(high);
1885                                         low = GUINT32_SWAP_LE_BE(low);
1886                                 }
1887                                 wblock->data.if_stats.isb_endtime = (guint64)high;
1888                                 wblock->data.if_stats.isb_endtime <<= 32;
1889                                 wblock->data.if_stats.isb_endtime += (guint64)low;
1890                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_endtime);
1891                         } else {
1892                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1893                         }
1894                         break;
1895                     case(4): /* isb_ifrecv */
1896                         if (oh.option_length == 8) {
1897                                 /*  Don't cast a char[] into a guint32--the
1898                                  *  char[] may not be aligned correctly.
1899                                  */
1900                                 memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
1901                                 if (pn->byte_swapped)
1902                                         wblock->data.if_stats.isb_ifrecv = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_ifrecv);
1903                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifrecv);
1904                         } else {
1905                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
1906                         }
1907                         break;
1908                     case(5): /* isb_ifdrop */
1909                         if (oh.option_length == 8) {
1910                                 /*  Don't cast a char[] into a guint32--the
1911                                  *  char[] may not be aligned correctly.
1912                                  */
1913                                 memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
1914                                 if (pn->byte_swapped)
1915                                         wblock->data.if_stats.isb_ifdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_ifdrop);
1916                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifdrop);
1917                         } else {
1918                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
1919                         }
1920                         break;
1921                     case(6): /* isb_filteraccept 6 */
1922                         if (oh.option_length == 8) {
1923                                 /*  Don't cast a char[] into a guint32--the
1924                                  *  char[] may not be aligned correctly.
1925                                  */
1926                                 memcpy(&wblock->data.if_stats.isb_filteraccept, option_content, sizeof(guint64));
1927                                 if (pn->byte_swapped)
1928                                         wblock->data.if_stats.isb_ifdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_filteraccept);
1929                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_filteraccept);
1930                         } else {
1931                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
1932                         }
1933                         break;
1934                     case(7): /* isb_osdrop 7 */
1935                         if (oh.option_length == 8) {
1936                                 /*  Don't cast a char[] into a guint32--the
1937                                  *  char[] may not be aligned correctly.
1938                                  */
1939                                 memcpy(&wblock->data.if_stats.isb_osdrop, option_content, sizeof(guint64));
1940                                 if (pn->byte_swapped)
1941                                         wblock->data.if_stats.isb_osdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_osdrop);
1942                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_osdrop);
1943                         } else {
1944                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
1945                         }
1946                         break;
1947                     case(8): /* isb_usrdeliv 8  */
1948                         if (oh.option_length == 8) {
1949                                 /*  Don't cast a char[] into a guint32--the
1950                                  *  char[] may not be aligned correctly.
1951                                  */
1952                                 memcpy(&wblock->data.if_stats.isb_usrdeliv, option_content, sizeof(guint64));
1953                                 if (pn->byte_swapped)
1954                                         wblock->data.if_stats.isb_usrdeliv = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_osdrop);
1955                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_usrdeliv);
1956                         } else {
1957                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
1958                         }
1959                         break;
1960                     default:
1961                         pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
1962                                       oh.option_code, oh.option_length);
1963                 }
1964         }
1965
1966         g_free(option_content);
1967
1968         return block_read;
1969 }
1970
1971
1972 static int
1973 pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn _U_, wtapng_block_t *wblock _U_, int *err, gchar **err_info)
1974 {
1975         int block_read;
1976         guint64 file_offset64;
1977         guint32 block_total_length;
1978
1979         if (bh->block_total_length < MIN_BLOCK_SIZE) {
1980                 *err = WTAP_ERR_BAD_FILE;
1981                 *err_info = g_strdup_printf("pcapng_read_unknown_block: total block length %u of an unknown block type is less than the minimum block size %u",
1982                               bh->block_total_length, MIN_BLOCK_SIZE);
1983                 return -1;
1984         }
1985
1986         /* add padding bytes to "block total length" */
1987         /* (the "block total length" of some example files don't contain any padding bytes!) */
1988         if (bh->block_total_length % 4) {
1989                 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1990         } else {
1991                 block_total_length = bh->block_total_length;
1992         }
1993
1994         block_read = block_total_length - MIN_BLOCK_SIZE;
1995
1996         /* jump over this unknown block */
1997         file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
1998         if (file_offset64 <= 0) {
1999                 if (*err != 0)
2000                         return -1;
2001                 return 0;
2002         }
2003
2004         return block_read;
2005 }
2006
2007
2008 static int
2009 pcapng_read_block(FILE_T fh, gboolean first_block, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
2010 {
2011         int block_read;
2012         int bytes_read;
2013         pcapng_block_header_t bh;
2014         guint32 block_total_length;
2015
2016
2017         /* Try to read the (next) block header */
2018         errno = WTAP_ERR_CANT_READ;
2019         bytes_read = file_read(&bh, sizeof bh, fh);
2020         if (bytes_read != sizeof bh) {
2021                 *err = file_error(fh, err_info);
2022                 pcapng_debug3("pcapng_read_block: file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
2023                 if (*err != 0)
2024                         return -1;
2025                 return 0;
2026         }
2027
2028         block_read = bytes_read;
2029         if (pn->byte_swapped) {
2030                 bh.block_type         = GUINT32_SWAP_LE_BE(bh.block_type);
2031                 bh.block_total_length = GUINT32_SWAP_LE_BE(bh.block_total_length);
2032         }
2033
2034         wblock->type = bh.block_type;
2035
2036         pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
2037
2038         if (first_block) {
2039                 /*
2040                  * This is being read in by pcapng_open(), so this block
2041                  * must be an SHB.  If it's not, this is not a pcap-ng
2042                  * file.
2043                  *
2044                  * XXX - check for various forms of Windows <-> UN*X
2045                  * mangling, and suggest that the file might be a
2046                  * pcap-ng file that was damaged in transit?
2047                  */
2048                 if (bh.block_type != BLOCK_TYPE_SHB)
2049                         return 0;       /* not a pcap-ng file */
2050         }
2051
2052         switch (bh.block_type) {
2053                 case(BLOCK_TYPE_SHB):
2054                         bytes_read = pcapng_read_section_header_block(fh, first_block, &bh, pn, wblock, err, err_info);
2055                         break;
2056                 case(BLOCK_TYPE_IDB):
2057                         bytes_read = pcapng_read_if_descr_block(fh, &bh, pn, wblock, err, err_info);
2058                         break;
2059                 case(BLOCK_TYPE_PB):
2060                         bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE);
2061                         break;
2062                 case(BLOCK_TYPE_SPB):
2063                         bytes_read = pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info);
2064                         break;
2065                 case(BLOCK_TYPE_EPB):
2066                         bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
2067                         break;
2068                 case(BLOCK_TYPE_NRB):
2069                         bytes_read = pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info);
2070                         break;
2071                 case(BLOCK_TYPE_ISB):
2072                         bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
2073                         break;
2074                 default:
2075                         pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
2076                         bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
2077         }
2078
2079         if (bytes_read <= 0) {
2080                 return bytes_read;
2081         }
2082         block_read += bytes_read;
2083
2084         /* sanity check: first and second block lengths must match */
2085         errno = WTAP_ERR_CANT_READ;
2086         bytes_read = file_read(&block_total_length, sizeof block_total_length, fh);
2087         if (bytes_read != sizeof block_total_length) {
2088                 pcapng_debug0("pcapng_read_block: couldn't read second block length");
2089                 *err = file_error(fh, err_info);
2090                 if (*err == 0)
2091                         *err = WTAP_ERR_SHORT_READ;
2092                 return -1;
2093         }
2094         block_read += bytes_read;
2095
2096         if (pn->byte_swapped)
2097                 block_total_length = GUINT32_SWAP_LE_BE(block_total_length);
2098
2099         if (!(block_total_length == bh.block_total_length)) {
2100                 *err = WTAP_ERR_BAD_FILE;
2101                 *err_info = g_strdup_printf("pcapng_read_block: total block lengths (first %u and second %u) don't match",
2102                               bh.block_total_length, block_total_length);
2103                 return -1;
2104         }
2105
2106         return block_read;
2107 }
2108
2109 /* Process an IDB that we've just read. */
2110 static void
2111 pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock)
2112 {
2113         wtapng_if_descr_t int_data;
2114         interface_data_t interface_data;
2115
2116         int_data.wtap_encap = wblock->data.if_descr.wtap_encap;
2117         int_data.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2118         int_data.link_type = wblock->data.if_descr.link_type;
2119         int_data.snap_len = wblock->data.if_descr.snap_len;
2120         /* Options */
2121         int_data.opt_comment = wblock->data.if_descr.opt_comment;
2122         int_data.if_name = wblock->data.if_descr.if_name;
2123         int_data.if_description = wblock->data.if_descr.if_description;
2124         /* XXX: if_IPv4addr opt 4  Interface network address and netmask.*/
2125         /* XXX: if_IPv6addr opt 5  Interface network address and prefix length (stored in the last byte).*/
2126         /* XXX: if_MACaddr  opt 6  Interface Hardware MAC address (48 bits).*/
2127         /* XXX: if_EUIaddr  opt 7  Interface Hardware EUI address (64 bits)*/
2128         int_data.if_speed = wblock->data.if_descr.if_speed;
2129         int_data.if_tsresol = wblock->data.if_descr.if_tsresol;
2130         /* XXX: if_tzone      10  Time zone for GMT support (TODO: specify better). */
2131         int_data.if_filter_str = wblock->data.if_descr.if_filter_str;
2132         int_data.bpf_filter_len = wblock->data.if_descr.bpf_filter_len;
2133         int_data.if_filter_bpf_bytes = wblock->data.if_descr.if_filter_bpf_bytes;
2134         int_data.if_os = wblock->data.if_descr.if_os;
2135         int_data.if_fcslen = wblock->data.if_descr.if_fcslen;
2136         /* XXX if_tsoffset; opt 14  A 64 bits integer value that specifies an offset (in seconds)...*/
2137         /* Interface statistics */
2138         int_data.num_stat_entries = 0;
2139         int_data.interface_statistics = NULL;
2140
2141         g_array_append_val(wth->interface_data, int_data);
2142         wth->number_of_interfaces++;
2143
2144         interface_data.wtap_encap = wblock->data.if_descr.wtap_encap;
2145         interface_data.snap_len = wblock->data.if_descr.snap_len;
2146         interface_data.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2147
2148         g_array_append_val(pcapng->interface_data, interface_data);
2149         pcapng->number_of_interfaces++;
2150 }
2151
2152 /* classic wtap: open capture file */
2153 int
2154 pcapng_open(wtap *wth, int *err, gchar **err_info)
2155 {
2156         int bytes_read;
2157         pcapng_t pn;
2158         wtapng_block_t wblock;
2159         pcapng_t *pcapng;
2160         pcapng_block_header_t bh;
2161         gint64 saved_offset;
2162
2163         pn.shb_read = FALSE;
2164         /* we don't know the byte swapping of the file yet */
2165         pn.byte_swapped = FALSE;
2166         pn.if_fcslen = -1;
2167         pn.version_major = -1;
2168         pn.version_minor = -1;
2169         pn.interface_data = g_array_new(FALSE, FALSE, sizeof(interface_data_t));
2170         pn.number_of_interfaces = 0;
2171
2172
2173         /* we don't expect any packet blocks yet */
2174         wblock.frame_buffer = NULL;
2175         wblock.packet_header = NULL;
2176         wblock.file_encap = &wth->file_encap;
2177
2178         pcapng_debug0("pcapng_open: opening file");
2179         /* read first block */
2180         bytes_read = pcapng_read_block(wth->fh, TRUE, &pn, &wblock, err, err_info);
2181         if (bytes_read <= 0) {
2182                 pcapng_debug0("pcapng_open: couldn't read first SHB");
2183                 *err = file_error(wth->fh, err_info);
2184                 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
2185                         return -1;
2186                 return 0;
2187         }
2188
2189         /* first block must be a "Section Header Block" */
2190         if (wblock.type != BLOCK_TYPE_SHB) {
2191                 /*
2192                  * XXX - check for damage from transferring a file
2193                  * between Windows and UN*X as text rather than
2194                  * binary data?
2195                  */
2196                 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
2197                 return 0;
2198         }
2199         pn.shb_read = TRUE;
2200
2201         /*
2202          * At this point, we've decided this is a pcap-NG file, not
2203          * some other type of file, so we can't return 0, as that
2204          * means "this isn't a pcap-NG file, try some other file
2205          * type".
2206          */
2207         wth->shb_hdr.opt_comment = wblock.data.section.opt_comment;
2208         wth->shb_hdr.shb_hardware = wblock.data.section.shb_hardware;
2209         wth->shb_hdr.shb_os = wblock.data.section.shb_os;
2210         wth->shb_hdr.shb_user_appl = wblock.data.section.shb_user_appl;
2211
2212         wth->file_encap = WTAP_ENCAP_UNKNOWN;
2213         wth->snapshot_length = 0;
2214         wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
2215         pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
2216         wth->priv = (void *)pcapng;
2217         *pcapng = pn;
2218
2219         wth->subtype_read = pcapng_read;
2220         wth->subtype_seek_read = pcapng_seek_read;
2221         wth->subtype_close = pcapng_close;
2222         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
2223
2224         /* Read IDBs */
2225         wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
2226         wth->number_of_interfaces = 0;
2227
2228         /* Loop over all IDB:s that appear before any packets */
2229         while (1) {
2230                 /* peek at next block */
2231                 /* Try to read the (next) block header */
2232                 saved_offset = file_tell(wth->fh);
2233                 errno = WTAP_ERR_CANT_READ;
2234                 bytes_read = file_read(&bh, sizeof bh, wth->fh);
2235                 if (bytes_read == 0) {
2236                         pcapng_debug0("No more IDBs available...");
2237                         break;
2238                 }
2239                 if (bytes_read != sizeof bh) {
2240                         *err = file_error(wth->fh, err_info);
2241                         pcapng_debug3("pcapng_open:  Check for more IDB:s, file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
2242                         if (*err == 0)
2243                                 *err = WTAP_ERR_SHORT_READ;
2244                         return -1;
2245                 }
2246
2247                 /* go back to where we were */
2248                 file_seek(wth->fh, saved_offset, SEEK_SET, err);
2249
2250                 if (pn.byte_swapped) {
2251                         bh.block_type         = GUINT32_SWAP_LE_BE(bh.block_type);
2252                 }
2253
2254                 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh.block_type);
2255
2256                 if (bh.block_type != BLOCK_TYPE_IDB) {
2257                         break;  /* No more IDB:s */
2258                 }
2259                 bytes_read = pcapng_read_block(wth->fh, FALSE, &pn, &wblock, err, err_info);
2260                 if (bytes_read == 0) {
2261                         pcapng_debug0("No more IDBs available...");
2262                         break;
2263                 }
2264                 if (bytes_read <= 0) {
2265                         pcapng_debug0("pcapng_open: couldn't read IDB");
2266                         *err = file_error(wth->fh, err_info);
2267                         if (*err == 0)
2268                                 *err = WTAP_ERR_SHORT_READ;
2269                         return -1;
2270                 }
2271                 pcapng_process_idb(wth, pcapng, &wblock);
2272                 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i", wth->number_of_interfaces, *wblock.file_encap);
2273         }
2274         return 1;
2275 }
2276
2277
2278 /* classic wtap: read packet */
2279 static gboolean
2280 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
2281 {
2282         pcapng_t *pcapng = (pcapng_t *)wth->priv;
2283         int bytes_read;
2284         wtapng_block_t wblock;
2285         wtapng_if_descr_t *wtapng_if_descr;
2286         wtapng_if_stats_t if_stats;
2287
2288         *data_offset = file_tell(wth->fh);
2289         pcapng_debug1("pcapng_read: data_offset is initially %" G_GINT64_MODIFIER "d", *data_offset);
2290
2291         wblock.frame_buffer  = wth->frame_buffer;
2292         wblock.packet_header = &wth->phdr;
2293         wblock.file_encap    = &wth->file_encap;
2294
2295         pcapng->add_new_ipv4 = wth->add_new_ipv4;
2296         pcapng->add_new_ipv6 = wth->add_new_ipv6;
2297
2298         /* read next block */
2299         while (1) {
2300                 bytes_read = pcapng_read_block(wth->fh, FALSE, pcapng, &wblock, err, err_info);
2301                 if (bytes_read <= 0) {
2302                         pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
2303                         pcapng_debug0("pcapng_read: couldn't read packet block");
2304                         return FALSE;
2305                 }
2306
2307                 switch (wblock.type) {
2308
2309                 case(BLOCK_TYPE_SHB):
2310                         /* We don't currently support multi-section files. */
2311                         wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
2312                         *err = WTAP_ERR_UNSUPPORTED;
2313                         *err_info = g_strdup_printf("pcapng: multi-section files not currently supported");
2314                         return FALSE;
2315
2316                 case(BLOCK_TYPE_PB):
2317                 case(BLOCK_TYPE_SPB):
2318                 case(BLOCK_TYPE_EPB):
2319                         /* packet block - we've found a packet */
2320                         goto got_packet;
2321
2322                 case(BLOCK_TYPE_IDB):
2323                         /* A new interface */
2324                         pcapng_debug0("pcapng_read: block type BLOCK_TYPE_IDB");
2325                         *data_offset += bytes_read;
2326                         pcapng_process_idb(wth, pcapng, &wblock);
2327                         break;
2328
2329                 case(BLOCK_TYPE_NRB):
2330                         /* More name resolution entries */
2331                         pcapng_debug0("pcapng_read: block type BLOCK_TYPE_NRB");
2332                         *data_offset += bytes_read;
2333                         break;
2334
2335                 case(BLOCK_TYPE_ISB):
2336                         /* Another interface statistics report */
2337                         pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB");
2338                         *data_offset += bytes_read;
2339                         pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "d", *data_offset);
2340                         if (wth->number_of_interfaces < wblock.data.if_stats.interface_id) {
2341                                 pcapng_debug1("pcapng_read: BLOCK_TYPE_ISB wblock.if_stats.interface_id %u > number_of_interfaces", wblock.data.if_stats.interface_id);
2342                         } else {
2343                                 /* Get the interface description */
2344                                 wtapng_if_descr = &g_array_index(wth->interface_data, wtapng_if_descr_t, wblock.data.if_stats.interface_id);
2345                                 if (wtapng_if_descr->num_stat_entries == 0) {
2346                                     /* First ISB found, no previous entry */
2347                                     pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB. First ISB found, no previous entry");
2348                                     wtapng_if_descr->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtapng_if_stats_t));
2349                                 }
2350
2351                                 if_stats.interface_id       = wblock.data.if_stats.interface_id;
2352                                 if_stats.ts_high            = wblock.data.if_stats.ts_high;
2353                                 if_stats.ts_low             = wblock.data.if_stats.ts_low;
2354                                 /* options */
2355                                 if_stats.opt_comment        = wblock.data.if_stats.opt_comment; /* NULL if not available */
2356                                 if_stats.isb_starttime      = wblock.data.if_stats.isb_starttime;
2357                                 if_stats.isb_endtime        = wblock.data.if_stats.isb_endtime;
2358                                 if_stats.isb_ifrecv         = wblock.data.if_stats.isb_ifrecv;
2359                                 if_stats.isb_ifdrop         = wblock.data.if_stats.isb_ifdrop;
2360                                 if_stats.isb_filteraccept   = wblock.data.if_stats.isb_filteraccept;
2361                                 if_stats.isb_osdrop         = wblock.data.if_stats.isb_osdrop;
2362                                 if_stats.isb_usrdeliv       = wblock.data.if_stats.isb_usrdeliv;
2363
2364                                 g_array_append_val(wtapng_if_descr->interface_statistics, if_stats);
2365                                 wtapng_if_descr->num_stat_entries++;
2366                         }
2367                         break;
2368
2369                 default:
2370                         /* XXX - improve handling of "unknown" blocks */
2371                         pcapng_debug1("pcapng_read: Unknown block type 0x%08x", wblock.type);
2372                         *data_offset += bytes_read;
2373                         pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "d", *data_offset);
2374                         break;
2375                 }
2376         }
2377
2378 got_packet:
2379
2380         /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2381         pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset + bytes_read);
2382
2383         return TRUE;
2384 }
2385
2386
2387 /* classic wtap: seek to file position and read packet */
2388 static gboolean
2389 pcapng_seek_read(wtap *wth, gint64 seek_off,
2390     struct wtap_pkthdr *phdr, Buffer *buf,
2391     int *err, gchar **err_info)
2392 {
2393         pcapng_t *pcapng = (pcapng_t *)wth->priv;
2394         guint64 bytes_read64;
2395         int bytes_read;
2396         wtapng_block_t wblock;
2397
2398
2399         /* seek to the right file position */
2400         bytes_read64 = file_seek(wth->random_fh, seek_off, SEEK_SET, err);
2401         if (bytes_read64 <= 0) {
2402                 return FALSE;   /* Seek error */
2403         }
2404         pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
2405
2406         wblock.frame_buffer = buf;
2407         wblock.packet_header = phdr;
2408         wblock.file_encap = &wth->file_encap;
2409
2410         /* read the block */
2411         bytes_read = pcapng_read_block(wth->random_fh, FALSE, pcapng, &wblock, err, err_info);
2412         if (bytes_read <= 0) {
2413                 pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
2414                               *err, errno, bytes_read);
2415                 return FALSE;
2416         }
2417
2418         /* block must be a "Packet Block", an "Enhanced Packet Block",
2419            or a "Simple Packet Block" */
2420         if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB &&
2421             wblock.type != BLOCK_TYPE_SPB) {
2422                 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB/SPB", wblock.type);
2423                 return FALSE;
2424         }
2425
2426         return TRUE;
2427 }
2428
2429
2430 /* classic wtap: close capture file */
2431 static void
2432 pcapng_close(wtap *wth)
2433 {
2434         pcapng_t *pcapng = (pcapng_t *)wth->priv;
2435
2436         pcapng_debug0("pcapng_close: closing file");
2437         if (pcapng->interface_data != NULL) {
2438                 g_array_free(pcapng->interface_data, TRUE);
2439         }
2440 }
2441
2442
2443
2444 typedef struct {
2445         GArray *interface_data;
2446         guint number_of_interfaces;
2447 } pcapng_dump_t;
2448
2449 static gboolean
2450 pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
2451 {
2452         pcapng_block_header_t bh;
2453         pcapng_section_header_block_t shb;
2454         const guint32 zero_pad = 0;
2455         gboolean have_options = FALSE;
2456         struct option option_hdr;                   /* guint16 type, guint16 value_length; */
2457         guint32 options_total_length = 0;
2458         guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0;
2459         guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
2460
2461         if (wdh->shb_hdr) {
2462                 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
2463                 /* Check if we should write comment option */
2464                 if (wdh->shb_hdr->opt_comment) {
2465                         have_options = TRUE;
2466                         comment_len = (guint32)strlen(wdh->shb_hdr->opt_comment) & 0xffff;
2467                         if ((comment_len % 4)) {
2468                                 comment_pad_len = 4 - (comment_len % 4);
2469                         } else {
2470                                 comment_pad_len = 0;
2471                         }
2472                         options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2473                 }
2474
2475                 /* Check if we should write shb_hardware option */
2476                 if (wdh->shb_hdr->shb_hardware) {
2477                         have_options = TRUE;
2478                         shb_hardware_len = (guint32)strlen(wdh->shb_hdr->shb_hardware) & 0xffff;
2479                         if ((shb_hardware_len % 4)) {
2480                                 shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
2481                         } else {
2482                                 shb_hardware_pad_len = 0;
2483                         }
2484                         options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
2485                 }
2486
2487                 /* Check if we should write shb_os option */
2488                 if (wdh->shb_hdr->shb_os) {
2489                         have_options = TRUE;
2490                         shb_os_len = (guint32)strlen(wdh->shb_hdr->shb_os) & 0xffff;
2491                         if ((shb_os_len % 4)) {
2492                                 shb_os_pad_len = 4 - (shb_os_len % 4);
2493                         } else {
2494                                 shb_os_pad_len = 0;
2495                         }
2496                         options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
2497                 }
2498
2499                 /* Check if we should write shb_user_appl option */
2500                 if (wdh->shb_hdr->shb_user_appl) {
2501                         have_options = TRUE;
2502                         shb_user_appl_len = (guint32)strlen(wdh->shb_hdr->shb_user_appl) & 0xffff;
2503                         if ((shb_user_appl_len % 4)) {
2504                                 shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
2505                         } else {
2506                                 shb_user_appl_pad_len = 0;
2507                         }
2508                         options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
2509                 }
2510                 if (have_options) {
2511                         /* End-of-options tag */
2512                         options_total_length += 4;
2513                 }
2514         }
2515
2516         /* write block header */
2517         bh.block_type = BLOCK_TYPE_SHB;
2518         bh.block_total_length = (guint32)(sizeof(bh) + sizeof(shb) + options_total_length + 4);
2519         pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
2520
2521         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2522                 return FALSE;
2523         wdh->bytes_dumped += sizeof bh;
2524
2525         /* write block fixed content */
2526         /* XXX - get these values from wblock? */
2527         shb.magic = 0x1A2B3C4D;
2528         shb.version_major = 1;
2529         shb.version_minor = 0;
2530         shb.section_length = -1;
2531
2532         if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
2533                 return FALSE;
2534         wdh->bytes_dumped += sizeof shb;
2535
2536         /* XXX - write (optional) block options
2537          * opt_comment  1
2538          * shb_hardware 2
2539          * shb_os       3
2540          * shb_user_appl 4
2541          */
2542
2543         if (comment_len) {
2544                 option_hdr.type          = OPT_COMMENT;
2545                 option_hdr.value_length = comment_len;
2546                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2547                         return FALSE;
2548                 wdh->bytes_dumped += 4;
2549
2550                 /* Write the comments string */
2551                 pcapng_debug3("pcapng_write_section_header_block, comment:'%s' comment_len %u comment_pad_len %u" , wdh->shb_hdr->opt_comment, comment_len, comment_pad_len);
2552                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->opt_comment, comment_len, err))
2553                         return FALSE;
2554                 wdh->bytes_dumped += comment_len;
2555
2556                 /* write padding (if any) */
2557                 if (comment_pad_len != 0) {
2558                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2559                                 return FALSE;
2560                         wdh->bytes_dumped += comment_pad_len;
2561                 }
2562         }
2563
2564         if (shb_hardware_len) {
2565                 option_hdr.type          = OPT_SHB_HARDWARE;
2566                 option_hdr.value_length = shb_hardware_len;
2567                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2568                         return FALSE;
2569                 wdh->bytes_dumped += 4;
2570
2571                 /* Write the string */
2572                 pcapng_debug3("pcapng_write_section_header_block, shb_hardware:'%s' shb_hardware_len %u shb_hardware_pad_len %u" , wdh->shb_hdr->shb_hardware, shb_hardware_len, shb_hardware_pad_len);
2573                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_hardware, shb_hardware_len, err))
2574                         return FALSE;
2575                 wdh->bytes_dumped += shb_hardware_len;
2576
2577                 /* write padding (if any) */
2578                 if (shb_hardware_pad_len != 0) {
2579                         if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
2580                                 return FALSE;
2581                         wdh->bytes_dumped += shb_hardware_pad_len;
2582                 }
2583         }
2584
2585         if (shb_os_len) {
2586                 option_hdr.type          = OPT_SHB_OS;
2587                 option_hdr.value_length = shb_os_len;
2588                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2589                         return FALSE;
2590                 wdh->bytes_dumped += 4;
2591
2592                 /* Write the string */
2593                 pcapng_debug3("pcapng_write_section_header_block, shb_os:'%s' shb_os_len %u shb_os_pad_len %u" , wdh->shb_hdr->shb_os, shb_os_len, shb_os_pad_len);
2594                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_os, shb_os_len, err))
2595                         return FALSE;
2596                 wdh->bytes_dumped += shb_os_len;
2597
2598                 /* write padding (if any) */
2599                 if (shb_os_pad_len != 0) {
2600                         if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
2601                                 return FALSE;
2602                         wdh->bytes_dumped += shb_os_pad_len;
2603                 }
2604         }
2605
2606         if (shb_user_appl_len) {
2607                 option_hdr.type          = OPT_SHB_USERAPPL;
2608                 option_hdr.value_length = shb_user_appl_len;
2609                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2610                         return FALSE;
2611                 wdh->bytes_dumped += 4;
2612
2613                 /* Write the comments string */
2614                 pcapng_debug3("pcapng_write_section_header_block, shb_user_appl:'%s' shb_user_appl_len %u shb_user_appl_pad_len %u" , wdh->shb_hdr->shb_user_appl, shb_user_appl_len, shb_user_appl_pad_len);
2615                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_user_appl, shb_user_appl_len, err))
2616                         return FALSE;
2617                 wdh->bytes_dumped += shb_user_appl_len;
2618
2619                 /* write padding (if any) */
2620                 if (shb_user_appl_pad_len != 0) {
2621                         if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
2622                                 return FALSE;
2623                         wdh->bytes_dumped += shb_user_appl_pad_len;
2624                 }
2625         }
2626
2627         /* Write end of options if we have otions */
2628         if (have_options) {
2629                 option_hdr.type = OPT_EOFOPT;
2630                 option_hdr.value_length = 0;
2631                 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2632                         return FALSE;
2633                 wdh->bytes_dumped += 4;
2634         }
2635
2636         /* write block footer */
2637         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2638             sizeof bh.block_total_length, err))
2639                 return FALSE;
2640         wdh->bytes_dumped += sizeof bh.block_total_length;
2641
2642         return TRUE;
2643 }
2644
2645 #define IDB_OPT_IF_NAME         2
2646 #define IDB_OPT_IF_DESCR        3
2647 #define IDB_OPT_IF_SPEED        8
2648 #define IDB_OPT_IF_TSRESOL      9
2649 #define IDB_OPT_IF_FILTER       11
2650 #define IDB_OPT_IF_OS           12
2651
2652 static gboolean
2653 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_if_descr_t *int_data, int *err)
2654 {
2655         pcapng_block_header_t bh;
2656         pcapng_interface_description_block_t idb;
2657         const guint32 zero_pad = 0;
2658         gboolean have_options = FALSE;
2659         struct option option_hdr;                   /* guint16 type, guint16 value_length; */
2660         guint32 options_total_length = 0;
2661         guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0, if_filter_str_len = 0;
2662         guint32 comment_pad_len = 0, if_name_pad_len = 0, if_description_pad_len = 0, if_os_pad_len = 0, if_filter_str_pad_len = 0;
2663
2664
2665         pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2666                       int_data->link_type,
2667                       wtap_encap_string(wtap_pcap_encap_to_wtap_encap(int_data->link_type)),
2668                       int_data->snap_len);
2669
2670         if (int_data->link_type == (guint16)-1) {
2671                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
2672                 return FALSE;
2673         }
2674
2675         /* Calculate options length */
2676         if (int_data->opt_comment) {
2677                 have_options = TRUE;
2678                 comment_len = (guint32)strlen(int_data->opt_comment) & 0xffff;
2679                 if ((comment_len % 4)) {
2680                         comment_pad_len = 4 - (comment_len % 4);
2681                 } else {
2682                         comment_pad_len = 0;
2683                 }
2684                 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2685         }
2686
2687         /*
2688          * if_name        2  A UTF-8 string containing the name of the device used to capture data.
2689          */
2690         if (int_data->if_name) {
2691                 have_options = TRUE;
2692                 if_name_len = (guint32)strlen(int_data->if_name) & 0xffff;
2693                 if ((if_name_len % 4)) {
2694                         if_name_pad_len = 4 - (if_name_len % 4);
2695                 } else {
2696                         if_name_pad_len = 0;
2697                 }
2698                 options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
2699         }
2700
2701         /*
2702          * if_description 3  A UTF-8 string containing the description of the device used to capture data.
2703          */
2704         if (int_data->if_description) {
2705                 have_options = TRUE;
2706                 if_description_len = (guint32)strlen(int_data->if_description) & 0xffff;
2707                 if ((if_description_len % 4)) {
2708                         if_description_pad_len = 4 - (if_description_len % 4);
2709                 } else {
2710                         if_description_pad_len = 0;
2711                 }
2712                 options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
2713         }
2714         /* Currently not handled
2715          * if_IPv4addr    4  Interface network address and netmask.
2716          * if_IPv6addr    5  Interface network address and prefix length (stored in the last byte).
2717          * if_MACaddr     6  Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2718          * if_EUIaddr     7  Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2719          */
2720         /*
2721          * if_speed       8  Interface speed (in bps). 100000000 for 100Mbps
2722          */
2723         if (int_data->if_speed != 0) {
2724                 have_options = TRUE;
2725                 options_total_length = options_total_length + 8 + 4;
2726         }
2727         /*
2728          * if_tsresol     9  Resolution of timestamps.
2729          */
2730         if (int_data->if_tsresol != 0) {
2731                 have_options = TRUE;
2732                 options_total_length = options_total_length + 4 + 4;
2733         }
2734         /* Not used
2735          * if_tzone      10  Time zone for GMT support (TODO: specify better). TODO: give a good example
2736          */
2737         /*
2738          * if_filter     11  The filter (e.g. "capture only TCP traffic") used to capture traffic.
2739          * The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more).
2740          */
2741         if (int_data->if_filter_str) {
2742                 have_options = TRUE;
2743                 if_filter_str_len = (guint32)(strlen(int_data->if_filter_str) + 1) & 0xffff;
2744                 if ((if_filter_str_len % 4)) {
2745                         if_filter_str_pad_len = 4 - (if_filter_str_len % 4);
2746                 } else {
2747                         if_filter_str_pad_len = 0;
2748                 }
2749                 options_total_length = options_total_length + if_filter_str_len + if_filter_str_pad_len + 4 /* comment options tag */ ;
2750         }
2751         /*
2752          * if_os         12  A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2753          */
2754         if (int_data->if_os) {
2755                 have_options = TRUE;
2756                 if_os_len = (guint32)strlen(int_data->if_os) & 0xffff;
2757                 if ((if_os_len % 4)) {
2758                         if_os_pad_len = 4 - (if_os_len % 4);
2759                 } else {
2760                         if_os_pad_len = 0;
2761                 }
2762                 options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
2763         }
2764         /*
2765          * if_fcslen     13  An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2766          * -1 if unknown or changes between packets, opt 13  An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2767          */
2768         if (int_data->if_fcslen != 0) {
2769         }
2770         /* Not used
2771          * if_tsoffset   14  A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2772          * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2773          */
2774
2775         if (have_options) {
2776                 /* End-of-options tag */
2777                 options_total_length += 4;
2778         }
2779
2780         /* write block header */
2781         bh.block_type = BLOCK_TYPE_IDB;
2782         bh.block_total_length = (guint32)(sizeof(bh) + sizeof(idb) + options_total_length + 4);
2783
2784         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2785                 return FALSE;
2786         wdh->bytes_dumped += sizeof bh;
2787
2788         /* write block fixed content */
2789         idb.linktype    = int_data->link_type;
2790         idb.reserved    = 0;
2791         idb.snaplen     = int_data->snap_len;
2792
2793         if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
2794                 return FALSE;
2795         wdh->bytes_dumped += sizeof idb;
2796
2797         /* XXX - write (optional) block options */
2798         if (comment_len != 0) {
2799                 option_hdr.type         = OPT_COMMENT;
2800                 option_hdr.value_length = comment_len;
2801                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2802                         return FALSE;
2803                 wdh->bytes_dumped += 4;
2804
2805                 /* Write the comments string */
2806                 pcapng_debug3("pcapng_write_if_descr_block, comment:'%s' comment_len %u comment_pad_len %u" , int_data->opt_comment, comment_len, comment_pad_len);
2807                 if (!wtap_dump_file_write(wdh, int_data->opt_comment, comment_len, err))
2808                         return FALSE;
2809                 wdh->bytes_dumped += comment_len;
2810
2811                 /* write padding (if any) */
2812                 if (comment_pad_len != 0) {
2813                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2814                                 return FALSE;
2815                         wdh->bytes_dumped += comment_pad_len;
2816                 }
2817         }
2818         /*
2819          * if_name        2  A UTF-8 string containing the name of the device used to capture data.
2820          */
2821         if (if_name_len !=0) {
2822                 option_hdr.type = IDB_OPT_IF_NAME;
2823                 option_hdr.value_length = if_name_len;
2824                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2825                         return FALSE;
2826                 wdh->bytes_dumped += 4;
2827
2828                 /* Write the comments string */
2829                 pcapng_debug3("pcapng_write_if_descr_block, if_name:'%s' if_name_len %u if_name_pad_len %u" , int_data->if_name, if_name_len, if_name_pad_len);
2830                 if (!wtap_dump_file_write(wdh, int_data->if_name, if_name_len, err))
2831                         return FALSE;
2832                 wdh->bytes_dumped += if_name_len;
2833
2834                 /* write padding (if any) */
2835                 if (if_name_pad_len != 0) {
2836                         if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
2837                                 return FALSE;
2838                         wdh->bytes_dumped += if_name_pad_len;
2839                 }
2840         }
2841         /*
2842          * if_description 3  A UTF-8 string containing the description of the device used to capture data.
2843          */
2844         if (if_description_len != 0) {
2845                 option_hdr.type          = IDB_OPT_IF_NAME;
2846                 option_hdr.value_length = if_description_len;
2847                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2848                         return FALSE;
2849                 wdh->bytes_dumped += 4;
2850
2851                 /* Write the comments string */
2852                 pcapng_debug3("pcapng_write_if_descr_block, if_description:'%s' if_description_len %u if_description_pad_len %u" , int_data->if_description, if_description_len, if_description_pad_len);
2853                 if (!wtap_dump_file_write(wdh, int_data->if_description, if_description_len, err))
2854                         return FALSE;
2855                 wdh->bytes_dumped += if_description_len;
2856
2857                 /* write padding (if any) */
2858                 if (if_description_pad_len != 0) {
2859                         if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
2860                                 return FALSE;
2861                         wdh->bytes_dumped += if_description_pad_len;
2862                 }
2863         }
2864         /* Currently not handled
2865          * if_IPv4addr    4  Interface network address and netmask.
2866          * if_IPv6addr    5  Interface network address and prefix length (stored in the last byte).
2867          * if_MACaddr     6  Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2868          * if_EUIaddr     7  Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2869          */
2870         /*
2871          * if_speed       8  Interface speed (in bps). 100000000 for 100Mbps
2872          */
2873         if (int_data->if_speed != 0) {
2874                 option_hdr.type          = IDB_OPT_IF_SPEED;
2875                 option_hdr.value_length = 8;
2876                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2877                         return FALSE;
2878                 wdh->bytes_dumped += 4;
2879
2880                 /* Write the comments string */
2881                 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", int_data->if_speed);
2882                 if (!wtap_dump_file_write(wdh, &int_data->if_speed, sizeof(guint64), err))
2883                         return FALSE;
2884                 wdh->bytes_dumped += 8;
2885         }
2886         /*
2887          * if_tsresol     9  Resolution of timestamps.
2888          * default is 6 for microsecond resolution, opt 9  Resolution of timestamps.
2889          * If the Most Significant Bit is equal to zero, the remaining bits indicates
2890          * the resolution of the timestamp as as a negative power of 10
2891          */
2892         if (int_data->if_tsresol != 0) {
2893                 option_hdr.type          = IDB_OPT_IF_TSRESOL;
2894                 option_hdr.value_length = 1;
2895                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2896                         return FALSE;
2897                 wdh->bytes_dumped += 4;
2898
2899                 /* Write the time stamp resolution */
2900                 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", int_data->if_tsresol);
2901                 if (!wtap_dump_file_write(wdh, &int_data->if_tsresol, 1, err))
2902                         return FALSE;
2903                 wdh->bytes_dumped += 1;
2904                 if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
2905                         return FALSE;
2906                 wdh->bytes_dumped += 3;
2907         }
2908         /* not used
2909          * if_tzone      10  Time zone for GMT support (TODO: specify better). TODO: give a good example
2910          */
2911         /*
2912          * if_filter     11  The filter (e.g. "capture only TCP traffic") used to capture traffic.
2913          */
2914         /* Libpcap string variant */
2915         if (if_filter_str_len !=0) {
2916                 option_hdr.type          = IDB_OPT_IF_FILTER;
2917                 option_hdr.value_length = if_filter_str_len;
2918                 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2919                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2920                         return FALSE;
2921                 wdh->bytes_dumped += 4;
2922
2923                 /* Write the zero indicating libpcap filter variant */
2924                 if (!wtap_dump_file_write(wdh, &zero_pad, 1, err))
2925                         return FALSE;
2926                 wdh->bytes_dumped += 1;
2927
2928                 /* Write the comments string */
2929                 pcapng_debug3("pcapng_write_if_descr_block, if_filter_str:'%s' if_filter_str_len %u if_filter_str_pad_len %u" , int_data->if_filter_str, if_filter_str_len, if_filter_str_pad_len);
2930                 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2931                 if (!wtap_dump_file_write(wdh, int_data->if_filter_str, if_filter_str_len-1, err))
2932                         return FALSE;
2933                 wdh->bytes_dumped += if_filter_str_len - 1;
2934
2935                 /* write padding (if any) */
2936                 if (if_filter_str_pad_len != 0) {
2937                         if (!wtap_dump_file_write(wdh, &zero_pad, if_filter_str_pad_len, err))
2938                                 return FALSE;
2939                         wdh->bytes_dumped += if_filter_str_pad_len;
2940                 }
2941         }
2942         /*
2943          * if_os         12  A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2944          */
2945         if (if_os_len != 0) {
2946                 option_hdr.type          = IDB_OPT_IF_OS;
2947                 option_hdr.value_length = if_os_len;
2948                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2949                         return FALSE;
2950                 wdh->bytes_dumped += 4;
2951
2952                 /* Write the comments string */
2953                 pcapng_debug3("pcapng_write_if_descr_block, if_os:'%s' if_os_len %u if_os_pad_len %u" , int_data->if_os, if_os_len, if_os_pad_len);
2954                 if (!wtap_dump_file_write(wdh, int_data->if_os, if_os_len, err))
2955                         return FALSE;
2956                 wdh->bytes_dumped += if_os_len;
2957
2958                 /* write padding (if any) */
2959                 if (if_os_pad_len != 0) {
2960                         if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
2961                                 return FALSE;
2962                         wdh->bytes_dumped += if_os_pad_len;
2963                 }
2964         }
2965
2966         if (have_options) {
2967                 option_hdr.type = OPT_EOFOPT;
2968                 option_hdr.value_length = 0;
2969                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2970                         return FALSE;
2971                 wdh->bytes_dumped += 4;
2972         }
2973
2974         /*
2975          * if_fcslen     13  An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2976          */
2977         /*
2978          * if_tsoffset   14  A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2979          * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2980          */
2981
2982         /* write block footer */
2983         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2984             sizeof bh.block_total_length, err))
2985                 return FALSE;
2986         wdh->bytes_dumped += sizeof bh.block_total_length;
2987
2988         return TRUE;
2989 }
2990
2991 #define ISB_STARTTIME     2
2992 #define ISB_ENDTIME       3
2993 #define ISB_IFRECV        4
2994 #define ISB_IFDROP        5
2995 #define ISB_FILTERACCEPT  6
2996 #define ISB_OSDROP        7
2997 #define ISB_USRDELIV      8
2998
2999 static gboolean
3000 pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtapng_if_stats_t *if_stats, int *err)
3001 {
3002
3003         pcapng_block_header_t bh;
3004         pcapng_interface_statistics_block_t isb;
3005         const guint32 zero_pad = 0;
3006         gboolean have_options = FALSE;
3007         struct option option_hdr;                   /* guint16 type, guint16 value_length; */
3008         guint32 options_total_length = 0;
3009         guint32 comment_len = 0;
3010         guint32 comment_pad_len = 0;
3011
3012         pcapng_debug0("pcapng_write_interface_statistics_block");
3013
3014
3015         /* Calculate options length */
3016         if (if_stats->opt_comment) {
3017                 have_options = TRUE;
3018                 comment_len = (guint32)strlen(if_stats->opt_comment) & 0xffff;
3019                 if ((comment_len % 4)) {
3020                         comment_pad_len = 4 - (comment_len % 4);
3021                 } else {
3022                         comment_pad_len = 0;
3023                 }
3024                 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3025         }
3026         /*guint64                               isb_starttime */
3027         if (if_stats->isb_starttime != 0) {
3028                 have_options = TRUE;
3029                 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3030         }
3031         /*guint64                               isb_endtime */
3032         if (if_stats->isb_endtime != 0) {
3033                 have_options = TRUE;
3034                 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3035         }
3036         /*guint64                               isb_ifrecv */
3037         if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3038                 have_options = TRUE;
3039                 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3040         }
3041         /*guint64                               isb_ifdrop */
3042         if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3043                 have_options = TRUE;
3044                 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3045         }
3046         /*guint64                               isb_filteraccept */
3047         if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3048                 have_options = TRUE;
3049                 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3050         }
3051         /*guint64                               isb_osdrop */
3052         if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3053                 have_options = TRUE;
3054                 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3055         }
3056         /*guint64                               isb_usrdeliv */
3057         if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3058                 have_options = TRUE;
3059                 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3060         }
3061
3062         /* write block header */
3063         if (have_options) {
3064                 /* End-of-optios tag */
3065                 options_total_length += 4;
3066         }
3067
3068         /* write block header */
3069         bh.block_type = BLOCK_TYPE_ISB;
3070         bh.block_total_length = (guint32)(sizeof(bh) + sizeof(isb) + options_total_length + 4);
3071
3072         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3073                 return FALSE;
3074         wdh->bytes_dumped += sizeof bh;
3075
3076         /* write block fixed content */
3077         isb.interface_id                = if_stats->interface_id;
3078         isb.timestamp_high              = if_stats->ts_high;
3079         isb.timestamp_low               = if_stats->ts_low;
3080
3081
3082         if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
3083                 return FALSE;
3084         wdh->bytes_dumped += sizeof isb;
3085
3086         /* write (optional) block options */
3087         if (comment_len) {
3088                 option_hdr.type          = OPT_COMMENT;
3089                 option_hdr.value_length  = comment_len;
3090                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3091                         return FALSE;
3092                 wdh->bytes_dumped += 4;
3093
3094                 /* Write the comments string */
3095                 pcapng_debug3("pcapng_write_interface_statistics_block, comment:'%s' comment_len %u comment_pad_len %u" , if_stats->opt_comment, comment_len, comment_pad_len);
3096                 if (!wtap_dump_file_write(wdh, if_stats->opt_comment, comment_len, err))
3097                         return FALSE;
3098                 wdh->bytes_dumped += comment_len;
3099
3100                 /* write padding (if any) */
3101                 if (comment_pad_len != 0) {
3102                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3103                                 return FALSE;
3104                         wdh->bytes_dumped += comment_pad_len;
3105                 }
3106         }
3107         /*guint64               isb_starttime */
3108         if (if_stats->isb_starttime != 0) {
3109                 guint32 high, low;
3110
3111                 option_hdr.type = ISB_STARTTIME;
3112                 option_hdr.value_length = 8;
3113                 high = (guint32)((if_stats->isb_starttime>>32) & 0xffffffff);
3114                 low = (guint32)(if_stats->isb_starttime & 0xffffffff);
3115                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3116                         return FALSE;
3117                 wdh->bytes_dumped += 4;
3118
3119                 /* Write isb_starttime */
3120                 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_starttime);
3121                 if (!wtap_dump_file_write(wdh, &high, 4, err))
3122                         return FALSE;
3123                 wdh->bytes_dumped += 4;
3124                 if (!wtap_dump_file_write(wdh, &low, 4, err))
3125                         return FALSE;
3126                 wdh->bytes_dumped += 4;
3127         }
3128         /*guint64               isb_endtime */
3129         if (if_stats->isb_endtime != 0) {
3130                 guint32 high, low;
3131
3132                 option_hdr.type = ISB_ENDTIME;
3133                 option_hdr.value_length = 8;
3134                 high = (guint32)((if_stats->isb_endtime>>32) & 0xffffffff);
3135                 low = (guint32)(if_stats->isb_endtime & 0xffffffff);
3136                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3137                         return FALSE;
3138                 wdh->bytes_dumped += 4;
3139
3140                 /* Write isb_endtime */
3141                 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_endtime);
3142                 if (!wtap_dump_file_write(wdh, &high, 4, err))
3143                         return FALSE;
3144                 wdh->bytes_dumped += 4;
3145                 if (!wtap_dump_file_write(wdh, &low, 4, err))
3146                         return FALSE;
3147                 wdh->bytes_dumped += 4;
3148         }
3149         /*guint64               isb_ifrecv;*/
3150         if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3151                 option_hdr.type          = ISB_IFRECV;
3152                 option_hdr.value_length  = 8;
3153                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3154                         return FALSE;
3155                 wdh->bytes_dumped += 4;
3156
3157                 /* Write isb_ifrecv */
3158                 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifrecv: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifrecv);
3159                 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifrecv, 8, err))
3160                         return FALSE;
3161                 wdh->bytes_dumped += 8;
3162         }
3163         /*guint64               isb_ifdrop;*/
3164         if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3165                 option_hdr.type          = ISB_IFDROP;
3166                 option_hdr.value_length  = 8;
3167                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3168                         return FALSE;
3169                 wdh->bytes_dumped += 4;
3170
3171                 /* Write isb_ifdrop */
3172                 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifdrop);
3173                 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifdrop, 8, err))
3174                         return FALSE;
3175                 wdh->bytes_dumped += 8;
3176         }
3177         /*guint64               isb_filteraccept;*/
3178         if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3179                 option_hdr.type          = ISB_FILTERACCEPT;
3180                 option_hdr.value_length  = 8;
3181                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3182                         return FALSE;
3183                 wdh->bytes_dumped += 4;
3184
3185                 /* Write isb_filteraccept */
3186                 pcapng_debug1("pcapng_write_interface_statistics_block, isb_filteraccept: %" G_GINT64_MODIFIER "u" , if_stats->isb_filteraccept);
3187                 if (!wtap_dump_file_write(wdh, &if_stats->isb_filteraccept, 8, err))
3188                         return FALSE;
3189                 wdh->bytes_dumped += 8;
3190         }
3191         /*guint64               isb_osdrop;*/
3192         if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3193                 option_hdr.type          = ISB_OSDROP;
3194                 option_hdr.value_length  = 8;
3195                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3196                         return FALSE;
3197                 wdh->bytes_dumped += 4;
3198
3199                 /* Write isb_osdrop */
3200                 pcapng_debug1("pcapng_write_interface_statistics_block, isb_osdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_osdrop);
3201                 if (!wtap_dump_file_write(wdh, &if_stats->isb_osdrop, 8, err))
3202                         return FALSE;
3203                 wdh->bytes_dumped += 8;
3204         }
3205         /*guint64               isb_usrdeliv;*/
3206         if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3207                 option_hdr.type          = ISB_USRDELIV;
3208                 option_hdr.value_length  = 8;
3209                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3210                         return FALSE;
3211                 wdh->bytes_dumped += 4;
3212
3213                 /* Write isb_usrdeliv */
3214                 pcapng_debug1("pcapng_write_interface_statistics_block, isb_usrdeliv: %" G_GINT64_MODIFIER "u" , if_stats->isb_usrdeliv);
3215                 if (!wtap_dump_file_write(wdh, &if_stats->isb_usrdeliv, 8, err))
3216                         return FALSE;
3217                 wdh->bytes_dumped += 8;
3218         }
3219
3220         if (have_options) {
3221                 option_hdr.type = OPT_EOFOPT;
3222                 option_hdr.value_length = 0;
3223                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3224                         return FALSE;
3225                 wdh->bytes_dumped += 4;
3226         }
3227
3228         /* write block footer */
3229         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3230             sizeof bh.block_total_length, err))
3231                 return FALSE;
3232         wdh->bytes_dumped += sizeof bh.block_total_length;
3233
3234         return TRUE;
3235
3236 }
3237
3238
3239 static gboolean
3240 pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
3241     const struct wtap_pkthdr *phdr,
3242     const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
3243 {
3244         pcapng_block_header_t bh;
3245         pcapng_enhanced_packet_block_t epb;
3246         guint64 ts;
3247         const guint32 zero_pad = 0;
3248         guint32 pad_len;
3249         guint32 phdr_len;
3250         gboolean have_options = FALSE;
3251         guint32 options_total_length = 0;
3252         struct option option_hdr;
3253         guint32 comment_len = 0, comment_pad_len = 0;
3254         wtapng_if_descr_t int_data;
3255
3256         /* Don't write anything we're not willing to read. */
3257         if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
3258                 *err = WTAP_ERR_PACKET_TOO_LARGE;
3259                 return FALSE;
3260         }
3261
3262         phdr_len = (guint32)pcap_get_phdr_size(phdr->pkt_encap, pseudo_header);
3263         if ((phdr_len + phdr->caplen) % 4) {
3264                 pad_len = 4 - ((phdr_len + phdr->caplen) % 4);
3265         } else {
3266                 pad_len = 0;
3267         }
3268
3269         /* Check if we should write comment option */
3270         if (phdr->opt_comment) {
3271                 have_options = TRUE;
3272                 comment_len = (guint32)strlen(phdr->opt_comment) & 0xffff;
3273                 if ((comment_len % 4)) {
3274                         comment_pad_len = 4 - (comment_len % 4);
3275                 } else {
3276                         comment_pad_len = 0;
3277                 }
3278                 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3279         }
3280         if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3281                 have_options = TRUE;
3282                 options_total_length = options_total_length + 8;
3283         }
3284         if (have_options) {
3285                 /* End-of optios tag */
3286                 options_total_length += 4;
3287         }
3288
3289         /* write (enhanced) packet block header */
3290         bh.block_type = BLOCK_TYPE_EPB;
3291         bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + phdr->caplen + pad_len + options_total_length + 4;
3292
3293         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3294                 return FALSE;
3295         wdh->bytes_dumped += sizeof bh;
3296
3297         /* write block fixed content */
3298         if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3299                 epb.interface_id        = phdr->interface_id;
3300         else {
3301                 /*
3302                  * XXX - we should support writing WTAP_ENCAP_PER_PACKET
3303                  * data to pcap-NG files even if we *don't* have interface
3304                  * IDs.
3305                  */
3306                 epb.interface_id        = 0;
3307         }
3308         /*
3309          * Split the 64-bit timestamp into two 32-bit pieces, using
3310          * the time stamp resolution for the interface.
3311          */
3312         if (epb.interface_id >= wdh->number_of_interfaces) {
3313                 /*
3314                  * Our caller is doing something bad.
3315                  */
3316                 *err = WTAP_ERR_INTERNAL;
3317                 return FALSE;
3318         }
3319         int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t,
3320             epb.interface_id);
3321         ts = ((guint64)phdr->ts.secs) * int_data.time_units_per_second +
3322              (((guint64)phdr->ts.nsecs) * int_data.time_units_per_second) / 1000000000;
3323         epb.timestamp_high      = (guint32)(ts >> 32);
3324         epb.timestamp_low       = (guint32)ts;
3325         epb.captured_len        = phdr->caplen + phdr_len;
3326         epb.packet_len          = phdr->len + phdr_len;
3327
3328         if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
3329                 return FALSE;
3330         wdh->bytes_dumped += sizeof epb;
3331
3332         /* write pseudo header */
3333         if (!pcap_write_phdr(wdh, phdr->pkt_encap, pseudo_header, err)) {
3334                 return FALSE;
3335         }
3336         wdh->bytes_dumped += phdr_len;
3337
3338         /* write packet data */
3339         if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
3340                 return FALSE;
3341         wdh->bytes_dumped += phdr->caplen;
3342
3343         /* write padding (if any) */
3344         if (pad_len != 0) {
3345                 if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
3346                         return FALSE;
3347                 wdh->bytes_dumped += pad_len;
3348         }
3349
3350         /* XXX - write (optional) block options */
3351         /* options defined in Section 2.5 (Options)
3352          * Name           Code Length     Description
3353          * opt_comment    1    variable   A UTF-8 string containing a comment that is associated to the current block.
3354          *
3355          * Enhanced Packet Block options
3356          * epb_flags      2    4          A flags word containing link-layer information. A complete specification of
3357          *                                the allowed flags can be found in Appendix A (Packet Block Flags Word).
3358          * epb_hash       3    variable   This option contains a hash of the packet. The first byte specifies the hashing algorithm,
3359          *                                while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
3360          *                                                                and hence from the value in the first bit. The hashing algorithm can be: 2s complement
3361          *                                                                (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
3362          *                                                                MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
3363          *                                                                The hash covers only the packet, not the header added by the capture driver:
3364          *                                                                this gives the possibility to calculate it inside the network card.
3365          *                                                                The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
3366          *                                                                data acquisition system and the capture library.
3367          * epb_dropcount   4   8          A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
3368          *                                between this packet and the preceding one.
3369          * opt_endofopt    0   0          It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
3370          */
3371         if (phdr->opt_comment) {
3372                 option_hdr.type         = OPT_COMMENT;
3373                 option_hdr.value_length = comment_len;
3374                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3375                         return FALSE;
3376                 wdh->bytes_dumped += 4;
3377
3378                 /* Write the comments string */
3379                 pcapng_debug3("pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , phdr->opt_comment, comment_len, comment_pad_len);
3380                 if (!wtap_dump_file_write(wdh, phdr->opt_comment, comment_len, err))
3381                         return FALSE;
3382                 wdh->bytes_dumped += comment_len;
3383
3384                 /* write padding (if any) */
3385                 if (comment_pad_len != 0) {
3386                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3387                                 return FALSE;
3388                         wdh->bytes_dumped += comment_pad_len;
3389                 }
3390
3391                 pcapng_debug2("pcapng_write_enhanced_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
3392                         comment_len,
3393                         comment_pad_len);
3394         }
3395         if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3396                 option_hdr.type         = OPT_EPB_FLAGS;
3397                 option_hdr.value_length = 4;
3398                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3399                         return FALSE;
3400                 wdh->bytes_dumped += 4;
3401                 if (!wtap_dump_file_write(wdh, &phdr->pack_flags, 4, err))
3402                         return FALSE;
3403                 wdh->bytes_dumped += 4;
3404                 pcapng_debug1("pcapng_write_enhanced_packet_block: Wrote Options packet flags: %x", phdr->pack_flags);
3405         }
3406         /* Write end of options if we have otions */
3407         if (have_options) {
3408                 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
3409                         return FALSE;
3410                 wdh->bytes_dumped += 4;
3411         }
3412
3413         /* write block footer */
3414         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3415             sizeof bh.block_total_length, err))
3416                 return FALSE;
3417         wdh->bytes_dumped += sizeof bh.block_total_length;
3418
3419         return TRUE;
3420 }
3421
3422 /* Arbitrary. */
3423 #define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
3424 static gboolean
3425 pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
3426 {
3427     pcapng_block_header_t bh;
3428     pcapng_name_resolution_block_t nrb;
3429     guint8 *rec_data;
3430     gint rec_off, namelen, tot_rec_len;
3431     hashipv4_t *ipv4_hash_list_entry;
3432     hashipv6_t *ipv6_hash_list_entry;
3433     int i;
3434
3435     if ((!wdh->addrinfo_lists) || ((!wdh->addrinfo_lists->ipv4_addr_list)&&(!wdh->addrinfo_lists->ipv6_addr_list))) {
3436         return TRUE;
3437     }
3438
3439     rec_off = 8; /* block type + block total length */
3440     bh.block_type = BLOCK_TYPE_NRB;
3441     bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3442     rec_data = (guint8 *)g_malloc(NRES_REC_MAX_SIZE);
3443
3444     if (wdh->addrinfo_lists->ipv4_addr_list){
3445         i = 0;
3446         ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3447         while(ipv4_hash_list_entry != NULL){
3448
3449             nrb.record_type = NRES_IP4RECORD;
3450             namelen = (gint)strlen(ipv4_hash_list_entry->name) + 1;
3451             nrb.record_len = 4 + namelen;
3452             tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3453
3454             if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3455                 /* We know the total length now; copy the block header. */
3456                 memcpy(rec_data, &bh, sizeof(bh));
3457
3458                 /* End of record */
3459                 memset(rec_data + rec_off, 0, 4);
3460                 rec_off += 4;
3461
3462                 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3463
3464                 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3465
3466                 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3467                     g_free(rec_data);
3468                     return FALSE;
3469                 }
3470                 wdh->bytes_dumped += bh.block_total_length;
3471
3472                 /*Start a new NRB */
3473                 rec_off = 8; /* block type + block total length */
3474                 bh.block_type = BLOCK_TYPE_NRB;
3475                 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3476
3477             }
3478
3479             bh.block_total_length += tot_rec_len;
3480             memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3481             rec_off += 4;
3482             memcpy(rec_data + rec_off, &(ipv4_hash_list_entry->addr), 4);
3483             rec_off += 4;
3484             memcpy(rec_data + rec_off, ipv4_hash_list_entry->name, namelen);
3485             rec_off += namelen;
3486             memset(rec_data + rec_off, 0, PADDING4(namelen));
3487             rec_off += PADDING4(namelen);
3488             pcapng_debug1("NRB: added IPv4 record for %s", ipv4_hash_list_entry->name);
3489
3490             i++;
3491             ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3492         }
3493         g_list_free(wdh->addrinfo_lists->ipv4_addr_list);
3494         wdh->addrinfo_lists->ipv4_addr_list = NULL;
3495     }
3496
3497     if (wdh->addrinfo_lists->ipv6_addr_list){
3498         i = 0;
3499         ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3500         while(ipv6_hash_list_entry != NULL){
3501
3502             nrb.record_type = NRES_IP6RECORD;
3503             namelen = (gint)strlen(ipv6_hash_list_entry->name) + 1;
3504             nrb.record_len = 16 + namelen;  /* 16 bytes IPv6 address length */
3505             /* 2 bytes record type, 2 bytes length field */
3506             tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3507
3508             if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3509                 /* We know the total length now; copy the block header. */
3510                 memcpy(rec_data, &bh, sizeof(bh));
3511
3512                 /* End of record */
3513                 memset(rec_data + rec_off, 0, 4);
3514                 rec_off += 4;
3515
3516                 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3517
3518                 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3519
3520                 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3521                     g_free(rec_data);
3522                     return FALSE;
3523                 }
3524                 wdh->bytes_dumped += bh.block_total_length;
3525
3526                 /*Start a new NRB */
3527                 rec_off = 8; /* block type + block total length */
3528                 bh.block_type = BLOCK_TYPE_NRB;
3529                 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3530
3531             }
3532
3533             bh.block_total_length += tot_rec_len;
3534             memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3535             rec_off += 4;
3536             memcpy(rec_data + rec_off, &(ipv6_hash_list_entry->addr), 16);
3537             rec_off += 16;
3538             memcpy(rec_data + rec_off, ipv6_hash_list_entry->name, namelen);
3539             rec_off += namelen;
3540             memset(rec_data + rec_off, 0, PADDING4(namelen));
3541             rec_off += PADDING4(namelen);
3542             pcapng_debug1("NRB: added IPv6 record for %s", ipv6_hash_list_entry->name);
3543
3544             i++;
3545             ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3546         }
3547         g_list_free(wdh->addrinfo_lists->ipv6_addr_list);
3548         wdh->addrinfo_lists->ipv6_addr_list = NULL;
3549     }
3550
3551     /* We know the total length now; copy the block header. */
3552     memcpy(rec_data, &bh, sizeof(bh));
3553
3554     /* End of record */
3555     memset(rec_data + rec_off, 0, 4);
3556     rec_off += 4;
3557
3558     memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3559
3560     pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3561
3562     if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3563         g_free(rec_data);
3564         return FALSE;
3565     }
3566
3567     g_free(rec_data);
3568     wdh->bytes_dumped += bh.block_total_length;
3569     return TRUE;
3570 }
3571
3572 #if 0
3573 static guint32
3574 pcapng_lookup_interface_id_by_encap(int wtap_encap, wtap_dumper *wdh)
3575 {
3576         gint i;
3577         interface_data_t int_data;
3578         pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3579
3580         for(i = 0; i < (gint)pcapng->number_of_interfaces; i++) {
3581                 int_data = g_array_index(pcapng->interface_data, interface_data_t, i);
3582                 if (wtap_encap == int_data.wtap_encap) {
3583                         return (guint32)i;
3584                 }
3585         }
3586         return G_MAXUINT32;
3587 }
3588 #endif
3589
3590 static gboolean pcapng_dump(wtap_dumper *wdh,
3591         const struct wtap_pkthdr *phdr,
3592         const guint8 *pd, int *err)
3593 {
3594         const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
3595         /*interface_data_t int_data;*/
3596         /* pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv; */
3597         /*int pcap_encap;*/
3598
3599         pcapng_debug2("pcapng_dump: encap = %d (%s)",
3600                       phdr->pkt_encap,
3601                       wtap_encap_string(phdr->pkt_encap));
3602
3603         /* Flush any hostname resolution info we may have */
3604         pcapng_write_name_resolution_block(wdh, err);
3605
3606         if (!pcapng_write_enhanced_packet_block(wdh, phdr, pseudo_header, pd, err)) {
3607                 return FALSE;
3608         }
3609
3610         return TRUE;
3611 }
3612
3613
3614 /* Finish writing to a dump file.
3615    Returns TRUE on success, FALSE on failure. */
3616 static gboolean pcapng_dump_close(wtap_dumper *wdh, int *err _U_)
3617 {
3618         int i, j;
3619         pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3620
3621         if ((wdh->number_of_interfaces > 0) && (wdh->interface_data != NULL)) {
3622                 for (i = 0; i < (int)wdh->number_of_interfaces; i++) {
3623
3624                         /* Get the interface description */
3625                         wtapng_if_descr_t int_data;
3626
3627                         int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3628                         for (j = 0; j < (int)int_data.num_stat_entries; j++) {
3629                                 wtapng_if_stats_t if_stats;
3630
3631                                 if_stats = g_array_index(int_data.interface_statistics, wtapng_if_stats_t, j);
3632                                 pcapng_debug1("pcapng_dump_close: write ISB for interface %u",if_stats.interface_id);
3633                                 if (!pcapng_write_interface_statistics_block(wdh, &if_stats, err)) {
3634                                         return FALSE;
3635                                 }
3636                         }
3637                 }
3638         }
3639
3640         pcapng_debug0("pcapng_dump_close");
3641         g_array_free(pcapng->interface_data, TRUE);
3642         pcapng->number_of_interfaces = 0;
3643         return TRUE;
3644 }
3645
3646
3647 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
3648    failure */
3649 gboolean
3650 pcapng_dump_open(wtap_dumper *wdh, int *err)
3651 {
3652         pcapng_dump_t *pcapng;
3653         int i;
3654         interface_data_t interface_data;
3655
3656         pcapng_debug0("pcapng_dump_open");
3657         /* This is a pcapng file */
3658         wdh->subtype_write = pcapng_dump;
3659         wdh->subtype_close = pcapng_dump_close;
3660         pcapng = (pcapng_dump_t *)g_malloc0(sizeof(pcapng_dump_t));
3661         wdh->priv = (void *)pcapng;
3662         pcapng->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
3663
3664         if ((wdh->number_of_interfaces == 0) || (wdh->interface_data == NULL)) {
3665                 pcapng_debug0("There are no interfaces. Can't handle that...");
3666                 *err = WTAP_ERR_INTERNAL;
3667                 return FALSE;
3668         }
3669
3670         /* write the section header block */
3671         if (!pcapng_write_section_header_block(wdh, err)) {
3672                 return FALSE;
3673         }
3674         pcapng_debug0("pcapng_dump_open: wrote section header block.");
3675
3676         /* Write the Interface description blocks */
3677         pcapng_debug1("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u", wdh->number_of_interfaces);
3678
3679         for (i = 0; i < (int)wdh->number_of_interfaces; i++) {
3680
3681                 /* Get the interface description */
3682                 wtapng_if_descr_t int_data;
3683
3684                 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3685
3686                 interface_data.wtap_encap = int_data.wtap_encap;
3687                 interface_data.time_units_per_second = int_data.time_units_per_second;
3688
3689                 g_array_append_val(pcapng->interface_data, interface_data);
3690                 pcapng->number_of_interfaces++;
3691
3692                 if (!pcapng_write_if_descr_block(wdh, &int_data, err)) {
3693                         return FALSE;
3694                 }
3695
3696         }
3697 #if 0
3698         interface_id = pcapng_lookup_interface_id_by_encap(phdr->pkt_encap, wdh);
3699         if (interface_id == G_MAXUINT32) {
3700                 /*
3701                  * We haven't yet written out an interface description
3702                  * block for an interface with this encapsulation.
3703                  *
3704                  * Is this encapsulation even supported in pcap-ng?
3705                  */
3706                 pcap_encap = wtap_wtap_encap_to_pcap_encap(phdr->pkt_encap);
3707                 if (pcap_encap == -1) {
3708                         /*
3709                          * No.  Fail.
3710                          */
3711                         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
3712                         return FALSE;
3713                 }
3714
3715                 /* write the interface description block */
3716                 wblock.frame_buffer            = NULL;
3717                 wblock.pseudo_header           = NULL;
3718                 wblock.packet_header           = NULL;
3719                 wblock.file_encap              = NULL;
3720                 wblock.type                    = BLOCK_TYPE_IDB;
3721                 wblock.data.if_descr.link_type = pcap_encap;
3722                 wblock.data.if_descr.snap_len = (wdh->snaplen != 0) ? wdh->snaplen :
3723                                                                       WTAP_MAX_PACKET_SIZE; /* XXX */
3724
3725                 /* XXX - options unused */
3726                 wblock.data.if_descr.if_speed   = -1;
3727                 /*wblock.data.if_descr.if_tsresol = 6;*/    /* default: usec */
3728                 wblock.data.if_descr.if_os      = NULL;
3729                 wblock.data.if_descr.if_fcslen  = -1;
3730
3731                 if (!pcapng_write_if_descr_block(wdh, &wblock, err)) {
3732                         return FALSE;
3733                 }
3734
3735                 interface_id = pcapng->number_of_interfaces;
3736                 int_data.wtap_encap = phdr->pkt_encap;
3737                 int_data.time_units_per_second = 0;
3738                 g_array_append_val(pcapng->interface_data, int_data);
3739                 pcapng->number_of_interfaces++;
3740
3741                 pcapng_debug3("pcapng_dump: added interface description block with index %u for encap = %d (%s).",
3742                               interface_id,
3743                               phdr->pkt_encap,
3744                               wtap_encap_string(phdr->pkt_encap));
3745         }
3746 #endif
3747
3748         return TRUE;
3749 }
3750
3751
3752 /* Returns 0 if we could write the specified encapsulation type,
3753    an error indication otherwise. */
3754 int pcapng_dump_can_write_encap(int wtap_encap)
3755 {
3756         pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
3757                       wtap_encap,
3758                       wtap_encap_string(wtap_encap));
3759
3760         /* Per-packet encapsulation is supported. */
3761         if (wtap_encap == WTAP_ENCAP_PER_PACKET)
3762                 return 0;
3763
3764         /* Make sure we can figure out this DLT type */
3765         if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
3766                 return WTAP_ERR_UNSUPPORTED_ENCAP;
3767
3768         return 0;
3769 }
3770
3771 /*
3772  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
3773  *
3774  * Local variables:
3775  * c-basic-offset: 4
3776  * tab-width: 8
3777  * indent-tabs-mode: nil
3778  * End:
3779  *
3780  * vi: set shiftwidth=4 tabstop=8 expandtab:
3781  * :indentSize=4:tabSize=8:noTabs=true:
3782  */