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