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