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