Move the new files to the same places as in automake.
[obnox/wireshark/wip.git] / wiretap / pcapng.c
1 /* pcapng.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
8  * File format support for pcap-ng file format
9  * Copyright (c) 2007 by Ulf Lamping <ulf.lamping@web.de>
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 /* File format reference:
27  *   http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
28  * Related Wiki page:
29  *   http://wiki.wireshark.org/Development/PcapNg
30  */
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <errno.h>
39
40 /* Needed for addrinfo */
41 #ifdef HAVE_SYS_TYPES_H
42 # include <sys/types.h>
43 #endif
44
45 #ifdef HAVE_SYS_SOCKET_H
46 #include <sys/socket.h>
47 #endif
48
49 #ifdef HAVE_NETINET_IN_H
50 # include <netinet/in.h>
51 #endif
52
53 #ifdef HAVE_NETDB_H
54 # include <netdb.h>
55 #endif
56
57 #ifdef HAVE_WINSOCK2_H
58 # include <winsock2.h>
59 #endif
60
61 #if defined(_WIN32) && defined(INET6)
62 # include <ws2tcpip.h>
63 #endif
64
65 #include "wtap-int.h"
66 #include "file_wrappers.h"
67 #include "buffer.h"
68 #include "libpcap.h"
69 #include "pcap-common.h"
70 #include "pcap-encap.h"
71 #include "pcapng.h"
72
73 #if 0
74 #define pcapng_debug0(str) g_warning(str)
75 #define pcapng_debug1(str,p1) g_warning(str,p1)
76 #define pcapng_debug2(str,p1,p2) g_warning(str,p1,p2)
77 #define pcapng_debug3(str,p1,p2,p3) g_warning(str,p1,p2,p3)
78 #else
79 #define pcapng_debug0(str)
80 #define pcapng_debug1(str,p1)
81 #define pcapng_debug2(str,p1,p2)
82 #define pcapng_debug3(str,p1,p2,p3)
83 #endif
84
85 static gboolean
86 pcapng_read(wtap *wth, int *err, gchar **err_info,
87     gint64 *data_offset);
88 static gboolean
89 pcapng_seek_read(wtap *wth, gint64 seek_off,
90     union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
91     int *err, gchar **err_info);
92 static void
93 pcapng_close(wtap *wth);
94
95
96 /* pcapng: common block header for every block type */
97 typedef struct pcapng_block_header_s {
98         guint32 block_type;
99         guint32 block_total_length;
100         /* x bytes block_body */
101         /* guint32 block_total_length */
102 } pcapng_block_header_t;
103
104 /*
105  * Minimum block size = size of block header + size of block trailer.
106  */
107 #define MIN_BLOCK_SIZE  ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
108
109 /* pcapng: section header block */
110 typedef struct pcapng_section_header_block_s {
111         /* pcapng_block_header_t */
112         guint32 magic;
113         guint16 version_major;
114         guint16 version_minor;
115         guint64 section_length; /* might be -1 for unknown */
116         /* ... Options ... */
117 } pcapng_section_header_block_t;
118
119 /*
120  * Minimum SHB size = minimum block size + size of fixed length portion of SHB.
121  */
122 #define MIN_SHB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
123
124 /* pcapng: interface description block */
125 typedef struct pcapng_interface_description_block_s {
126         guint16 linktype;
127         guint16 reserved;
128         guint32 snaplen;
129         /* ... Options ... */
130 } pcapng_interface_description_block_t;
131
132 /*
133  * Minimum IDB size = minimum block size + size of fixed length portion of IDB.
134  */
135 #define MIN_IDB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
136
137 /* pcapng: packet block (obsolete) */
138 typedef struct pcapng_packet_block_s {
139         guint16 interface_id;
140         guint16 drops_count;
141         guint32 timestamp_high;
142         guint32 timestamp_low;
143         guint32 captured_len;
144         guint32 packet_len;
145         /* ... Packet Data ... */
146         /* ... Padding ... */
147         /* ... Options ... */
148 } pcapng_packet_block_t;
149
150 /*
151  * Minimum PB size = minimum block size + size of fixed length portion of PB.
152  */
153 #define MIN_PB_SIZE     ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_packet_block_t)))
154
155 /* pcapng: enhanced packet block */
156 typedef struct pcapng_enhanced_packet_block_s {
157         guint32 interface_id;
158         guint32 timestamp_high;
159         guint32 timestamp_low;
160         guint32 captured_len;
161         guint32 packet_len;
162         /* ... Packet Data ... */
163         /* ... Padding ... */
164         /* ... Options ... */
165 } pcapng_enhanced_packet_block_t;
166
167 /*
168  * Minimum EPB size = minimum block size + size of fixed length portion of EPB.
169  */
170 #define MIN_EPB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_enhanced_packet_block_t)))
171
172 /* pcapng: simple packet block */
173 typedef struct pcapng_simple_packet_block_s {
174         guint32 packet_len;
175         /* ... Packet Data ... */
176         /* ... Padding ... */
177 } pcapng_simple_packet_block_t;
178
179 /*
180  * Minimum SPB size = minimum block size + size of fixed length portion of SPB.
181  */
182 #define MIN_SPB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_simple_packet_block_t)))
183
184 /* pcapng: name resolution block */
185 typedef struct pcapng_name_resolution_block_s {
186         guint16 record_type;
187         guint16 record_len;
188         /* ... Record ... */
189 } pcapng_name_resolution_block_t;
190
191 /*
192  * Minimum NRB size = minimum block size + size of smallest NRB record
193  * (there must at least be an "end of records" record).
194  */
195 #define MIN_NRB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
196
197 /* pcapng: interface statistics block */
198 typedef struct pcapng_interface_statistics_block_s {
199         guint32 interface_id;
200         guint32 timestamp_high;
201         guint32 timestamp_low;
202         /* ... Options ... */
203 } pcapng_interface_statistics_block_t;
204
205 /*
206  * Minimum ISB size = minimum block size + size of fixed length portion of ISB.
207  */
208 #define MIN_ISB_SIZE    ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_statistics_block_t)))
209
210 /* pcapng: common option header for every option type */
211 typedef struct pcapng_option_header_s {
212         guint16 option_code;
213         guint16 option_length;
214         /* ... x bytes Option Body ... */
215         /* ... Padding ... */
216 } pcapng_option_header_t;
217
218 struct option {
219         guint16 type;
220         guint16 value_length;
221 };
222
223 /* Block types */
224 #define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
225 #define BLOCK_TYPE_PB  0x00000002 /* Packet Block (obsolete) */
226 #define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
227 #define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
228 #define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
229 #define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
230 #define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
231
232 /* Options */
233 #define OPT_EOFOPT       0
234 #define OPT_COMMENT      1
235 #define OPT_SHB_HARDWARE 2
236 #define OPT_SHB_OS       3
237 #define OPT_SHB_USERAPPL 4
238
239 /* Capture section */
240 #if 0
241 /* Moved to wtap.h */
242 typedef struct wtapng_section_s {
243         /* mandatory */
244         guint64                         section_length;
245         /* options */
246         gchar                           *opt_comment;   /* NULL if not available */
247         gchar                           *shb_hardware;  /* NULL if not available */
248         gchar                           *shb_os;                /* NULL if not available */
249         gchar                           *shb_user_appl; /* NULL if not available */
250 } wtapng_section_t;
251 #endif
252
253 #if 0
254 /* Moved to wtap.h */
255
256 /* Interface Description 
257  *
258  * Options:
259  * 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}" / ... 
260  * if_description 3  A UTF-8 string containing the description of the device used to capture data. "Broadcom NetXtreme" / "First Ethernet Interface" / ... 
261  * 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 
262  * 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" 
263  * if_MACaddr     6  Interface Hardware MAC address (48 bits). 00 01 02 03 04 05 
264  * if_EUIaddr     7  Interface Hardware EUI address (64 bits), if available. TODO: give a good example 
265  * if_speed       8  Interface speed (in bps). 100000000 for 100Mbps 
266  * 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 
267  * if_tzone      10  Time zone for GMT support (TODO: specify better). TODO: give a good example 
268  * 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" 
269  * 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" / ... 
270  * 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 
271  * 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 syncronized capture systems? 1234 
272  */
273
274 typedef struct wtapng_if_descr_s {
275         /* mandatory */
276         guint16                         link_type;
277         guint                           encap;
278         guint32                         snap_len;
279         /* options */
280         gchar                           *opt_comment;   /* NULL if not available */
281         gchar                           *if_name;               /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
282         gchar                           *if_description;/* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
283         /* XXX: if_IPv4addr opt 4  Interface network address and netmask.*/
284         /* XXX: if_IPv6addr opt 5  Interface network address and prefix length (stored in the last byte).*/
285         /* XXX: if_MACaddr  opt 6  Interface Hardware MAC address (48 bits).*/
286         /* XXX: if_EUIaddr  opt 7  Interface Hardware EUI address (64 bits)*/
287         guint64                         if_speed;       /* 0 if unknown, opt 8  Interface speed (in bps). 100000000 for 100Mbps */
288         guint8                          if_tsresol;     /* default is 6 for microsecond resolution, opt 9  Resolution of timestamps. 
289                                                                          * 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
290                                                                          */
291         /* XXX: if_tzone      10  Time zone for GMT support (TODO: specify better). */
292         gchar                           *if_filter;     /* NULL if not available, opt 11  The filter (e.g. "capture only TCP traffic") used to capture traffic.
293                                                                          * 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).
294                                                                          */
295         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. */
296         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. */
297         /* XXX: guint64 if_tsoffset; opt 14  A 64 bits integer value that specifies an offset (in seconds)...*/
298 } wtapng_if_descr_t;
299 #endif
300
301 /* Packets */
302 typedef struct wtapng_packet_s {
303         /* mandatory */
304         guint32                         ts_high;                /* seconds since 1.1.1970 */
305         guint32                         ts_low;                 /* fraction of seconds, depends on if_tsresol */
306         guint32                         cap_len;        /* data length in the file */
307         guint32                         packet_len;     /* data length on the wire */
308         guint32                         interface_id;   /* identifier of the interface. */
309         guint16                         drops_count;    /* drops count, only valid for packet block */
310                                                                                 /* 0xffff if information no available */
311         /* options */
312         gchar                           *opt_comment;   /* NULL if not available */
313         guint64                         drop_count;
314         guint32                         pack_flags;     /* XXX - 0 for now (any value for "we don't have it"?) */
315         /* pack_hash */
316
317         guint32                         pseudo_header_len;
318         int                                     wtap_encap;
319         /* XXX - put the packet data / pseudo_header here as well? */
320 } wtapng_packet_t;
321
322 /* Simple Packets */
323 typedef struct wtapng_simple_packet_s {
324         /* mandatory */
325         guint32                         cap_len;        /* data length in the file */
326         guint32                         packet_len;     /* data length on the wire */
327         guint32                         pseudo_header_len;
328         int                             wtap_encap;
329         /* XXX - put the packet data / pseudo_header here as well? */
330 } wtapng_simple_packet_t;
331
332 /* Name Resolution */
333 typedef struct wtapng_name_res_s {
334         /* options */
335         gchar                           *opt_comment;   /* NULL if not available */
336         /* XXX */
337 } wtapng_name_res_t;
338
339 /* Interface Statistics */
340 typedef struct wtapng_if_stats_s {
341         /* mandatory */
342         guint32                         interface_id;
343         guint32                         ts_high;
344         guint32                         ts_low;
345         /* options */
346         gchar                           *opt_comment;   /* NULL if not available */
347         guint64                         isb_starttime;
348         guint64                         isb_endtime;
349         guint64                         isb_ifrecv;
350         guint64                         isb_ifdrop;
351         guint64                         isb_filteraccept;
352         guint64                         isb_osdrop;
353         guint64                         isb_usrdeliv;
354 } wtapng_if_stats_t;
355
356
357 typedef struct wtapng_block_s {
358         guint32                                 type;           /* block_type as defined by pcapng */
359         union {
360                 wtapng_section_t        section;
361                 wtapng_if_descr_t       if_descr;
362                 wtapng_packet_t         packet;
363                 wtapng_simple_packet_t  simple_packet;
364                 wtapng_name_res_t       name_res;
365                 wtapng_if_stats_t       if_stats;
366         } data;
367
368         /*
369          * XXX - currently don't know how to handle these!
370          *
371          * For one thing, when we're reading a block, they must be
372          * writable, i.e. not const, so that we can read into them,
373          * but, when we're writing a block, they can be const, and,
374          * in fact, they sometimes point to const values.
375          */
376         const union wtap_pseudo_header *pseudo_header;
377         struct wtap_pkthdr *packet_header;
378         const guint8 *frame_buffer;
379         int *file_encap;
380 } wtapng_block_t;
381
382 /* Interface data in private struct */
383 typedef struct interface_data_s {
384         int wtap_encap;
385         guint64 time_units_per_second;
386 } interface_data_t;
387
388 typedef struct {
389         gboolean shb_read;                                              /**< Set when fisrt SHB read, second read will fail */
390         gboolean read_idbs;                                             /**< Idicates that it is the first read after a SHB, atl east one IDB is expected */
391         gboolean byte_swapped;
392         guint16 version_major;
393         guint16 version_minor;
394         GArray *interface_data;
395         guint number_of_interfaces;
396         gint8 if_fcslen;
397         wtap_new_ipv4_callback_t add_new_ipv4;
398         wtap_new_ipv6_callback_t add_new_ipv6;
399 } pcapng_t;
400
401 static int
402 pcapng_get_encap(gint id, pcapng_t *pn)
403 {
404         interface_data_t int_data;
405
406
407         if ((id >= 0) && ((guint)id < pn->number_of_interfaces)) {
408                 int_data = g_array_index(pn->interface_data, interface_data_t, id);
409                 pcapng_debug2("pcapng_get_encap: id %i, wtap_encap %i",id, int_data.wtap_encap);
410                 return int_data.wtap_encap;
411         } else {
412                 pcapng_debug2("pcapng_get_encap: id %i number_of_interfaces %u, wtap_encap = WTAP_ERR_UNSUPPORTED_ENCAP",id,pn->number_of_interfaces);
413                 return WTAP_ERR_UNSUPPORTED_ENCAP;
414         }
415 }
416
417 static int
418 pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
419                    char *content, int len, int *err, gchar **err_info)
420 {
421         int     bytes_read;
422         int     block_read;
423         guint64 file_offset64;
424
425
426         /* read option header */
427         errno = WTAP_ERR_CANT_READ;
428         bytes_read = file_read(oh, sizeof (*oh), fh);
429         if (bytes_read != sizeof (*oh)) {
430             pcapng_debug0("pcapng_read_option: failed to read option");
431             *err = file_error(fh, err_info);
432             if (*err != 0)
433                     return -1;
434             return 0;
435         }
436         block_read = sizeof (*oh);
437         if(pn->byte_swapped) {
438                 oh->option_code      = BSWAP16(oh->option_code);
439                 oh->option_length    = BSWAP16(oh->option_length);
440         }
441
442         /* sanity check: option length */
443         if (oh->option_length > len) {
444                 pcapng_debug2("pcapng_read_option: option_length %u larger than buffer (%u)",
445                               oh->option_length, len);
446                 return 0;
447         }
448
449         /* read option content */
450         errno = WTAP_ERR_CANT_READ;
451         bytes_read = file_read(content, oh->option_length, fh);
452         if (bytes_read != oh->option_length) {
453                 pcapng_debug1("pcapng_read_option: failed to read content of option %u", oh->option_code);
454                 *err = file_error(fh, err_info);
455                 if (*err != 0)
456                         return -1;
457                 return 0;
458         }
459         block_read += oh->option_length;
460
461         /* jump over potential padding bytes at end of option */
462         if( (oh->option_length % 4) != 0) {
463                 file_offset64 = file_seek(fh, 4 - (oh->option_length % 4), SEEK_CUR, err);
464                 if (file_offset64 <= 0) {
465                         if (*err != 0)
466                                 return -1;
467                         return 0;
468                 }
469                 block_read += 4 - (oh->option_length % 4);
470         }
471
472         return block_read;
473 }
474
475
476 static int
477 pcapng_read_section_header_block(FILE_T fh, gboolean first_block,
478                                  pcapng_block_header_t *bh, pcapng_t *pn,
479                                  wtapng_block_t *wblock, int *err,
480                                  gchar **err_info)
481 {
482         int     bytes_read;
483         int     block_read;
484         int to_read, opt_cont_buf_len;
485         pcapng_section_header_block_t shb;
486         pcapng_option_header_t oh;
487         char *option_content = NULL; /* Allocate as large as the options block */
488
489         /*
490          * Is this block long enough to be an SHB?
491          */
492         if (bh->block_total_length < MIN_SHB_SIZE) {
493                 /*
494                  * No.
495                  */
496                 if (first_block)
497                         return 0;       /* probably not a pcap-ng file */
498                 *err = WTAP_ERR_BAD_FILE;
499                 *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",
500                               bh->block_total_length, MIN_SHB_SIZE);
501                 return -1;
502         }
503
504         /* read block content */
505         errno = WTAP_ERR_CANT_READ;
506         bytes_read = file_read(&shb, sizeof shb, fh);
507         if (bytes_read != sizeof shb) {
508                 *err = file_error(fh, err_info);
509                 if (*err == 0) {
510                         if (first_block) {
511                                 /*
512                                  * We're reading this as part of an open,
513                                  * and this block is too short to be
514                                  * an SHB, so the file is too short
515                                  * to be a pcap-ng file.
516                                  */
517                                 return 0;
518                         }
519
520                         /*
521                          * Otherwise, just report this as an error.
522                          */
523                         *err = WTAP_ERR_SHORT_READ;
524                 }
525                 return -1;
526         }
527         block_read = bytes_read;
528
529         /* is the magic number one we expect? */
530         switch(shb.magic) {
531             case(0x1A2B3C4D):
532                 /* this seems pcapng with correct byte order */
533                 pn->byte_swapped                = FALSE;
534                 pn->version_major               = shb.version_major;
535                 pn->version_minor               = shb.version_minor;
536
537                 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
538                                 pn->version_major, pn->version_minor, bh->block_total_length);
539                 break;
540             case(0x4D3C2B1A):
541                 /* this seems pcapng with swapped byte order */
542                 pn->byte_swapped                = TRUE;
543                 pn->version_major               = BSWAP16(shb.version_major);
544                 pn->version_minor               = BSWAP16(shb.version_minor);
545
546                 /* tweak the block length to meet current swapping that we know now */
547                 bh->block_total_length  = BSWAP32(bh->block_total_length);
548
549                 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
550                                 pn->version_major, pn->version_minor, bh->block_total_length);
551                 break;
552             default:
553                 /* Not a "pcapng" magic number we know about. */
554                 if (first_block) {
555                         /* Not a pcap-ng file. */
556                         return 0;
557                 }
558
559                 /* A bad block */
560                 *err = WTAP_ERR_BAD_FILE;
561                 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown byte-order magic number 0x%08x", shb.magic);
562                 return 0;
563         }
564
565         /* OK, at this point we assume it's a pcap-ng file. */
566         /* We currently only suport one SHB */
567         if (pn->shb_read == TRUE) {
568                 *err = WTAP_ERR_UNSUPPORTED;
569                 *err_info = g_strdup_printf("pcapng: multiple section header blocks not supported.");
570                 return 0;
571         }
572
573         /* we currently only understand SHB V1.0 */
574         if (pn->version_major != 1 || pn->version_minor > 0) {
575                 *err = WTAP_ERR_UNSUPPORTED;
576                 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
577                               pn->version_major, pn->version_minor);
578                 return -1;
579         }
580
581
582         /* 64bit section_length (currently unused) */
583         if (pn->byte_swapped) {
584                 wblock->data.section.section_length = BSWAP64(shb.section_length);
585         } else {
586                 wblock->data.section.section_length = shb.section_length;
587         }
588
589         /* Option defaults */
590         wblock->data.section.opt_comment        = NULL;
591         wblock->data.section.shb_hardware       = NULL;
592         wblock->data.section.shb_os                     = NULL;
593         wblock->data.section.shb_user_appl      = NULL;
594
595         /* Options */
596         errno = WTAP_ERR_CANT_READ;
597         to_read = bh->block_total_length - MIN_SHB_SIZE;
598         /* Allocate enough memory to hold all options */
599         opt_cont_buf_len = to_read;
600         option_content = g_malloc(opt_cont_buf_len);
601         pcapng_debug1("pcapng_read_section_header_block: Options %u bytes", to_read);
602         while(to_read > 0) {
603                 /* read option */
604                 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes remaining", to_read);
605                 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
606                 if (bytes_read <= 0) {
607                         pcapng_debug0("pcapng_read_section_header_block: failed to read option");
608                         return bytes_read;
609                 }
610                 block_read += bytes_read;
611                 to_read -= bytes_read;
612
613                 /* handle option content */
614                 switch(oh.option_code) {
615                     case(0): /* opt_endofopt */
616                         if(to_read != 0) {
617                                 pcapng_debug1("pcapng_read_section_header_block: %u bytes after opt_endofopt", to_read);
618                         }
619                         /* padding should be ok here, just get out of this */
620                         to_read = 0;
621                         break;
622                     case(1): /* opt_comment */
623                         if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
624                                 wblock->data.section.opt_comment = g_strndup(option_content, oh.option_length);
625                                 pcapng_debug1("pcapng_read_section_header_block: opt_comment %s", wblock->data.section.opt_comment);
626                         } else {
627                                 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh.option_length);
628                         }
629                         break;
630                     case(2): /* shb_hardware */
631                         if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
632                                 wblock->data.section.shb_hardware = g_strndup(option_content, oh.option_length);
633                                 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock->data.section.shb_hardware);
634                         } else {
635                                 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh.option_length);
636                         }
637                         break;
638                     case(3): /* shb_os */
639                         if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
640                                 wblock->data.section.shb_os = g_strndup(option_content, oh.option_length);
641                                 pcapng_debug1("pcapng_read_section_header_block: shb_os %s", wblock->data.section.shb_os);
642                         } else {
643                                 pcapng_debug2("pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u", oh.option_length,to_read);
644                         }
645                         break;
646                     case(4): /* shb_user_appl */
647                         if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
648                                 wblock->data.section.shb_user_appl = g_strndup(option_content, oh.option_length);
649                                 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl %s", wblock->data.section.shb_user_appl);
650                         } else {
651                                 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl length %u seems strange", oh.option_length);
652                         }
653                         break;
654                     default:
655                         pcapng_debug2("pcapng_read_section_header_block: unknown option %u - ignoring %u bytes",
656                                       oh.option_code, oh.option_length);
657                 }
658         }
659         g_free(option_content);
660
661         return block_read;
662 }
663
664
665 /* "Interface Description Block" */
666 static int
667 pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
668                            wtapng_block_t *wblock, int *err, gchar **err_info)
669 {
670         guint64 time_units_per_second = 1000000; /* default */
671         int     bytes_read;
672         int     block_read;
673         int to_read, opt_cont_buf_len;
674         pcapng_interface_description_block_t idb;
675         pcapng_option_header_t oh;
676         char *option_content = NULL; /* Allocate as large as the options block */
677
678         /*
679          * Is this block long enough to be an IDB?
680          */
681         if (bh->block_total_length < MIN_IDB_SIZE) {
682                 /*
683                  * No.
684                  */
685                 *err = WTAP_ERR_BAD_FILE;
686                 *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",
687                               bh->block_total_length, MIN_IDB_SIZE);
688                 return -1;
689         }
690
691         /* read block content */
692         errno = WTAP_ERR_CANT_READ;
693         bytes_read = file_read(&idb, sizeof idb, fh);
694         if (bytes_read != sizeof idb) {
695                 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
696                 *err = file_error(fh, err_info);
697                 if (*err != 0)
698                         return -1;
699                 return 0;
700         }
701         block_read = bytes_read;
702
703         /* mandatory values */
704         if (pn->byte_swapped) {
705                 wblock->data.if_descr.link_type = BSWAP16(idb.linktype);
706                 wblock->data.if_descr.snap_len  = BSWAP32(idb.snaplen);
707         } else {
708                 wblock->data.if_descr.link_type = idb.linktype;
709                 wblock->data.if_descr.snap_len  = idb.snaplen;
710         }
711
712         wblock->data.if_descr.wtap_encap = wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type);
713         wblock->data.if_descr.time_units_per_second = time_units_per_second;
714
715         pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
716                       wblock->data.if_descr.link_type,
717                       wtap_encap_string(wblock->data.if_descr.wtap_encap),
718                       wblock->data.if_descr.snap_len);
719
720         if (wblock->data.if_descr.snap_len > WTAP_MAX_PACKET_SIZE) {
721                 /* This is unrealisitic, but text2pcap currently uses 102400.
722                  * We do not use this value, maybe we should check the
723                  * snap_len of the packets against it. For now, only warn.
724                  */
725                 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
726                               wblock->data.if_descr.snap_len);
727                 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
728         }
729
730         /* Option defaults */
731         wblock->data.if_descr.opt_comment = NULL;
732         wblock->data.if_descr.if_name = NULL;
733         wblock->data.if_descr.if_description = NULL;
734         /* XXX: if_IPv4addr */
735         /* XXX: if_IPv6addr */
736         /* XXX: if_MACaddr */
737         /* XXX: if_EUIaddr */
738         wblock->data.if_descr.if_speed = 0;                     /* "unknown" */
739         wblock->data.if_descr.if_tsresol = 6;                   /* default is 6 for microsecond resolution */
740         wblock->data.if_descr.if_filter = NULL;
741         wblock->data.if_descr.if_os = NULL;
742         wblock->data.if_descr.if_fcslen = -1;                   /* unknown or changes between packets */
743         /* XXX: guint64 if_tsoffset; */
744
745
746         /* Options */
747         errno = WTAP_ERR_CANT_READ;
748         to_read = bh->block_total_length - MIN_IDB_SIZE;
749
750         /* Allocate enough memory to hold all options */
751         opt_cont_buf_len = to_read;
752         option_content = g_malloc(opt_cont_buf_len);
753
754         while (to_read > 0) {
755                 /* read option */
756                 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
757                 if (bytes_read <= 0) {
758                         pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
759                         return bytes_read;
760                 }
761                 block_read += bytes_read;
762                 to_read -= bytes_read;
763
764                 /* handle option content */
765                 switch(oh.option_code) {
766                     case(0): /* opt_endofopt */
767                         if(to_read != 0) {
768                                 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read);
769                         }
770                         /* padding should be ok here, just get out of this */
771                         to_read = 0;
772                         break;
773                     case(1): /* opt_comment */
774                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
775                                 wblock->data.if_descr.opt_comment = g_strndup(option_content, oh.option_length);
776                                 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock->data.if_descr.opt_comment);
777                         } else {
778                                 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh.option_length);
779                         }
780                         break;
781                     case(2): /* if_name */
782                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
783                                 wblock->data.if_descr.if_name = g_strndup(option_content, oh.option_length);
784                                 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock->data.if_descr.if_name);
785                         } else {
786                                 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh.option_length);
787                         }
788                         break;
789                     case(3): /* if_description */
790                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
791                             wblock->data.if_descr.if_description = g_strndup(option_content, oh.option_length);
792                                 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock->data.if_descr.if_description);
793                         } else {
794                                 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
795                         }
796                         break;
797                         /*
798                          * 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 
799                          * 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" 
800                          * if_MACaddr     6  Interface Hardware MAC address (48 bits). 00 01 02 03 04 05 
801                          * if_EUIaddr     7  Interface Hardware EUI address (64 bits), if available. TODO: give a good example 
802                          */
803                     case(8): /* if_speed */
804                         if (oh.option_length == 8) {
805                                 /*  Don't cast a char[] into a guint64--the
806                                  *  char[] may not be aligned correctly.
807                                  */
808                                 memcpy(&wblock->data.if_descr.if_speed, option_content, sizeof(guint64));
809                                 if(pn->byte_swapped)
810                                         wblock->data.if_descr.if_speed = BSWAP64(wblock->data.if_descr.if_speed);
811                                 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
812                         } else {
813                                     pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
814                         }
815                         break;
816                     case(9): /* if_tsresol */
817                         if (oh.option_length == 1) {
818                                 guint64 base;
819                                 guint64 result;
820                                 guint8 i, exponent, if_tsresol;
821
822                                 if_tsresol = option_content[0];
823                                 if (if_tsresol & 0x80) {
824                                         base = 2;
825                                 } else {
826                                         base = 10;
827                                 }
828                                 exponent = (guint8)(if_tsresol & 0x7f);
829                                 if (((base == 2) && (exponent < 64)) || ((base == 10) && (exponent < 20))) {
830                                         result = 1;
831                                         for (i = 0; i < exponent; i++) {
832                                                 result *= base;
833                                         }
834                                         time_units_per_second = result;
835                                 } else {
836                                         time_units_per_second = G_MAXUINT64;
837                                 }
838                                 if (time_units_per_second > (((guint64)1) << 32)) {
839                                         pcapng_debug0("pcapng_open: time conversion might be inaccurate");
840                                 }
841                                 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol %u", wblock->data.if_descr.if_tsresol);
842                                 wblock->data.if_descr.time_units_per_second = time_units_per_second;
843                                 wblock->data.if_descr.if_tsresol = if_tsresol;
844                         } else {
845                                 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
846                         }
847                         break;
848                         /*
849                          * if_tzone      10  Time zone for GMT support (TODO: specify better). TODO: give a good example 
850                          */
851                     case(11): /* if_filter */
852                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
853                                 wblock->data.if_descr.if_filter = g_strndup(option_content, oh.option_length);
854                                 pcapng_debug1("pcapng_read_if_descr_block: if_filter %s", wblock->data.if_descr.if_filter);
855                         } else {
856                                 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
857                         }
858                         break;
859                         case(12): /* if_os */
860                         /*
861                          * if_os         12  A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. 
862                          * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory))) 
863                          * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ... 
864                          */
865                         if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
866                             wblock->data.if_descr.if_os = g_strndup(option_content, oh.option_length);
867                                 pcapng_debug1("pcapng_read_if_descr_block: if_os %s", wblock->data.if_descr.if_os);
868                         } else {
869                                 pcapng_debug1("pcapng_read_if_descr_block: if_os length %u seems strange", oh.option_length);
870                         }
871                         break;
872                     case(13): /* if_fcslen */
873                         if (oh.option_length == 1) {
874                                 wblock->data.if_descr.if_fcslen = option_content[0];
875                                 pn->if_fcslen = wblock->data.if_descr.if_fcslen;
876                                 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock->data.if_descr.if_fcslen);
877                                 /* XXX - add sanity check */
878                         } else {
879                                 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
880                         }
881                         break;
882                         /*
883                          * if_tsoffset   14  A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
884                          * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps. 
885                          * The time zone of the offset can be specified with the option if_tzone. 
886                          * TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly syncronized capture systems? 1234 
887                          */
888                     default:
889                         pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
890                                       oh.option_code, oh.option_length);
891                 }
892         }
893
894         g_free(option_content);
895
896         if (*wblock->file_encap == WTAP_ENCAP_UNKNOWN) {
897                 *wblock->file_encap = wblock->data.if_descr.wtap_encap;
898         } else {
899                 if (*wblock->file_encap != wblock->data.if_descr.wtap_encap) {
900                         *wblock->file_encap = WTAP_ENCAP_PER_PACKET;
901                 }
902         }
903
904         return block_read;
905 }
906
907
908 static int
909 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)
910 {
911         int bytes_read;
912         int block_read;
913         int to_read, opt_cont_buf_len;
914         guint64 file_offset64;
915         pcapng_enhanced_packet_block_t epb;
916         pcapng_packet_block_t pb;
917         guint32 block_total_length;
918         guint32 padding;
919         pcapng_option_header_t oh;
920         gint wtap_encap;
921         int pseudo_header_len;
922         char *option_content = NULL; /* Allocate as large as the options block */
923         int fcslen;
924
925         /* "(Enhanced) Packet Block" read fixed part */
926         errno = WTAP_ERR_CANT_READ;
927         if (enhanced) {
928                 /*
929                  * Is this block long enough to be an EPB?
930                  */
931                 if (bh->block_total_length < MIN_EPB_SIZE) {
932                         /*
933                          * No.
934                          */
935                         *err = WTAP_ERR_BAD_FILE;
936                         *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of an EPB is less than the minimum EPB size %u",
937                                       bh->block_total_length, MIN_EPB_SIZE);
938                         return -1;
939                 }
940                 bytes_read = file_read(&epb, sizeof epb, fh);
941                 if (bytes_read != sizeof epb) {
942                         pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
943                         *err = file_error(fh, err_info);
944                         return 0;
945                 }
946                 block_read = bytes_read;
947
948                 if (pn->byte_swapped) {
949                         wblock->data.packet.interface_id        = BSWAP32(epb.interface_id);
950                         wblock->data.packet.drops_count         = -1; /* invalid */
951                         wblock->data.packet.ts_high             = BSWAP32(epb.timestamp_high);
952                         wblock->data.packet.ts_low              = BSWAP32(epb.timestamp_low);
953                         wblock->data.packet.cap_len             = BSWAP32(epb.captured_len);
954                         wblock->data.packet.packet_len          = BSWAP32(epb.packet_len);
955                 } else {
956                         wblock->data.packet.interface_id        = epb.interface_id;
957                         wblock->data.packet.drops_count         = -1; /* invalid */
958                         wblock->data.packet.ts_high             = epb.timestamp_high;
959                         wblock->data.packet.ts_low              = epb.timestamp_low;
960                         wblock->data.packet.cap_len             = epb.captured_len;
961                         wblock->data.packet.packet_len          = epb.packet_len;
962                 }
963         } else {
964                 /*
965                  * Is this block long enough to be a PB?
966                  */
967                 if (bh->block_total_length < MIN_PB_SIZE) {
968                         /*
969                          * No.
970                          */
971                         *err = WTAP_ERR_BAD_FILE;
972                         *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of a PB is less than the minimum PB size %u",
973                                       bh->block_total_length, MIN_PB_SIZE);
974                         return -1;
975                 }
976                 bytes_read = file_read(&pb, sizeof pb, fh);
977                 if (bytes_read != sizeof pb) {
978                         pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
979                         *err = file_error(fh, err_info);
980                         return 0;
981                 }
982                 block_read = bytes_read;
983
984                 if (pn->byte_swapped) {
985                         wblock->data.packet.interface_id        = BSWAP16(pb.interface_id);
986                         wblock->data.packet.drops_count         = BSWAP16(pb.drops_count);
987                         wblock->data.packet.ts_high             = BSWAP32(pb.timestamp_high);
988                         wblock->data.packet.ts_low              = BSWAP32(pb.timestamp_low);
989                         wblock->data.packet.cap_len             = BSWAP32(pb.captured_len);
990                         wblock->data.packet.packet_len          = BSWAP32(pb.packet_len);
991                 } else {
992                         wblock->data.packet.interface_id        = pb.interface_id;
993                         wblock->data.packet.drops_count         = pb.drops_count;
994                         wblock->data.packet.ts_high             = pb.timestamp_high;
995                         wblock->data.packet.ts_low              = pb.timestamp_low;
996                         wblock->data.packet.cap_len             = pb.captured_len;
997                         wblock->data.packet.packet_len          = pb.packet_len;
998                 }
999
1000         }
1001
1002         /*
1003          * How much padding is there at the end of the packet data?
1004          */
1005         if ((wblock->data.packet.cap_len % 4) != 0)
1006                 padding = 4 - (wblock->data.packet.cap_len % 4);
1007         else
1008                 padding = 0;
1009
1010         /* add padding bytes to "block total length" */
1011         /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1012         if (bh->block_total_length % 4) {
1013                 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1014         } else {
1015                 block_total_length = bh->block_total_length;
1016         }
1017
1018         /*
1019          * Is this block long enough to hold the packet data?
1020          */
1021         if (enhanced) {
1022                 if (block_total_length <
1023                     MIN_EPB_SIZE + wblock->data.packet.cap_len + padding) {
1024                         /*
1025                          * No.
1026                          */
1027                         *err = WTAP_ERR_BAD_FILE;
1028                         *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of EPB is too small for %u bytes of packet data",
1029                                       block_total_length, wblock->data.packet.cap_len);
1030                         return -1;
1031                 }
1032         } else {
1033                 if (block_total_length <
1034                     MIN_PB_SIZE + wblock->data.packet.cap_len + padding) {
1035                         /*
1036                          * No.
1037                          */
1038                         *err = WTAP_ERR_BAD_FILE;
1039                         *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1040                                       block_total_length, wblock->data.packet.cap_len);
1041                         return -1;
1042                 }
1043         }
1044
1045         if (wblock->data.packet.cap_len > wblock->data.packet.packet_len) {
1046                 *err = WTAP_ERR_BAD_FILE;
1047                 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than packet_len %u.",
1048                     wblock->data.packet.cap_len, wblock->data.packet.packet_len);
1049                 return 0;
1050         }
1051         if (wblock->data.packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1052                 *err = WTAP_ERR_BAD_FILE;
1053                 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
1054                     wblock->data.packet.cap_len, WTAP_MAX_PACKET_SIZE);
1055                 return 0;
1056         }
1057         pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
1058                       wblock->data.packet.packet_len,
1059                       wblock->data.packet.cap_len,
1060                       wblock->data.packet.interface_id);
1061
1062         wtap_encap = pcapng_get_encap(wblock->data.packet.interface_id, pn);
1063         pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
1064                        wtap_encap,
1065                        wtap_encap_string(wtap_encap),
1066                        pcap_get_phdr_size(wtap_encap, wblock->pseudo_header));
1067
1068         memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1069         pseudo_header_len = pcap_process_pseudo_header(fh,
1070                                                        WTAP_FILE_PCAPNG,
1071                                                        wtap_encap,
1072                                                        wblock->data.packet.cap_len,
1073                                                        TRUE,
1074                                                        wblock->packet_header,
1075                                                        (union wtap_pseudo_header *)wblock->pseudo_header,
1076                                                        err,
1077                                                        err_info);
1078         if (pseudo_header_len < 0) {
1079                 return 0;
1080         }
1081         wblock->data.packet.pseudo_header_len = (guint32)pseudo_header_len;
1082         block_read += pseudo_header_len;
1083         if (pseudo_header_len != pcap_get_phdr_size(wtap_encap, wblock->pseudo_header)) {
1084                 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
1085                               pseudo_header_len);
1086         }
1087
1088         /* "(Enhanced) Packet Block" read capture data */
1089         errno = WTAP_ERR_CANT_READ;
1090         bytes_read = file_read((guint8 *) (wblock->frame_buffer), wblock->data.packet.cap_len - pseudo_header_len, fh);
1091         if (bytes_read != (int) (wblock->data.packet.cap_len - pseudo_header_len)) {
1092                 *err = file_error(fh, err_info);
1093                 pcapng_debug1("pcapng_read_packet_block: couldn't read %u bytes of captured data",
1094                               wblock->data.packet.cap_len - pseudo_header_len);
1095                 if (*err == 0)
1096                         *err = WTAP_ERR_SHORT_READ;
1097                 return 0;
1098         }
1099         block_read += bytes_read;
1100
1101         /* jump over potential padding bytes at end of the packet data */
1102         if (padding != 0) {
1103                 file_offset64 = file_seek(fh, padding, SEEK_CUR, err);
1104                 if (file_offset64 <= 0) {
1105                         if (*err != 0)
1106                                 return -1;
1107                         return 0;
1108                 }
1109                 block_read += padding;
1110         }
1111
1112         /* Option defaults */
1113         wblock->data.packet.opt_comment = NULL;
1114         wblock->data.packet.drop_count  = -1;
1115         wblock->data.packet.pack_flags  = 0;    /* XXX - is 0 ok to signal "not used"? */
1116
1117         /* FCS length default */
1118         fcslen = pn->if_fcslen;
1119
1120         /* Options 
1121          * opt_comment    1
1122          * epb_flags      2
1123          * epb_hash       3
1124          * epb_dropcount  4
1125          */
1126         errno = WTAP_ERR_CANT_READ;
1127         to_read = block_total_length -
1128                   (int)sizeof(pcapng_block_header_t) -
1129                   block_read -    /* fixed and variable part, including padding */
1130                   (int)sizeof(bh->block_total_length);
1131
1132         /* Allocate enough memory to hold all options */
1133         opt_cont_buf_len = to_read;
1134         option_content = g_malloc(opt_cont_buf_len);
1135
1136         while(to_read > 0) {
1137                 /* read option */
1138                 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
1139                 if (bytes_read <= 0) {
1140                         pcapng_debug0("pcapng_read_packet_block: failed to read option");
1141                         return bytes_read;
1142                 }
1143                 block_read += bytes_read;
1144                 to_read -= bytes_read;
1145
1146                 /* handle option content */
1147                 switch(oh.option_code) {
1148                     case(0): /* opt_endofopt */
1149                         if(to_read != 0) {
1150                                 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
1151                         }
1152                         /* padding should be ok here, just get out of this */
1153                         to_read = 0;
1154                         break;
1155                     case(1): /* opt_comment */
1156                         if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1157                                 wblock->data.packet.opt_comment = g_strndup(option_content, oh.option_length);
1158                                 pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh.option_length, wblock->data.packet.opt_comment);
1159                         } else {
1160                                 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh.option_length);
1161                         }
1162                         break;
1163                     case(2): /* pack_flags / epb_flags */
1164                         if(oh.option_length == 4) {
1165                                 /*  Don't cast a char[] into a guint32--the
1166                                  *  char[] may not be aligned correctly.
1167                                  */
1168                                 memcpy(&wblock->data.packet.pack_flags, option_content, sizeof(guint32));
1169                                 if(pn->byte_swapped)
1170                                         wblock->data.packet.pack_flags = BSWAP32(wblock->data.packet.pack_flags);
1171                                 if (wblock->data.packet.pack_flags & 0x000001E0) {
1172                                         /* The FCS length is present */
1173                                         fcslen = (wblock->data.packet.pack_flags & 0x000001E0) >> 5;
1174                                 }
1175                                 pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->data.packet.pack_flags);
1176                         } else {
1177                                 pcapng_debug1("pcapng_read_packet_block: pack_flags length %u not 4 as expected", oh.option_length);
1178                         }
1179                         break;
1180                         case(3): /* epb_hash */
1181                         pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
1182                                       oh.option_code, oh.option_length);
1183                         break;
1184                         case(4): /* epb_dropcount */
1185                         if(oh.option_length == 8) {
1186                                 /*  Don't cast a char[] into a guint32--the
1187                                  *  char[] may not be aligned correctly.
1188                                  */
1189                                 memcpy(&wblock->data.packet.drop_count, option_content, sizeof(guint64));
1190                                 if(pn->byte_swapped)
1191                                         wblock->data.packet.drop_count = BSWAP64(wblock->data.packet.drop_count);
1192
1193                                 pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->data.packet.drop_count);
1194                         } else {
1195                                 pcapng_debug1("pcapng_read_packet_block: drop_count length %u not 8 as expected", oh.option_length);
1196                         }
1197                         break;
1198                     default:
1199                         pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
1200                                       oh.option_code, oh.option_length);
1201                 }
1202         }
1203
1204         g_free(option_content);
1205
1206         pcap_read_post_process(WTAP_FILE_PCAPNG, wtap_encap,
1207             (union wtap_pseudo_header *)wblock->pseudo_header,
1208             (guint8 *) (wblock->frame_buffer),
1209             (int) (wblock->data.packet.cap_len - pseudo_header_len),
1210             pn->byte_swapped, fcslen);
1211         return block_read;
1212 }
1213
1214
1215 static int
1216 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)
1217 {
1218         int bytes_read;
1219         int block_read;
1220         guint64 file_offset64;
1221         gint encap;
1222         int pseudo_header_len;
1223         pcapng_simple_packet_block_t spb;
1224
1225         /*
1226          * Is this block long enough to be an SPB?
1227          */
1228         if (bh->block_total_length < MIN_SPB_SIZE) {
1229                 /*
1230                  * No.
1231                  */
1232                 *err = WTAP_ERR_BAD_FILE;
1233                 *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",
1234                               bh->block_total_length, MIN_SPB_SIZE);
1235                 return -1;
1236         }
1237
1238         /* "Simple Packet Block" read fixed part */
1239         errno = WTAP_ERR_CANT_READ;
1240         bytes_read = file_read(&spb, sizeof spb, fh);
1241         if (bytes_read != sizeof spb) {
1242                 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
1243                 *err = file_error(fh, err_info);
1244                 return 0;
1245         }
1246         block_read = bytes_read;
1247
1248         if (pn->byte_swapped) {
1249                 wblock->data.simple_packet.packet_len   = BSWAP32(spb.packet_len);
1250         } else {
1251                 wblock->data.simple_packet.packet_len   = spb.packet_len;
1252         }
1253
1254         wblock->data.simple_packet.cap_len = bh->block_total_length
1255                                              - (guint32)sizeof(pcapng_simple_packet_block_t)
1256                                              - (guint32)sizeof(bh->block_total_length);
1257
1258         if (wblock->data.simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1259                 *err = WTAP_ERR_BAD_FILE;
1260                 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
1261                     wblock->data.simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
1262                 return 0;
1263         }
1264         pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
1265                        wblock->data.simple_packet.packet_len);
1266
1267         encap = pcapng_get_encap(0, pn);
1268         pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
1269                       pcap_get_phdr_size(encap, wblock->pseudo_header));
1270
1271         memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1272         pseudo_header_len = pcap_process_pseudo_header(fh,
1273                                                        WTAP_FILE_PCAPNG,
1274                                                        encap,
1275                                                        wblock->data.simple_packet.cap_len,
1276                                                        TRUE,
1277                                                        wblock->packet_header,
1278                                                        (union wtap_pseudo_header *)wblock->pseudo_header,
1279                                                        err,
1280                                                        err_info);
1281         if (pseudo_header_len < 0) {
1282                 return 0;
1283         }
1284         wblock->data.simple_packet.pseudo_header_len = (guint32)pseudo_header_len;
1285         block_read += pseudo_header_len;
1286         if (pseudo_header_len != pcap_get_phdr_size(encap, wblock->pseudo_header)) {
1287                 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
1288                               pseudo_header_len);
1289         }
1290
1291         memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1292
1293         /* "Simple Packet Block" read capture data */
1294         errno = WTAP_ERR_CANT_READ;
1295         bytes_read = file_read((guint8 *) (wblock->frame_buffer), wblock->data.simple_packet.cap_len, fh);
1296         if (bytes_read != (int) wblock->data.simple_packet.cap_len) {
1297                 *err = file_error(fh, err_info);
1298                 pcapng_debug1("pcapng_read_simple_packet_block: couldn't read %u bytes of captured data",
1299                               wblock->data.simple_packet.cap_len);
1300                 if (*err == 0)
1301                         *err = WTAP_ERR_SHORT_READ;
1302                 return 0;
1303         }
1304         block_read += bytes_read;
1305
1306         /* jump over potential padding bytes at end of the packet data */
1307         if ((wblock->data.simple_packet.cap_len % 4) != 0) {
1308                 file_offset64 = file_seek(fh, 4 - (wblock->data.simple_packet.cap_len % 4), SEEK_CUR, err);
1309                 if (file_offset64 <= 0) {
1310                         if (*err != 0)
1311                                 return -1;
1312                         return 0;
1313                 }
1314                 block_read += 4 - (wblock->data.simple_packet.cap_len % 4);
1315         }
1316
1317         pcap_read_post_process(WTAP_FILE_PCAPNG, encap,
1318             (union wtap_pseudo_header *)wblock->pseudo_header,
1319             (guint8 *) (wblock->frame_buffer),
1320             (int) wblock->data.simple_packet.cap_len,
1321             pn->byte_swapped, pn->if_fcslen);
1322         return block_read;
1323 }
1324
1325 #define NRES_ENDOFRECORD 0
1326 #define NRES_IP4RECORD 1
1327 #define NRES_IP6RECORD 2
1328 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
1329 /* IPv6 + MAXNAMELEN */
1330 #define MAX_NRB_REC_SIZE (16 + 64)
1331 static int
1332 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)
1333 {
1334         int bytes_read = 0;
1335         int block_read = 0;
1336         int to_read;
1337         guint64 file_offset64;
1338         pcapng_name_resolution_block_t nrb;
1339         guint8 nrb_rec[MAX_NRB_REC_SIZE];
1340         guint32 v4_addr;
1341
1342         /*
1343          * Is this block long enough to be an NRB?
1344          */
1345         if (bh->block_total_length < MIN_NRB_SIZE) {
1346                 /*
1347                  * No.
1348                  */
1349                 *err = WTAP_ERR_BAD_FILE;
1350                 *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",
1351                               bh->block_total_length, MIN_NRB_SIZE);
1352                 return -1;
1353         }
1354
1355         errno = WTAP_ERR_CANT_READ;
1356         to_read = bh->block_total_length - MIN_NRB_SIZE;
1357
1358         while (block_read < to_read) {
1359                 /*
1360                  * There must be at least one record's worth of data
1361                  * here.
1362                  */
1363                 if ((size_t)(to_read - block_read) < sizeof nrb) {
1364                         *err = WTAP_ERR_BAD_FILE;
1365                         *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record header size %u",
1366                                       to_read - block_read,
1367                                       (guint)sizeof nrb);
1368                         return -1;
1369                 }
1370                 bytes_read = file_read(&nrb, sizeof nrb, fh);
1371                 if (bytes_read != sizeof nrb) {
1372                         pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
1373                         *err = file_error(fh, err_info);
1374                         return 0;
1375                 }
1376                 block_read += bytes_read;
1377
1378                 if (pn->byte_swapped) {
1379                         nrb.record_type = BSWAP16(nrb.record_type);
1380                         nrb.record_len  = BSWAP16(nrb.record_len);
1381                 }
1382
1383                 if (to_read - block_read < nrb.record_len + PADDING4(nrb.record_len)) {
1384                         *err = WTAP_ERR_BAD_FILE;
1385                         *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record length + padding %u",
1386                                       to_read - block_read,
1387                                       nrb.record_len + PADDING4(nrb.record_len));
1388                         return -1;
1389                 }
1390                 switch(nrb.record_type) {
1391                         case NRES_ENDOFRECORD:
1392                                 /* There shouldn't be any more data */
1393                                 to_read = 0;
1394                                 break;
1395                         case NRES_IP4RECORD:
1396                                 if (nrb.record_len < 4) {
1397                                         *err = WTAP_ERR_BAD_FILE;
1398                                         *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv4 record %u < minimum length 4",
1399                                                       nrb.record_len);
1400                                         return -1;
1401                                 }
1402                                 if (nrb.record_len > MAX_NRB_REC_SIZE) {
1403                                         pcapng_debug0("pcapng_read_name_resolution_block: bad length or insufficient data for IPv4 record");
1404                                         return 0;
1405                                 }
1406                                 bytes_read = file_read(nrb_rec, nrb.record_len, fh);
1407                                 if (bytes_read != nrb.record_len) {
1408                                         pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
1409                                         *err = file_error(fh, err_info);
1410                                         return 0;
1411                                 }
1412                                 block_read += bytes_read;
1413
1414                                 if (pn->add_new_ipv4) {
1415                                         memcpy(&v4_addr, nrb_rec, 4);
1416                                         if (pn->byte_swapped)
1417                                                 v4_addr = BSWAP32(v4_addr);
1418                                         pn->add_new_ipv4(v4_addr, nrb_rec + 4);
1419                                 }
1420
1421                                 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1422                                 if (file_offset64 <= 0) {
1423                                         if (*err != 0)
1424                                                 return -1;
1425                                         return 0;
1426                                 }
1427                                 block_read += PADDING4(nrb.record_len);
1428                                 break;
1429                         case NRES_IP6RECORD:
1430                                 if (nrb.record_len < 16) {
1431                                         *err = WTAP_ERR_BAD_FILE;
1432                                         *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u < minimum length 16",
1433                                                       nrb.record_len);
1434                                         return -1;
1435                                 }
1436                                 if (nrb.record_len > MAX_NRB_REC_SIZE || to_read < nrb.record_len) {
1437                                         pcapng_debug0("pcapng_read_name_resolution_block: bad length or insufficient data for IPv6 record");
1438                                         return 0;
1439                                 }
1440                                 bytes_read = file_read(nrb_rec, nrb.record_len, fh);
1441                                 if (bytes_read != nrb.record_len) {
1442                                         pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv6 record data");
1443                                         *err = file_error(fh, err_info);
1444                                         return 0;
1445                                 }
1446                                 block_read += bytes_read;
1447
1448                                 if (pn->add_new_ipv6) {
1449                                         pn->add_new_ipv6(nrb_rec, nrb_rec + 16);
1450                                 }
1451
1452                                 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1453                                 if (file_offset64 <= 0) {
1454                                         if (*err != 0)
1455                                                 return -1;
1456                                         return 0;
1457                                 }
1458                                 block_read += PADDING4(nrb.record_len);
1459                                 break;
1460                         default:
1461                                 pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
1462                                 file_offset64 = file_seek(fh, nrb.record_len + PADDING4(nrb.record_len), SEEK_CUR, err);
1463                                 if (file_offset64 <= 0) {
1464                                         if (*err != 0)
1465                                                 return -1;
1466                                         return 0;
1467                                 }
1468                                 block_read += nrb.record_len + PADDING4(nrb.record_len);
1469                                 break;
1470                 }
1471         }
1472
1473         return block_read;
1474 }
1475
1476 static int
1477 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)
1478 {
1479         int bytes_read;
1480         int block_read;
1481         int to_read, opt_cont_buf_len;
1482         pcapng_interface_statistics_block_t isb;
1483         pcapng_option_header_t oh;
1484         char *option_content = NULL; /* Allocate as large as the options block */
1485
1486         /*
1487          * Is this block long enough to be an ISB?
1488          */
1489         if (bh->block_total_length < MIN_ISB_SIZE) {
1490                 /*
1491                  * No.
1492                  */
1493                 *err = WTAP_ERR_BAD_FILE;
1494                 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: total block length %u is too small (< %u)",
1495                               bh->block_total_length, MIN_NRB_SIZE);
1496                 return -1;
1497         }
1498
1499         /* "Interface Statistics Block" read fixed part */
1500         errno = WTAP_ERR_CANT_READ;
1501         bytes_read = file_read(&isb, sizeof isb, fh);
1502         if (bytes_read != sizeof isb) {
1503                 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1504                 *err = file_error(fh, err_info);
1505                 return 0;
1506         }
1507         block_read = bytes_read;
1508
1509         if(pn->byte_swapped) {
1510                 wblock->data.if_stats.interface_id      = BSWAP64(isb.interface_id);
1511                 wblock->data.if_stats.ts_high           = BSWAP32(isb.timestamp_high);
1512                 wblock->data.if_stats.ts_low            = BSWAP32(isb.timestamp_low);
1513         } else {
1514                 wblock->data.if_stats.interface_id      = isb.interface_id;
1515                 wblock->data.if_stats.ts_high           = isb.timestamp_high;
1516                 wblock->data.if_stats.ts_low            = isb.timestamp_low;
1517         }
1518         pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %u", wblock->data.if_stats.interface_id);
1519
1520         /* Option defaults */
1521         wblock->data.if_stats.opt_comment = NULL;
1522         wblock->data.if_stats.isb_ifrecv  = -1;
1523         wblock->data.if_stats.isb_ifdrop  = -1;
1524
1525         /* Options */
1526         errno = WTAP_ERR_CANT_READ;
1527         to_read = bh->block_total_length -
1528                   (MIN_BLOCK_SIZE + block_read);    /* fixed and variable part, including padding */
1529
1530         /* Allocate enough memory to hold all options */
1531         opt_cont_buf_len = to_read;
1532         option_content = g_malloc(opt_cont_buf_len);
1533
1534         while(to_read > 0) {
1535                 /* read option */
1536                 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
1537                 if (bytes_read <= 0) {
1538                         pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
1539                         return bytes_read;
1540                 }
1541                 block_read += bytes_read;
1542                 to_read -= bytes_read;
1543
1544                 /* handle option content */
1545                 switch(oh.option_code) {
1546                     case(0): /* opt_endofopt */
1547                         if(to_read != 0) {
1548                                 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
1549                         }
1550                         /* padding should be ok here, just get out of this */
1551                         to_read = 0;
1552                         break;
1553                     case(1): /* opt_comment */
1554                         if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1555                                 wblock->data.if_stats.opt_comment = g_strndup(option_content, oh.option_length);
1556                                 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.if_stats.opt_comment);
1557                         } else {
1558                                 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
1559                         }
1560                         break;
1561                     case(2): /* isb_starttime */
1562                         if(oh.option_length == 8) {
1563                                 /*  Don't cast a char[] into a guint32--the
1564                                  *  char[] may not be aligned correctly.
1565                                  */
1566                                 memcpy(&wblock->data.if_stats.isb_starttime, option_content, sizeof(guint64));
1567                                 if(pn->byte_swapped)
1568                                         wblock->data.if_stats.isb_starttime = BSWAP64(wblock->data.if_stats.isb_starttime);
1569                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_starttime);
1570                         } else {
1571                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1572                         }
1573                         break;
1574                     case(3): /* isb_endtime */
1575                         if(oh.option_length == 8) {
1576                                 /*  Don't cast a char[] into a guint32--the
1577                                  *  char[] may not be aligned correctly.
1578                                  */
1579                                 memcpy(&wblock->data.if_stats.isb_endtime, option_content, sizeof(guint64));
1580                                 if(pn->byte_swapped)
1581                                         wblock->data.if_stats.isb_endtime = BSWAP64(wblock->data.if_stats.isb_endtime);
1582                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_endtime);
1583                         } else {
1584                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1585                         }
1586                         break;
1587                     case(4): /* isb_ifrecv */
1588                         if(oh.option_length == 8) {
1589                                 /*  Don't cast a char[] into a guint32--the
1590                                  *  char[] may not be aligned correctly.
1591                                  */
1592                                 memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
1593                                 if(pn->byte_swapped)
1594                                         wblock->data.if_stats.isb_ifrecv = BSWAP64(wblock->data.if_stats.isb_ifrecv);
1595                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifrecv);
1596                         } else {
1597                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
1598                         }
1599                         break;
1600                     case(5): /* isb_ifdrop */
1601                         if(oh.option_length == 8) {
1602                                 /*  Don't cast a char[] into a guint32--the
1603                                  *  char[] may not be aligned correctly.
1604                                  */
1605                                 memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
1606                                 if(pn->byte_swapped)
1607                                         wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_ifdrop);
1608                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifdrop);
1609                         } else {
1610                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
1611                         }
1612                         break;
1613                     case(6): /* isb_filteraccept 6 */
1614                         if(oh.option_length == 8) {
1615                                 /*  Don't cast a char[] into a guint32--the
1616                                  *  char[] may not be aligned correctly.
1617                                  */
1618                                 memcpy(&wblock->data.if_stats.isb_filteraccept, option_content, sizeof(guint64));
1619                                 if(pn->byte_swapped)
1620                                         wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_filteraccept);
1621                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_filteraccept);
1622                         } else {
1623                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
1624                         }
1625                         break;
1626                     case(7): /* isb_osdrop 7 */
1627                         if(oh.option_length == 8) {
1628                                 /*  Don't cast a char[] into a guint32--the
1629                                  *  char[] may not be aligned correctly.
1630                                  */
1631                                 memcpy(&wblock->data.if_stats.isb_osdrop, option_content, sizeof(guint64));
1632                                 if(pn->byte_swapped)
1633                                         wblock->data.if_stats.isb_osdrop = BSWAP64(wblock->data.if_stats.isb_osdrop);
1634                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_osdrop);
1635                         } else {
1636                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
1637                         }
1638                         break;
1639                     case(8): /* isb_usrdeliv 8  */
1640                         if(oh.option_length == 8) {
1641                                 /*  Don't cast a char[] into a guint32--the
1642                                  *  char[] may not be aligned correctly.
1643                                  */
1644                                 memcpy(&wblock->data.if_stats.isb_usrdeliv, option_content, sizeof(guint64));
1645                                 if(pn->byte_swapped)
1646                                         wblock->data.if_stats.isb_usrdeliv = BSWAP64(wblock->data.if_stats.isb_osdrop);
1647                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_usrdeliv);
1648                         } else {
1649                                 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
1650                         }
1651                         break;
1652                     default:
1653                         pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
1654                                       oh.option_code, oh.option_length);
1655                 }
1656         }
1657
1658         g_free(option_content);
1659
1660         return block_read;
1661 }
1662
1663
1664 static int
1665 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)
1666 {
1667         int block_read;
1668         guint64 file_offset64;
1669         guint32 block_total_length;
1670
1671         if (bh->block_total_length < MIN_BLOCK_SIZE) {
1672                 *err = WTAP_ERR_BAD_FILE;
1673                 *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",
1674                               bh->block_total_length, MIN_BLOCK_SIZE);
1675                 return -1;
1676         }
1677
1678         /* add padding bytes to "block total length" */
1679         /* (the "block total length" of some example files don't contain any padding bytes!) */
1680         if (bh->block_total_length % 4) {
1681                 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1682         } else {
1683                 block_total_length = bh->block_total_length;
1684         }
1685
1686         block_read = block_total_length - MIN_BLOCK_SIZE;
1687
1688         /* jump over this unknown block */
1689         file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
1690         if (file_offset64 <= 0) {
1691                 if (*err != 0)
1692                         return -1;
1693                 return 0;
1694         }
1695
1696         return block_read;
1697 }
1698
1699
1700 static int
1701 pcapng_read_block(FILE_T fh, gboolean first_block, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
1702 {
1703         int block_read;
1704         int bytes_read;
1705         pcapng_block_header_t bh;
1706         guint32 block_total_length;
1707
1708
1709         /* Try to read the (next) block header */
1710         errno = WTAP_ERR_CANT_READ;
1711         bytes_read = file_read(&bh, sizeof bh, fh);
1712         if (bytes_read != sizeof bh) {
1713                 *err = file_error(fh, err_info);
1714                 pcapng_debug3("pcapng_read_block: file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
1715                 if (*err != 0)
1716                         return -1;
1717                 return 0;
1718         }
1719
1720         block_read = bytes_read;
1721         if (pn->byte_swapped) {
1722                 bh.block_type         = BSWAP32(bh.block_type);
1723                 bh.block_total_length = BSWAP32(bh.block_total_length);
1724         }
1725
1726         wblock->type = bh.block_type;
1727
1728         pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
1729
1730         if (first_block) {
1731                 /*
1732                  * This is being read in by pcapng_open(), so this block
1733                  * must be an SHB.  If it's not, this is not a pcap-ng
1734                  * file.
1735                  *
1736                  * XXX - check for various forms of Windows <-> UN*X
1737                  * mangling, and suggest that the file might be a
1738                  * pcap-ng file that was damaged in transit?
1739                  */
1740                 if (bh.block_type != BLOCK_TYPE_SHB)
1741                         return 0;       /* not a pcap-ng file */
1742         }
1743
1744         switch(bh.block_type) {
1745                 case(BLOCK_TYPE_SHB):
1746                         bytes_read = pcapng_read_section_header_block(fh, first_block, &bh, pn, wblock, err, err_info);
1747                         break;
1748                 case(BLOCK_TYPE_IDB):
1749                         bytes_read = pcapng_read_if_descr_block(fh, &bh, pn, wblock, err, err_info);
1750                         break;
1751                 case(BLOCK_TYPE_PB):
1752                         bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE);
1753                         break;
1754                 case(BLOCK_TYPE_SPB):
1755                         bytes_read = pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info);
1756                         break;
1757                 case(BLOCK_TYPE_EPB):
1758                         bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
1759                         break;
1760                 case(BLOCK_TYPE_NRB):
1761                         bytes_read = pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info);
1762                         break;
1763                 case(BLOCK_TYPE_ISB):
1764                         bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
1765                         break;
1766                 default:
1767                         pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
1768                         bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
1769         }
1770
1771         if (bytes_read <= 0) {
1772                 return bytes_read;
1773         }
1774         block_read += bytes_read;
1775
1776         /* sanity check: first and second block lengths must match */
1777         errno = WTAP_ERR_CANT_READ;
1778         bytes_read = file_read(&block_total_length, sizeof block_total_length, fh);
1779         if (bytes_read != sizeof block_total_length) {
1780                 pcapng_debug0("pcapng_read_block: couldn't read second block length");
1781                 *err = file_error(fh, err_info);
1782                 if (*err == 0)
1783                         *err = WTAP_ERR_SHORT_READ;
1784                 return -1;
1785         }
1786         block_read += bytes_read;
1787
1788         if (pn->byte_swapped)
1789                 block_total_length = BSWAP32(block_total_length);
1790
1791         if (!(block_total_length == bh.block_total_length)) {
1792                 *err = WTAP_ERR_BAD_FILE;
1793                 *err_info = g_strdup_printf("pcapng_read_block: total block lengths (first %u and second %u) don't match",
1794                               bh.block_total_length, block_total_length);
1795                 return -1;
1796         }
1797
1798         return block_read;
1799 }
1800
1801
1802 /* classic wtap: open capture file */
1803 int
1804 pcapng_open(wtap *wth, int *err, gchar **err_info)
1805 {
1806         int bytes_read;
1807         pcapng_t pn;
1808         wtapng_block_t wblock;
1809         pcapng_t *pcapng;
1810         wtapng_if_descr_t int_data;
1811         interface_data_t interface_data;
1812         pcapng_block_header_t bh;
1813
1814
1815         pn.shb_read = FALSE;
1816         pn.read_idbs = TRUE;            /* IDB expected after SHB */
1817         /* we don't know the byte swapping of the file yet */
1818         pn.byte_swapped = FALSE;
1819         pn.if_fcslen = -1;
1820         pn.version_major = -1;
1821         pn.version_minor = -1;
1822         pn.interface_data = g_array_new(FALSE, FALSE, sizeof(interface_data_t));
1823         pn.number_of_interfaces = 0;
1824
1825
1826         /* we don't expect any packet blocks yet */
1827         wblock.frame_buffer = NULL;
1828         wblock.pseudo_header = NULL;
1829         wblock.packet_header = NULL;
1830         wblock.file_encap = &wth->file_encap;
1831
1832         pcapng_debug0("pcapng_open: opening file");
1833         /* read first block */
1834         bytes_read = pcapng_read_block(wth->fh, TRUE, &pn, &wblock, err, err_info);
1835         if (bytes_read <= 0) {
1836                 pcapng_debug0("pcapng_open: couldn't read first SHB");
1837                 *err = file_error(wth->fh, err_info);
1838                 if (*err != 0)
1839                         return -1;
1840                 return 0;
1841         }
1842         wth->data_offset += bytes_read;
1843
1844         /* first block must be a "Section Header Block" */
1845         if (wblock.type != BLOCK_TYPE_SHB) {
1846                 /*
1847                  * XXX - check for damage from transferring a file
1848                  * between Windows and UN*X as text rather than
1849                  * binary data?
1850                  */
1851                 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
1852                 return 0;
1853         }
1854         pn.shb_read = TRUE;
1855
1856         /*
1857          * At this point, we've decided this is a pcap-NG file, not
1858          * some other type of file, so we can't return 0, as that
1859          * means "this isn't a pcap-NG file, try some other file
1860          * type".
1861          */      
1862         wth->shb_hdr.opt_comment = wblock.data.section.opt_comment;
1863         wth->shb_hdr.shb_hardware = wblock.data.section.shb_hardware;
1864         wth->shb_hdr.shb_os = wblock.data.section.shb_os;
1865         wth->shb_hdr.shb_user_appl = wblock.data.section.shb_user_appl;
1866
1867         wth->file_encap = WTAP_ENCAP_UNKNOWN;
1868         wth->snapshot_length = 0;
1869         wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
1870         pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
1871         wth->priv = (void *)pcapng;
1872         *pcapng = pn;
1873
1874         wth->subtype_read = pcapng_read;
1875         wth->subtype_seek_read = pcapng_seek_read;
1876         wth->subtype_close = pcapng_close;
1877         wth->file_type = WTAP_FILE_PCAPNG;
1878
1879         /* Read IDBs */
1880         wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1881         wth->number_of_interfaces = 0;
1882
1883         /* Loop ower all IDB:s that appear before any packets */
1884         while(1){
1885                 bytes_read = pcapng_read_block(wth->fh, FALSE, &pn, &wblock, err, err_info);
1886                 wth->data_offset += bytes_read;
1887                 if (bytes_read == 0) {
1888                         pcapng_debug0("No more IDBs available...");
1889                         break;
1890                 }
1891                 if (bytes_read <= 0) {
1892                         pcapng_debug0("pcapng_open: couldn't read IDB");
1893                         *err = file_error(wth->fh, err_info);
1894                         if (*err == 0)
1895                                 *err = WTAP_ERR_SHORT_READ;
1896                         return -1;
1897                 }
1898
1899                 int_data.wtap_encap = wblock.data.if_descr.wtap_encap;
1900                 int_data.time_units_per_second = wblock.data.if_descr.time_units_per_second;
1901                 int_data.link_type = wblock.data.if_descr.link_type;
1902                 int_data.snap_len = wblock.data.if_descr.snap_len;
1903                 /* Options */
1904                 int_data.opt_comment = wblock.data.if_descr.opt_comment;
1905                 int_data.if_name = wblock.data.if_descr.if_name;
1906                 int_data.if_description = wblock.data.if_descr.if_description;
1907                 /* XXX: if_IPv4addr opt 4  Interface network address and netmask.*/
1908                 /* XXX: if_IPv6addr opt 5  Interface network address and prefix length (stored in the last byte).*/
1909                 /* XXX: if_MACaddr  opt 6  Interface Hardware MAC address (48 bits).*/
1910                 /* XXX: if_EUIaddr  opt 7  Interface Hardware EUI address (64 bits)*/
1911                 int_data.if_speed = wblock.data.if_descr.if_speed;
1912                 int_data.if_tsresol = wblock.data.if_descr.if_tsresol;
1913                 /* XXX: if_tzone      10  Time zone for GMT support (TODO: specify better). */
1914                 int_data.if_filter = wblock.data.if_descr.if_filter;
1915                 int_data.if_os = wblock.data.if_descr.if_os;
1916                 int_data.if_fcslen = wblock.data.if_descr.if_fcslen;
1917                 /* XXX if_tsoffset; opt 14  A 64 bits integer value that specifies an offset (in seconds)...*/
1918
1919                 g_array_append_val(wth->interface_data, int_data);
1920                 wth->number_of_interfaces++;
1921
1922                 interface_data.wtap_encap = wblock.data.if_descr.wtap_encap;
1923                 interface_data.time_units_per_second = 1000000; /* default */
1924
1925                 g_array_append_val(pcapng->interface_data, interface_data);
1926                 pcapng->number_of_interfaces++;
1927
1928                 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i", wth->number_of_interfaces, int_data.wtap_encap);
1929
1930                 /* peek at next block */
1931                 /* Try to read the (next) block header */
1932                 errno = WTAP_ERR_CANT_READ;
1933                 bytes_read = file_read(&bh, sizeof bh, wth->fh);
1934                 if (bytes_read == 0) {
1935                         pcapng_debug0("No more IDBs available...");
1936                         break;
1937                 }
1938                 if (bytes_read != sizeof bh) {
1939                         *err = file_error(wth->fh, err_info);
1940                         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);
1941                         if (*err == 0)
1942                                 *err = WTAP_ERR_SHORT_READ;
1943                         return -1;
1944                 }
1945
1946                 /* go back to where we were */
1947                 file_seek(wth->fh, wth->data_offset, SEEK_SET, err);
1948
1949                 if (pn.byte_swapped) {
1950                         bh.block_type         = BSWAP32(bh.block_type);
1951                 }
1952
1953                 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh.block_type);
1954
1955                 if (bh.block_type != BLOCK_TYPE_IDB){
1956                         break;  /* No more IDB:s */
1957                 }
1958         }
1959
1960         pcapng->read_idbs = FALSE;
1961
1962         return 1;
1963 }
1964
1965
1966 /* classic wtap: read packet */
1967 static gboolean
1968 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
1969 {
1970         pcapng_t *pcapng = (pcapng_t *)wth->priv;
1971         int bytes_read;
1972         guint64 ts;
1973         wtapng_block_t wblock;
1974
1975         pcapng_debug1("pcapng_read: wth->data_offset is initially %" G_GINT64_MODIFIER "u", wth->data_offset);
1976         *data_offset = wth->data_offset;
1977         pcapng_debug1("pcapng_read: *data_offset is initially set to %" G_GINT64_MODIFIER "u", *data_offset);
1978
1979         /* XXX - This should be done in the packet block reading function and
1980          * should make use of the caplen of the packet.
1981          */
1982         if (wth->snapshot_length > 0) {
1983                 buffer_assure_space(wth->frame_buffer, wth->snapshot_length);
1984         } else {
1985                 buffer_assure_space(wth->frame_buffer, WTAP_MAX_PACKET_SIZE);
1986         }
1987
1988         wblock.frame_buffer  = buffer_start_ptr(wth->frame_buffer);
1989         wblock.pseudo_header = &wth->pseudo_header;
1990         wblock.packet_header = &wth->phdr;
1991         wblock.file_encap    = &wth->file_encap;
1992
1993         pcapng->add_new_ipv4 = wth->add_new_ipv4;
1994         pcapng->add_new_ipv6 = wth->add_new_ipv6;
1995
1996         /* read next block */
1997         while (1) {
1998                 bytes_read = pcapng_read_block(wth->fh, FALSE, pcapng, &wblock, err, err_info);
1999                 if (bytes_read <= 0) {
2000                         wth->data_offset = *data_offset;
2001                         pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
2002                         pcapng_debug0("pcapng_read: couldn't read packet block");
2003                         return FALSE;
2004                 }
2005
2006                 /* block must be a "Packet Block" or an "Enhanced Packet Block" -> otherwise continue */
2007                 if (wblock.type == BLOCK_TYPE_PB || wblock.type == BLOCK_TYPE_EPB) {
2008                         break;
2009                 }
2010
2011                 /* XXX - improve handling of "unknown" blocks */
2012                 pcapng_debug1("pcapng_read: block type 0x%x not PB/EPB", wblock.type);
2013                 *data_offset += bytes_read;
2014                 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "u", *data_offset);
2015         }
2016
2017         /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
2018         ts = (((guint64)wblock.data.packet.ts_high) << 32) | ((guint64)wblock.data.packet.ts_low);
2019
2020         wth->phdr.caplen = wblock.data.packet.cap_len - wblock.data.packet.pseudo_header_len;
2021         wth->phdr.len = wblock.data.packet.packet_len - wblock.data.packet.pseudo_header_len;
2022         if (wblock.data.packet.interface_id < pcapng->number_of_interfaces) {
2023                 interface_data_t int_data;
2024                 guint64 time_units_per_second;
2025                 gint id;
2026
2027                 id = (gint)wblock.data.packet.interface_id;
2028                 int_data = g_array_index(pcapng->interface_data, interface_data_t, id);
2029                 time_units_per_second = int_data.time_units_per_second;
2030                 /* XXX - not WTAP_HAS_TS for an SPB */
2031                 wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
2032                 if (wblock.data.packet.opt_comment != NULL)
2033                         wth->phdr.presence_flags |= WTAP_HAS_COMMENTS;
2034                 /* XXX - only if the option is present, for an EPB */
2035                 wth->phdr.presence_flags |= WTAP_HAS_DROP_COUNT;
2036                 /* XXX - only if the option is present */
2037                 wth->phdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
2038                 wth->phdr.pkt_encap = int_data.wtap_encap;
2039                 wth->phdr.ts.secs = (time_t)(ts / time_units_per_second);
2040                 wth->phdr.ts.nsecs = (int)(((ts % time_units_per_second) * 1000000000) / time_units_per_second);
2041
2042                 wth->phdr.interface_id = wblock.data.packet.interface_id;
2043                 wth->phdr.opt_comment  = wblock.data.packet.opt_comment;
2044                 wth->phdr.drop_count   = wblock.data.packet.drop_count;
2045                 wth->phdr.pack_flags   = wblock.data.packet.pack_flags;
2046         } else {
2047                 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
2048                 *err = WTAP_ERR_BAD_FILE;
2049                 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u.",
2050                     wblock.data.packet.interface_id, pcapng->number_of_interfaces);
2051                 wth->data_offset = *data_offset + bytes_read;
2052                 pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
2053                 return FALSE;
2054         }
2055
2056         /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2057         wth->data_offset = *data_offset + bytes_read;
2058         pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
2059
2060         return TRUE;
2061 }
2062
2063
2064 /* classic wtap: seek to file position and read packet */
2065 static gboolean
2066 pcapng_seek_read(wtap *wth, gint64 seek_off,
2067     union wtap_pseudo_header *pseudo_header, guint8 *pd, int length _U_,
2068     int *err, gchar **err_info)
2069 {
2070         pcapng_t *pcapng = (pcapng_t *)wth->priv;
2071         guint64 bytes_read64;
2072         int bytes_read;
2073         wtapng_block_t wblock;
2074
2075
2076         /* seek to the right file position */
2077         bytes_read64 = file_seek(wth->random_fh, seek_off, SEEK_SET, err);
2078         if (bytes_read64 <= 0) {
2079                 return FALSE;   /* Seek error */
2080         }
2081         pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
2082
2083         wblock.frame_buffer = pd;
2084         wblock.pseudo_header = pseudo_header;
2085         wblock.packet_header = &wth->phdr;
2086         wblock.file_encap = &wth->file_encap;
2087
2088         /* read the block */
2089         bytes_read = pcapng_read_block(wth->random_fh, FALSE, pcapng, &wblock, err, err_info);
2090         if (bytes_read <= 0) {
2091                 *err = file_error(wth->random_fh, err_info);
2092                 pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
2093                               *err, errno, bytes_read);
2094                 return FALSE;
2095         }
2096
2097         /* block must be a "Packet Block" or an "Enhanced Packet Block" */
2098         if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB) {
2099                 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB", wblock.type);
2100                 return FALSE;
2101         }
2102
2103         return TRUE;
2104 }
2105
2106
2107 /* classic wtap: close capture file */
2108 static void
2109 pcapng_close(wtap *wth)
2110 {
2111         pcapng_t *pcapng = (pcapng_t *)wth->priv;
2112
2113         pcapng_debug0("pcapng_close: closing file");
2114         if (pcapng->interface_data != NULL) {
2115                 g_array_free(pcapng->interface_data, TRUE);
2116         }
2117 }
2118
2119
2120
2121 typedef struct {
2122         GArray *interface_data;
2123         guint number_of_interfaces;
2124         struct addrinfo *addrinfo_list_last;
2125 } pcapng_dump_t;
2126
2127 static gboolean
2128 pcapng_write_section_header_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2129 {
2130         pcapng_block_header_t bh;
2131         pcapng_section_header_block_t shb;
2132         const guint32 zero_pad = 0;
2133         gboolean have_options = FALSE;
2134         struct option option_hdr;                   /* guint16 type, guint16 value_length; */
2135         guint32 options_total_length = 0;
2136         guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0; 
2137         guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
2138
2139         if (wdh->shb_hdr) {
2140                 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
2141                 /* Check if we should write comment option */
2142                 if (wdh->shb_hdr->opt_comment) {
2143                         have_options = TRUE;
2144                         comment_len = (guint32)strlen(wdh->shb_hdr->opt_comment) & 0xffff;
2145                         if ((comment_len % 4)) {
2146                                 comment_pad_len = 4 - (comment_len % 4);
2147                         } else {
2148                                 comment_pad_len = 0;
2149                         }
2150                         options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2151                 }
2152
2153                 /* Check if we should write shb_hardware option */
2154                 if (wdh->shb_hdr->shb_hardware) {
2155                         have_options = TRUE;
2156                         shb_hardware_len = (guint32)strlen(wdh->shb_hdr->shb_hardware) & 0xffff;
2157                         if ((shb_hardware_len % 4)) {
2158                                 shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
2159                         } else {
2160                                 shb_hardware_pad_len = 0;
2161                         }
2162                         options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
2163                 }
2164
2165                 /* Check if we should write shb_os option */
2166                 if (wdh->shb_hdr->shb_os) {
2167                         have_options = TRUE;
2168                         shb_os_len = (guint32)strlen(wdh->shb_hdr->shb_os) & 0xffff;
2169                         if ((shb_os_len % 4)) {
2170                                 shb_os_pad_len = 4 - (shb_os_len % 4);
2171                         } else {
2172                                 shb_os_pad_len = 0;
2173                         }
2174                         options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
2175                 }
2176
2177                 /* Check if we should write shb_user_appl option */
2178                 if (wdh->shb_hdr->shb_user_appl) {
2179                         have_options = TRUE;
2180                         shb_user_appl_len = (guint32)strlen(wdh->shb_hdr->shb_user_appl) & 0xffff;
2181                         if ((shb_user_appl_len % 4)) {
2182                                 shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
2183                         } else {
2184                                 shb_user_appl_pad_len = 0;
2185                         }
2186                         options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
2187                 }
2188                 if (have_options) {
2189                         /* End-of-optios tag */
2190                         options_total_length += 4;
2191                 }
2192         }
2193
2194         /* write block header */
2195         bh.block_type = wblock->type;
2196         bh.block_total_length = sizeof(bh) + sizeof(shb) + options_total_length + 4;
2197         pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
2198
2199         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2200                 return FALSE;
2201         wdh->bytes_dumped += sizeof bh;
2202
2203         /* write block fixed content */
2204         /* XXX - get these values from wblock? */
2205         shb.magic = 0x1A2B3C4D;
2206         shb.version_major = 1;
2207         shb.version_minor = 0;
2208         shb.section_length = -1;
2209
2210         if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
2211                 return FALSE;
2212         wdh->bytes_dumped += sizeof shb;
2213
2214         /* XXX - write (optional) block options 
2215          * opt_comment  1 
2216          * shb_hardware 2
2217          * shb_os       3 
2218          * shb_user_appl 4 
2219          */
2220
2221         if (comment_len) {
2222                 option_hdr.type          = OPT_COMMENT;
2223                 option_hdr.value_length = comment_len;
2224                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2225                         return FALSE;
2226                 wdh->bytes_dumped += 4;
2227
2228                 /* Write the comments string */
2229                 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);
2230                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->opt_comment, comment_len, err))
2231                         return FALSE;
2232                 wdh->bytes_dumped += comment_len;
2233
2234                 /* write padding (if any) */
2235                 if (comment_pad_len != 0) {
2236                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2237                                 return FALSE;
2238                         wdh->bytes_dumped += comment_pad_len;
2239                 }
2240         }
2241
2242         if (shb_hardware_len) {
2243                 option_hdr.type          = OPT_SHB_HARDWARE;
2244                 option_hdr.value_length = shb_hardware_len;
2245                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2246                         return FALSE;
2247                 wdh->bytes_dumped += 4;
2248
2249                 /* Write the string */
2250                 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);
2251                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_hardware, shb_hardware_len, err))
2252                         return FALSE;
2253                 wdh->bytes_dumped += shb_hardware_len;
2254
2255                 /* write padding (if any) */
2256                 if (shb_hardware_pad_len != 0) {
2257                         if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
2258                                 return FALSE;
2259                         wdh->bytes_dumped += shb_hardware_pad_len;
2260                 }
2261         }
2262
2263         if (shb_os_len) {
2264                 option_hdr.type          = OPT_SHB_OS;
2265                 option_hdr.value_length = shb_os_len;
2266                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2267                         return FALSE;
2268                 wdh->bytes_dumped += 4;
2269
2270                 /* Write the string */
2271                 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);
2272                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_os, shb_os_len, err))
2273                         return FALSE;
2274                 wdh->bytes_dumped += shb_os_len;
2275
2276                 /* write padding (if any) */
2277                 if (shb_os_pad_len != 0) {
2278                         if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
2279                                 return FALSE;
2280                         wdh->bytes_dumped += shb_os_pad_len;
2281                 }
2282         }
2283
2284         if (shb_user_appl_len) {
2285                 option_hdr.type          = OPT_SHB_USERAPPL;
2286                 option_hdr.value_length = shb_user_appl_len;
2287                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2288                         return FALSE;
2289                 wdh->bytes_dumped += 4;
2290
2291                 /* Write the comments string */
2292                 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);
2293                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_user_appl, shb_user_appl_len, err))
2294                         return FALSE;
2295                 wdh->bytes_dumped += shb_user_appl_len;
2296
2297                 /* write padding (if any) */
2298                 if (shb_user_appl_pad_len != 0) {
2299                         if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
2300                                 return FALSE;
2301                         wdh->bytes_dumped += shb_user_appl_pad_len;
2302                 }
2303         }
2304
2305         /* Write end of options if we have otions */
2306         if (have_options) {
2307                 option_hdr.type = OPT_EOFOPT;
2308                 option_hdr.value_length = 0;
2309                 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2310                         return FALSE;
2311                 wdh->bytes_dumped += 4;
2312         }
2313
2314         /* write block footer */
2315         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2316             sizeof bh.block_total_length, err))
2317                 return FALSE;
2318         wdh->bytes_dumped += sizeof bh.block_total_length;
2319
2320         return TRUE;
2321 }
2322
2323 #define IDB_OPT_IF_NAME         2
2324 #define IDB_OPT_IF_DESCR        3
2325 #define IDB_OPT_IF_SPEED        8
2326 #define IDB_OPT_IF_TSRESOL      9
2327 #define IDB_OPT_IF_FILTER       11
2328 #define IDB_OPT_IF_OS           12
2329
2330 static gboolean
2331 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2332 {
2333         pcapng_block_header_t bh;
2334         pcapng_interface_description_block_t idb;
2335         const guint32 zero_pad = 0;
2336         gboolean have_options = FALSE;
2337         struct option option_hdr;                   /* guint16 type, guint16 value_length; */
2338         guint32 options_total_length = 0;
2339         guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0;
2340         guint32 comment_pad_len = 0, if_name_pad_len = 0, if_description_pad_len = 0, if_os_pad_len = 0;
2341
2342
2343         pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2344                       wblock->data.if_descr.link_type,
2345                       wtap_encap_string(wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type)),
2346                       wblock->data.if_descr.snap_len);
2347
2348         if (wblock->data.if_descr.link_type == (guint16)-1) {
2349                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
2350                 return FALSE;
2351         }
2352
2353         /* Calculate options length */
2354         if (wblock->data.if_descr.opt_comment) {
2355                 have_options = TRUE;
2356                 comment_len = (guint32)strlen(wblock->data.if_descr.opt_comment) & 0xffff;
2357                 if ((comment_len % 4)){
2358                         comment_pad_len = 4 - (comment_len % 4);
2359                 } else {
2360                         comment_pad_len = 0;
2361                 }
2362                 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2363         }
2364
2365         /*
2366          * if_name        2  A UTF-8 string containing the name of the device used to capture data. 
2367          */
2368         if (wblock->data.if_descr.if_name){
2369                 have_options = TRUE;
2370                 if_name_len = (guint32)strlen(wblock->data.if_descr.if_name) & 0xffff;
2371                 if ((if_name_len % 4)) {
2372                         if_name_pad_len = 4 - (if_name_len % 4);
2373                 } else {
2374                         if_name_pad_len = 0;
2375                 }
2376                 options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
2377         }
2378
2379         /*
2380          * if_description 3  A UTF-8 string containing the description of the device used to capture data. 
2381          */
2382         if (wblock->data.if_descr.if_description) {
2383                 have_options = TRUE;
2384                 if_name_len = (guint32)strlen(wblock->data.if_descr.if_description) & 0xffff;
2385                 if ((if_description_len % 4)) {
2386                         if_description_pad_len = 4 - (if_description_len % 4);
2387                 } else {
2388                         if_description_pad_len = 0;
2389                 }
2390                 options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
2391         }
2392         /* Currently not handled
2393          * if_IPv4addr    4  Interface network address and netmask.
2394          * if_IPv6addr    5  Interface network address and prefix length (stored in the last byte). 
2395          * if_MACaddr     6  Interface Hardware MAC address (48 bits). 00 01 02 03 04 05 
2396          * if_EUIaddr     7  Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2397          */
2398         /*
2399          * if_speed       8  Interface speed (in bps). 100000000 for 100Mbps 
2400          */
2401         if (wblock->data.if_descr.if_speed != 0) {
2402                 have_options = TRUE;
2403                 options_total_length = options_total_length + 8 + 4;
2404         }
2405         /*
2406          * if_tsresol     9  Resolution of timestamps.
2407          */
2408         if (wblock->data.if_descr.if_tsresol != 0) {
2409                 have_options = TRUE;
2410                 options_total_length = options_total_length + 4 + 4;
2411         }
2412         /* Not used
2413          * if_tzone      10  Time zone for GMT support (TODO: specify better). TODO: give a good example 
2414          */
2415         /*
2416          * if_filter     11  The filter (e.g. "capture only TCP traffic") used to capture traffic. 
2417          */
2418         if (wblock->data.if_descr.if_filter) {
2419         }
2420         /*
2421          * if_os         12  A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. 
2422          */
2423         if (wblock->data.if_descr.if_os) {
2424                 have_options = TRUE;
2425                 if_os_len = (guint32)strlen(wblock->data.if_descr.if_os) & 0xffff;
2426                 if ((if_os_len % 4)) {
2427                         if_os_pad_len = 4 - (if_os_len % 4);
2428                 } else {
2429                         if_os_pad_len = 0;
2430                 }
2431                 options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
2432         }
2433         /*
2434          * if_fcslen     13  An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. 
2435          */
2436         if (wblock->data.if_descr.opt_comment) {
2437         }
2438         /* Not used
2439          * if_tsoffset   14  A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet 
2440          * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2441          */
2442
2443         if (have_options) {
2444                 /* End-of-optios tag */
2445                 options_total_length += 4;
2446         }
2447
2448         /* write block header */
2449         bh.block_type = wblock->type;
2450         bh.block_total_length = sizeof(bh) + sizeof(idb) + options_total_length + 4;
2451
2452         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2453                 return FALSE;
2454         wdh->bytes_dumped += sizeof bh;
2455
2456         /* write block fixed content */
2457         idb.linktype    = wblock->data.if_descr.link_type;
2458         idb.reserved    = 0;
2459         idb.snaplen     = wblock->data.if_descr.snap_len;
2460
2461         if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
2462                 return FALSE;
2463         wdh->bytes_dumped += sizeof idb;
2464
2465         /* XXX - write (optional) block options */
2466         if (comment_len) {
2467                 option_hdr.type          = OPT_COMMENT;
2468                 option_hdr.value_length = comment_len;
2469                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2470                         return FALSE;
2471                 wdh->bytes_dumped += 4;
2472
2473                 /* Write the comments string */
2474                 pcapng_debug3("pcapng_write_if_descr_block, comment:'%s' comment_len %u comment_pad_len %u" , wblock->data.if_descr.opt_comment, comment_len, comment_pad_len);
2475                 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.opt_comment, comment_len, err))
2476                         return FALSE;
2477                 wdh->bytes_dumped += comment_len;
2478
2479                 /* write padding (if any) */
2480                 if (comment_pad_len != 0) {
2481                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2482                                 return FALSE;
2483                         wdh->bytes_dumped += comment_pad_len;
2484                 }
2485         }
2486         /*
2487          * if_name        2  A UTF-8 string containing the name of the device used to capture data.
2488          */
2489         if (if_name_len) {
2490                 option_hdr.type = IDB_OPT_IF_NAME;
2491                 option_hdr.value_length = if_name_len;
2492                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2493                         return FALSE;
2494                 wdh->bytes_dumped += 4;
2495
2496                 /* Write the comments string */
2497                 pcapng_debug3("pcapng_write_if_descr_block, if_name:'%s' if_name_len %u if_name_pad_len %u" , wblock->data.if_descr.if_name, if_name_len, if_name_pad_len);
2498                 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_name, if_name_len, err))
2499                         return FALSE;
2500                 wdh->bytes_dumped += if_name_len;
2501
2502                 /* write padding (if any) */
2503                 if (if_name_pad_len != 0) {
2504                         if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
2505                                 return FALSE;
2506                         wdh->bytes_dumped += if_name_pad_len;
2507                 }
2508         }
2509         /*
2510          * if_description 3  A UTF-8 string containing the description of the device used to capture data. 
2511          */
2512         if (if_description_len) {
2513                 option_hdr.type          = IDB_OPT_IF_NAME;
2514                 option_hdr.value_length = if_description_len;
2515                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2516                         return FALSE;
2517                 wdh->bytes_dumped += 4;
2518
2519                 /* Write the comments string */
2520                 pcapng_debug3("pcapng_write_if_descr_block, if_description:'%s' if_description_len %u if_description_pad_len %u" , wblock->data.if_descr.if_description, if_description_len, if_description_pad_len);
2521                 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_description, if_description_len, err))
2522                         return FALSE;
2523                 wdh->bytes_dumped += comment_len;
2524
2525                 /* write padding (if any) */
2526                 if (if_description_pad_len != 0) {
2527                         if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
2528                                 return FALSE;
2529                         wdh->bytes_dumped += if_description_pad_len;
2530                 }
2531         }
2532         /* Currently not handled
2533          * if_IPv4addr    4  Interface network address and netmask.
2534          * if_IPv6addr    5  Interface network address and prefix length (stored in the last byte). 
2535          * if_MACaddr     6  Interface Hardware MAC address (48 bits). 00 01 02 03 04 05 
2536          * if_EUIaddr     7  Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2537          */
2538         /*
2539          * if_speed       8  Interface speed (in bps). 100000000 for 100Mbps 
2540          */
2541         if (wblock->data.if_descr.if_speed != 0) {
2542                 printf("HJKHJHK\n");
2543                 option_hdr.type          = IDB_OPT_IF_SPEED;
2544                 option_hdr.value_length = 8;
2545                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2546                         return FALSE;
2547                 wdh->bytes_dumped += 4;
2548
2549                 /* Write the comments string */
2550                 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
2551                 if (!wtap_dump_file_write(wdh, &wblock->data.if_descr.if_speed, sizeof(guint64), err))
2552                         return FALSE;
2553                 wdh->bytes_dumped += 8;
2554         }
2555         /*
2556          * if_tsresol     9  Resolution of timestamps.
2557          */
2558         if (wblock->data.if_descr.if_tsresol != 0) {
2559                 option_hdr.type          = IDB_OPT_IF_TSRESOL;
2560                 option_hdr.value_length = 1;
2561                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2562                         return FALSE;
2563                 wdh->bytes_dumped += 4;
2564
2565                 /* Write the comments string */
2566                 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", wblock->data.if_descr.if_tsresol);
2567                 if (!wtap_dump_file_write(wdh, &wblock->data.if_descr.if_tsresol, 1, err))
2568                         return FALSE;
2569                 wdh->bytes_dumped += 1;
2570                 if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
2571                         return FALSE;
2572                 wdh->bytes_dumped += 3;
2573         }
2574         /* not used
2575          * if_tzone      10  Time zone for GMT support (TODO: specify better). TODO: give a good example 
2576          */
2577         /*
2578          * if_filter     11  The filter (e.g. "capture only TCP traffic") used to capture traffic. 
2579          */
2580         /*
2581          * if_os         12  A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. 
2582          */
2583         if (if_os_len) {
2584                 option_hdr.type          = IDB_OPT_IF_OS;
2585                 option_hdr.value_length = if_os_len;
2586                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2587                         return FALSE;
2588                 wdh->bytes_dumped += 4;
2589
2590                 /* Write the comments string */
2591                 pcapng_debug3("pcapng_write_if_descr_block, if_os:'%s' if_os_len %u if_os_pad_len %u" , wblock->data.if_descr.if_os, if_os_len, if_os_pad_len);
2592                 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_os, if_os_len, err))
2593                         return FALSE;
2594                 wdh->bytes_dumped += comment_len;
2595
2596                 /* write padding (if any) */
2597                 if (if_os_pad_len != 0) {
2598                         if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
2599                                 return FALSE;
2600                         wdh->bytes_dumped += if_os_pad_len;
2601                 }
2602         }
2603
2604         if (have_options) {
2605                 option_hdr.type = OPT_EOFOPT;
2606                 option_hdr.value_length = 0;
2607                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2608                         return FALSE;
2609                 wdh->bytes_dumped += 4;
2610         }
2611
2612         /*
2613          * if_fcslen     13  An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. 
2614          */
2615         /*
2616          * if_tsoffset   14  A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet 
2617          * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2618          */
2619
2620         /* write block footer */
2621         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2622             sizeof bh.block_total_length, err))
2623                 return FALSE;
2624         wdh->bytes_dumped += sizeof bh.block_total_length;
2625
2626         return TRUE;
2627 }
2628
2629 static gboolean
2630 pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2631 {
2632
2633         pcapng_block_header_t bh;
2634         pcapng_interface_statistics_block_t isb;
2635         const guint32 zero_pad = 0;
2636         gboolean have_options = FALSE;
2637         struct option option_hdr;                   /* guint16 type, guint16 value_length; */
2638         guint32 options_total_length = 0;
2639         guint32 comment_len = 0;
2640         guint32 comment_pad_len = 0;
2641
2642         pcapng_debug0("pcapng_write_interface_statistics_block");
2643
2644
2645         /* Calculate options length */
2646         if (wblock->data.if_descr.opt_comment) {
2647                 have_options = TRUE;
2648                 comment_len = (guint32)strlen(wblock->data.if_descr.opt_comment) & 0xffff;
2649                 if ((comment_len % 4)){
2650                         comment_pad_len = 4 - (comment_len % 4);
2651                 } else {
2652                         comment_pad_len = 0;
2653                 }
2654                 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2655         }
2656         /* XXX */
2657         /*guint32                       isb_starttime_high;*/
2658         /*guint32                       isb_starttime_low;*/
2659         /*guint32                       isb_endtime_high;*/
2660         /*guint32                       isb_endtime_low;*/
2661         /*guint64                               isb_ifrecv;*/
2662         /*guint64                               isb_ifdrop;*/
2663         /*guint64                       isb_filteraccept;*/
2664         /*guint64                       isb_osdrop;*/
2665         /*guint64                       isb_usrdeliv;*/
2666
2667
2668         /* write block header */
2669         if (have_options) {
2670                 /* End-of-optios tag */
2671                 options_total_length += 4;
2672         }
2673
2674         /* write block header */
2675         bh.block_type = wblock->type;
2676         bh.block_total_length = sizeof(bh) + sizeof(isb) + options_total_length + 4;
2677
2678         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2679                 return FALSE;
2680         wdh->bytes_dumped += sizeof bh;
2681
2682         /* write block fixed content */
2683         isb.interface_id                = wblock->data.if_stats.interface_id;
2684         isb.timestamp_high              = wblock->data.if_stats.ts_high;
2685         isb.timestamp_low               = wblock->data.if_stats.ts_low;
2686
2687
2688         if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
2689                 return FALSE;
2690         wdh->bytes_dumped += sizeof isb;
2691
2692         /* write (optional) block options */
2693         if (comment_len) {
2694                 option_hdr.type          = OPT_COMMENT;
2695                 option_hdr.value_length = comment_len;
2696                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2697                         return FALSE;
2698                 wdh->bytes_dumped += 4;
2699
2700                 /* Write the comments string */
2701                 pcapng_debug3("pcapng_write_if_descr_block, comment:'%s' comment_len %u comment_pad_len %u" , wblock->data.if_descr.opt_comment, comment_len, comment_pad_len);
2702                 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.opt_comment, comment_len, err))
2703                         return FALSE;
2704                 wdh->bytes_dumped += comment_len;
2705
2706                 /* write padding (if any) */
2707                 if (comment_pad_len != 0) {
2708                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2709                                 return FALSE;
2710                         wdh->bytes_dumped += comment_pad_len;
2711                 }
2712         }
2713         /* XXX */
2714         /*guint32                       isb_starttime */
2715         /*guint32                       isb_endtime */
2716         /*guint64                       isb_ifrecv;*/
2717         /*guint64                       isb_ifdrop;*/
2718         /*guint64                       isb_filteraccept;*/
2719         /*guint64                       isb_osdrop;*/
2720         /*guint64                       isb_usrdeliv;*/
2721
2722         if (have_options) {
2723                 option_hdr.type = OPT_EOFOPT;
2724                 option_hdr.value_length = 0;
2725                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2726                         return FALSE;
2727                 wdh->bytes_dumped += 4;
2728         }
2729
2730         /* write block footer */
2731         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2732             sizeof bh.block_total_length, err))
2733                 return FALSE;
2734         wdh->bytes_dumped += sizeof bh.block_total_length;
2735
2736         return TRUE;
2737
2738 }
2739
2740
2741 static gboolean
2742 pcapng_write_packet_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2743 {
2744         pcapng_block_header_t bh;
2745         pcapng_enhanced_packet_block_t epb;
2746         const guint32 zero_pad = 0;
2747         guint32 pad_len;
2748         guint32 phdr_len;
2749         gboolean have_options = FALSE;
2750         guint32 options_total_length = 0;
2751         guint32 options_hdr = 0; 
2752         guint32 comment_len = 0, comment_pad_len = 0;
2753
2754         phdr_len = (guint32)pcap_get_phdr_size(wblock->data.packet.wtap_encap, wblock->pseudo_header);
2755         if ((phdr_len + wblock->data.packet.cap_len) % 4) {
2756                 pad_len = 4 - ((phdr_len + wblock->data.packet.cap_len) % 4);
2757         } else {
2758                 pad_len = 0;
2759         }
2760
2761         /* Check if we should write comment option */
2762         if(wblock->data.packet.opt_comment){
2763                 have_options = TRUE;
2764                 comment_len = (guint32)strlen(wblock->data.packet.opt_comment) & 0xffff;
2765                 if((comment_len % 4)){
2766                         comment_pad_len = 4 - (comment_len % 4);
2767                 }else{
2768                         comment_pad_len = 0;
2769                 }
2770                 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2771         }
2772
2773         if(have_options){
2774                 /* End-of optios tag */
2775                 options_total_length += 4;
2776         }
2777
2778
2779         /* write (enhanced) packet block header */
2780         bh.block_type = wblock->type;
2781         bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + wblock->data.packet.cap_len + pad_len + options_total_length + 4;
2782
2783         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2784                 return FALSE;
2785         wdh->bytes_dumped += sizeof bh;
2786
2787         /* write block fixed content */
2788         epb.interface_id        = wblock->data.packet.interface_id;
2789         epb.timestamp_high      = wblock->data.packet.ts_high;
2790         epb.timestamp_low       = wblock->data.packet.ts_low;
2791         epb.captured_len        = wblock->data.packet.cap_len + phdr_len;
2792         epb.packet_len          = wblock->data.packet.packet_len + phdr_len;
2793
2794         if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
2795                 return FALSE;
2796         wdh->bytes_dumped += sizeof epb;
2797
2798         /* write pseudo header */
2799         if (!pcap_write_phdr(wdh, wblock->data.packet.wtap_encap, wblock->pseudo_header, err)) {
2800                 return FALSE;
2801         }
2802         wdh->bytes_dumped += phdr_len;
2803
2804         /* write packet data */
2805         if (!wtap_dump_file_write(wdh, wblock->frame_buffer,
2806             wblock->data.packet.cap_len, err))
2807                 return FALSE;
2808         wdh->bytes_dumped += wblock->data.packet.cap_len;
2809
2810         /* write padding (if any) */
2811         if (pad_len != 0) {
2812                 if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
2813                         return FALSE;
2814                 wdh->bytes_dumped += pad_len;
2815         }
2816
2817         /* XXX - write (optional) block options */
2818         /* options defined in Section 2.5 (Options) 
2819          * Name           Code Length     Description 
2820          * opt_comment    1    variable   A UTF-8 string containing a comment that is associated to the current block. 
2821          *
2822          * Enhanced Packet Block options
2823          * epb_flags      2    4          A flags word containing link-layer information. A complete specification of 
2824          *                                the allowed flags can be found in Appendix A (Packet Block Flags Word). 
2825          * epb_hash       3    variable   This option contains a hash of the packet. The first byte specifies the hashing algorithm, 
2826          *                                while the following bytes contain the actual hash, whose size depends on the hashing algorithm, 
2827          *                                                                and hence from the value in the first bit. The hashing algorithm can be: 2s complement 
2828          *                                                                (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4), 
2829          *                                                                MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX). 
2830          *                                                                The hash covers only the packet, not the header added by the capture driver: 
2831          *                                                                this gives the possibility to calculate it inside the network card. 
2832          *                                                                The hash allows easier comparison/merging of different capture files, and reliable data transfer between the 
2833          *                                                                data acquisition system and the capture library. 
2834          * epb_dropcount   4   8          A 64bit integer value specifying the number of packets lost (by the interface and the operating system) 
2835          *                                between this packet and the preceding one.
2836          * opt_endofopt    0   0          It delimits the end of the optional fields. This block cannot be repeated within a given list of options. 
2837          */
2838         if(wblock->data.packet.opt_comment){
2839                 options_hdr = comment_len;
2840                 options_hdr = options_hdr << 16;
2841                 /* Option 1  */
2842                 options_hdr += 1;
2843                 if (!wtap_dump_file_write(wdh, &options_hdr, 4, err))
2844                         return FALSE;
2845                 wdh->bytes_dumped += 4;
2846
2847                 /* Write the comments string */
2848                 pcapng_debug3("pcapng_write_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , wblock->data.packet.opt_comment, comment_len, comment_pad_len);
2849                 if (!wtap_dump_file_write(wdh, wblock->data.packet.opt_comment, comment_len, err))
2850                         return FALSE;
2851                 wdh->bytes_dumped += comment_len;
2852
2853                 /* write padding (if any) */
2854                 if (comment_pad_len != 0) {
2855                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2856                                 return FALSE;
2857                         wdh->bytes_dumped += comment_pad_len;
2858                 }
2859
2860                 pcapng_debug2("pcapng_write_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
2861                         comment_len,
2862                         comment_pad_len);
2863         }
2864
2865         /* Write end of options if we have otions */
2866         if(have_options){
2867                 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2868                         return FALSE;
2869                 wdh->bytes_dumped += 4;
2870         }
2871
2872         /* write block footer */
2873         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2874             sizeof bh.block_total_length, err))
2875                 return FALSE;
2876         wdh->bytes_dumped += sizeof bh.block_total_length;
2877
2878         return TRUE;