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