123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- /* $Id: pcapmerge.c 767 2004-10-06 12:48:49Z aturner $ */
- /*
- * Copyright (c) 2001-2004 Aaron Turner, Matt Bing.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the names of the copyright owners nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- /* The pcapmerge available at http://indev.insu.com/Fwctl/pcapmerge.html
- * is written in Perl and does not handle large pcaps very well. This
- * is meant to be small and efficient.
- *
- * gcc -o pcapmerge pcapmerge.c -lpcap
- *
- * usage: pcapmerge -o bigpcap pcap1 pcap2 pcap3 ..
- *
- * Tested on OpenBSD 3.1. Probably won't work on non BSD.
- */
- #include <pcap.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include "config.h"
- #include "tcpreplay.h"
- #include "err.h"
- #include "queue.h"
- /* we get this from libpcap */
- extern char pcap_version[];
- #ifdef DEBUG
- int debug = 0;
- #endif
- /* magic constants for various pcap file types */
- #define PCAP_MAGIC 0xa1b2c3d4
- #define PCAP_SWAPPED_MAGIC 0xd4c3b2a1
- #define PCAP_MODIFIED_MAGIC 0xa1b2cd34
- #define PCAP_SWAPPED_MODIFIED_MAGIC 0x34cdb2a1
- #define SWAPLONG(y) \
- ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
- #define SWAPSHORT(y) \
- ( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) )
- /* data prefixing each packet in modified pcap */
- struct pcap_mod_pkthdr {
- struct pcap_pkthdr hdr; /* normal header */
- u_int32_t ifindex; /* receiving interface index */
- u_int16_t protocol; /* ethernet packet type */
- u_int8_t pkt_type; /* ethernet packet type */
- u_int8_t pad; /* padding */
- };
- /* info about each open file */
- struct pcap_file {
- int fd;
- int modified;
- int swapped;
- char *name;
- SLIST_ENTRY(pcap_file) next;
- };
- void init_files(int, char **);
- void write_packets(struct pcap_file *, int);
- void usage();
- SLIST_HEAD(, pcap_file) files;
- struct pcap_file_header hdr;
- int outfd;
- char *outfile;
- void
- version()
- {
- fprintf(stderr, "pcapmerge version: %s\n", VERSION);
- fprintf(stderr, "Compiled against libpcap: %s\n", pcap_version);
- exit(0);
- }
- int
- main(int argc, char *argv[])
- {
- struct pcap_file *p;
- int ch, fd;
- outfile = NULL;
- while ((ch = getopt(argc, argv, "o:h?V")) != -1) {
- switch (ch) {
- case 'o': /* output file */
- outfile = optarg;
- break;
- case 'V':
- version();
- break;
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
- if (outfile == NULL)
- errx(1, "must specify output file");
- SLIST_INIT(&files);
- init_files(argc, argv);
- if ((fd = open(outfile, O_WRONLY | O_CREAT, 0644)) < 0)
- err(1, "open %s", outfile);
- /* write file header */
- if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
- err(1, "write");
- SLIST_FOREACH(p, &files, next) {
- write_packets(p, fd);
- }
- return 0;
- }
- /* Read all the file headers and set the pcap_file_header for output file */
- void
- init_files(int len, char *filelist[])
- {
- struct pcap_file_header phdr;
- struct pcap_file *file;
- int i, fd, modified, swapped;
- u_int32_t snaplen, linktype;
- snaplen = linktype = 0;
- for (i = 0; i < len; i++) {
- if ((fd = open(filelist[i], O_RDONLY, 0)) < 0) {
- warn("skipping %s: could not open", filelist[i]);
- close(fd);
- continue;
- }
- if (read(fd, (void *)&phdr, sizeof(phdr)) != sizeof(phdr)) {
- warn("skipping %s: could not read header", filelist[i]);
- close(fd);
- continue;
- }
- switch (phdr.magic) {
- case PCAP_MAGIC:
- swapped = 0;
- modified = 0;
- break;
- case PCAP_SWAPPED_MAGIC:
- swapped = 1;
- modified = 0;
- break;
- case PCAP_MODIFIED_MAGIC:
- swapped = 0;
- modified = 1;
- break;
- case PCAP_SWAPPED_MODIFIED_MAGIC:
- swapped = 1;
- modified = 1;
- break;
- default:
- warn("skipping %s: invalid pcap", filelist[i]);
- close(fd);
- continue;
- }
- /* ensure everything is in host-byte order */
- if (swapped) {
- phdr.snaplen = SWAPLONG(phdr.snaplen);
- phdr.linktype = SWAPLONG(phdr.linktype);
- }
- if (linktype == 0) {
- linktype = phdr.linktype;
- }
- else if (linktype != phdr.linktype) {
- warn("skipping %s: inconsistent linktype", filelist[i]);
- close(fd);
- continue;
- }
- /* pick the largest snaplen */
- if (phdr.snaplen > snaplen)
- snaplen = phdr.snaplen;
- if ((file = (struct pcap_file *)malloc(sizeof(*file))) == NULL)
- errx(1, "out of memory");
- file->fd = fd;
- file->modified = modified;
- file->swapped = swapped;
- file->name = filelist[i];
- SLIST_INSERT_HEAD(&files, file, next);
- }
- /* set the header for the output file */
- hdr.magic = PCAP_MAGIC;
- hdr.version_major = 2;
- hdr.version_minor = 4;
- hdr.thiszone = 0;
- hdr.sigfigs = 0;
- hdr.snaplen = snaplen;
- hdr.linktype = linktype;
- }
- void
- write_packets(struct pcap_file *p, int out)
- {
- struct pcap_pkthdr p1, *phdr;
- struct pcap_mod_pkthdr p2;
- char pkt[MAXPACKET];
- int len, ret;
- for (;;) {
- if (p->modified) {
- ret = read(p->fd, &p2, sizeof(p2));
- if (ret == -1)
- err(1, "read");
- else if (ret == 0)
- break;
- phdr = &p2.hdr;
- }
- else {
- ret = read(p->fd, &p1, sizeof(p1));
- if (ret == -1)
- err(1, "read");
- else if (ret == 0)
- break;
- phdr = &p1;
- }
- if (p->swapped) {
- len = SWAPLONG(phdr->caplen);
- phdr->ts.tv_sec = SWAPLONG(phdr->ts.tv_sec);
- phdr->ts.tv_usec = SWAPLONG(phdr->ts.tv_usec);
- phdr->caplen = SWAPLONG(phdr->caplen);
- phdr->len = SWAPLONG(phdr->len);
- }
- else {
- len = phdr->caplen;
- }
- if (len > MAXPACKET) {
- warn("skipping %s: abnormally large packet (%d bytes)", p->name,
- len);
- break;
- }
- ret = read(p->fd, pkt, len);
- if (ret == -1)
- err(1, "read");
- else if (ret == 0) {
- warn("skipping %s: truncated packet3", p->name);
- break;
- }
- if (write(out, phdr, sizeof(*phdr)) != sizeof(*phdr))
- err(1, "write");
- if (write(out, pkt, len) != len)
- err(1, "write");
- }
- close(p->fd);
- }
- void
- usage()
- {
- fprintf(stderr, "usage: pcapmerge -o bigpcap pcap1 pcap2 pcap3 ..\n");
- exit(1);
- }
|