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