1 /*
2  * Copyright (c) 2000 Paul Herman
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $Id: catpcap.c,v 1.6 2002/09/18 21:00:29 pherman Exp $
28  */
29 
30 #include "tcpstat.h"
31 
32 #if 0
33 #ifdef WORDS_BIGENDIAN
34 # define LAST_CHAR(x)	( (x) >> 8 )
35 # define SWAPEM(x)	( (x) )
36 #else
37 # define LAST_CHAR(x)	( (x) & 0x00ff )
38 # define SWAPEM(x)	( (((x) << 8)&0xff00) | (((x) >> 8)&0x00ff))
39 #endif
40 #endif
41 
42 #define SHOW_HIGH_BIT	0
43 
44 /* GLOBALS */
45 char filterexpr[BUF_SIZ]	= "";
46 int p_number			= 1;
47 
char_conv(char c)48 char char_conv(char c) {
49 	if (isgraph(c)) return c;
50 	if (c == ' ') return c;
51 	if ((u_char)c > 0xa1 && SHOW_HIGH_BIT) return c;
52 	return '.';
53 }
54 
proc_pcap(u_char * user,const struct pcap_pkthdr * h,const u_char * p)55 void proc_pcap(u_char *user, const struct pcap_pkthdr *h, const u_char *p) {
56 	u_int length = h->caplen, i, j, k, step;
57 	u_char *r, *s;
58 	char c;
59 
60 	r = (u_char *)p;
61 	s = (u_char *)p;
62 	step = 22;
63 	printf("%u: %lu.%.6lu, caplen %u, len %u\n",
64 		p_number++,
65 		(long unsigned int) h->ts.tv_sec,
66 		(long unsigned int) h->ts.tv_usec,
67 		h->caplen, h->len
68 		);
69 	for (i=0; i<length; ) {
70 		printf(" ");
71 		for (j=0; j<step && (j+i)<length;) {
72 			printf("%.2X", *r++);
73 			j++;
74 			if ( (j+i) == length ) {
75 				printf("   "); j++; break; }
76 			printf("%.2X ", *r++);
77 			j++;
78 			}
79 		for (k=j; k<step; k++, k++) printf("     ");
80 		printf(" ");
81 
82 		for (j=0; j<step && (j+i)<length; j++) {
83 			c = *p++;
84 			printf("%c", char_conv(c));
85 			}
86 		printf("\n");
87 		i += j;
88 		}
89 	printf("\n");
90 }
91 /*
92  * process_file() takes the output of tcpdump, saves packets, and displays
93  * statistics
94  */
process_file(char * fname,u_int unused)95 void process_file(char *fname, u_int unused) {
96 	int run = 1, i;
97 	pcap_t	*pd;
98 	char	ebuf[PCAP_ERRBUF_SIZE];
99 	struct bpf_program	bpf_prog;
100 
101 	pd = pcap_open_offline(fname, ebuf);
102 	if (pd == NULL) {
103 		fprintf(stderr, "pcap_open(): %s\n", ebuf);
104 		return;
105 		}
106 	if (pcap_compile(pd, &bpf_prog, filterexpr, 1, 0) < 0) {
107 		fprintf(stderr, "pcap_compile(): %s\n", pcap_geterr(pd));
108 		return;
109 		}
110 	if (pcap_setfilter(pd, &bpf_prog) < 0) {
111 		fprintf(stderr, "pcap_compile(): %s\n", pcap_geterr(pd));
112 		return;
113 		}
114 	printf("Pcap Version %d.%d,  Datalink 0x%.8X,  Snapshot %d, %s swapped\n",
115 		pcap_major_version(pd), pcap_minor_version(pd),
116 		pcap_datalink(pd), pcap_snapshot(pd),
117 		(pcap_is_swapped(pd))? "" : "not"
118 		);
119 	printf("-------------------------------------------------\n");
120 	while (run) {
121 		i = pcap_dispatch(pd, -1, proc_pcap, NULL);
122 		if (i == 0) run = 0;
123 		if (i == -1) {
124 			fprintf(stderr, "pcap_dispatch(): %s\n", pcap_geterr(pd));
125 			run = 0;
126 			}
127 		}
128 	pcap_close(pd);
129 }
130 
131 #define USAGE 							\
132 "Usage: %s [-?heBLITC] [-f filter expr] [-r file]		\
133 \n	-?, -h 		- display this help			\
134 \n	-f filter expr 	- filter expression to pass to tcpdump	\
135 \n	-r file 	- file to read data from		\
136 \n"
137 
Usage(int r,char * prog)138 int Usage(int r, char *prog) {
139 	fprintf(stderr, USAGE, prog); return r;
140 }
141 
error(char * s)142 void error(char *s) {
143 	fprintf(stderr, "error: %s\n", s);
144 	Usage(-1, "catpcap"); exit(-1);
145 }
146 
main(int argc,char ** argv)147 int main(int argc, char **argv) {
148 	char filename[BUF_SIZ];
149 	int ch;
150 
151 	*filename = 0;
152 	while ( (ch = getopt(argc, argv, "h?f:r:")) != -1) {
153 		switch(ch) {
154 			case 'h':
155 			case '?':
156 				return Usage(1, argv[0]);
157 				break;
158 			case 'f':
159 				strncpy(filterexpr, optarg, BUF_SIZ);
160 				break;
161 			case 'r':
162 				strncpy(filename, optarg, BUF_SIZ);
163 				break;
164 			default:
165 				return Usage(1, argv[0]);
166 				break;
167 			}
168 		}
169 
170 	if (*filename == 0) error("must specify filename");
171 
172 	process_file(filename, 0);
173 
174 	return 0;
175 }
176