1 | /* |
---|
2 | * |
---|
3 | * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand. |
---|
4 | * All rights reserved. |
---|
5 | * |
---|
6 | * This file is part of libtrace. |
---|
7 | * |
---|
8 | * This code has been developed by the University of Waikato WAND |
---|
9 | * research group. For further information please see http://www.wand.net.nz/ |
---|
10 | * |
---|
11 | * libtrace is free software; you can redistribute it and/or modify |
---|
12 | * it under the terms of the GNU Lesser General Public License as published by |
---|
13 | * the Free Software Foundation; either version 3 of the License, or |
---|
14 | * (at your option) any later version. |
---|
15 | * |
---|
16 | * libtrace is distributed in the hope that it will be useful, |
---|
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
19 | * GNU Lesser General Public License for more details. |
---|
20 | * |
---|
21 | * You should have received a copy of the GNU Lesser General Public License |
---|
22 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
23 | * |
---|
24 | * |
---|
25 | */ |
---|
26 | |
---|
27 | |
---|
28 | #include <netdb.h> |
---|
29 | #include <inttypes.h> |
---|
30 | #include <lt_inttypes.h> |
---|
31 | #include <stdio.h> |
---|
32 | #include "libtrace.h" |
---|
33 | #include "tracereport.h" |
---|
34 | #include "report.h" |
---|
35 | |
---|
36 | struct tcp_opts { |
---|
37 | bool mss; |
---|
38 | bool sack; |
---|
39 | bool winscale; |
---|
40 | bool ts; |
---|
41 | bool ttcp; |
---|
42 | bool other; |
---|
43 | }; |
---|
44 | |
---|
45 | struct opt_counter { |
---|
46 | uint64_t no_options; |
---|
47 | uint64_t mss_only; |
---|
48 | uint64_t ts_only; |
---|
49 | uint64_t ms; |
---|
50 | uint64_t mw; |
---|
51 | uint64_t msw; |
---|
52 | uint64_t mt; |
---|
53 | uint64_t all_four; |
---|
54 | uint64_t ts_and_sack; |
---|
55 | uint64_t wt; |
---|
56 | uint64_t tms; |
---|
57 | uint64_t tws; |
---|
58 | uint64_t tmw; |
---|
59 | uint64_t ts_and_another; |
---|
60 | uint64_t ttcp; |
---|
61 | uint64_t other; |
---|
62 | }; |
---|
63 | |
---|
64 | struct opt_counter syn_counts = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
---|
65 | struct opt_counter synack_counts = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
---|
66 | |
---|
67 | uint64_t total_syns = 0; |
---|
68 | uint64_t total_synacks = 0; |
---|
69 | |
---|
70 | static void classify_packet(struct tcp_opts opts, struct opt_counter *counts) { |
---|
71 | if (!opts.mss && !opts.sack && !opts.winscale && !opts.ts && !opts.ttcp && !opts.other) |
---|
72 | { |
---|
73 | counts->no_options ++; |
---|
74 | return; |
---|
75 | } |
---|
76 | |
---|
77 | if (opts.mss && !opts.sack && !opts.winscale && !opts.ts && !opts.ttcp && !opts.other) |
---|
78 | { |
---|
79 | counts->mss_only ++; |
---|
80 | return; |
---|
81 | } |
---|
82 | |
---|
83 | if (!opts.mss && !opts.sack && !opts.winscale && opts.ts && !opts.ttcp && !opts.other) |
---|
84 | { |
---|
85 | counts->ts_only ++; |
---|
86 | return; |
---|
87 | } |
---|
88 | |
---|
89 | if (opts.mss && opts.sack && !opts.winscale && !opts.ts) |
---|
90 | counts->ms ++; |
---|
91 | |
---|
92 | if (opts.mss && opts.winscale && !opts.sack && !opts.ts) |
---|
93 | counts->mw ++; |
---|
94 | |
---|
95 | if (opts.mss && opts.winscale && opts.sack && !opts.ts) |
---|
96 | counts->msw ++; |
---|
97 | |
---|
98 | if (opts.mss && opts.ts && !opts.winscale && !opts.sack) |
---|
99 | counts->mt ++; |
---|
100 | if (opts.ts && opts.sack && !opts.mss && !opts.winscale) |
---|
101 | counts->ts_and_sack ++; |
---|
102 | |
---|
103 | if (opts.ts && opts.winscale && !opts.mss && !opts.sack) |
---|
104 | counts->wt ++; |
---|
105 | |
---|
106 | if (opts.ts && opts.mss && opts.winscale && !opts.sack) |
---|
107 | counts->tmw ++; |
---|
108 | if (opts.ts && opts.mss && opts.sack && !opts.winscale) |
---|
109 | counts->tms ++; |
---|
110 | if (opts.ts && opts.sack && opts.winscale && !opts.mss) |
---|
111 | counts->tws ++; |
---|
112 | |
---|
113 | |
---|
114 | if (opts.mss && opts.sack && opts.winscale && opts.ts) { |
---|
115 | counts->all_four ++; |
---|
116 | } |
---|
117 | |
---|
118 | if (opts.ts && (opts.mss || opts.winscale || opts.sack)) { |
---|
119 | counts->ts_and_another ++; |
---|
120 | } |
---|
121 | |
---|
122 | if (opts.ttcp) |
---|
123 | counts->ttcp ++; |
---|
124 | if (opts.other) |
---|
125 | counts->other ++; |
---|
126 | } |
---|
127 | |
---|
128 | void synopt_per_packet(struct libtrace_packet_t *packet) |
---|
129 | { |
---|
130 | struct libtrace_tcp *tcp = trace_get_tcp(packet); |
---|
131 | unsigned char *opt_ptr; |
---|
132 | libtrace_direction_t dir = trace_get_direction(packet); |
---|
133 | int len; |
---|
134 | unsigned char type, optlen, *data; |
---|
135 | struct tcp_opts opts_seen = {false, false, false, false, false, false}; |
---|
136 | |
---|
137 | if(!tcp) |
---|
138 | return; |
---|
139 | |
---|
140 | if (!tcp->syn) |
---|
141 | return; |
---|
142 | |
---|
143 | if (dir != TRACE_DIR_INCOMING && dir != TRACE_DIR_OUTGOING) |
---|
144 | dir = TRACE_DIR_OTHER; |
---|
145 | |
---|
146 | len = tcp->doff * 4 - sizeof(libtrace_tcp_t); |
---|
147 | if(len == 0) |
---|
148 | return; |
---|
149 | |
---|
150 | opt_ptr = (unsigned char *)tcp + sizeof (libtrace_tcp_t); |
---|
151 | |
---|
152 | while(trace_get_next_option(&opt_ptr,&len,&type,&optlen,&data)){ |
---|
153 | /* I don't think we need to count NO-OPs */ |
---|
154 | if (type == 1) |
---|
155 | continue; |
---|
156 | switch(type) { |
---|
157 | case 2: |
---|
158 | opts_seen.mss = true; |
---|
159 | break; |
---|
160 | case 3: |
---|
161 | opts_seen.winscale = true; |
---|
162 | break; |
---|
163 | case 4: |
---|
164 | opts_seen.sack = true; |
---|
165 | break; |
---|
166 | case 5: |
---|
167 | opts_seen.sack = true; |
---|
168 | break; |
---|
169 | case 8: |
---|
170 | opts_seen.ts = true; |
---|
171 | break; |
---|
172 | case 11: |
---|
173 | case 12: |
---|
174 | case 13: |
---|
175 | opts_seen.ttcp = true; |
---|
176 | break; |
---|
177 | default: |
---|
178 | opts_seen.other = true; |
---|
179 | } |
---|
180 | } |
---|
181 | |
---|
182 | if (tcp->ack) { |
---|
183 | total_synacks ++; |
---|
184 | classify_packet(opts_seen, &synack_counts); |
---|
185 | } else { |
---|
186 | total_syns ++; |
---|
187 | classify_packet(opts_seen, &syn_counts); |
---|
188 | } |
---|
189 | } |
---|
190 | |
---|
191 | |
---|
192 | void synopt_report(void) |
---|
193 | { |
---|
194 | |
---|
195 | FILE *out = fopen("tcpopt_syn.rpt", "w"); |
---|
196 | if (!out) { |
---|
197 | perror("fopen"); |
---|
198 | return; |
---|
199 | } |
---|
200 | |
---|
201 | |
---|
202 | |
---|
203 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
204 | "No Options", |
---|
205 | (double)(syn_counts.no_options) / total_syns * 100.0, |
---|
206 | (double)(synack_counts.no_options) / total_synacks * 100.0); |
---|
207 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
208 | "M Only", |
---|
209 | (double)(syn_counts.mss_only) / total_syns * 100.0, |
---|
210 | (double)(synack_counts.mss_only) / total_synacks * 100.0); |
---|
211 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
212 | "T Only", |
---|
213 | (double)(syn_counts.ts_only) / total_syns * 100.0, |
---|
214 | (double)(synack_counts.ts_only) / total_synacks * 100.0); |
---|
215 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
216 | "M and S", |
---|
217 | (double)(syn_counts.ms) / total_syns * 100.0, |
---|
218 | (double)(synack_counts.ms) / total_synacks * 100.0); |
---|
219 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
220 | "M and W", |
---|
221 | (double)(syn_counts.mw) / total_syns * 100.0, |
---|
222 | (double)(synack_counts.mw) / total_synacks * 100.0); |
---|
223 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
224 | "M, S and W", |
---|
225 | (double)(syn_counts.msw) / total_syns * 100.0, |
---|
226 | (double)(synack_counts.msw) / total_synacks * 100.0); |
---|
227 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
228 | "M, T", |
---|
229 | (double)(syn_counts.mt) / total_syns * 100.0, |
---|
230 | (double)(synack_counts.mt) / total_synacks * 100.0); |
---|
231 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
232 | "W, T", |
---|
233 | (double)(syn_counts.wt) / total_syns * 100.0, |
---|
234 | (double)(synack_counts.wt) / total_synacks * 100.0); |
---|
235 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
236 | "S, T", |
---|
237 | (double)(syn_counts.ts_and_sack) / total_syns * 100.0, |
---|
238 | (double)(synack_counts.ts_and_sack) / total_synacks * 100.0); |
---|
239 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
240 | "S, M, T", |
---|
241 | (double)(syn_counts.tms) / total_syns * 100.0, |
---|
242 | (double)(synack_counts.tms) / total_synacks * 100.0); |
---|
243 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
244 | "W, M, T", |
---|
245 | (double)(syn_counts.tmw) / total_syns * 100.0, |
---|
246 | (double)(synack_counts.tmw) / total_synacks * 100.0); |
---|
247 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
248 | "S, W, T", |
---|
249 | (double)(syn_counts.tws) / total_syns * 100.0, |
---|
250 | (double)(synack_counts.tws) / total_synacks * 100.0); |
---|
251 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
252 | "M, S, W and T", |
---|
253 | (double)(syn_counts.all_four) / total_syns * 100.0, |
---|
254 | (double)(synack_counts.all_four) / total_synacks * 100.0); |
---|
255 | //fprintf(out, "%-20s\t%.2f%%\n", |
---|
256 | // "T and (M or S or W)", |
---|
257 | // (double)(counts.ts_and_another) / total_syns * 100.0); |
---|
258 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
259 | "T/TCP", |
---|
260 | (double)(syn_counts.ttcp) / total_syns * 100.0, |
---|
261 | (double)(synack_counts.ttcp) / total_synacks * 100.0); |
---|
262 | fprintf(out, "%-20s\t%.2f%%\t%.2f%%\n", |
---|
263 | "Other options", |
---|
264 | (double)(syn_counts.other) / total_syns * 100.0, |
---|
265 | (double)(synack_counts.other) / total_synacks * 100.0); |
---|
266 | |
---|
267 | |
---|
268 | fclose(out); |
---|
269 | } |
---|