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: tcpprof.c,v 1.7 2002/01/19 04:31:37 pherman Exp $
28 */
29
30 #include "tcpprof.h"
31
32 char numbers_only = 0;
33 char filterexpr[BUF_SIZ] = "";
34 char registered_only = 0;
35 char src_dest_split = 0;
36 int ports_to_show = IPPORT_RESERVED;
37 int lines_to_show = -1;
38
39 #define USAGE \
40 "Usage: %s [-?hnpR] [-f filter expr] [-i interface] [-P port] \
41 \n [-r file] [-s seconds] [-S letters] [-t lines] \
42 \n -?, -h - display this help \
43 \n -d - show source/dest statistics \
44 \n -f filter expr - tcpdump(1) filter expression \
45 \n -i interface - do live capture on [interface], not from file \
46 \n -n - don't resolve network numbers \
47 \n -p - non-promiscuous mode when doing live capture \
48 \n -P port - ignore port numbers >= port \
49 \n -r file - read tcpdump data from file \
50 \n -R - display only registered ports \
51 \n -s seconds - capture only [seconds] long \
52 \n -S letters - collect stats \
53 \n a - collect ALL stats \
54 \n l - collect link stats \
55 \n i - collect ip stats \
56 \n p - collect port stats \
57 \n h - collect host stats \
58 \n n - collect network stats \
59 \n -t lines - show at most [lines] lines for each stat \
60 \n \
61 \nExample: %s -S ph -r data.dump \
62 \n Displays port and host statistics from the file 'data.dump' \
63 \n"
64
my_hook(packet_data * pd,void ** args)65 void my_hook(packet_data *pd, void **args) {
66 u_int *types;
67
68 types = (u_int *) *args++;
69 stats_insert(pd, *types);
70 }
71
72 /*
73 * process_file() takes the output of tcpdump, saves packets, and creates
74 * statistics
75 */
process_file(char * fname,u_int s_types,int flags,Double capture_seconds)76 void process_file(char *fname, u_int s_types, int flags, Double capture_seconds) {
77 void *argv[1];
78
79 stats_initdb(s_types);
80
81 argv[0] = (void *) &s_types;
82 if (get_dump_data(fname, filterexpr, flags, capture_seconds, my_hook, argv) == 0)
83 show_results(s_types);
84
85 stats_closedb();
86 }
87
parse_stats_types(char * in)88 u_int parse_stats_types(char *in) {
89 u_int ret = 0;
90 while (*in) {
91 if (*in == 'l' || *in == 'a' ) ret |= TYPE_LINK;
92 if (*in == 'i' || *in == 'a' ) ret |= TYPE_IP_PROTO;
93 if (*in == 'p' || *in == 'a' ) ret |= TYPE_PORT;
94 if (*in == 'h' || *in == 'a' ) ret |= TYPE_HOST;
95 if (*in == 'n' || *in == 'a' ) ret |= TYPE_NET;
96 in++;
97 }
98 return ret;
99 }
100
Usage(int r,char * prog)101 int Usage(int r, char *prog) {
102 fprintf(stderr, USAGE, my_basename(prog), prog);
103 return r;
104 }
105
error(char * s)106 void error(char *s) {
107 fprintf(stderr, "error: %s\n", s);
108 Usage(-1, "tcpprof"); exit(-1);
109 }
110
main(int argc,char ** argv)111 int main(int argc, char **argv) {
112 char filename[BUF_SIZ];
113 u_int stats_types = TYPE_ALL;
114 int flags = GET_TCPD_COUNT_LINKSIZE | GET_TCPD_DO_LIVE_PROMISC;
115 int ch;
116 Double capture_seconds = -1.0;
117
118 filename[0] = 0;
119 while ( (ch = getopt(argc, argv, "h?ndpP:Rf:i:s:S:r:t:")) != -1) {
120 switch(ch) {
121 case 'h':
122 case '?':
123 return Usage(1, argv[0]);
124 break;
125 case 'd':
126 src_dest_split = 1;
127 break;
128 case 'f':
129 strncpy(filterexpr, optarg, BUF_SIZ);
130 break;
131 case 'i':
132 strncpy(filename, optarg, BUF_SIZ);
133 flags |= GET_TCPD_DO_LIVE;
134 break;
135 case 'r':
136 strncpy(filename, optarg, BUF_SIZ);
137 flags &= ~GET_TCPD_DO_LIVE;
138 break;
139 case 'n':
140 numbers_only = 1;
141 break;
142 case 'p':
143 flags &= ~GET_TCPD_DO_LIVE_PROMISC;
144 break;
145 case 'P':
146 ports_to_show = (int) strtol(optarg, NULL, 10);
147 registered_only = 1;
148 break;
149 case 'R':
150 registered_only = 1;
151 break;
152 case 's':
153 capture_seconds = atof(optarg);
154 if (capture_seconds <= 0.0 &&
155 capture_seconds != -1.0)
156 return Usage(1, argv[0]);
157 break;
158 case 'S':
159 stats_types |= parse_stats_types(optarg);
160 break;
161 case 't':
162 lines_to_show = (int) strtol(optarg, NULL, 10);
163 break;
164 default:
165 break;
166 }
167 }
168
169 if (filename == NULL || strlen(filename) < 1) {
170 strncpy(filename, "auto", BUF_SIZ);
171 flags |= GET_TCPD_DO_LIVE;
172 }
173
174 process_file(filename, stats_types, flags, capture_seconds);
175
176 return 0;
177 }
178