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