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