Fix typo introduced by previous checkin.
[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 is too small (< %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 %" G_GINT64_MODIFIER "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 _U_)
1666 {
1667         int block_read;
1668         guint64 file_offset64;
1669         guint32 block_total_length;
1670
1671
1672         /* add padding bytes to "block total length" */
1673         /* (the "block total length" of some example files don't contain any padding bytes!) */
1674         if (bh->block_total_length % 4) {
1675                 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1676         } else {
1677                 block_total_length = bh->block_total_length;
1678         }
1679
1680         block_read = block_total_length - MIN_BLOCK_SIZE;
1681
1682         /* jump over this unknown block */
1683         file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
1684         if (file_offset64 <= 0) {
1685                 if (*err != 0)
1686                         return -1;
1687                 return 0;
1688         }
1689
1690         return block_read;
1691 }
1692
1693
1694 static int
1695 pcapng_read_block(FILE_T fh, gboolean first_block, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
1696 {
1697         int block_read;
1698         int bytes_read;
1699         pcapng_block_header_t bh;
1700         guint32 block_total_length;
1701
1702
1703         /* Try to read the (next) block header */
1704         errno = WTAP_ERR_CANT_READ;
1705         bytes_read = file_read(&bh, sizeof bh, fh);
1706         if (bytes_read != sizeof bh) {
1707                 *err = file_error(fh, err_info);
1708                 pcapng_debug3("pcapng_read_block: file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
1709                 if (*err != 0)
1710                         return -1;
1711                 return 0;
1712         }
1713
1714         block_read = bytes_read;
1715         if (pn->byte_swapped) {
1716                 bh.block_type         = BSWAP32(bh.block_type);
1717                 bh.block_total_length = BSWAP32(bh.block_total_length);
1718         }
1719
1720         wblock->type = bh.block_type;
1721
1722         pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
1723
1724         if (first_block) {
1725                 /*
1726                  * This is being read in by pcapng_open(), so this block
1727                  * must be an SHB.  If it's not, this is not a pcap-ng
1728                  * file.
1729                  *
1730                  * XXX - check for various forms of Windows <-> UN*X
1731                  * mangling, and suggest that the file might be a
1732                  * pcap-ng file that was damaged in transit?
1733                  */
1734                 if (bh.block_type != BLOCK_TYPE_SHB)
1735                         return 0;       /* not a pcap-ng file */
1736         }
1737
1738         if (bh.block_total_length < MIN_BLOCK_SIZE) {
1739                 /*
1740                  * This isn't even enough for the block type and 2
1741                  * block total length fields.
1742                  */
1743                 if (first_block)
1744                         return 0;       /* probably not a pcap-ng file */
1745                 *err = WTAP_ERR_BAD_FILE;
1746                 *err_info = g_strdup_printf("pcapng_read_block: total block length %u is too small (< %u)",
1747                               bh.block_total_length, (guint32)MIN_BLOCK_SIZE);
1748                 return -1;
1749         }
1750
1751         switch(bh.block_type) {
1752                 case(BLOCK_TYPE_SHB):
1753                         bytes_read = pcapng_read_section_header_block(fh, first_block, &bh, pn, wblock, err, err_info);
1754                         break;
1755                 case(BLOCK_TYPE_IDB):
1756                         bytes_read = pcapng_read_if_descr_block(fh, &bh, pn, wblock, err, err_info);
1757                         break;
1758                 case(BLOCK_TYPE_PB):
1759                         bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE);
1760                         break;
1761                 case(BLOCK_TYPE_SPB):
1762                         bytes_read = pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info);
1763                         break;
1764                 case(BLOCK_TYPE_EPB):
1765                         bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
1766                         break;
1767                 case(BLOCK_TYPE_NRB):
1768                         bytes_read = pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info);
1769                         break;
1770                 case(BLOCK_TYPE_ISB):
1771                         bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
1772                         break;
1773                 default:
1774                         pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
1775                         bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
1776         }
1777
1778         if (bytes_read <= 0) {
1779                 return bytes_read;
1780         }
1781         block_read += bytes_read;
1782
1783         /* sanity check: first and second block lengths must match */
1784         errno = WTAP_ERR_CANT_READ;
1785         bytes_read = file_read(&block_total_length, sizeof block_total_length, fh);
1786         if (bytes_read != sizeof block_total_length) {
1787                 pcapng_debug0("pcapng_read_block: couldn't read second block length");
1788                 *err = file_error(fh, err_info);
1789                 if (*err == 0)
1790                         *err = WTAP_ERR_SHORT_READ;
1791                 return -1;
1792         }
1793         block_read += bytes_read;
1794
1795         if (pn->byte_swapped)
1796                 block_total_length = BSWAP32(block_total_length);
1797
1798         if (!(block_total_length == bh.block_total_length)) {
1799                 *err = WTAP_ERR_BAD_FILE;
1800                 *err_info = g_strdup_printf("pcapng_read_block: total block lengths (first %u and second %u) don't match",
1801                               bh.block_total_length, block_total_length);
1802                 return -1;
1803         }
1804
1805         return block_read;
1806 }
1807
1808
1809 /* classic wtap: open capture file */
1810 int
1811 pcapng_open(wtap *wth, int *err, gchar **err_info)
1812 {
1813         int bytes_read;
1814         pcapng_t pn;
1815         wtapng_block_t wblock;
1816         pcapng_t *pcapng;
1817         wtapng_if_descr_t int_data;
1818         interface_data_t interface_data;
1819         pcapng_block_header_t bh;
1820
1821
1822         pn.shb_read = FALSE;
1823         pn.read_idbs = TRUE;            /* IDB expected after SHB */
1824         /* we don't know the byte swapping of the file yet */
1825         pn.byte_swapped = FALSE;
1826         pn.if_fcslen = -1;
1827         pn.version_major = -1;
1828         pn.version_minor = -1;
1829         pn.interface_data = g_array_new(FALSE, FALSE, sizeof(interface_data_t));
1830         pn.number_of_interfaces = 0;
1831
1832
1833         /* we don't expect any packet blocks yet */
1834         wblock.frame_buffer = NULL;
1835         wblock.pseudo_header = NULL;
1836         wblock.packet_header = NULL;
1837         wblock.file_encap = &wth->file_encap;
1838
1839         pcapng_debug0("pcapng_open: opening file");
1840         /* read first block */
1841         bytes_read = pcapng_read_block(wth->fh, TRUE, &pn, &wblock, err, err_info);
1842         if (bytes_read <= 0) {
1843                 pcapng_debug0("pcapng_open: couldn't read first SHB");
1844                 *err = file_error(wth->fh, err_info);
1845                 if (*err != 0)
1846                         return -1;
1847                 return 0;
1848         }
1849         wth->data_offset += bytes_read;
1850
1851         /* first block must be a "Section Header Block" */
1852         if (wblock.type != BLOCK_TYPE_SHB) {
1853                 /*
1854                  * XXX - check for damage from transferring a file
1855                  * between Windows and UN*X as text rather than
1856                  * binary data?
1857                  */
1858                 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
1859                 return 0;
1860         }
1861         pn.shb_read = TRUE;
1862
1863         /*
1864          * At this point, we've decided this is a pcap-NG file, not
1865          * some other type of file, so we can't return 0, as that
1866          * means "this isn't a pcap-NG file, try some other file
1867          * type".
1868          */      
1869         wth->shb_hdr.opt_comment = wblock.data.section.opt_comment;
1870         wth->shb_hdr.shb_hardware = wblock.data.section.shb_hardware;
1871         wth->shb_hdr.shb_os = wblock.data.section.shb_os;
1872         wth->shb_hdr.shb_user_appl = wblock.data.section.shb_user_appl;
1873
1874         wth->file_encap = WTAP_ENCAP_UNKNOWN;
1875         wth->snapshot_length = 0;
1876         wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
1877         pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
1878         wth->priv = (void *)pcapng;
1879         *pcapng = pn;
1880
1881         wth->subtype_read = pcapng_read;
1882         wth->subtype_seek_read = pcapng_seek_read;
1883         wth->subtype_close = pcapng_close;
1884         wth->file_type = WTAP_FILE_PCAPNG;
1885
1886         /* Read IDBs */
1887         wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1888         wth->number_of_interfaces = 0;
1889
1890         /* Loop ower all IDB:s that appear before any packets */
1891         while(1){
1892                 bytes_read = pcapng_read_block(wth->fh, FALSE, &pn, &wblock, err, err_info);
1893                 wth->data_offset += bytes_read;
1894                 if (bytes_read == 0) {
1895                         pcapng_debug0("No more IDBs available...");
1896                         break;
1897                 }
1898                 if (bytes_read <= 0) {
1899                         pcapng_debug0("pcapng_open: couldn't read IDB");
1900                         *err = file_error(wth->fh, err_info);
1901                         if (*err == 0)
1902                                 *err = WTAP_ERR_SHORT_READ;
1903                         return -1;
1904                 }
1905
1906                 int_data.wtap_encap = wblock.data.if_descr.wtap_encap;
1907                 int_data.time_units_per_second = wblock.data.if_descr.time_units_per_second;
1908                 int_data.link_type = wblock.data.if_descr.link_type;
1909                 int_data.snap_len = wblock.data.if_descr.snap_len;
1910                 /* Options */
1911                 int_data.opt_comment = wblock.data.if_descr.opt_comment;
1912                 int_data.if_name = wblock.data.if_descr.if_name;
1913                 int_data.if_description = wblock.data.if_descr.if_description;
1914                 /* XXX: if_IPv4addr opt 4  Interface network address and netmask.*/
1915                 /* XXX: if_IPv6addr opt 5  Interface network address and prefix length (stored in the last byte).*/
1916                 /* XXX: if_MACaddr  opt 6  Interface Hardware MAC address (48 bits).*/
1917                 /* XXX: if_EUIaddr  opt 7  Interface Hardware EUI address (64 bits)*/
1918                 int_data.if_speed = wblock.data.if_descr.if_speed;
1919                 int_data.if_tsresol = wblock.data.if_descr.if_tsresol;
1920                 /* XXX: if_tzone      10  Time zone for GMT support (TODO: specify better). */
1921                 int_data.if_filter = wblock.data.if_descr.if_filter;
1922                 int_data.if_os = wblock.data.if_descr.if_os;
1923                 int_data.if_fcslen = wblock.data.if_descr.if_fcslen;
1924                 /* XXX if_tsoffset; opt 14  A 64 bits integer value that specifies an offset (in seconds)...*/
1925
1926                 g_array_append_val(wth->interface_data, int_data);
1927                 wth->number_of_interfaces++;
1928
1929                 interface_data.wtap_encap = wblock.data.if_descr.wtap_encap;
1930                 interface_data.time_units_per_second = 1000000; /* default */
1931
1932                 g_array_append_val(pcapng->interface_data, interface_data);
1933                 pcapng->number_of_interfaces++;
1934
1935                 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i", wth->number_of_interfaces, int_data.wtap_encap);
1936
1937                 /* peek at next block */
1938                 /* Try to read the (next) block header */
1939                 errno = WTAP_ERR_CANT_READ;
1940                 bytes_read = file_read(&bh, sizeof bh, wth->fh);
1941                 if (bytes_read == 0) {
1942                         pcapng_debug0("No more IDBs available...");
1943                         break;
1944                 }
1945                 if (bytes_read != sizeof bh) {
1946                         *err = file_error(wth->fh, err_info);
1947                         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);
1948                         if (*err == 0)
1949                                 *err = WTAP_ERR_SHORT_READ;
1950                         return -1;
1951                 }
1952
1953                 /* go back to where we were */
1954                 file_seek(wth->fh, wth->data_offset, SEEK_SET, err);
1955
1956                 if (pn.byte_swapped) {
1957                         bh.block_type         = BSWAP32(bh.block_type);
1958                 }
1959
1960                 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh.block_type);
1961
1962                 if (bh.block_type != BLOCK_TYPE_IDB){
1963                         break;  /* No more IDB:s */
1964                 }
1965         }
1966
1967         pcapng->read_idbs = FALSE;
1968
1969         return 1;
1970 }
1971
1972
1973 /* classic wtap: read packet */
1974 static gboolean
1975 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
1976 {
1977         pcapng_t *pcapng = (pcapng_t *)wth->priv;
1978         int bytes_read;
1979         guint64 ts;
1980         wtapng_block_t wblock;
1981
1982         pcapng_debug1("pcapng_read: wth->data_offset is initially %" G_GINT64_MODIFIER "u", wth->data_offset);
1983         *data_offset = wth->data_offset;
1984         pcapng_debug1("pcapng_read: *data_offset is initially set to %" G_GINT64_MODIFIER "u", *data_offset);
1985
1986         /* XXX - This should be done in the packet block reading function and
1987          * should make use of the caplen of the packet.
1988          */
1989         if (wth->snapshot_length > 0) {
1990                 buffer_assure_space(wth->frame_buffer, wth->snapshot_length);
1991         } else {
1992                 buffer_assure_space(wth->frame_buffer, WTAP_MAX_PACKET_SIZE);
1993         }
1994
1995         wblock.frame_buffer  = buffer_start_ptr(wth->frame_buffer);
1996         wblock.pseudo_header = &wth->pseudo_header;
1997         wblock.packet_header = &wth->phdr;
1998         wblock.file_encap    = &wth->file_encap;
1999
2000         pcapng->add_new_ipv4 = wth->add_new_ipv4;
2001         pcapng->add_new_ipv6 = wth->add_new_ipv6;
2002
2003         /* read next block */
2004         while (1) {
2005                 bytes_read = pcapng_read_block(wth->fh, FALSE, pcapng, &wblock, err, err_info);
2006                 if (bytes_read <= 0) {
2007                         wth->data_offset = *data_offset;
2008                         pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
2009                         pcapng_debug0("pcapng_read: couldn't read packet block");
2010                         return FALSE;
2011                 }
2012
2013                 /* block must be a "Packet Block" or an "Enhanced Packet Block" -> otherwise continue */
2014                 if (wblock.type == BLOCK_TYPE_PB || wblock.type == BLOCK_TYPE_EPB) {
2015                         break;
2016                 }
2017
2018                 /* XXX - improve handling of "unknown" blocks */
2019                 pcapng_debug1("pcapng_read: block type 0x%x not PB/EPB", wblock.type);
2020                 *data_offset += bytes_read;
2021                 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "u", *data_offset);
2022         }
2023
2024         /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
2025         ts = (((guint64)wblock.data.packet.ts_high) << 32) | ((guint64)wblock.data.packet.ts_low);
2026
2027         wth->phdr.caplen = wblock.data.packet.cap_len - wblock.data.packet.pseudo_header_len;
2028         wth->phdr.len = wblock.data.packet.packet_len - wblock.data.packet.pseudo_header_len;
2029         if (wblock.data.packet.interface_id < pcapng->number_of_interfaces) {
2030                 interface_data_t int_data;
2031                 guint64 time_units_per_second;
2032                 gint id;
2033
2034                 id = (gint)wblock.data.packet.interface_id;
2035                 int_data = g_array_index(pcapng->interface_data, interface_data_t, id);
2036                 time_units_per_second = int_data.time_units_per_second;
2037                 wth->phdr.pkt_encap = int_data.wtap_encap;
2038                 wth->phdr.ts.secs = (time_t)(ts / time_units_per_second);
2039                 wth->phdr.ts.nsecs = (int)(((ts % time_units_per_second) * 1000000000) / time_units_per_second);
2040
2041                 wth->phdr.interface_id = wblock.data.packet.interface_id;
2042                 wth->phdr.opt_comment  = wblock.data.packet.opt_comment;
2043                 wth->phdr.drop_count   = wblock.data.packet.drop_count;
2044                 wth->phdr.pack_flags   = wblock.data.packet.pack_flags;
2045         } else {
2046                 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
2047                 *err = WTAP_ERR_BAD_FILE;
2048                 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u.",
2049                     wblock.data.packet.interface_id, pcapng->number_of_interfaces);
2050                 wth->data_offset = *data_offset + bytes_read;
2051                 pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
2052                 return FALSE;
2053         }
2054
2055         /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2056         wth->data_offset = *data_offset + bytes_read;
2057         pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
2058
2059         return TRUE;
2060 }
2061
2062
2063 /* classic wtap: seek to file position and read packet */
2064 static gboolean
2065 pcapng_seek_read(wtap *wth, gint64 seek_off,
2066     union wtap_pseudo_header *pseudo_header, guint8 *pd, int length _U_,
2067     int *err, gchar **err_info)
2068 {
2069         pcapng_t *pcapng = (pcapng_t *)wth->priv;
2070         guint64 bytes_read64;
2071         int bytes_read;
2072         wtapng_block_t wblock;
2073
2074
2075         /* seek to the right file position */
2076         bytes_read64 = file_seek(wth->random_fh, seek_off, SEEK_SET, err);
2077         if (bytes_read64 <= 0) {
2078                 return FALSE;   /* Seek error */
2079         }
2080         pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
2081
2082         wblock.frame_buffer = pd;
2083         wblock.pseudo_header = pseudo_header;
2084         wblock.packet_header = &wth->phdr;
2085         wblock.file_encap = &wth->file_encap;
2086
2087         /* read the block */
2088         bytes_read = pcapng_read_block(wth->random_fh, FALSE, pcapng, &wblock, err, err_info);
2089         if (bytes_read <= 0) {
2090                 *err = file_error(wth->random_fh, err_info);
2091                 pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
2092                               *err, errno, bytes_read);
2093                 return FALSE;
2094         }
2095
2096         /* block must be a "Packet Block" or an "Enhanced Packet Block" */
2097         if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB) {
2098                 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB", wblock.type);
2099                 return FALSE;
2100         }
2101
2102         return TRUE;
2103 }
2104
2105
2106 /* classic wtap: close capture file */
2107 static void
2108 pcapng_close(wtap *wth)
2109 {
2110         pcapng_t *pcapng = (pcapng_t *)wth->priv;
2111
2112         pcapng_debug0("pcapng_close: closing file");
2113         if (pcapng->interface_data != NULL) {
2114                 g_array_free(pcapng->interface_data, TRUE);
2115         }
2116 }
2117
2118
2119
2120 typedef struct {
2121         GArray *interface_data;
2122         guint number_of_interfaces;
2123         struct addrinfo *addrinfo_list_last;
2124 } pcapng_dump_t;
2125
2126 static gboolean
2127 pcapng_write_section_header_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2128 {
2129         pcapng_block_header_t bh;
2130         pcapng_section_header_block_t shb;
2131         const guint32 zero_pad = 0;
2132         gboolean have_options = FALSE;
2133         struct option option_hdr;                   /* guint16 type, guint16 value_length; */
2134         guint32 options_total_length = 0;
2135         guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0; 
2136         guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
2137
2138         if (wdh->shb_hdr) {
2139                 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
2140                 /* Check if we should write comment option */
2141                 if (wdh->shb_hdr->opt_comment) {
2142                         have_options = TRUE;
2143                         comment_len = (guint32)strlen(wdh->shb_hdr->opt_comment) & 0xffff;
2144                         if ((comment_len % 4)) {
2145                                 comment_pad_len = 4 - (comment_len % 4);
2146                         } else {
2147                                 comment_pad_len = 0;
2148                         }
2149                         options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2150                 }
2151
2152                 /* Check if we should write shb_hardware option */
2153                 if (wdh->shb_hdr->shb_hardware) {
2154                         have_options = TRUE;
2155                         shb_hardware_len = (guint32)strlen(wdh->shb_hdr->shb_hardware) & 0xffff;
2156                         if ((shb_hardware_len % 4)) {
2157                                 shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
2158                         } else {
2159                                 shb_hardware_pad_len = 0;
2160                         }
2161                         options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
2162                 }
2163
2164                 /* Check if we should write shb_os option */
2165                 if (wdh->shb_hdr->shb_os) {
2166                         have_options = TRUE;
2167                         shb_os_len = (guint32)strlen(wdh->shb_hdr->shb_os) & 0xffff;
2168                         if ((shb_os_len % 4)) {
2169                                 shb_os_pad_len = 4 - (shb_os_len % 4);
2170                         } else {
2171                                 shb_os_pad_len = 0;
2172                         }
2173                         options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
2174                 }
2175
2176                 /* Check if we should write shb_user_appl option */
2177                 if (wdh->shb_hdr->shb_user_appl) {
2178                         have_options = TRUE;
2179                         shb_user_appl_len = (guint32)strlen(wdh->shb_hdr->shb_user_appl) & 0xffff;
2180                         if ((shb_user_appl_len % 4)) {
2181                                 shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
2182                         } else {
2183                                 shb_user_appl_pad_len = 0;
2184                         }
2185                         options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
2186                 }
2187                 if (have_options) {
2188                         /* End-of-optios tag */
2189                         options_total_length += 4;
2190                 }
2191         }
2192
2193         /* write block header */
2194         bh.block_type = wblock->type;
2195         bh.block_total_length = sizeof(bh) + sizeof(shb) + options_total_length + 4;
2196         pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
2197
2198         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2199                 return FALSE;
2200         wdh->bytes_dumped += sizeof bh;
2201
2202         /* write block fixed content */
2203         /* XXX - get these values from wblock? */
2204         shb.magic = 0x1A2B3C4D;
2205         shb.version_major = 1;
2206         shb.version_minor = 0;
2207         shb.section_length = -1;
2208
2209         if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
2210                 return FALSE;
2211         wdh->bytes_dumped += sizeof shb;
2212
2213         /* XXX - write (optional) block options 
2214          * opt_comment  1 
2215          * shb_hardware 2
2216          * shb_os       3 
2217          * shb_user_appl 4 
2218          */
2219
2220         if (comment_len) {
2221                 option_hdr.type          = OPT_COMMENT;
2222                 option_hdr.value_length = comment_len;
2223                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2224                         return FALSE;
2225                 wdh->bytes_dumped += 4;
2226
2227                 /* Write the comments string */
2228                 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);
2229                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->opt_comment, comment_len, err))
2230                         return FALSE;
2231                 wdh->bytes_dumped += comment_len;
2232
2233                 /* write padding (if any) */
2234                 if (comment_pad_len != 0) {
2235                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2236                                 return FALSE;
2237                         wdh->bytes_dumped += comment_pad_len;
2238                 }
2239         }
2240
2241         if (shb_hardware_len) {
2242                 option_hdr.type          = OPT_SHB_HARDWARE;
2243                 option_hdr.value_length = shb_hardware_len;
2244                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2245                         return FALSE;
2246                 wdh->bytes_dumped += 4;
2247
2248                 /* Write the string */
2249                 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);
2250                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_hardware, shb_hardware_len, err))
2251                         return FALSE;
2252                 wdh->bytes_dumped += shb_hardware_len;
2253
2254                 /* write padding (if any) */
2255                 if (shb_hardware_pad_len != 0) {
2256                         if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
2257                                 return FALSE;
2258                         wdh->bytes_dumped += shb_hardware_pad_len;
2259                 }
2260         }
2261
2262         if (shb_os_len) {
2263                 option_hdr.type          = OPT_SHB_OS;
2264                 option_hdr.value_length = shb_os_len;
2265                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2266                         return FALSE;
2267                 wdh->bytes_dumped += 4;
2268
2269                 /* Write the string */
2270                 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);
2271                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_os, shb_os_len, err))
2272                         return FALSE;
2273                 wdh->bytes_dumped += shb_os_len;
2274
2275                 /* write padding (if any) */
2276                 if (shb_os_pad_len != 0) {
2277                         if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
2278                                 return FALSE;
2279                         wdh->bytes_dumped += shb_os_pad_len;
2280                 }
2281         }
2282
2283         if (shb_user_appl_len) {
2284                 option_hdr.type          = OPT_SHB_USERAPPL;
2285                 option_hdr.value_length = shb_user_appl_len;
2286                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2287                         return FALSE;
2288                 wdh->bytes_dumped += 4;
2289
2290                 /* Write the comments string */
2291                 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);
2292                 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_user_appl, shb_user_appl_len, err))
2293                         return FALSE;
2294                 wdh->bytes_dumped += shb_user_appl_len;
2295
2296                 /* write padding (if any) */
2297                 if (shb_user_appl_pad_len != 0) {
2298                         if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
2299                                 return FALSE;
2300                         wdh->bytes_dumped += shb_user_appl_pad_len;
2301                 }
2302         }
2303
2304         /* Write end of options if we have otions */
2305         if (have_options) {
2306                 option_hdr.type = OPT_EOFOPT;
2307                 option_hdr.value_length = 0;
2308                 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2309                         return FALSE;
2310                 wdh->bytes_dumped += 4;
2311         }
2312
2313         /* write block footer */
2314         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2315             sizeof bh.block_total_length, err))
2316                 return FALSE;
2317         wdh->bytes_dumped += sizeof bh.block_total_length;
2318
2319         return TRUE;
2320 }
2321
2322 #define IDB_OPT_IF_NAME         2
2323 #define IDB_OPT_IF_DESCR        3
2324 #define IDB_OPT_IF_SPEED        8
2325 #define IDB_OPT_IF_TSRESOL      9
2326 #define IDB_OPT_IF_FILTER       11
2327 #define IDB_OPT_IF_OS           12
2328
2329 static gboolean
2330 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2331 {
2332         pcapng_block_header_t bh;
2333         pcapng_interface_description_block_t idb;
2334         const guint32 zero_pad = 0;
2335         gboolean have_options = FALSE;
2336         struct option option_hdr;                   /* guint16 type, guint16 value_length; */
2337         guint32 options_total_length = 0;
2338         guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0;
2339         guint32 comment_pad_len = 0, if_name_pad_len = 0, if_description_pad_len = 0, if_os_pad_len = 0;
2340
2341
2342         pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2343                       wblock->data.if_descr.link_type,
2344                       wtap_encap_string(wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type)),
2345                       wblock->data.if_descr.snap_len);
2346
2347         if (wblock->data.if_descr.link_type == (guint16)-1) {
2348                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
2349                 return FALSE;
2350         }
2351
2352         /* Calculate options length */
2353         if (wblock->data.if_descr.opt_comment) {
2354                 have_options = TRUE;
2355                 comment_len = (guint32)strlen(wblock->data.if_descr.opt_comment) & 0xffff;
2356                 if ((comment_len % 4)){
2357                         comment_pad_len = 4 - (comment_len % 4);
2358                 } else {
2359                         comment_pad_len = 0;
2360                 }
2361                 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2362         }
2363
2364         /*
2365          * if_name        2  A UTF-8 string containing the name of the device used to capture data. 
2366          */
2367         if (wblock->data.if_descr.if_name){
2368                 have_options = TRUE;
2369                 if_name_len = (guint32)strlen(wblock->data.if_descr.if_name) & 0xffff;
2370                 if ((if_name_len % 4)) {
2371                         if_name_pad_len = 4 - (if_name_len % 4);
2372                 } else {
2373                         if_name_pad_len = 0;
2374                 }
2375                 options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
2376         }
2377
2378         /*
2379          * if_description 3  A UTF-8 string containing the description of the device used to capture data. 
2380          */
2381         if (wblock->data.if_descr.if_description) {
2382                 have_options = TRUE;
2383                 if_name_len = (guint32)strlen(wblock->data.if_descr.if_description) & 0xffff;
2384                 if ((if_description_len % 4)) {
2385                         if_description_pad_len = 4 - (if_description_len % 4);
2386                 } else {
2387                         if_description_pad_len = 0;
2388                 }
2389                 options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
2390         }
2391         /* Currently not handled
2392          * if_IPv4addr    4  Interface network address and netmask.
2393          * if_IPv6addr    5  Interface network address and prefix length (stored in the last byte). 
2394          * if_MACaddr     6  Interface Hardware MAC address (48 bits). 00 01 02 03 04 05 
2395          * if_EUIaddr     7  Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2396          */
2397         /*
2398          * if_speed       8  Interface speed (in bps). 100000000 for 100Mbps 
2399          */
2400         if (wblock->data.if_descr.if_speed != 0) {
2401                 have_options = TRUE;
2402                 options_total_length = options_total_length + 8 + 4;
2403         }
2404         /*
2405          * if_tsresol     9  Resolution of timestamps.
2406          */
2407         if (wblock->data.if_descr.if_tsresol != 0) {
2408                 have_options = TRUE;
2409                 options_total_length = options_total_length + 4 + 4;
2410         }
2411         /* Not used
2412          * if_tzone      10  Time zone for GMT support (TODO: specify better). TODO: give a good example 
2413          */
2414         /*
2415          * if_filter     11  The filter (e.g. "capture only TCP traffic") used to capture traffic. 
2416          */
2417         if (wblock->data.if_descr.if_filter) {
2418         }
2419         /*
2420          * if_os         12  A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. 
2421          */
2422         if (wblock->data.if_descr.if_os) {
2423                 have_options = TRUE;
2424                 if_os_len = (guint32)strlen(wblock->data.if_descr.if_os) & 0xffff;
2425                 if ((if_os_len % 4)) {
2426                         if_os_pad_len = 4 - (if_os_len % 4);
2427                 } else {
2428                         if_os_pad_len = 0;
2429                 }
2430                 options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
2431         }
2432         /*
2433          * if_fcslen     13  An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. 
2434          */
2435         if (wblock->data.if_descr.opt_comment) {
2436         }
2437         /* Not used
2438          * if_tsoffset   14  A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet 
2439          * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2440          */
2441
2442         if (have_options) {
2443                 /* End-of-optios tag */
2444                 options_total_length += 4;
2445         }
2446
2447         /* write block header */
2448         bh.block_type = wblock->type;
2449         bh.block_total_length = sizeof(bh) + sizeof(idb) + options_total_length + 4;
2450
2451         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2452                 return FALSE;
2453         wdh->bytes_dumped += sizeof bh;
2454
2455         /* write block fixed content */
2456         idb.linktype    = wblock->data.if_descr.link_type;
2457         idb.reserved    = 0;
2458         idb.snaplen     = wblock->data.if_descr.snap_len;
2459
2460         if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
2461                 return FALSE;
2462         wdh->bytes_dumped += sizeof idb;
2463
2464         /* XXX - write (optional) block options */
2465         if (comment_len) {
2466                 option_hdr.type          = OPT_COMMENT;
2467                 option_hdr.value_length = comment_len;
2468                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2469                         return FALSE;
2470                 wdh->bytes_dumped += 4;
2471
2472                 /* Write the comments string */
2473                 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);
2474                 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.opt_comment, comment_len, err))
2475                         return FALSE;
2476                 wdh->bytes_dumped += comment_len;
2477
2478                 /* write padding (if any) */
2479                 if (comment_pad_len != 0) {
2480                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2481                                 return FALSE;
2482                         wdh->bytes_dumped += comment_pad_len;
2483                 }
2484         }
2485         /*
2486          * if_name        2  A UTF-8 string containing the name of the device used to capture data.
2487          */
2488         if (if_name_len) {
2489                 option_hdr.type = IDB_OPT_IF_NAME;
2490                 option_hdr.value_length = if_name_len;
2491                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2492                         return FALSE;
2493                 wdh->bytes_dumped += 4;
2494
2495                 /* Write the comments string */
2496                 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);
2497                 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_name, if_name_len, err))
2498                         return FALSE;
2499                 wdh->bytes_dumped += if_name_len;
2500
2501                 /* write padding (if any) */
2502                 if (if_name_pad_len != 0) {
2503                         if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
2504                                 return FALSE;
2505                         wdh->bytes_dumped += if_name_pad_len;
2506                 }
2507         }
2508         /*
2509          * if_description 3  A UTF-8 string containing the description of the device used to capture data. 
2510          */
2511         if (if_description_len) {
2512                 option_hdr.type          = IDB_OPT_IF_NAME;
2513                 option_hdr.value_length = if_description_len;
2514                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2515                         return FALSE;
2516                 wdh->bytes_dumped += 4;
2517
2518                 /* Write the comments string */
2519                 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);
2520                 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_description, if_description_len, err))
2521                         return FALSE;
2522                 wdh->bytes_dumped += comment_len;
2523
2524                 /* write padding (if any) */
2525                 if (if_description_pad_len != 0) {
2526                         if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
2527                                 return FALSE;
2528                         wdh->bytes_dumped += if_description_pad_len;
2529                 }
2530         }
2531         /* Currently not handled
2532          * if_IPv4addr    4  Interface network address and netmask.
2533          * if_IPv6addr    5  Interface network address and prefix length (stored in the last byte). 
2534          * if_MACaddr     6  Interface Hardware MAC address (48 bits). 00 01 02 03 04 05 
2535          * if_EUIaddr     7  Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2536          */
2537         /*
2538          * if_speed       8  Interface speed (in bps). 100000000 for 100Mbps 
2539          */
2540         if (wblock->data.if_descr.if_speed != 0) {
2541                 printf("HJKHJHK\n");
2542                 option_hdr.type          = IDB_OPT_IF_SPEED;
2543                 option_hdr.value_length = 8;
2544                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2545                         return FALSE;
2546                 wdh->bytes_dumped += 4;
2547
2548                 /* Write the comments string */
2549                 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
2550                 if (!wtap_dump_file_write(wdh, &wblock->data.if_descr.if_speed, sizeof(guint64), err))
2551                         return FALSE;
2552                 wdh->bytes_dumped += 8;
2553         }
2554         /*
2555          * if_tsresol     9  Resolution of timestamps.
2556          */
2557         if (wblock->data.if_descr.if_tsresol != 0) {
2558                 option_hdr.type          = IDB_OPT_IF_TSRESOL;
2559                 option_hdr.value_length = 1;
2560                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2561                         return FALSE;
2562                 wdh->bytes_dumped += 4;
2563
2564                 /* Write the comments string */
2565                 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", wblock->data.if_descr.if_tsresol);
2566                 if (!wtap_dump_file_write(wdh, &wblock->data.if_descr.if_tsresol, 1, err))
2567                         return FALSE;
2568                 wdh->bytes_dumped += 1;
2569                 if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
2570                         return FALSE;
2571                 wdh->bytes_dumped += 3;
2572         }
2573         /* not used
2574          * if_tzone      10  Time zone for GMT support (TODO: specify better). TODO: give a good example 
2575          */
2576         /*
2577          * if_filter     11  The filter (e.g. "capture only TCP traffic") used to capture traffic. 
2578          */
2579         /*
2580          * if_os         12  A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. 
2581          */
2582         if (if_os_len) {
2583                 option_hdr.type          = IDB_OPT_IF_OS;
2584                 option_hdr.value_length = if_os_len;
2585                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2586                         return FALSE;
2587                 wdh->bytes_dumped += 4;
2588
2589                 /* Write the comments string */
2590                 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);
2591                 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_os, if_os_len, err))
2592                         return FALSE;
2593                 wdh->bytes_dumped += comment_len;
2594
2595                 /* write padding (if any) */
2596                 if (if_os_pad_len != 0) {
2597                         if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
2598                                 return FALSE;
2599                         wdh->bytes_dumped += if_os_pad_len;
2600                 }
2601         }
2602
2603         if (have_options) {
2604                 option_hdr.type = OPT_EOFOPT;
2605                 option_hdr.value_length = 0;
2606                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2607                         return FALSE;
2608                 wdh->bytes_dumped += 4;
2609         }
2610
2611         /*
2612          * if_fcslen     13  An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. 
2613          */
2614         /*
2615          * if_tsoffset   14  A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet 
2616          * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2617          */
2618
2619         /* write block footer */
2620         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2621             sizeof bh.block_total_length, err))
2622                 return FALSE;
2623         wdh->bytes_dumped += sizeof bh.block_total_length;
2624
2625         return TRUE;
2626 }
2627
2628 static gboolean
2629 pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2630 {
2631
2632         pcapng_block_header_t bh;
2633         pcapng_interface_statistics_block_t isb;
2634         const guint32 zero_pad = 0;
2635         gboolean have_options = FALSE;
2636         struct option option_hdr;                   /* guint16 type, guint16 value_length; */
2637         guint32 options_total_length = 0;
2638         guint32 comment_len = 0;
2639         guint32 comment_pad_len = 0;
2640
2641         pcapng_debug0("pcapng_write_interface_statistics_block");
2642
2643
2644         /* Calculate options length */
2645         if (wblock->data.if_descr.opt_comment) {
2646                 have_options = TRUE;
2647                 comment_len = (guint32)strlen(wblock->data.if_descr.opt_comment) & 0xffff;
2648                 if ((comment_len % 4)){
2649                         comment_pad_len = 4 - (comment_len % 4);
2650                 } else {
2651                         comment_pad_len = 0;
2652                 }
2653                 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2654         }
2655         /* XXX */
2656         /*guint32                       isb_starttime_high;*/
2657         /*guint32                       isb_starttime_low;*/
2658         /*guint32                       isb_endtime_high;*/
2659         /*guint32                       isb_endtime_low;*/
2660         /*guint64                               isb_ifrecv;*/
2661         /*guint64                               isb_ifdrop;*/
2662         /*guint64                       isb_filteraccept;*/
2663         /*guint64                       isb_osdrop;*/
2664         /*guint64                       isb_usrdeliv;*/
2665
2666
2667         /* write block header */
2668         if (have_options) {
2669                 /* End-of-optios tag */
2670                 options_total_length += 4;
2671         }
2672
2673         /* write block header */
2674         bh.block_type = wblock->type;
2675         bh.block_total_length = sizeof(bh) + sizeof(isb) + options_total_length + 4;
2676
2677         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2678                 return FALSE;
2679         wdh->bytes_dumped += sizeof bh;
2680
2681         /* write block fixed content */
2682         isb.interface_id                = wblock->data.if_stats.interface_id;
2683         isb.timestamp_high              = wblock->data.if_stats.ts_high;
2684         isb.timestamp_low               = wblock->data.if_stats.ts_low;
2685
2686
2687         if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
2688                 return FALSE;
2689         wdh->bytes_dumped += sizeof isb;
2690
2691         /* write (optional) block options */
2692         if (comment_len) {
2693                 option_hdr.type          = OPT_COMMENT;
2694                 option_hdr.value_length = comment_len;
2695                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2696                         return FALSE;
2697                 wdh->bytes_dumped += 4;
2698
2699                 /* Write the comments string */
2700                 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);
2701                 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.opt_comment, comment_len, err))
2702                         return FALSE;
2703                 wdh->bytes_dumped += comment_len;
2704
2705                 /* write padding (if any) */
2706                 if (comment_pad_len != 0) {
2707                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2708                                 return FALSE;
2709                         wdh->bytes_dumped += comment_pad_len;
2710                 }
2711         }
2712         /* XXX */
2713         /*guint32                       isb_starttime */
2714         /*guint32                       isb_endtime */
2715         /*guint64                       isb_ifrecv;*/
2716         /*guint64                       isb_ifdrop;*/
2717         /*guint64                       isb_filteraccept;*/
2718         /*guint64                       isb_osdrop;*/
2719         /*guint64                       isb_usrdeliv;*/
2720
2721         if (have_options) {
2722                 option_hdr.type = OPT_EOFOPT;
2723                 option_hdr.value_length = 0;
2724                 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2725                         return FALSE;
2726                 wdh->bytes_dumped += 4;
2727         }
2728
2729         /* write block footer */
2730         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2731             sizeof bh.block_total_length, err))
2732                 return FALSE;
2733         wdh->bytes_dumped += sizeof bh.block_total_length;
2734
2735         return TRUE;
2736
2737 }
2738
2739
2740 static gboolean
2741 pcapng_write_packet_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2742 {
2743         pcapng_block_header_t bh;
2744         pcapng_enhanced_packet_block_t epb;
2745         const guint32 zero_pad = 0;
2746         guint32 pad_len;
2747         guint32 phdr_len;
2748         gboolean have_options = FALSE;
2749         guint32 options_total_length = 0;
2750         guint32 options_hdr = 0; 
2751         guint32 comment_len = 0, comment_pad_len = 0;
2752
2753         phdr_len = (guint32)pcap_get_phdr_size(wblock->data.packet.wtap_encap, wblock->pseudo_header);
2754         if ((phdr_len + wblock->data.packet.cap_len) % 4) {
2755                 pad_len = 4 - ((phdr_len + wblock->data.packet.cap_len) % 4);
2756         } else {
2757                 pad_len = 0;
2758         }
2759
2760         /* Check if we should write comment option */
2761         if(wblock->data.packet.opt_comment){
2762                 have_options = TRUE;
2763                 comment_len = (guint32)strlen(wblock->data.packet.opt_comment) & 0xffff;
2764                 if((comment_len % 4)){
2765                         comment_pad_len = 4 - (comment_len % 4);
2766                 }else{
2767                         comment_pad_len = 0;
2768                 }
2769                 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2770         }
2771
2772         if(have_options){
2773                 /* End-of optios tag */
2774                 options_total_length += 4;
2775         }
2776
2777
2778         /* write (enhanced) packet block header */
2779         bh.block_type = wblock->type;
2780         bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + wblock->data.packet.cap_len + pad_len + options_total_length + 4;
2781
2782         if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2783                 return FALSE;
2784         wdh->bytes_dumped += sizeof bh;
2785
2786         /* write block fixed content */
2787         epb.interface_id        = wblock->data.packet.interface_id;
2788         epb.timestamp_high      = wblock->data.packet.ts_high;
2789         epb.timestamp_low       = wblock->data.packet.ts_low;
2790         epb.captured_len        = wblock->data.packet.cap_len + phdr_len;
2791         epb.packet_len          = wblock->data.packet.packet_len + phdr_len;
2792
2793         if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
2794                 return FALSE;
2795         wdh->bytes_dumped += sizeof epb;
2796
2797         /* write pseudo header */
2798         if (!pcap_write_phdr(wdh, wblock->data.packet.wtap_encap, wblock->pseudo_header, err)) {
2799                 return FALSE;
2800         }
2801         wdh->bytes_dumped += phdr_len;
2802
2803         /* write packet data */
2804         if (!wtap_dump_file_write(wdh, wblock->frame_buffer,
2805             wblock->data.packet.cap_len, err))
2806                 return FALSE;
2807         wdh->bytes_dumped += wblock->data.packet.cap_len;
2808
2809         /* write padding (if any) */
2810         if (pad_len != 0) {
2811                 if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
2812                         return FALSE;
2813                 wdh->bytes_dumped += pad_len;
2814         }
2815
2816         /* XXX - write (optional) block options */
2817         /* options defined in Section 2.5 (Options) 
2818          * Name           Code Length     Description 
2819          * opt_comment    1    variable   A UTF-8 string containing a comment that is associated to the current block. 
2820          *
2821          * Enhanced Packet Block options
2822          * epb_flags      2    4          A flags word containing link-layer information. A complete specification of 
2823          *                                the allowed flags can be found in Appendix A (Packet Block Flags Word). 
2824          * epb_hash       3    variable   This option contains a hash of the packet. The first byte specifies the hashing algorithm, 
2825          *                                while the following bytes contain the actual hash, whose size depends on the hashing algorithm, 
2826          *                                                                and hence from the value in the first bit. The hashing algorithm can be: 2s complement 
2827          *                                                                (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4), 
2828          *                                                                MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX). 
2829          *                                                                The hash covers only the packet, not the header added by the capture driver: 
2830          *                                                                this gives the possibility to calculate it inside the network card. 
2831          *                                                                The hash allows easier comparison/merging of different capture files, and reliable data transfer between the 
2832          *                                                                data acquisition system and the capture library. 
2833          * epb_dropcount   4   8          A 64bit integer value specifying the number of packets lost (by the interface and the operating system) 
2834          *                                between this packet and the preceding one.
2835          * opt_endofopt    0   0          It delimits the end of the optional fields. This block cannot be repeated within a given list of options. 
2836          */
2837         if(wblock->data.packet.opt_comment){
2838                 options_hdr = comment_len;
2839                 options_hdr = options_hdr << 16;
2840                 /* Option 1  */
2841                 options_hdr += 1;
2842                 if (!wtap_dump_file_write(wdh, &options_hdr, 4, err))
2843                         return FALSE;
2844                 wdh->bytes_dumped += 4;
2845
2846                 /* Write the comments string */
2847                 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);
2848                 if (!wtap_dump_file_write(wdh, wblock->data.packet.opt_comment, comment_len, err))
2849                         return FALSE;
2850                 wdh->bytes_dumped += comment_len;
2851
2852                 /* write padding (if any) */
2853                 if (comment_pad_len != 0) {
2854                         if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2855                                 return FALSE;
2856                         wdh->bytes_dumped += comment_pad_len;
2857                 }
2858
2859                 pcapng_debug2("pcapng_write_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
2860                         comment_len,
2861                         comment_pad_len);
2862         }
2863
2864         /* Write end of options if we have otions */
2865         if(have_options){
2866                 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2867                         return FALSE;
2868                 wdh->bytes_dumped += 4;
2869         }
2870
2871         /* write block footer */
2872         if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2873             sizeof bh.block_total_length, err))
2874                 return FALSE;
2875         wdh->bytes_dumped += sizeof bh.block_total_length;
2876
2877         return TRUE;
2878 }
2879
2880 /* Arbitrary. */
2881 #define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
2882 static gboolean
2883 pcapng_write_name_resolution_block(wtap_dumper *wdh, pcapng_dump_t *pcapng, int *err)
2884 {
2885         pcapng_block_header_t bh;
2886         pcapng_name_resolution_block_t nrb;
2887         struct addrinfo *ai;
2888         struct sockaddr_in *sa4;
2889         struct sockaddr_in6 *sa6;
2890         guint8 *rec_data;
2891         gint rec_off, namelen, tot_rec_len;
2892
2893         if (! pcapng->addrinfo_list_last || ! pcapng->addrinfo_list_last->ai_next) {
2894                 return TRUE;
2895         }
2896
2897         rec_off = 8; /* block type + block total length */
2898         bh.block_type = BLOCK_TYPE_NRB;
2899         bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
2900         rec_data = g_malloc(NRES_REC_MAX_SIZE);
2901
2902         for (; pcapng->addrinfo_list_last && pcapng->addrinfo_list_last->ai_next; pcapng->addrinfo_list_last = pcapng->addrinfo_list_last->ai_next ) {
2903                 ai = pcapng->addrinfo_list_last->ai_next; /* Skips over the first (dummy) entry */
2904                 namelen = (gint)strlen(ai->ai_canonname) + 1;
2905                 if (ai->ai_family == AF_INET) {
2906                         nrb.record_type = NRES_IP4RECORD;
2907                         nrb.record_len = 4 + namelen;
2908                         tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
2909                         bh.block_total_length += tot_rec_len;
2910
2911                         if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE)
2912                                 break;
2913
2914                         /*
2915                          * The joys of BSD sockaddrs.  In practice, this
2916                          * cast is alignment-safe.
2917                          */
2918                         sa4 = (struct sockaddr_in *)(void *)ai->ai_addr;
2919                         memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
2920                         rec_off += 4;
2921
2922                         memcpy(rec_data + rec_off, &(sa4->sin_addr.s_addr), 4);
2923                         rec_off += 4;
2924
2925                         memcpy(rec_data + rec_off, ai->ai_canonname, namelen);
2926                         rec_off += namelen;
2927
2928                         memset(rec_data + rec_off, 0, PADDING4(namelen));
2929                         rec_off += PADDING4(namelen);
2930                         pcapng_debug1("NRB: added IPv4 record for %s", ai->ai_canonname);
2931                 } else if (ai->ai_family == AF_INET6) {
2932                         nrb.record_type = NRES_IP6RECORD;
2933                         nrb.record_len = 16 + namelen;
2934                         tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
2935                         bh.block_total_length += tot_rec_len;
2936
2937                         if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE)
2938                                 break;
2939
2940                         /*
2941                          * The joys of BSD sockaddrs.  In practice, this
2942                          * cast is alignment-safe.
2943                          */
2944                         sa6 = (struct sockaddr_in6 *)(void *)ai->ai_addr;
2945                         memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
2946                         rec_off += 4;
2947
2948                         memcpy(rec_data + rec_off, sa6->sin6_addr.s6_addr, 16);
2949                         rec_off += 16;
2950
2951                         memcpy(rec_data + rec_off, ai->ai_canonname, namelen);
2952                         rec_off += namelen;
2953
2954                         memset(rec_data + rec_off, 0, PADDING4(namelen));
2955                         rec_off += PADDING4(namelen);
2956                         pcapng_debug1("NRB: added IPv6 record for %s", ai->ai_canonname);
2957                 }
2958         }
2959
2960         /* We know the total length now; copy the block header. */
2961         memcpy(rec_data, &bh, sizeof(bh));
2962
2963         /* End of record */
2964         memset(rec_data + rec_off, 0, 4);
2965         rec_off += 4;
2966
2967         memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
2968
2969         if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
2970                 g_free(rec_data);
2971                 return FALSE;
2972         }
2973
2974         g_free(rec_data);
2975         wdh->bytes_dumped += bh.block_total_length;
2976         return TRUE;
2977 }
2978
2979
2980 static gboolean
2981 pcapng_write_block(wtap_dumper *wdh, /*pcapng_t *pn, */wtapng_block_t *wblock, int *err)
2982 {
2983         switch(wblock->type) {
2984             case(BLOCK_TYPE_SHB):
2985                 return pcapng_write_section_header_block(wdh, wblock, err);
2986             case(BLOCK_TYPE_IDB):
2987                 return pcapng_write_if_descr_block(wdh, wblock, err);
2988             case(BLOCK_TYPE_PB):
2989                 /* Packet Block is obsolete */
2990                 return FALSE;
2991                 case(BLOCK_TYPE_ISB):
2992                 /* Interface Statistics Block */
2993                 return pcapng_write_interface_statistics_block(wdh, wblock, err);
2994             case(BLOCK_TYPE_EPB):
2995                 return pcapng_write_packet_block(wdh, wblock, err);
2996             default:
2997                 pcapng_debug1("Unknown block_type: 0x%x", wblock->type);
2998                 return FALSE;
2999         }
3000 }
3001
3002 #if 0
3003 static guint32
3004 pcapng_lookup_interface_id_by_encap(int wtap_encap, wtap_dumper *wdh)
3005 {
3006         gint i;
3007         interface_data_t int_data;
3008         pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3009
3010         for(i = 0; i < (gint)pcapng->number_of_interfaces; i++) {
3011                 int_data = g_array_index(pcapng->interface_data, interface_data_t, i);
3012                 if (wtap_encap == int_data.wtap_encap) {
3013                         return (guint32)i;
3014                 }
3015         }
3016         return G_MAXUINT32;
3017 }
3018 #endif
3019
3020 static gboolean pcapng_dump(wtap_dumper *wdh,
3021         const struct wtap_pkthdr *phdr,
3022         const union wtap_pseudo_header *pseudo_header,
3023         const guint8 *pd, int *err)
3024 {
3025         wtapng_block_t wblock;
3026         /*interface_data_t int_data;*/
3027         guint32 interface_id = 0;
3028         guint64 ts;
3029         pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3030         /*int pcap_encap;*/
3031
3032         pcapng_debug2("pcapng_dump: encap = %d (%s)",
3033                       phdr->pkt_encap,
3034                       wtap_encap_string(phdr->pkt_encap));
3035
3036         if (!pcapng->addrinfo_list_last)
3037                 pcapng->addrinfo_list_last = wdh->addrinfo_list;
3038         /* Flush any hostname resolution info we may have */
3039         while (pcapng->addrinfo_list_last && pcapng->addrinfo_list_last->ai_next) {
3040                 pcapng_write_name_resolution_block(wdh, pcapng, err);
3041         }
3042
3043         wblock.frame_buffer  = pd;
3044         wblock.pseudo_header = pseudo_header;
3045         wblock.packet_header = NULL;
3046         wblock.file_encap    = NULL;
3047
3048         /* write the (enhanced) packet block */
3049         wblock.type = BLOCK_TYPE_EPB;
3050
3051         /* default is to write out in microsecond resolution */
3052         ts = (((guint64)phdr->ts.secs) * 1000000) + (phdr->ts.nsecs / 1000);
3053
3054         /* Split the 64-bit timestamp into two 32-bit pieces */
3055         wblock.data.packet.ts_high      = (guint32)(ts >> 32);
3056         wblock.data.packet.ts_low       = (guint32)ts;
3057
3058         wblock.data.packet.cap_len      = phdr->caplen;
3059         wblock.data.packet.packet_len   = phdr->len;
3060         wblock.data.packet.interface_id = interface_id;
3061         wblock.data.packet.wtap_encap   = phdr->pkt_encap;
3062
3063         /* currently unused */
3064         wblock.data.packet.drop_count   = phdr->drop_count;
3065         wblock.data.packet.opt_comment  = phdr->opt_comment;
3066         pcapng_debug1("pcapng_dump: Comment %s",phdr->opt_comment);
3067
3068         if (!pcapng_write_block(wdh, &wblock, err)) {
3069                 return FALSE;
3070         }
3071
3072         return TRUE;
3073 }
3074
3075
3076 /* Finish writing to a dump file.
3077    Returns TRUE on success, FALSE on failure. */
3078 static gboolean pcapng_dump_close(wtap_dumper *wdh, int *err _U_)
3079 {
3080         pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3081
3082         pcapng_debug0("pcapng_dump_close");
3083         g_array_free(pcapng->interface_data, TRUE);
3084         pcapng->number_of_interfaces = 0;
3085         return TRUE;
3086 }
3087
3088
3089 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
3090    failure */
3091 gboolean
3092 pcapng_dump_open(wtap_dumper *wdh, int *err)
3093 {
3094         wtapng_block_t wblock;
3095         pcapng_dump_t *pcapng;
3096         int i;
3097         interface_data_t interface_data;
3098         
3099         wblock.frame_buffer  = NULL;
3100         wblock.pseudo_header = NULL;
3101         wblock.packet_header = NULL;
3102         wblock.file_encap    = NULL;
3103
3104         pcapng_debug0("pcapng_dump_open");
3105         /* This is a pcapng file */
3106         wdh->subtype_write = pcapng_dump;
3107         wdh->subtype_close = pcapng_dump_close;
3108         pcapng = (pcapng_dump_t *)g_malloc0(sizeof(pcapng_dump_t));
3109         wdh->priv = (void *)pcapng;
3110         pcapng->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
3111
3112         if ((wdh->number_of_interfaces == 0) || (wdh->interface_data == NULL)) {
3113                 pcapng_debug0("There are no interfaces. Can't handle that...");
3114                 *err = WTAP_ERR_INTERNAL;
3115                 return FALSE;
3116         }
3117
3118         /* write the section header block */
3119         wblock.type = BLOCK_TYPE_SHB;
3120         wblock.data.section.section_length = -1;
3121
3122         /* Options */
3123         if (wdh->shb_hdr) {
3124                 wblock.data.section.opt_comment   = wdh->shb_hdr->opt_comment;
3125                 wblock.data.section.shb_hardware  = wdh->shb_hdr->shb_hardware;
3126                 wblock.data.section.shb_os        = wdh->shb_hdr->shb_os;
3127                 wblock.data.section.shb_user_appl = wdh->shb_hdr->shb_user_appl;
3128         } else {
3129                 wblock.data.section.opt_comment   = NULL;
3130                 wblock.data.section.shb_hardware  = NULL;
3131                 wblock.data.section.shb_os        = NULL;
3132                 wblock.data.section.shb_user_appl = NULL;
3133         }
3134
3135         if (!pcapng_write_block(wdh, &wblock, err)) {
3136                 return FALSE;
3137         }
3138         pcapng_debug0("pcapng_dump_open: wrote section header block.");
3139
3140         /* Write the Interface description blocks */
3141         pcapng_debug1("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u", wdh->number_of_interfaces);
3142
3143         for (i = 0; i < (int)wdh->number_of_interfaces; i++) {
3144
3145                 /* Get the interface description */
3146                 wtapng_if_descr_t int_data;
3147
3148                 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3149
3150                 /* write the interface description block */
3151                 wblock.data.if_descr.link_type = int_data.link_type;
3152                 wblock.data.if_descr.wtap_encap = int_data.wtap_encap;
3153                 wblock.data.if_descr.snap_len = int_data.snap_len;
3154                 /* options */
3155                 /* NULL if not available */
3156                 wblock.data.if_descr.opt_comment = int_data.opt_comment;
3157                 /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
3158                 wblock.data.if_descr.if_name = int_data.if_name;
3159                 /* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
3160                 wblock.data.if_descr.if_description = int_data.if_description;
3161                 /* XXX: if_IPv4addr opt 4  Interface network address and netmask.*/
3162                 /* XXX: if_IPv6addr opt 5  Interface network address and prefix length (stored in the last byte).*/
3163                 /* XXX: if_MACaddr  opt 6  Interface Hardware MAC address (48 bits).*/
3164                 /* XXX: if_EUIaddr  opt 7  Interface Hardware EUI address (64 bits)*/
3165                 /* 0xFFFFFFFF if unknown, opt 8  Interface speed (in bps). 100000000 for 100Mbps */
3166                 wblock.data.if_descr.if_speed = int_data.if_speed;
3167                 /* default is 6 for microsecond resolution, opt 9  Resolution of timestamps.
3168                  * If the Most Significant Bit is equal to zero, the remaining bits indicates
3169                  * the resolution of the timestamp as as a negative power of 10
3170                  */
3171                 wblock.data.if_descr.if_tsresol = int_data.if_tsresol;
3172                 /* XXX: if_tzone      10  Time zone for GMT support (TODO: specify better). */
3173                 /* NULL if not available, opt 11  The filter (e.g. "capture only TCP traffic") used to capture traffic.
3174                  * 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).
3175                  */
3176                 wblock.data.if_descr.if_filter = int_data.if_filter;
3177                 /* 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. */
3178                 wblock.data.if_descr.if_os = int_data.if_os;
3179                 /* -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. */
3180                 wblock.data.if_descr.if_fcslen = int_data.if_fcslen;            
3181                 /* XXX: guint64 if_tsoffset; opt 14  A 64 bits integer value that specifies an offset (in seconds)...*/
3182
3183                 wblock.frame_buffer            = NULL;
3184                 wblock.pseudo_header           = NULL;
3185                 wblock.packet_header           = NULL;
3186                 wblock.file_encap              = NULL;
3187                 wblock.type                    = BLOCK_TYPE_IDB;
3188
3189                 interface_data.wtap_encap = int_data.wtap_encap;;
3190                 interface_data.time_units_per_second = int_data.time_units_per_second; 
3191
3192                 g_array_append_val(pcapng->interface_data, interface_data);
3193                 pcapng->number_of_interfaces++;
3194
3195                 if (!pcapng_write_block(wdh, &wblock, err)) {
3196                         return FALSE;
3197                 }
3198
3199         }
3200 #if 0
3201         interface_id = pcapng_lookup_interface_id_by_encap(phdr->pkt_encap, wdh);
3202         if (interface_id == G_MAXUINT32) {
3203                 /*
3204                  * We haven't yet written out an interface description
3205                  * block for an interface with this encapsulation.
3206                  *
3207                  * Is this encapsulation even supported in pcap-ng?
3208                  */
3209                 pcap_encap = wtap_wtap_encap_to_pcap_encap(phdr->pkt_encap);
3210                 if (pcap_encap == -1) {
3211                         /*
3212                          * No.  Fail.
3213                          */
3214                         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
3215                         return FALSE;
3216                 }
3217
3218                 /* write the interface description block */
3219                 wblock.frame_buffer            = NULL;
3220                 wblock.pseudo_header           = NULL;
3221                 wblock.packet_header           = NULL;
3222                 wblock.file_encap              = NULL;
3223                 wblock.type                    = BLOCK_TYPE_IDB;
3224                 wblock.data.if_descr.link_type = pcap_encap;
3225                 wblock.data.if_descr.snap_len = (wdh->snaplen != 0) ? wdh->snaplen :
3226                                                                       WTAP_MAX_PACKET_SIZE; /* XXX */
3227
3228                 /* XXX - options unused */
3229                 wblock.data.if_descr.if_speed   = -1;
3230                 /*wblock.data.if_descr.if_tsresol = 6;*/    /* default: usec */
3231                 wblock.data.if_descr.if_os      = NULL;
3232                 wblock.data.if_descr.if_fcslen  = -1;
3233
3234                 if (!pcapng_write_block(wdh, &wblock, err)) {
3235                         return FALSE;
3236                 }
3237
3238                 interface_id = pcapng->number_of_interfaces;
3239                 int_data.wtap_encap = phdr->pkt_encap;
3240                 int_data.time_units_per_second = 0;
3241                 g_array_append_val(pcapng->interface_data, int_data);
3242                 pcapng->number_of_interfaces++;
3243
3244                 pcapng_debug3("pcapng_dump: added interface description block with index %u for encap = %d (%s).",
3245                               interface_id,
3246                               phdr->pkt_encap,
3247                               wtap_encap_string(phdr->pkt_encap));
3248         }
3249 #endif
3250
3251         return TRUE;
3252 }
3253
3254
3255 /* Returns 0 if we could write the specified encapsulation type,
3256    an error indication otherwise. */
3257 int pcapng_dump_can_write_encap(int wtap_encap)
3258 {
3259         pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
3260                       wtap_encap,
3261                       wtap_encap_string(wtap_encap));
3262
3263         /* Per-packet encapsulations is supported. */
3264         if (wtap_encap == WTAP_ENCAP_PER_PACKET)
3265                 return 0;
3266
3267         /* Make sure we can figure out this DLT type */
3268         if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
3269                 return WTAP_ERR_UNSUPPORTED_ENCAP;
3270
3271         return 0;
3272 }