xref: /libbtbb/lib/src/pcapng.c (revision 8f3e7eea1eae731e517c4fd7ac22f1ce3ad3cd5f)
1*8f3e7eeaSChristopher Kilgour /* -*- c -*- */
2*8f3e7eeaSChristopher Kilgour /*
3*8f3e7eeaSChristopher Kilgour  * Copyright 2014 Christopher D. Kilgour techie AT whiterocker.com
4*8f3e7eeaSChristopher Kilgour  *
5*8f3e7eeaSChristopher Kilgour  * This file is part of libbtbb
6*8f3e7eeaSChristopher Kilgour  *
7*8f3e7eeaSChristopher Kilgour  * This program is free software; you can redistribute it and/or modify
8*8f3e7eeaSChristopher Kilgour  * it under the terms of the GNU General Public License as published by
9*8f3e7eeaSChristopher Kilgour  * the Free Software Foundation; either version 2, or (at your option)
10*8f3e7eeaSChristopher Kilgour  * any later version.
11*8f3e7eeaSChristopher Kilgour  *
12*8f3e7eeaSChristopher Kilgour  * This program is distributed in the hope that it will be useful,
13*8f3e7eeaSChristopher Kilgour  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*8f3e7eeaSChristopher Kilgour  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*8f3e7eeaSChristopher Kilgour  * GNU General Public License for more details.
16*8f3e7eeaSChristopher Kilgour  *
17*8f3e7eeaSChristopher Kilgour  * You should have received a copy of the GNU General Public License
18*8f3e7eeaSChristopher Kilgour  * along with libbtbb; see the file COPYING.  If not, write to
19*8f3e7eeaSChristopher Kilgour  * the Free Software Foundation, Inc., 51 Franklin Street,
20*8f3e7eeaSChristopher Kilgour  * Boston, MA 02110-1301, USA.
21*8f3e7eeaSChristopher Kilgour  */
22*8f3e7eeaSChristopher Kilgour 
23*8f3e7eeaSChristopher Kilgour #include "pcapng.h"
24*8f3e7eeaSChristopher Kilgour 
25*8f3e7eeaSChristopher Kilgour #include <errno.h>
26*8f3e7eeaSChristopher Kilgour #include <fcntl.h>
27*8f3e7eeaSChristopher Kilgour #include <string.h>
28*8f3e7eeaSChristopher Kilgour #include <sys/mman.h>
29*8f3e7eeaSChristopher Kilgour #include <sys/stat.h>
30*8f3e7eeaSChristopher Kilgour #include <sys/types.h>
31*8f3e7eeaSChristopher Kilgour #include <unistd.h>
32*8f3e7eeaSChristopher Kilgour 
33*8f3e7eeaSChristopher Kilgour static option_header padopt = {
34*8f3e7eeaSChristopher Kilgour 	.option_code = 0xffff,
35*8f3e7eeaSChristopher Kilgour };
36*8f3e7eeaSChristopher Kilgour 
37*8f3e7eeaSChristopher Kilgour PCAPNG_RESULT pcapng_create( PCAPNG_HANDLE * handle,
38*8f3e7eeaSChristopher Kilgour 			     const char * filename,
39*8f3e7eeaSChristopher Kilgour 			     const option_header * section_options,
40*8f3e7eeaSChristopher Kilgour 			     const size_t section_options_space,
41*8f3e7eeaSChristopher Kilgour 			     const uint16_t link_type,
42*8f3e7eeaSChristopher Kilgour 			     const uint32_t snaplen,
43*8f3e7eeaSChristopher Kilgour 			     const option_header * interface_options,
44*8f3e7eeaSChristopher Kilgour 			     const size_t interface_options_space )
45*8f3e7eeaSChristopher Kilgour {
46*8f3e7eeaSChristopher Kilgour 	PCAPNG_RESULT retval = PCAPNG_OK;
47*8f3e7eeaSChristopher Kilgour 	int PGSZ = getpagesize( );
48*8f3e7eeaSChristopher Kilgour 	size_t zeroes = 0, result = -1;
49*8f3e7eeaSChristopher Kilgour 
50*8f3e7eeaSChristopher Kilgour 	handle->section_header = NULL;
51*8f3e7eeaSChristopher Kilgour 	handle->interface_description = NULL;
52*8f3e7eeaSChristopher Kilgour 	handle->section_header_size = handle->next_section_option_offset =
53*8f3e7eeaSChristopher Kilgour 		handle->interface_description_size =
54*8f3e7eeaSChristopher Kilgour 		handle->next_interface_option_offset = 0;
55*8f3e7eeaSChristopher Kilgour 
56*8f3e7eeaSChristopher Kilgour 	handle->fd = open( filename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP );
57*8f3e7eeaSChristopher Kilgour 	if (handle->fd == -1) {
58*8f3e7eeaSChristopher Kilgour 		switch( errno ) {
59*8f3e7eeaSChristopher Kilgour 		case EEXIST:
60*8f3e7eeaSChristopher Kilgour 			retval = PCAPNG_FILE_EXISTS;
61*8f3e7eeaSChristopher Kilgour 			break;
62*8f3e7eeaSChristopher Kilgour 		case EMFILE:
63*8f3e7eeaSChristopher Kilgour 		case ENFILE:
64*8f3e7eeaSChristopher Kilgour 			retval = PCAPNG_TOO_MANY_FILES_OPEN;
65*8f3e7eeaSChristopher Kilgour 			break;
66*8f3e7eeaSChristopher Kilgour 		case ENOMEM:
67*8f3e7eeaSChristopher Kilgour 		case ENOSPC:
68*8f3e7eeaSChristopher Kilgour 			retval = PCAPNG_NO_MEMORY;
69*8f3e7eeaSChristopher Kilgour 			break;
70*8f3e7eeaSChristopher Kilgour 		default:
71*8f3e7eeaSChristopher Kilgour 			retval = PCAPNG_FILE_NOT_ALLOWED;
72*8f3e7eeaSChristopher Kilgour 		}
73*8f3e7eeaSChristopher Kilgour 	}
74*8f3e7eeaSChristopher Kilgour 
75*8f3e7eeaSChristopher Kilgour 	if (retval == PCAPNG_OK) {
76*8f3e7eeaSChristopher Kilgour 		/* section header */
77*8f3e7eeaSChristopher Kilgour 		const section_header_block shb = {
78*8f3e7eeaSChristopher Kilgour 			.block_type = BLOCK_TYPE_SECTION_HEADER,
79*8f3e7eeaSChristopher Kilgour 			.block_total_length = 28,
80*8f3e7eeaSChristopher Kilgour 			.byte_order_magic = SECTION_HEADER_BYTE_ORDER_MAGIC,
81*8f3e7eeaSChristopher Kilgour 			.major_version = 1,
82*8f3e7eeaSChristopher Kilgour 			.minor_version = 0,
83*8f3e7eeaSChristopher Kilgour 			.section_length = (uint64_t) -1,
84*8f3e7eeaSChristopher Kilgour 		};
85*8f3e7eeaSChristopher Kilgour 		handle->section_header_size = sizeof( shb );
86*8f3e7eeaSChristopher Kilgour 		result = write( handle->fd, &shb, sizeof( shb ) );
87*8f3e7eeaSChristopher Kilgour 		/* write initial section options */
88*8f3e7eeaSChristopher Kilgour 		while ((result != -1) &&
89*8f3e7eeaSChristopher Kilgour 		       section_options &&
90*8f3e7eeaSChristopher Kilgour 		       section_options->option_code &&
91*8f3e7eeaSChristopher Kilgour 		       section_options->option_length) {
92*8f3e7eeaSChristopher Kilgour 			size_t paddedsz = 4*((section_options->option_length+3)/4);
93*8f3e7eeaSChristopher Kilgour 			zeroes = paddedsz - section_options->option_length;
94*8f3e7eeaSChristopher Kilgour 			result = write( handle->fd, section_options, 4+section_options->option_length );
95*8f3e7eeaSChristopher Kilgour 			while ((zeroes > 0) && (result != -1)) {
96*8f3e7eeaSChristopher Kilgour 				result = write( handle->fd, "\0", 1 );
97*8f3e7eeaSChristopher Kilgour 				zeroes--;
98*8f3e7eeaSChristopher Kilgour 			}
99*8f3e7eeaSChristopher Kilgour 			section_options = (const option_header *) &((uint8_t *)section_options)[4+paddedsz];
100*8f3e7eeaSChristopher Kilgour 			handle->section_header_size += (4+paddedsz);
101*8f3e7eeaSChristopher Kilgour 		}
102*8f3e7eeaSChristopher Kilgour 		handle->next_section_option_offset = handle->section_header_size;
103*8f3e7eeaSChristopher Kilgour 	}
104*8f3e7eeaSChristopher Kilgour 
105*8f3e7eeaSChristopher Kilgour 	if (result == -1) {
106*8f3e7eeaSChristopher Kilgour 		retval = PCAPNG_FILE_WRITE_ERROR;
107*8f3e7eeaSChristopher Kilgour 	}
108*8f3e7eeaSChristopher Kilgour 	else {
109*8f3e7eeaSChristopher Kilgour 		/* determine the size of section header with desired space */
110*8f3e7eeaSChristopher Kilgour 		zeroes = (size_t) PGSZ*((handle->section_header_size + 4 +
111*8f3e7eeaSChristopher Kilgour 					 section_options_space + PGSZ - 1)/PGSZ) -
112*8f3e7eeaSChristopher Kilgour 			handle->section_header_size;
113*8f3e7eeaSChristopher Kilgour 		handle->section_header_size += zeroes;
114*8f3e7eeaSChristopher Kilgour 		while ((zeroes > 0) && (result != -1)) {
115*8f3e7eeaSChristopher Kilgour 			result = write( handle->fd, "\0", 1 );
116*8f3e7eeaSChristopher Kilgour 			zeroes--;
117*8f3e7eeaSChristopher Kilgour 		}
118*8f3e7eeaSChristopher Kilgour 
119*8f3e7eeaSChristopher Kilgour 		/* mmap the section header */
120*8f3e7eeaSChristopher Kilgour 		handle->section_header = mmap( NULL, handle->section_header_size,
121*8f3e7eeaSChristopher Kilgour 					       PROT_READ|PROT_WRITE,
122*8f3e7eeaSChristopher Kilgour 					       MAP_SHARED,
123*8f3e7eeaSChristopher Kilgour 					       handle->fd, 0 );
124*8f3e7eeaSChristopher Kilgour 	}
125*8f3e7eeaSChristopher Kilgour 
126*8f3e7eeaSChristopher Kilgour 	if (retval == PCAPNG_OK) {
127*8f3e7eeaSChristopher Kilgour 		if (result == -1) {
128*8f3e7eeaSChristopher Kilgour 			retval = PCAPNG_FILE_WRITE_ERROR;
129*8f3e7eeaSChristopher Kilgour 		}
130*8f3e7eeaSChristopher Kilgour 		else if (handle->section_header == MAP_FAILED) {
131*8f3e7eeaSChristopher Kilgour 			retval = PCAPNG_MMAP_FAILED;
132*8f3e7eeaSChristopher Kilgour 		}
133*8f3e7eeaSChristopher Kilgour 		else {
134*8f3e7eeaSChristopher Kilgour 			/* write the interface header */
135*8f3e7eeaSChristopher Kilgour 			const interface_description_block idb = {
136*8f3e7eeaSChristopher Kilgour 				.block_type = BLOCK_TYPE_INTERFACE,
137*8f3e7eeaSChristopher Kilgour 				.block_total_length = 0,
138*8f3e7eeaSChristopher Kilgour 				.link_type = link_type,
139*8f3e7eeaSChristopher Kilgour 				.snaplen = snaplen
140*8f3e7eeaSChristopher Kilgour 			};
141*8f3e7eeaSChristopher Kilgour 			handle->interface_description_size = sizeof( idb );
142*8f3e7eeaSChristopher Kilgour 			result = write( handle->fd, &idb, sizeof( idb ) );
143*8f3e7eeaSChristopher Kilgour 
144*8f3e7eeaSChristopher Kilgour 			/* write interface options */
145*8f3e7eeaSChristopher Kilgour 			while ((result != -1) &&
146*8f3e7eeaSChristopher Kilgour 			       interface_options &&
147*8f3e7eeaSChristopher Kilgour 			       interface_options->option_code &&
148*8f3e7eeaSChristopher Kilgour 			       interface_options->option_length) {
149*8f3e7eeaSChristopher Kilgour 				size_t paddedsz = 4*((interface_options->option_length+3)/4);
150*8f3e7eeaSChristopher Kilgour 				zeroes = paddedsz - interface_options->option_length;
151*8f3e7eeaSChristopher Kilgour 				result = write( handle->fd, interface_options, 4+interface_options->option_length );
152*8f3e7eeaSChristopher Kilgour 				while ((zeroes > 0) && (result != -1)) {
153*8f3e7eeaSChristopher Kilgour 					result = write( handle->fd, "\0", 1 );
154*8f3e7eeaSChristopher Kilgour 					zeroes--;
155*8f3e7eeaSChristopher Kilgour 				}
156*8f3e7eeaSChristopher Kilgour 				interface_options = (const option_header *) &((uint8_t *)interface_options)[4+paddedsz];
157*8f3e7eeaSChristopher Kilgour 				handle->interface_description_size += (4+paddedsz);
158*8f3e7eeaSChristopher Kilgour 			}
159*8f3e7eeaSChristopher Kilgour 			handle->next_interface_option_offset = handle->interface_description_size;
160*8f3e7eeaSChristopher Kilgour 		}
161*8f3e7eeaSChristopher Kilgour 	}
162*8f3e7eeaSChristopher Kilgour 
163*8f3e7eeaSChristopher Kilgour 	if (retval == PCAPNG_OK) {
164*8f3e7eeaSChristopher Kilgour 		if (result == -1) {
165*8f3e7eeaSChristopher Kilgour 			retval = PCAPNG_FILE_WRITE_ERROR;
166*8f3e7eeaSChristopher Kilgour 		}
167*8f3e7eeaSChristopher Kilgour 		else {
168*8f3e7eeaSChristopher Kilgour 			/* determine the size of interface description with desired space */
169*8f3e7eeaSChristopher Kilgour 			zeroes = (size_t) PGSZ*((handle->interface_description_size + 4 +
170*8f3e7eeaSChristopher Kilgour 						 interface_options_space + PGSZ - 1)/PGSZ) -
171*8f3e7eeaSChristopher Kilgour 				handle->interface_description_size;
172*8f3e7eeaSChristopher Kilgour 			handle->interface_description_size += zeroes;
173*8f3e7eeaSChristopher Kilgour 			while ((zeroes > 0) && (result != -1)) {
174*8f3e7eeaSChristopher Kilgour 				result = write( handle->fd, "\0", 1 );
175*8f3e7eeaSChristopher Kilgour 				zeroes--;
176*8f3e7eeaSChristopher Kilgour 			}
177*8f3e7eeaSChristopher Kilgour 
178*8f3e7eeaSChristopher Kilgour 			/* mmap the interface description */
179*8f3e7eeaSChristopher Kilgour 			handle->interface_description = mmap( NULL, handle->interface_description_size,
180*8f3e7eeaSChristopher Kilgour 							      PROT_READ|PROT_WRITE,
181*8f3e7eeaSChristopher Kilgour 							      MAP_SHARED,
182*8f3e7eeaSChristopher Kilgour 							      handle->fd,
183*8f3e7eeaSChristopher Kilgour 							      handle->section_header_size );
184*8f3e7eeaSChristopher Kilgour 		}
185*8f3e7eeaSChristopher Kilgour 	}
186*8f3e7eeaSChristopher Kilgour 
187*8f3e7eeaSChristopher Kilgour 	if (retval == PCAPNG_OK) {
188*8f3e7eeaSChristopher Kilgour 		if (result == -1) {
189*8f3e7eeaSChristopher Kilgour 			retval = PCAPNG_FILE_WRITE_ERROR;
190*8f3e7eeaSChristopher Kilgour 		}
191*8f3e7eeaSChristopher Kilgour 		else if (handle->interface_description == MAP_FAILED) {
192*8f3e7eeaSChristopher Kilgour 			retval = PCAPNG_MMAP_FAILED;
193*8f3e7eeaSChristopher Kilgour 		}
194*8f3e7eeaSChristopher Kilgour 		else {
195*8f3e7eeaSChristopher Kilgour 			uint8_t * dest = &((uint8_t *)handle->section_header)[handle->next_section_option_offset];
196*8f3e7eeaSChristopher Kilgour 			padopt.option_length = handle->section_header_size -
197*8f3e7eeaSChristopher Kilgour 				handle->next_section_option_offset - 12;
198*8f3e7eeaSChristopher Kilgour 
199*8f3e7eeaSChristopher Kilgour 			/* Add padding options, update the header sizes. */
200*8f3e7eeaSChristopher Kilgour 			(void) memcpy( dest, &padopt, sizeof( padopt ) );
201*8f3e7eeaSChristopher Kilgour 			handle->section_header->block_total_length =
202*8f3e7eeaSChristopher Kilgour 				(uint32_t) handle->section_header_size;
203*8f3e7eeaSChristopher Kilgour 			((uint32_t*)handle->section_header)[handle->section_header_size/4-1] =
204*8f3e7eeaSChristopher Kilgour 				(uint32_t) handle->section_header_size;
205*8f3e7eeaSChristopher Kilgour 
206*8f3e7eeaSChristopher Kilgour 			padopt.option_length = handle->interface_description_size -
207*8f3e7eeaSChristopher Kilgour 				handle->next_interface_option_offset - 12;
208*8f3e7eeaSChristopher Kilgour 			dest = &((uint8_t *)handle->interface_description)[handle->next_interface_option_offset];
209*8f3e7eeaSChristopher Kilgour 			(void) memcpy( dest, &padopt, sizeof( padopt ) );
210*8f3e7eeaSChristopher Kilgour 			handle->interface_description->block_total_length =
211*8f3e7eeaSChristopher Kilgour 				(uint32_t) handle->interface_description_size;
212*8f3e7eeaSChristopher Kilgour 			((uint32_t*)handle->interface_description)[handle->interface_description_size/4-1] =
213*8f3e7eeaSChristopher Kilgour 				(uint32_t) handle->interface_description_size;
214*8f3e7eeaSChristopher Kilgour 
215*8f3e7eeaSChristopher Kilgour 			handle->section_header->section_length = (uint64_t) handle->interface_description_size;
216*8f3e7eeaSChristopher Kilgour 		}
217*8f3e7eeaSChristopher Kilgour 	}
218*8f3e7eeaSChristopher Kilgour 
219*8f3e7eeaSChristopher Kilgour 	if (retval != PCAPNG_OK) {
220*8f3e7eeaSChristopher Kilgour 		(void) pcapng_close( handle );
221*8f3e7eeaSChristopher Kilgour 	}
222*8f3e7eeaSChristopher Kilgour 
223*8f3e7eeaSChristopher Kilgour 	return retval;
224*8f3e7eeaSChristopher Kilgour }
225*8f3e7eeaSChristopher Kilgour 
226*8f3e7eeaSChristopher Kilgour PCAPNG_RESULT pcapng_append_section_option( PCAPNG_HANDLE * handle,
227*8f3e7eeaSChristopher Kilgour 					    const option_header * section_option )
228*8f3e7eeaSChristopher Kilgour {
229*8f3e7eeaSChristopher Kilgour 	PCAPNG_RESULT retval = PCAPNG_OK;
230*8f3e7eeaSChristopher Kilgour 	if (handle && (handle->fd != -1)) {
231*8f3e7eeaSChristopher Kilgour 		if (handle->section_header &&
232*8f3e7eeaSChristopher Kilgour 		    (handle->section_header != MAP_FAILED) &&
233*8f3e7eeaSChristopher Kilgour 		    handle->next_section_option_offset &&
234*8f3e7eeaSChristopher Kilgour 		    section_option) {
235*8f3e7eeaSChristopher Kilgour 			size_t copysz = 4+section_option->option_length;
236*8f3e7eeaSChristopher Kilgour 			uint8_t * dest = &((uint8_t *)handle->section_header)[handle->next_section_option_offset];
237*8f3e7eeaSChristopher Kilgour 			(void) memcpy( dest, section_option, copysz );
238*8f3e7eeaSChristopher Kilgour 			handle->next_section_option_offset += 4*((copysz+3)/4);
239*8f3e7eeaSChristopher Kilgour 
240*8f3e7eeaSChristopher Kilgour 			/* update padding option */
241*8f3e7eeaSChristopher Kilgour 			dest = &((uint8_t *)handle->section_header)[handle->next_section_option_offset];
242*8f3e7eeaSChristopher Kilgour 			padopt.option_length = handle->section_header_size -
243*8f3e7eeaSChristopher Kilgour 				handle->next_section_option_offset - 12;
244*8f3e7eeaSChristopher Kilgour 			(void) memcpy( dest, &padopt, sizeof( padopt ) );
245*8f3e7eeaSChristopher Kilgour 		}
246*8f3e7eeaSChristopher Kilgour 		else {
247*8f3e7eeaSChristopher Kilgour 			retval = PCAPNG_NO_MEMORY;
248*8f3e7eeaSChristopher Kilgour 		}
249*8f3e7eeaSChristopher Kilgour 	}
250*8f3e7eeaSChristopher Kilgour 	else {
251*8f3e7eeaSChristopher Kilgour 		retval = PCAPNG_INVALID_HANDLE;
252*8f3e7eeaSChristopher Kilgour 	}
253*8f3e7eeaSChristopher Kilgour 	return retval;
254*8f3e7eeaSChristopher Kilgour }
255*8f3e7eeaSChristopher Kilgour 
256*8f3e7eeaSChristopher Kilgour PCAPNG_RESULT pcapng_append_interface_option( PCAPNG_HANDLE * handle,
257*8f3e7eeaSChristopher Kilgour 					      const option_header * interface_option )
258*8f3e7eeaSChristopher Kilgour {
259*8f3e7eeaSChristopher Kilgour 	PCAPNG_RESULT retval = PCAPNG_OK;
260*8f3e7eeaSChristopher Kilgour 	if (handle && (handle->fd != -1)) {
261*8f3e7eeaSChristopher Kilgour 		if (handle->interface_description &&
262*8f3e7eeaSChristopher Kilgour 		    (handle->interface_description != MAP_FAILED) &&
263*8f3e7eeaSChristopher Kilgour 		    handle->next_interface_option_offset &&
264*8f3e7eeaSChristopher Kilgour 		    interface_option) {
265*8f3e7eeaSChristopher Kilgour 			size_t copysz = 4+interface_option->option_length;
266*8f3e7eeaSChristopher Kilgour 			uint8_t * dest = &((uint8_t *)handle->interface_description)[handle->next_interface_option_offset];
267*8f3e7eeaSChristopher Kilgour 			(void) memcpy( dest, interface_option, copysz );
268*8f3e7eeaSChristopher Kilgour 			handle->next_interface_option_offset += 4*((copysz+3)/4);
269*8f3e7eeaSChristopher Kilgour 
270*8f3e7eeaSChristopher Kilgour 			/* update padding option */
271*8f3e7eeaSChristopher Kilgour 			dest = &((uint8_t *)handle->interface_description)[handle->next_interface_option_offset];
272*8f3e7eeaSChristopher Kilgour 			padopt.option_length = handle->interface_description_size -
273*8f3e7eeaSChristopher Kilgour 				handle->next_interface_option_offset - 12;
274*8f3e7eeaSChristopher Kilgour 			(void) memcpy( dest, &padopt, sizeof( padopt ) );
275*8f3e7eeaSChristopher Kilgour 		}
276*8f3e7eeaSChristopher Kilgour 		else {
277*8f3e7eeaSChristopher Kilgour 			retval = PCAPNG_NO_MEMORY;
278*8f3e7eeaSChristopher Kilgour 		}
279*8f3e7eeaSChristopher Kilgour 	}
280*8f3e7eeaSChristopher Kilgour 	else {
281*8f3e7eeaSChristopher Kilgour 		retval = PCAPNG_INVALID_HANDLE;
282*8f3e7eeaSChristopher Kilgour 	}
283*8f3e7eeaSChristopher Kilgour 	return retval;
284*8f3e7eeaSChristopher Kilgour }
285*8f3e7eeaSChristopher Kilgour 
286*8f3e7eeaSChristopher Kilgour PCAPNG_RESULT pcapng_append_packet( PCAPNG_HANDLE * handle,
287*8f3e7eeaSChristopher Kilgour 				    const enhanced_packet_block * packet )
288*8f3e7eeaSChristopher Kilgour {
289*8f3e7eeaSChristopher Kilgour 	PCAPNG_RESULT retval = PCAPNG_OK;
290*8f3e7eeaSChristopher Kilgour 	if (handle && (handle->fd != -1)) {
291*8f3e7eeaSChristopher Kilgour 		size_t writesz = packet->block_total_length;
292*8f3e7eeaSChristopher Kilgour 		ssize_t result = write( handle->fd, packet, writesz );
293*8f3e7eeaSChristopher Kilgour 		if (result == -1) {
294*8f3e7eeaSChristopher Kilgour 			result = PCAPNG_FILE_WRITE_ERROR;
295*8f3e7eeaSChristopher Kilgour 		}
296*8f3e7eeaSChristopher Kilgour 		else {
297*8f3e7eeaSChristopher Kilgour 			handle->section_header->section_length += writesz;
298*8f3e7eeaSChristopher Kilgour 		}
299*8f3e7eeaSChristopher Kilgour 	}
300*8f3e7eeaSChristopher Kilgour 	else {
301*8f3e7eeaSChristopher Kilgour 		retval = PCAPNG_INVALID_HANDLE;
302*8f3e7eeaSChristopher Kilgour 	}
303*8f3e7eeaSChristopher Kilgour 	return retval;
304*8f3e7eeaSChristopher Kilgour }
305*8f3e7eeaSChristopher Kilgour 
306*8f3e7eeaSChristopher Kilgour PCAPNG_RESULT pcapng_close( PCAPNG_HANDLE * handle )
307*8f3e7eeaSChristopher Kilgour {
308*8f3e7eeaSChristopher Kilgour 	if (handle->interface_description &&
309*8f3e7eeaSChristopher Kilgour 	    (handle->interface_description != MAP_FAILED)) {
310*8f3e7eeaSChristopher Kilgour 		(void) munmap( handle->interface_description,
311*8f3e7eeaSChristopher Kilgour 			       handle->interface_description_size );
312*8f3e7eeaSChristopher Kilgour 	}
313*8f3e7eeaSChristopher Kilgour 	if (handle->section_header &&
314*8f3e7eeaSChristopher Kilgour 	    (handle->section_header != MAP_FAILED)) {
315*8f3e7eeaSChristopher Kilgour 		(void) munmap( handle->section_header,
316*8f3e7eeaSChristopher Kilgour 			       handle->section_header_size );
317*8f3e7eeaSChristopher Kilgour 	}
318*8f3e7eeaSChristopher Kilgour 	if (handle->fd != -1) {
319*8f3e7eeaSChristopher Kilgour 		(void) close( handle->fd );
320*8f3e7eeaSChristopher Kilgour 	}
321*8f3e7eeaSChristopher Kilgour 	return PCAPNG_OK;
322*8f3e7eeaSChristopher Kilgour }
323