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