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