1 /*
2  * This file is part of libtrace
3  *
4  * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5  * New Zealand.
6  *
7  * Authors: Daniel Lawson
8  *          Perry Lorier
9  *          Shane Alcock
10  *
11  * All rights reserved.
12  *
13  * This code has been developed by the University of Waikato WAND
14  * research group. For further information please see http://www.wand.net.nz/
15  *
16  * libtrace is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * libtrace is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with libtrace; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29  *
30  * $Id: format_pcap.c 1859 2014-02-20 21:38:06Z salcock $
31  *
32  */
33 
34 #include "common.h"
35 #include "config.h"
36 #include "libtrace.h"
37 #include "libtrace_int.h"
38 #include "format_helper.h"
39 
40 #include <sys/stat.h>
41 #include <assert.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <errno.h>
46 
47 #ifdef HAVE_PCAP_H
48 #  include <pcap.h>
49 #  ifdef HAVE_PCAP_INT_H
50 #    include <pcap-int.h>
51 #  endif
52 #endif
53 
54 /* This format module deals with traces captured using the PCAP library. This
55  * format module handles both captures from a live interface and from PCAP
56  * files.
57  *
58  * However, the PCAP file support featured in this code is superceded by our
59  * own implementation of the PCAP file format, called pcapfile. See
60  * format_pcapfile.c for more information.
61  *
62  * Both the live and trace formats support writing, provided your PCAP library
63  * also supports it.
64  *
65  */
66 
67 /* Formats implemented in this module:
68  * 	pcap - deals with PCAP trace files
69  * 	pcapint - deals with live PCAP interfaces
70  */
71 
72 #ifdef HAVE_LIBPCAP
73 static struct libtrace_format_t pcap;
74 static struct libtrace_format_t pcapint;
75 
76 #define DATA(x) ((struct pcap_format_data_t*)((x)->format_data))
77 #define DATAOUT(x) ((struct pcap_format_data_out_t*)((x)->format_data))
78 
79 #define INPUT DATA(libtrace)->input
80 #define OUTPUT DATAOUT(libtrace)->output
81 struct pcap_format_data_t {
82 	/** Information about the current state of the input trace */
83         union {
84                 /* The PCAP input source */
85 		pcap_t *pcap;
86         } input;
87 	/* A filter to be applied to all packets read from the source */
88 	libtrace_filter_t *filter;
89 	/* The snap length to be applied to all captured packets (live only) */
90 	int snaplen;
91 	/* Whether the capture interface should be set to promiscuous mode
92 	 * (live only) */
93 	int promisc;
94 };
95 
96 struct pcap_format_data_out_t {
97 	/* Information about the current state of the output trace */
98 	union {
99 		struct {
100 			/* The PCAP output device or trace */
101 			pcap_t *pcap;
102 			/* The PCAP dumper */
103 			pcap_dumper_t *dump;
104 		} trace;
105 
106 	} output;
107 };
108 
pcap_init_input(libtrace_t * libtrace)109 static int pcap_init_input(libtrace_t *libtrace) {
110 	libtrace->format_data = malloc(sizeof(struct pcap_format_data_t));
111 
112 	INPUT.pcap = NULL;
113 	DATA(libtrace)->filter = NULL;
114 	DATA(libtrace)->snaplen = LIBTRACE_PACKET_BUFSIZE;
115 	DATA(libtrace)->promisc = 0;
116 
117 	return 0;
118 }
119 
pcap_start_input(libtrace_t * libtrace)120 static int pcap_start_input(libtrace_t *libtrace) {
121 	char errbuf[PCAP_ERRBUF_SIZE];
122 
123 
124 	/* Check if the file is already open */
125 	if (INPUT.pcap)
126 		return 0; /* success */
127 
128 	/* Open the trace file for reading */
129 	if ((INPUT.pcap =
130 		pcap_open_offline(libtrace->uridata,
131 			errbuf)) == NULL) {
132 		trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",
133 				errbuf);
134 		return -1;
135 	}
136 
137 	/* If a filter has been configured, compile and apply it */
138 	if (DATA(libtrace)->filter) {
139 		if (DATA(libtrace)->filter->flag == 0) {
140 			pcap_compile(INPUT.pcap,
141 					&DATA(libtrace)->filter->filter,
142 					DATA(libtrace)->filter->filterstring,
143 					1, 0);
144 			DATA(libtrace)->filter->flag = 1;
145 		}
146 		if (pcap_setfilter(INPUT.pcap,&DATA(libtrace)->filter->filter)
147 				== -1) {
148 			trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",
149 					pcap_geterr(INPUT.pcap));
150 			return -1;
151 		}
152 	}
153 	return 0;
154 }
155 
pcap_config_input(libtrace_t * libtrace,trace_option_t option,void * data)156 static int pcap_config_input(libtrace_t *libtrace,
157 		trace_option_t option,
158 		void *data)
159 {
160 	switch(option) {
161 		case TRACE_OPTION_FILTER:
162 			DATA(libtrace)->filter=data;
163 			return 0;
164 		case TRACE_OPTION_SNAPLEN:
165 			/* Snapping isn't supported directly, so fall thru
166 			 * and let libtrace deal with it
167 			 */
168 		case TRACE_OPTION_PROMISC:
169 			/* Can't do promisc on a trace! */
170 		case TRACE_OPTION_META_FREQ:
171 			/* No meta data for this format */
172 		case TRACE_OPTION_EVENT_REALTIME:
173 			/* We do not support this option for PCAP traces */
174 		default:
175 			return -1;
176 	}
177 	assert(0);
178 }
179 
pcap_init_output(libtrace_out_t * libtrace)180 static int pcap_init_output(libtrace_out_t *libtrace) {
181 	libtrace->format_data = malloc(sizeof(struct pcap_format_data_out_t));
182 	OUTPUT.trace.pcap = NULL;
183 	OUTPUT.trace.dump = NULL;
184 	return 0;
185 }
186 
pcapint_init_output(libtrace_out_t * libtrace)187 static int pcapint_init_output(libtrace_out_t *libtrace) {
188 #ifdef HAVE_PCAP_INJECT
189 	libtrace->format_data = malloc(sizeof(struct pcap_format_data_out_t));
190 	OUTPUT.trace.pcap = NULL;
191 	OUTPUT.trace.dump = NULL;
192 	return 0;
193 #else
194 #ifdef HAVE_PCAP_SENDPACKET
195 	libtrace->format_data = malloc(sizeof(struct pcap_format_data_out_t));
196 	OUTPUT.trace.pcap = NULL;
197 	OUTPUT.trace.dump = NULL;
198 	return 0;
199 #else
200 	trace_set_err_out(libtrace,TRACE_ERR_UNSUPPORTED,
201 			"writing not supported by this version of pcap");
202 	return -1;
203 #endif
204 #endif
205 }
206 
pcapint_init_input(libtrace_t * libtrace)207 static int pcapint_init_input(libtrace_t *libtrace) {
208 	libtrace->format_data = malloc(sizeof(struct pcap_format_data_t));
209 	DATA(libtrace)->filter = NULL;
210 	DATA(libtrace)->snaplen = LIBTRACE_PACKET_BUFSIZE;
211 	DATA(libtrace)->promisc = 0;
212 	return 0; /* success */
213 }
214 
pcapint_config_input(libtrace_t * libtrace,trace_option_t option,void * data)215 static int pcapint_config_input(libtrace_t *libtrace,
216 		trace_option_t option,
217 		void *data)
218 {
219 	switch(option) {
220 		case TRACE_OPTION_FILTER:
221 			DATA(libtrace)->filter=(libtrace_filter_t*)data;
222 			return 0;
223 		case TRACE_OPTION_SNAPLEN:
224 			DATA(libtrace)->snaplen=*(int*)data;
225 			return 0;
226 		case TRACE_OPTION_PROMISC:
227 			DATA(libtrace)->promisc=*(int*)data;
228 			return 0;
229 		case TRACE_OPTION_META_FREQ:
230 			/* No meta-data for this format */
231 		case TRACE_OPTION_EVENT_REALTIME:
232 			/* live interface is always real-time! */
233 		default:
234 			/* Don't set an error here - trace_config will try
235 			 * to handle the option when we return. If it can't
236 			 * deal with it, then it will do the necessary
237 			 * error-setting. */
238 			return -1;
239 	}
240 	assert(0);
241 }
242 
pcapint_start_input(libtrace_t * libtrace)243 static int pcapint_start_input(libtrace_t *libtrace) {
244 	char errbuf[PCAP_ERRBUF_SIZE];
245 
246 #ifdef HAVE_PCAP_CREATE
247 	int ret = 0;
248 
249 	if ((INPUT.pcap = pcap_create(libtrace->uridata, errbuf)) == NULL) {
250 		trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf);
251 		return -1; /* failure */
252 	}
253 	if ((pcap_set_snaplen(INPUT.pcap, DATA(libtrace)->snaplen) ==
254 				PCAP_ERROR_ACTIVATED)) {
255 		trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf);
256 		return -1; /* failure */
257 	}
258 
259 	if ((pcap_set_promisc(INPUT.pcap, DATA(libtrace)->promisc) ==
260 				PCAP_ERROR_ACTIVATED)) {
261 		trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf);
262 		return -1; /* failure */
263 	}
264 
265 	if ((pcap_set_timeout(INPUT.pcap, 1) == PCAP_ERROR_ACTIVATED)) {
266 		trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf);
267 		return -1; /* failure */
268 	}
269 
270 	if ((ret = pcap_activate(INPUT.pcap)) != 0) {
271 		if (ret == PCAP_WARNING_PROMISC_NOTSUP) {
272 			trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,"Promiscuous mode unsupported");
273 			return -1;
274 		}
275 		if (ret == PCAP_WARNING) {
276 			pcap_perror(INPUT.pcap, "Pcap Warning:");
277 		} else {
278 			trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",
279 					pcap_geterr(INPUT.pcap));
280 			return -1;
281 		}
282 	}
283 
284 #else
285 
286 	/* Open the live device */
287 	if ((INPUT.pcap =
288 			pcap_open_live(libtrace->uridata,
289 			DATA(libtrace)->snaplen,
290 			DATA(libtrace)->promisc,
291 			1,
292 			errbuf)) == NULL) {
293 		trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf);
294 		return -1; /* failure */
295 	}
296 #endif
297 	/* Set a filter if one is defined */
298 	if (DATA(libtrace)->filter) {
299 		if (DATA(libtrace)->filter->flag == 0) {
300 			pcap_compile(INPUT.pcap,
301 					&DATA(libtrace)->filter->filter,
302 					DATA(libtrace)->filter->filterstring,
303 					1, 0);
304 			DATA(libtrace)->filter->flag = 1;
305 		}
306 		if (pcap_setfilter(INPUT.pcap,&DATA(libtrace)->filter->filter)
307 			== -1) {
308 			trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",
309 					pcap_geterr(INPUT.pcap));
310 			return -1; /* failure */
311 		}
312 	}
313 #ifdef HAVE_PCAP_SETNONBLOCK
314 	pcap_setnonblock(INPUT.pcap,0,errbuf);
315 #endif
316 	return 0; /* success */
317 }
318 
pcap_pause_input(libtrace_t * libtrace)319 static int pcap_pause_input(libtrace_t *libtrace)
320 {
321 	pcap_close(INPUT.pcap);
322 	INPUT.pcap=NULL;
323 	return 0; /* success */
324 }
325 
326 
pcap_fin_input(libtrace_t * libtrace)327 static int pcap_fin_input(libtrace_t *libtrace)
328 {
329 	free(libtrace->format_data);
330 	return 0; /* success */
331 }
332 
pcap_fin_output(libtrace_out_t * libtrace)333 static int pcap_fin_output(libtrace_out_t *libtrace)
334 {
335 	if (OUTPUT.trace.dump) {
336 		pcap_dump_flush(OUTPUT.trace.dump);
337 		pcap_dump_close(OUTPUT.trace.dump);
338 	}
339 	pcap_close(OUTPUT.trace.pcap);
340 	free(libtrace->format_data);
341 	return 0;
342 }
343 
pcapint_fin_output(libtrace_out_t * libtrace)344 static int pcapint_fin_output(libtrace_out_t *libtrace)
345 {
346 	pcap_close(OUTPUT.trace.pcap);
347 	free(libtrace->format_data);
348 	return 0;
349 }
350 
pcap_prepare_packet(libtrace_t * libtrace,libtrace_packet_t * packet,void * buffer,libtrace_rt_types_t rt_type,uint32_t flags)351 static int pcap_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
352 		void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
353 
354 	if (packet->buffer != buffer &&
355 			packet->buf_control == TRACE_CTRL_PACKET) {
356 			free(packet->buffer);
357 	}
358 
359 	if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
360 		packet->buf_control = TRACE_CTRL_PACKET;
361 	} else
362 		packet->buf_control = TRACE_CTRL_EXTERNAL;
363 
364 
365 	packet->buffer = buffer;
366 	packet->header = buffer;
367 	packet->type = rt_type;
368 
369 	/* Assuming header and payload are sequential in the buffer -
370 	 * regular pcap often doesn't work like this though, so hopefully
371 	 * we're not called by something that is reading genuine pcap! */
372 	packet->payload = (char *)packet->header + sizeof(struct pcap_pkthdr);
373 
374 	if (libtrace->format_data == NULL) {
375 		if (pcap_init_input(libtrace))
376 			return -1;
377 	}
378 	return 0;
379 }
380 
pcap_read_packet(libtrace_t * libtrace,libtrace_packet_t * packet)381 static int pcap_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
382 	int ret = 0;
383 	int linktype;
384 	uint32_t flags = 0;
385 
386 	assert(libtrace->format_data);
387 	linktype = pcap_datalink(DATA(libtrace)->input.pcap);
388 	packet->type = pcap_linktype_to_rt(linktype);
389 
390 	/* If we're using the replacement pcap_next_ex() we need to
391 	 * make sure we have a buffer to *shudder* memcpy into
392 	 */
393 	if (!packet->buffer) {
394 		packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
395 		if (!packet->buffer) {
396 			trace_set_err(libtrace, errno,
397 					"Cannot allocate memory");
398 			return -1;
399 		}
400 		packet->header = packet->buffer;
401 		packet->payload = (char *)packet->buffer+sizeof(struct pcap_pkthdr);
402 
403 	}
404 
405 	flags |= TRACE_PREP_OWN_BUFFER;
406 
407 	for(;;) {
408 
409 		struct pcap_pkthdr *pcap_hdr = NULL;
410 		u_char *pcap_payload = NULL;
411 
412 		ret = pcap_next_ex(INPUT.pcap, &pcap_hdr,
413 				(const u_char **)&pcap_payload);
414 
415 		packet->header = pcap_hdr;
416 		packet->payload = pcap_payload;
417 
418 		switch(ret) {
419 			case 1: break; /* no error */
420 			case 0:
421 				if (libtrace_halt)
422 					return 0;
423 				continue; /* timeout expired */
424 			case -1:
425 				trace_set_err(libtrace,TRACE_ERR_BAD_PACKET,
426 						"%s",pcap_geterr(INPUT.pcap));
427 				return -1; /* Error */
428 			case -2:
429 				return 0; /* EOF */
430 		}
431 
432 		/*
433 		 * pcap is nasty in that the header and payload aren't
434 		 * necessarily located sequentially in memory, but most
435 		 * sensible uses of pcap_prepare_packet will involve a
436 		 * buffer where header and payload are sequential.
437 		 *
438 		 * Basically, don't call pcap_prepare_packet here!
439 		 *
440 		if (pcap_prepare_packet(libtrace, packet, packet->buffer,
441 				packet->type, flags)) {
442 			return -1;
443 		}
444 		*/
445 		return ((struct pcap_pkthdr*)packet->header)->len
446 			+sizeof(struct pcap_pkthdr);
447 	}
448 }
449 
pcap_write_packet(libtrace_out_t * libtrace,libtrace_packet_t * packet)450 static int pcap_write_packet(libtrace_out_t *libtrace,
451 		libtrace_packet_t *packet)
452 {
453 	struct pcap_pkthdr pcap_pkt_hdr;
454 	void *link;
455 	libtrace_linktype_t linktype;
456 	uint32_t remaining;
457 
458 	link = trace_get_packet_buffer(packet,&linktype,&remaining);
459 
460 	/* We may have to convert this packet into a suitable PCAP packet */
461 
462 	/* If this packet cannot be converted to a pcap linktype then
463 	 * pop off the top header until it can be converted
464 	 */
465 	while (libtrace_to_pcap_linktype(linktype)==TRACE_DLT_ERROR) {
466 		if (!demote_packet(packet)) {
467 			trace_set_err_out(libtrace,
468 				TRACE_ERR_NO_CONVERSION,
469 				"pcap does not support this format");
470 			return -1;
471 		}
472 
473 		link = trace_get_packet_buffer(packet,&linktype,&remaining);
474 	}
475 
476 
477 	if (!OUTPUT.trace.pcap) {
478 		int linktype=libtrace_to_pcap_dlt(trace_get_link_type(packet));
479 		OUTPUT.trace.pcap = pcap_open_dead(linktype,65536);
480 		if (!OUTPUT.trace.pcap) {
481 			trace_set_err_out(libtrace,TRACE_ERR_INIT_FAILED,
482 					"Failed to open dead trace: %s\n",
483 					pcap_geterr(OUTPUT.trace.pcap));
484 		}
485 		OUTPUT.trace.dump = pcap_dump_open(OUTPUT.trace.pcap,
486 				libtrace->uridata);
487 		if (!OUTPUT.trace.dump) {
488 			char *errmsg = pcap_geterr(OUTPUT.trace.pcap);
489 			trace_set_err_out(libtrace,TRACE_ERR_INIT_FAILED,"Failed to open output file: %s\n",
490 					errmsg ? errmsg : "Unknown error");
491 			return -1;
492 		}
493 	}
494 
495 	/* Corrupt packet, or other "non data" packet, so skip it */
496 	if (link == NULL) {
497 		/* Return "success", but nothing written */
498 		return 0;
499 	}
500 
501 	/* Check if the packet was captured using one of the PCAP formats */
502 	if (packet->trace->format == &pcap ||
503 			packet->trace->format == &pcapint) {
504 		/* Yes - this means we can write it straight out */
505 		pcap_dump((u_char*)OUTPUT.trace.dump,
506 				(struct pcap_pkthdr *)packet->header,
507 				packet->payload);
508 	} else {
509 		/* No - need to fill in a PCAP header with the appropriate
510 		 * values */
511 
512 		/* Leave the manual copy as it is, as it gets around
513 		 * some OS's having different structures in pcap_pkt_hdr
514 		 */
515 		struct timeval ts = trace_get_timeval(packet);
516 		pcap_pkt_hdr.ts.tv_sec = ts.tv_sec;
517 		pcap_pkt_hdr.ts.tv_usec = ts.tv_usec;
518 		pcap_pkt_hdr.caplen = remaining;
519 		/* trace_get_wire_length includes FCS, while pcap doesn't */
520 		if (trace_get_link_type(packet)==TRACE_TYPE_ETH)
521 			if (trace_get_wire_length(packet) >= 4) {
522 				pcap_pkt_hdr.len =
523 					trace_get_wire_length(packet)-4;
524 			}
525 			else {
526 				pcap_pkt_hdr.len = 0;
527 			}
528 		else
529 			pcap_pkt_hdr.len = trace_get_wire_length(packet);
530 
531 		assert(pcap_pkt_hdr.caplen<65536);
532 		assert(pcap_pkt_hdr.len<65536);
533 
534 		pcap_dump((u_char*)OUTPUT.trace.dump, &pcap_pkt_hdr, packet->payload);
535 	}
536 	return 0;
537 }
538 
pcapint_write_packet(libtrace_out_t * libtrace,libtrace_packet_t * packet)539 static int pcapint_write_packet(libtrace_out_t *libtrace,
540 		libtrace_packet_t *packet)
541 {
542 	int err;
543 
544 	if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
545 		return 0;
546 
547 	if (!OUTPUT.trace.pcap) {
548 		OUTPUT.trace.pcap = (pcap_t *)pcap_open_live(
549 			libtrace->uridata,65536,0,0,NULL);
550 	}
551 #ifdef HAVE_PCAP_INJECT
552 	err=pcap_inject(OUTPUT.trace.pcap,
553 			packet->payload,
554 			trace_get_capture_length(packet));
555 	if (err!=(int)trace_get_capture_length(packet))
556 		err=-1;
557 #else
558 #ifdef HAVE_PCAP_SENDPACKET
559 	err=pcap_sendpacket(OUTPUT.trace.pcap,
560 			packet->payload,
561 			trace_get_capture_length(packet));
562 #else
563     trace_set_err(packet->trace,TRACE_ERR_UNSUPPORTED,"writing is not supported on this platform");
564 	return -1;
565 #endif
566 #endif
567 	return err;
568 }
569 
pcap_get_link_type(const libtrace_packet_t * packet)570 static libtrace_linktype_t pcap_get_link_type(const libtrace_packet_t *packet) {
571 	/* PCAP doesn't store linktype in the framing header so we need
572 	 * RT to do it for us
573 	 */
574 	int linktype = rt_to_pcap_linktype(packet->type);
575 	return pcap_linktype_to_libtrace(linktype);
576 }
577 
pcap_set_direction(libtrace_packet_t * packet,libtrace_direction_t dir)578 static libtrace_direction_t pcap_set_direction(libtrace_packet_t *packet,
579 		libtrace_direction_t dir) {
580 
581 	/* PCAP doesn't have a direction field in the header, so we need to
582 	 * promote to Linux SLL to tag it properly */
583 	libtrace_sll_header_t *sll;
584 	promote_packet(packet);
585 	sll=packet->payload;
586 
587 	/* sll->pkttype should be in the endianness of the host that the
588 	 * trace was taken on.  This is impossible to achieve so we assume
589 	 * host endianness
590 	 */
591 	if(dir==TRACE_DIR_OUTGOING)
592 		sll->pkttype=TRACE_SLL_OUTGOING;
593 	else
594 		sll->pkttype=TRACE_SLL_HOST;
595 	return dir;
596 }
597 
pcap_get_direction(const libtrace_packet_t * packet)598 static libtrace_direction_t pcap_get_direction(const libtrace_packet_t *packet) {
599 	libtrace_direction_t direction  = -1;
600 	switch(pcap_get_link_type(packet)) {
601 		/* Only packets encapsulated in Linux SLL or PFLOG have any
602 		 * direction information */
603 
604 		case TRACE_TYPE_LINUX_SLL:
605 		{
606 			libtrace_sll_header_t *sll;
607 			sll = trace_get_packet_buffer(packet, NULL, NULL);
608 			/* TODO: should check remaining>=sizeof(*sll) */
609 			if (!sll) {
610 				trace_set_err(packet->trace,
611 					TRACE_ERR_BAD_PACKET,
612 						"Bad or missing packet");
613 				return -1;
614 			}
615 			/* 0 == LINUX_SLL_HOST */
616 			/* the Waikato Capture point defines "packets
617 			 * originating locally" (ie, outbound), with a
618 			 * direction of 0, and "packets destined locally"
619 			 * (ie, inbound), with a direction of 1.
620 			 * This is kind-of-opposite to LINUX_SLL.
621 			 * We return consistent values here, however
622 			 *
623 			 * Note that in recent versions of pcap, you can
624 			 * use "inbound" and "outbound" on ppp in linux
625 			 */
626 			if (sll->pkttype == TRACE_SLL_OUTGOING) {
627 				direction = TRACE_DIR_OUTGOING;
628 			} else {
629 				direction = TRACE_DIR_INCOMING;
630 			}
631 			break;
632 
633 		}
634 		case TRACE_TYPE_PFLOG:
635 		{
636 			libtrace_pflog_header_t *pflog;
637 			pflog = trace_get_packet_buffer(packet, NULL, NULL);
638 			/* TODO: should check remaining >= sizeof(*pflog) */
639 			if (!pflog) {
640 				trace_set_err(packet->trace,
641 						TRACE_ERR_BAD_PACKET,
642 						"Bad or missing packet");
643 				return -1;
644 			}
645 			/* enum    { PF_IN=0, PF_OUT=1 }; */
646 			if (ntohs(pflog->dir==0)) {
647 
648 				direction = TRACE_DIR_INCOMING;
649 			}
650 			else {
651 				direction = TRACE_DIR_OUTGOING;
652 			}
653 			break;
654 		}
655 		default:
656 			break;
657 	}
658 	return direction;
659 }
660 
661 
pcap_get_timeval(const libtrace_packet_t * packet)662 static struct timeval pcap_get_timeval(const libtrace_packet_t *packet) {
663 	struct pcap_pkthdr *pcapptr = (struct pcap_pkthdr *)packet->header;
664 	struct timeval ts;
665 	ts.tv_sec = pcapptr->ts.tv_sec;
666 	ts.tv_usec = pcapptr->ts.tv_usec;
667 	return ts;
668 }
669 
670 
pcap_get_capture_length(const libtrace_packet_t * packet)671 static int pcap_get_capture_length(const libtrace_packet_t *packet) {
672 	struct pcap_pkthdr *pcapptr = 0;
673 	pcapptr = (struct pcap_pkthdr *)packet->header;
674 	assert(pcapptr->caplen<=65536);
675 
676 	return pcapptr->caplen;
677 }
678 
pcap_get_wire_length(const libtrace_packet_t * packet)679 static int pcap_get_wire_length(const libtrace_packet_t *packet) {
680 	struct pcap_pkthdr *pcapptr = 0;
681 	pcapptr = (struct pcap_pkthdr *)packet->header;
682 	if (packet->type==pcap_linktype_to_rt(TRACE_DLT_EN10MB))
683 		return pcapptr->len+4; /* Include the missing FCS */
684 	else if (packet->type==pcap_linktype_to_rt(TRACE_DLT_IEEE802_11_RADIO)) {
685 		libtrace_linktype_t linktype;
686 		void *link = trace_get_packet_buffer(packet,&linktype,NULL);
687 		/* If the packet is Radiotap and the flags field indicates
688 		 * that the FCS is not included in the 802.11 frame, then
689 		 * we need to add 4 to the wire-length to account for it.
690 		 */
691 		uint8_t flags;
692 		trace_get_wireless_flags(link,
693 				linktype, &flags);
694 		if ((flags & TRACE_RADIOTAP_F_FCS) == 0)
695 			return pcapptr->len + 4;
696 	}
697 	return pcapptr->len;
698 }
699 
pcap_get_framing_length(UNUSED const libtrace_packet_t * packet)700 static int pcap_get_framing_length(UNUSED const libtrace_packet_t *packet) {
701 	return sizeof(struct pcap_pkthdr);
702 }
703 
pcap_set_capture_length(libtrace_packet_t * packet,size_t size)704 static size_t pcap_set_capture_length(libtrace_packet_t *packet,size_t size) {
705 	struct pcap_pkthdr *pcapptr = 0;
706 	assert(packet);
707 	if (size > trace_get_capture_length(packet)) {
708 		/* Can't make a packet larger */
709 		return trace_get_capture_length(packet);
710 	}
711 	/* Reset the cached capture length */
712 	packet->capture_length = -1;
713 	pcapptr = (struct pcap_pkthdr *)packet->header;
714 	pcapptr->caplen = size;
715 	return trace_get_capture_length(packet);
716 }
717 
pcap_get_fd(const libtrace_t * trace)718 static int pcap_get_fd(const libtrace_t *trace) {
719 
720 	assert(trace->format_data);
721 	return pcap_fileno(DATA(trace)->input.pcap);
722 }
723 
pcap_get_dropped_packets(libtrace_t * trace)724 static uint64_t pcap_get_dropped_packets(libtrace_t *trace)
725 {
726 	struct pcap_stat stats;
727 	if (pcap_stats(DATA(trace)->input.pcap,&stats)==-1) {
728 		char *errmsg = pcap_geterr(DATA(trace)->input.pcap);
729 		trace_set_err(trace,TRACE_ERR_UNSUPPORTED,
730 				"Failed to retreive stats: %s\n",
731 				errmsg ? errmsg : "Unknown pcap error");
732 		return ~0;
733 	}
734 
735 	return stats.ps_drop;
736 }
737 
pcap_help(void)738 static void pcap_help(void) {
739 	printf("pcap format module: $Revision: 1729 $\n");
740 	printf("Supported input URIs:\n");
741 	printf("\tpcap:/path/to/file\n");
742 	printf("\n");
743 	printf("\te.g.: pcap:/tmp/trace.pcap\n");
744 	printf("\n");
745 	printf("Supported output URIs:\n");
746 	printf("\tnone\n");
747 	printf("\n");
748 }
749 
pcapint_help(void)750 static void pcapint_help(void) {
751 	printf("pcapint format module: $Revision: 1729 $\n");
752 	printf("Supported input URIs:\n");
753 	printf("\tpcapint:interface\n");
754 	printf("\n");
755 	printf("\te.g.: pcapint:eth0\n");
756 	printf("\n");
757 	printf("Supported output URIs:\n");
758 	printf("\tnone\n");
759 	printf("\n");
760 }
761 
762 
763 static struct libtrace_format_t pcap = {
764 	"pcap",
765 	"$Id: format_pcap.c 1859 2014-02-20 21:38:06Z salcock $",
766 	TRACE_FORMAT_PCAP,
767 	NULL,				/* probe filename */
768 	NULL,				/* probe magic */
769 	pcap_init_input,		/* init_input */
770 	pcap_config_input,		/* config_input */
771 	pcap_start_input,		/* start_input */
772 	NULL,				/* pause_input */
773 	pcap_init_output,		/* init_output */
774 	NULL,				/* config_output */
775 	NULL,				/* start_output */
776 	pcap_fin_input,			/* fin_input */
777 	pcap_fin_output,		/* fin_output */
778 	pcap_read_packet,		/* read_packet */
779 	pcap_prepare_packet,		/* prepare_packet */
780 	NULL,				/* fin_packet */
781 	pcap_write_packet,		/* write_packet */
782 	pcap_get_link_type,		/* get_link_type */
783 	pcap_get_direction,		/* get_direction */
784 	pcap_set_direction,		/* set_direction */
785 	NULL,				/* get_erf_timestamp */
786 	pcap_get_timeval,		/* get_timeval */
787 	NULL,				/* get_seconds */
788 	NULL,				/* get_timespec */
789 	NULL,				/* seek_erf */
790 	NULL,				/* seek_timeval */
791 	NULL,				/* seek_seconds */
792 	pcap_get_capture_length,	/* get_capture_length */
793 	pcap_get_wire_length,		/* get_wire_length */
794 	pcap_get_framing_length,	/* get_framing_length */
795 	pcap_set_capture_length,	/* set_capture_length */
796 	NULL,				/* get_received_packets */
797 	NULL,				/* get_filtered_packets */
798 	NULL,				/* get_dropped_packets */
799 	NULL,				/* get_captured_packets */
800 	NULL,				/* get_fd */
801 	trace_event_trace,		/* trace_event */
802 	pcap_help,			/* help */
803 	NULL				/* next pointer */
804 };
805 
806 static struct libtrace_format_t pcapint = {
807 	"pcapint",
808 	"$Id: format_pcap.c 1859 2014-02-20 21:38:06Z salcock $",
809 	TRACE_FORMAT_PCAP,
810 	NULL,				/* probe filename */
811 	NULL,				/* probe magic */
812 	pcapint_init_input,		/* init_input */
813 	pcapint_config_input,		/* config_input */
814 	pcapint_start_input,		/* start_input */
815 	pcap_pause_input,		/* pause_input */
816 	pcapint_init_output,		/* init_output */
817 	NULL,				/* config_output */
818 	NULL,				/* start_output */
819 	pcap_fin_input,			/* fin_input */
820 	pcapint_fin_output,		/* fin_output */
821 	pcap_read_packet,		/* read_packet */
822 	pcap_prepare_packet,		/* prepare_packet */
823 	NULL,				/* fin_packet */
824 	pcapint_write_packet,		/* write_packet */
825 	pcap_get_link_type,		/* get_link_type */
826 	pcap_get_direction,		/* get_direction */
827 	pcap_set_direction,		/* set_direction */
828 	NULL,				/* get_erf_timestamp */
829 	pcap_get_timeval,		/* get_timeval */
830 	NULL,				/* get_seconds */
831 	NULL,				/* get_timespec */
832 	NULL,				/* seek_erf */
833 	NULL,				/* seek_timeval */
834 	NULL,				/* seek_seconds */
835 	pcap_get_capture_length,	/* get_capture_length */
836 	pcap_get_wire_length,		/* get_wire_length */
837 	pcap_get_framing_length,	/* get_framing_length */
838 	pcap_set_capture_length,	/* set_capture_length */
839 	NULL,				/* get_received_packets */
840 	NULL,				/* get_filtered_packets */
841 	pcap_get_dropped_packets,	/* get_dropped_packets */
842 	NULL,				/* get_captured_packets */
843 	pcap_get_fd,			/* get_fd */
844 	trace_event_device,		/* trace_event */
845 	pcapint_help,			/* help */
846 	NULL				/* next pointer */
847 };
848 
pcap_constructor(void)849 void pcap_constructor(void) {
850 	register_format(&pcap);
851 	register_format(&pcapint);
852 }
853 
854 
855 #endif
856