nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Copyright (c) 1998-2007 The TCPDUMP project |
||
3 | * |
||
4 | * Redistribution and use in source and binary forms, with or without |
||
5 | * modification, are permitted provided that: (1) source code |
||
6 | * distributions retain the above copyright notice and this paragraph |
||
7 | * in its entirety, and (2) distributions including binary code include |
||
8 | * the above copyright notice and this paragraph in its entirety in |
||
9 | * the documentation or other materials provided with the distribution. |
||
10 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND |
||
11 | * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT |
||
12 | * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
||
13 | * FOR A PARTICULAR PURPOSE. |
||
14 | * |
||
15 | * The SFLOW protocol as per http://www.sflow.org/developers/specifications.php |
||
16 | * |
||
17 | * Original code by Carles Kishimoto <carles.kishimoto@gmail.com> |
||
18 | * |
||
19 | * Expansion and refactoring by Rick Jones <rick.jones2@hp.com> |
||
20 | */ |
||
21 | |||
22 | #define NETDISSECT_REWORKED |
||
23 | #ifdef HAVE_CONFIG_H |
||
24 | #include "config.h" |
||
25 | #endif |
||
26 | |||
27 | #include <tcpdump-stdinc.h> |
||
28 | |||
29 | #include "interface.h" |
||
30 | #include "extract.h" |
||
31 | #include "addrtoname.h" |
||
32 | |||
33 | /* |
||
34 | * sFlow datagram |
||
35 | * |
||
36 | * 0 1 2 3 |
||
37 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
||
38 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
||
39 | * | Sflow version (2,4,5) | |
||
40 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
||
41 | * | IP version (1 for IPv4 | 2 for IPv6) | |
||
42 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
||
43 | * | IP Address AGENT (4 or 16 bytes) | |
||
44 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
||
45 | * | Sub agent ID | |
||
46 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
||
47 | * | Datagram sequence number | |
||
48 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
||
49 | * | Switch uptime in ms | |
||
50 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
||
51 | * | num samples in datagram | |
||
52 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
||
53 | * |
||
54 | */ |
||
55 | |||
56 | struct sflow_datagram_t { |
||
57 | uint8_t version[4]; |
||
58 | uint8_t ip_version[4]; |
||
59 | uint8_t agent[4]; |
||
60 | uint8_t agent_id[4]; |
||
61 | uint8_t seqnum[4]; |
||
62 | uint8_t uptime[4]; |
||
63 | uint8_t samples[4]; |
||
64 | }; |
||
65 | |||
66 | struct sflow_sample_header { |
||
67 | uint8_t format[4]; |
||
68 | uint8_t len[4]; |
||
69 | }; |
||
70 | |||
71 | #define SFLOW_FLOW_SAMPLE 1 |
||
72 | #define SFLOW_COUNTER_SAMPLE 2 |
||
73 | #define SFLOW_EXPANDED_FLOW_SAMPLE 3 |
||
74 | #define SFLOW_EXPANDED_COUNTER_SAMPLE 4 |
||
75 | |||
76 | static const struct tok sflow_format_values[] = { |
||
77 | { SFLOW_FLOW_SAMPLE, "flow sample" }, |
||
78 | { SFLOW_COUNTER_SAMPLE, "counter sample" }, |
||
79 | { SFLOW_EXPANDED_FLOW_SAMPLE, "expanded flow sample" }, |
||
80 | { SFLOW_EXPANDED_COUNTER_SAMPLE, "expanded counter sample" }, |
||
81 | { 0, NULL} |
||
82 | }; |
||
83 | |||
84 | struct sflow_flow_sample_t { |
||
85 | uint8_t seqnum[4]; |
||
86 | uint8_t typesource[4]; |
||
87 | uint8_t rate[4]; |
||
88 | uint8_t pool[4]; |
||
89 | uint8_t drops[4]; |
||
90 | uint8_t in_interface[4]; |
||
91 | uint8_t out_interface[4]; |
||
92 | uint8_t records[4]; |
||
93 | |||
94 | }; |
||
95 | |||
96 | struct sflow_expanded_flow_sample_t { |
||
97 | uint8_t seqnum[4]; |
||
98 | uint8_t type[4]; |
||
99 | uint8_t index[4]; |
||
100 | uint8_t rate[4]; |
||
101 | uint8_t pool[4]; |
||
102 | uint8_t drops[4]; |
||
103 | uint8_t in_interface_format[4]; |
||
104 | uint8_t in_interface_value[4]; |
||
105 | uint8_t out_interface_format[4]; |
||
106 | uint8_t out_interface_value[4]; |
||
107 | uint8_t records[4]; |
||
108 | }; |
||
109 | |||
110 | #define SFLOW_FLOW_RAW_PACKET 1 |
||
111 | #define SFLOW_FLOW_ETHERNET_FRAME 2 |
||
112 | #define SFLOW_FLOW_IPV4_DATA 3 |
||
113 | #define SFLOW_FLOW_IPV6_DATA 4 |
||
114 | #define SFLOW_FLOW_EXTENDED_SWITCH_DATA 1001 |
||
115 | #define SFLOW_FLOW_EXTENDED_ROUTER_DATA 1002 |
||
116 | #define SFLOW_FLOW_EXTENDED_GATEWAY_DATA 1003 |
||
117 | #define SFLOW_FLOW_EXTENDED_USER_DATA 1004 |
||
118 | #define SFLOW_FLOW_EXTENDED_URL_DATA 1005 |
||
119 | #define SFLOW_FLOW_EXTENDED_MPLS_DATA 1006 |
||
120 | #define SFLOW_FLOW_EXTENDED_NAT_DATA 1007 |
||
121 | #define SFLOW_FLOW_EXTENDED_MPLS_TUNNEL 1008 |
||
122 | #define SFLOW_FLOW_EXTENDED_MPLS_VC 1009 |
||
123 | #define SFLOW_FLOW_EXTENDED_MPLS_FEC 1010 |
||
124 | #define SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC 1011 |
||
125 | #define SFLOW_FLOW_EXTENDED_VLAN_TUNNEL 1012 |
||
126 | |||
127 | static const struct tok sflow_flow_type_values[] = { |
||
128 | { SFLOW_FLOW_RAW_PACKET, "Raw packet"}, |
||
129 | { SFLOW_FLOW_ETHERNET_FRAME, "Ethernet frame"}, |
||
130 | { SFLOW_FLOW_IPV4_DATA, "IPv4 Data"}, |
||
131 | { SFLOW_FLOW_IPV6_DATA, "IPv6 Data"}, |
||
132 | { SFLOW_FLOW_EXTENDED_SWITCH_DATA, "Extended Switch data"}, |
||
133 | { SFLOW_FLOW_EXTENDED_ROUTER_DATA, "Extended Router data"}, |
||
134 | { SFLOW_FLOW_EXTENDED_GATEWAY_DATA, "Extended Gateway data"}, |
||
135 | { SFLOW_FLOW_EXTENDED_USER_DATA, "Extended User data"}, |
||
136 | { SFLOW_FLOW_EXTENDED_URL_DATA, "Extended URL data"}, |
||
137 | { SFLOW_FLOW_EXTENDED_MPLS_DATA, "Extended MPLS data"}, |
||
138 | { SFLOW_FLOW_EXTENDED_NAT_DATA, "Extended NAT data"}, |
||
139 | { SFLOW_FLOW_EXTENDED_MPLS_TUNNEL, "Extended MPLS tunnel"}, |
||
140 | { SFLOW_FLOW_EXTENDED_MPLS_VC, "Extended MPLS VC"}, |
||
141 | { SFLOW_FLOW_EXTENDED_MPLS_FEC, "Extended MPLS FEC"}, |
||
142 | { SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC, "Extended MPLS LVP FEC"}, |
||
143 | { SFLOW_FLOW_EXTENDED_VLAN_TUNNEL, "Extended VLAN Tunnel"}, |
||
144 | { 0, NULL} |
||
145 | }; |
||
146 | |||
147 | #define SFLOW_HEADER_PROTOCOL_ETHERNET 1 |
||
148 | #define SFLOW_HEADER_PROTOCOL_IPV4 11 |
||
149 | #define SFLOW_HEADER_PROTOCOL_IPV6 12 |
||
150 | |||
151 | static const struct tok sflow_flow_raw_protocol_values[] = { |
||
152 | { SFLOW_HEADER_PROTOCOL_ETHERNET, "Ethernet"}, |
||
153 | { SFLOW_HEADER_PROTOCOL_IPV4, "IPv4"}, |
||
154 | { SFLOW_HEADER_PROTOCOL_IPV6, "IPv6"}, |
||
155 | { 0, NULL} |
||
156 | }; |
||
157 | |||
158 | struct sflow_expanded_flow_raw_t { |
||
159 | uint8_t protocol[4]; |
||
160 | uint8_t length[4]; |
||
161 | uint8_t stripped_bytes[4]; |
||
162 | uint8_t header_size[4]; |
||
163 | }; |
||
164 | |||
165 | struct sflow_ethernet_frame_t { |
||
166 | uint8_t length[4]; |
||
167 | uint8_t src_mac[8]; |
||
168 | uint8_t dst_mac[8]; |
||
169 | uint8_t type[4]; |
||
170 | }; |
||
171 | |||
172 | struct sflow_extended_switch_data_t { |
||
173 | uint8_t src_vlan[4]; |
||
174 | uint8_t src_pri[4]; |
||
175 | uint8_t dst_vlan[4]; |
||
176 | uint8_t dst_pri[4]; |
||
177 | }; |
||
178 | |||
179 | struct sflow_counter_record_t { |
||
180 | uint8_t format[4]; |
||
181 | uint8_t length[4]; |
||
182 | }; |
||
183 | |||
184 | struct sflow_flow_record_t { |
||
185 | uint8_t format[4]; |
||
186 | uint8_t length[4]; |
||
187 | }; |
||
188 | |||
189 | struct sflow_counter_sample_t { |
||
190 | uint8_t seqnum[4]; |
||
191 | uint8_t typesource[4]; |
||
192 | uint8_t records[4]; |
||
193 | }; |
||
194 | |||
195 | struct sflow_expanded_counter_sample_t { |
||
196 | uint8_t seqnum[4]; |
||
197 | uint8_t type[4]; |
||
198 | uint8_t index[4]; |
||
199 | uint8_t records[4]; |
||
200 | }; |
||
201 | |||
202 | #define SFLOW_COUNTER_GENERIC 1 |
||
203 | #define SFLOW_COUNTER_ETHERNET 2 |
||
204 | #define SFLOW_COUNTER_TOKEN_RING 3 |
||
205 | #define SFLOW_COUNTER_BASEVG 4 |
||
206 | #define SFLOW_COUNTER_VLAN 5 |
||
207 | #define SFLOW_COUNTER_PROCESSOR 1001 |
||
208 | |||
209 | static const struct tok sflow_counter_type_values[] = { |
||
210 | { SFLOW_COUNTER_GENERIC, "Generic counter"}, |
||
211 | { SFLOW_COUNTER_ETHERNET, "Ethernet counter"}, |
||
212 | { SFLOW_COUNTER_TOKEN_RING, "Token ring counter"}, |
||
213 | { SFLOW_COUNTER_BASEVG, "100 BaseVG counter"}, |
||
214 | { SFLOW_COUNTER_VLAN, "Vlan counter"}, |
||
215 | { SFLOW_COUNTER_PROCESSOR, "Processor counter"}, |
||
216 | { 0, NULL} |
||
217 | }; |
||
218 | |||
219 | #define SFLOW_IFACE_DIRECTION_UNKNOWN 0 |
||
220 | #define SFLOW_IFACE_DIRECTION_FULLDUPLEX 1 |
||
221 | #define SFLOW_IFACE_DIRECTION_HALFDUPLEX 2 |
||
222 | #define SFLOW_IFACE_DIRECTION_IN 3 |
||
223 | #define SFLOW_IFACE_DIRECTION_OUT 4 |
||
224 | |||
225 | static const struct tok sflow_iface_direction_values[] = { |
||
226 | { SFLOW_IFACE_DIRECTION_UNKNOWN, "unknown"}, |
||
227 | { SFLOW_IFACE_DIRECTION_FULLDUPLEX, "full-duplex"}, |
||
228 | { SFLOW_IFACE_DIRECTION_HALFDUPLEX, "half-duplex"}, |
||
229 | { SFLOW_IFACE_DIRECTION_IN, "in"}, |
||
230 | { SFLOW_IFACE_DIRECTION_OUT, "out"}, |
||
231 | { 0, NULL} |
||
232 | }; |
||
233 | |||
234 | struct sflow_generic_counter_t { |
||
235 | uint8_t ifindex[4]; |
||
236 | uint8_t iftype[4]; |
||
237 | uint8_t ifspeed[8]; |
||
238 | uint8_t ifdirection[4]; |
||
239 | uint8_t ifstatus[4]; |
||
240 | uint8_t ifinoctets[8]; |
||
241 | uint8_t ifinunicastpkts[4]; |
||
242 | uint8_t ifinmulticastpkts[4]; |
||
243 | uint8_t ifinbroadcastpkts[4]; |
||
244 | uint8_t ifindiscards[4]; |
||
245 | uint8_t ifinerrors[4]; |
||
246 | uint8_t ifinunkownprotos[4]; |
||
247 | uint8_t ifoutoctets[8]; |
||
248 | uint8_t ifoutunicastpkts[4]; |
||
249 | uint8_t ifoutmulticastpkts[4]; |
||
250 | uint8_t ifoutbroadcastpkts[4]; |
||
251 | uint8_t ifoutdiscards[4]; |
||
252 | uint8_t ifouterrors[4]; |
||
253 | uint8_t ifpromiscmode[4]; |
||
254 | }; |
||
255 | |||
256 | struct sflow_ethernet_counter_t { |
||
257 | uint8_t alignerrors[4]; |
||
258 | uint8_t fcserrors[4]; |
||
259 | uint8_t single_collision_frames[4]; |
||
260 | uint8_t multiple_collision_frames[4]; |
||
261 | uint8_t test_errors[4]; |
||
262 | uint8_t deferred_transmissions[4]; |
||
263 | uint8_t late_collisions[4]; |
||
264 | uint8_t excessive_collisions[4]; |
||
265 | uint8_t mac_transmit_errors[4]; |
||
266 | uint8_t carrier_sense_errors[4]; |
||
267 | uint8_t frame_too_longs[4]; |
||
268 | uint8_t mac_receive_errors[4]; |
||
269 | uint8_t symbol_errors[4]; |
||
270 | }; |
||
271 | |||
272 | struct sflow_100basevg_counter_t { |
||
273 | uint8_t in_highpriority_frames[4]; |
||
274 | uint8_t in_highpriority_octets[8]; |
||
275 | uint8_t in_normpriority_frames[4]; |
||
276 | uint8_t in_normpriority_octets[8]; |
||
277 | uint8_t in_ipmerrors[4]; |
||
278 | uint8_t in_oversized[4]; |
||
279 | uint8_t in_data_errors[4]; |
||
280 | uint8_t in_null_addressed_frames[4]; |
||
281 | uint8_t out_highpriority_frames[4]; |
||
282 | uint8_t out_highpriority_octets[8]; |
||
283 | uint8_t transitioninto_frames[4]; |
||
284 | uint8_t hc_in_highpriority_octets[8]; |
||
285 | uint8_t hc_in_normpriority_octets[8]; |
||
286 | uint8_t hc_out_highpriority_octets[8]; |
||
287 | }; |
||
288 | |||
289 | struct sflow_vlan_counter_t { |
||
290 | uint8_t vlan_id[4]; |
||
291 | uint8_t octets[8]; |
||
292 | uint8_t unicast_pkt[4]; |
||
293 | uint8_t multicast_pkt[4]; |
||
294 | uint8_t broadcast_pkt[4]; |
||
295 | uint8_t discards[4]; |
||
296 | }; |
||
297 | |||
298 | static int |
||
299 | print_sflow_counter_generic(netdissect_options *ndo, |
||
300 | const u_char *pointer, u_int len) |
||
301 | { |
||
302 | const struct sflow_generic_counter_t *sflow_gen_counter; |
||
303 | |||
304 | if (len < sizeof(struct sflow_generic_counter_t)) |
||
305 | return 1; |
||
306 | |||
307 | |||
308 | sflow_gen_counter = (const struct sflow_generic_counter_t *)pointer; |
||
309 | ND_PRINT((ndo, "\n\t ifindex %u, iftype %u, ifspeed %" PRIu64 ", ifdirection %u (%s)", |
||
310 | EXTRACT_32BITS(sflow_gen_counter->ifindex), |
||
311 | EXTRACT_32BITS(sflow_gen_counter->iftype), |
||
312 | EXTRACT_64BITS(sflow_gen_counter->ifspeed), |
||
313 | EXTRACT_32BITS(sflow_gen_counter->ifdirection), |
||
314 | tok2str(sflow_iface_direction_values, "Unknown", |
||
315 | EXTRACT_32BITS(sflow_gen_counter->ifdirection)))); |
||
316 | ND_PRINT((ndo, "\n\t ifstatus %u, adminstatus: %s, operstatus: %s", |
||
317 | EXTRACT_32BITS(sflow_gen_counter->ifstatus), |
||
318 | EXTRACT_32BITS(sflow_gen_counter->ifstatus)&1 ? "up" : "down", |
||
319 | (EXTRACT_32BITS(sflow_gen_counter->ifstatus)>>1)&1 ? "up" : "down")); |
||
320 | ND_PRINT((ndo, "\n\t In octets %" PRIu64 |
||
321 | ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u", |
||
322 | EXTRACT_64BITS(sflow_gen_counter->ifinoctets), |
||
323 | EXTRACT_32BITS(sflow_gen_counter->ifinunicastpkts), |
||
324 | EXTRACT_32BITS(sflow_gen_counter->ifinmulticastpkts), |
||
325 | EXTRACT_32BITS(sflow_gen_counter->ifinbroadcastpkts), |
||
326 | EXTRACT_32BITS(sflow_gen_counter->ifindiscards))); |
||
327 | ND_PRINT((ndo, "\n\t In errors %u, unknown protos %u", |
||
328 | EXTRACT_32BITS(sflow_gen_counter->ifinerrors), |
||
329 | EXTRACT_32BITS(sflow_gen_counter->ifinunkownprotos))); |
||
330 | ND_PRINT((ndo, "\n\t Out octets %" PRIu64 |
||
331 | ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u", |
||
332 | EXTRACT_64BITS(sflow_gen_counter->ifoutoctets), |
||
333 | EXTRACT_32BITS(sflow_gen_counter->ifoutunicastpkts), |
||
334 | EXTRACT_32BITS(sflow_gen_counter->ifoutmulticastpkts), |
||
335 | EXTRACT_32BITS(sflow_gen_counter->ifoutbroadcastpkts), |
||
336 | EXTRACT_32BITS(sflow_gen_counter->ifoutdiscards))); |
||
337 | ND_PRINT((ndo, "\n\t Out errors %u, promisc mode %u", |
||
338 | EXTRACT_32BITS(sflow_gen_counter->ifouterrors), |
||
339 | EXTRACT_32BITS(sflow_gen_counter->ifpromiscmode))); |
||
340 | |||
341 | return 0; |
||
342 | } |
||
343 | |||
344 | static int |
||
345 | print_sflow_counter_ethernet(netdissect_options *ndo, |
||
346 | const u_char *pointer, u_int len) |
||
347 | { |
||
348 | const struct sflow_ethernet_counter_t *sflow_eth_counter; |
||
349 | |||
350 | if (len < sizeof(struct sflow_ethernet_counter_t)) |
||
351 | return 1; |
||
352 | |||
353 | sflow_eth_counter = (const struct sflow_ethernet_counter_t *)pointer; |
||
354 | ND_PRINT((ndo, "\n\t align errors %u, fcs errors %u, single collision %u, multiple collision %u, test error %u", |
||
355 | EXTRACT_32BITS(sflow_eth_counter->alignerrors), |
||
356 | EXTRACT_32BITS(sflow_eth_counter->fcserrors), |
||
357 | EXTRACT_32BITS(sflow_eth_counter->single_collision_frames), |
||
358 | EXTRACT_32BITS(sflow_eth_counter->multiple_collision_frames), |
||
359 | EXTRACT_32BITS(sflow_eth_counter->test_errors))); |
||
360 | ND_PRINT((ndo, "\n\t deferred %u, late collision %u, excessive collision %u, mac trans error %u", |
||
361 | EXTRACT_32BITS(sflow_eth_counter->deferred_transmissions), |
||
362 | EXTRACT_32BITS(sflow_eth_counter->late_collisions), |
||
363 | EXTRACT_32BITS(sflow_eth_counter->excessive_collisions), |
||
364 | EXTRACT_32BITS(sflow_eth_counter->mac_transmit_errors))); |
||
365 | ND_PRINT((ndo, "\n\t carrier error %u, frames too long %u, mac receive errors %u, symbol errors %u", |
||
366 | EXTRACT_32BITS(sflow_eth_counter->carrier_sense_errors), |
||
367 | EXTRACT_32BITS(sflow_eth_counter->frame_too_longs), |
||
368 | EXTRACT_32BITS(sflow_eth_counter->mac_receive_errors), |
||
369 | EXTRACT_32BITS(sflow_eth_counter->symbol_errors))); |
||
370 | |||
371 | return 0; |
||
372 | } |
||
373 | |||
374 | static int |
||
375 | print_sflow_counter_token_ring(netdissect_options *ndo _U_, |
||
376 | const u_char *pointer _U_, u_int len _U_) |
||
377 | { |
||
378 | return 0; |
||
379 | } |
||
380 | |||
381 | static int |
||
382 | print_sflow_counter_basevg(netdissect_options *ndo, |
||
383 | const u_char *pointer, u_int len) |
||
384 | { |
||
385 | const struct sflow_100basevg_counter_t *sflow_100basevg_counter; |
||
386 | |||
387 | if (len < sizeof(struct sflow_100basevg_counter_t)) |
||
388 | return 1; |
||
389 | |||
390 | sflow_100basevg_counter = (const struct sflow_100basevg_counter_t *)pointer; |
||
391 | ND_PRINT((ndo, "\n\t in high prio frames %u, in high prio octets %" PRIu64, |
||
392 | EXTRACT_32BITS(sflow_100basevg_counter->in_highpriority_frames), |
||
393 | EXTRACT_64BITS(sflow_100basevg_counter->in_highpriority_octets))); |
||
394 | ND_PRINT((ndo, "\n\t in norm prio frames %u, in norm prio octets %" PRIu64, |
||
395 | EXTRACT_32BITS(sflow_100basevg_counter->in_normpriority_frames), |
||
396 | EXTRACT_64BITS(sflow_100basevg_counter->in_normpriority_octets))); |
||
397 | ND_PRINT((ndo, "\n\t in ipm errors %u, oversized %u, in data errors %u, null addressed frames %u", |
||
398 | EXTRACT_32BITS(sflow_100basevg_counter->in_ipmerrors), |
||
399 | EXTRACT_32BITS(sflow_100basevg_counter->in_oversized), |
||
400 | EXTRACT_32BITS(sflow_100basevg_counter->in_data_errors), |
||
401 | EXTRACT_32BITS(sflow_100basevg_counter->in_null_addressed_frames))); |
||
402 | ND_PRINT((ndo, "\n\t out high prio frames %u, out high prio octets %" PRIu64 |
||
403 | ", trans into frames %u", |
||
404 | EXTRACT_32BITS(sflow_100basevg_counter->out_highpriority_frames), |
||
405 | EXTRACT_64BITS(sflow_100basevg_counter->out_highpriority_octets), |
||
406 | EXTRACT_32BITS(sflow_100basevg_counter->transitioninto_frames))); |
||
407 | ND_PRINT((ndo, "\n\t in hc high prio octets %" PRIu64 |
||
408 | ", in hc norm prio octets %" PRIu64 |
||
409 | ", out hc high prio octets %" PRIu64, |
||
410 | EXTRACT_64BITS(sflow_100basevg_counter->hc_in_highpriority_octets), |
||
411 | EXTRACT_64BITS(sflow_100basevg_counter->hc_in_normpriority_octets), |
||
412 | EXTRACT_64BITS(sflow_100basevg_counter->hc_out_highpriority_octets))); |
||
413 | |||
414 | return 0; |
||
415 | } |
||
416 | |||
417 | static int |
||
418 | print_sflow_counter_vlan(netdissect_options *ndo, |
||
419 | const u_char *pointer, u_int len) |
||
420 | { |
||
421 | const struct sflow_vlan_counter_t *sflow_vlan_counter; |
||
422 | |||
423 | if (len < sizeof(struct sflow_vlan_counter_t)) |
||
424 | return 1; |
||
425 | |||
426 | sflow_vlan_counter = (const struct sflow_vlan_counter_t *)pointer; |
||
427 | ND_PRINT((ndo, "\n\t vlan_id %u, octets %" PRIu64 |
||
428 | ", unicast_pkt %u, multicast_pkt %u, broadcast_pkt %u, discards %u", |
||
429 | EXTRACT_32BITS(sflow_vlan_counter->vlan_id), |
||
430 | EXTRACT_64BITS(sflow_vlan_counter->octets), |
||
431 | EXTRACT_32BITS(sflow_vlan_counter->unicast_pkt), |
||
432 | EXTRACT_32BITS(sflow_vlan_counter->multicast_pkt), |
||
433 | EXTRACT_32BITS(sflow_vlan_counter->broadcast_pkt), |
||
434 | EXTRACT_32BITS(sflow_vlan_counter->discards))); |
||
435 | |||
436 | return 0; |
||
437 | } |
||
438 | |||
439 | struct sflow_processor_counter_t { |
||
440 | uint8_t five_sec_util[4]; |
||
441 | uint8_t one_min_util[4]; |
||
442 | uint8_t five_min_util[4]; |
||
443 | uint8_t total_memory[8]; |
||
444 | uint8_t free_memory[8]; |
||
445 | }; |
||
446 | |||
447 | static int |
||
448 | print_sflow_counter_processor(netdissect_options *ndo, |
||
449 | const u_char *pointer, u_int len) |
||
450 | { |
||
451 | const struct sflow_processor_counter_t *sflow_processor_counter; |
||
452 | |||
453 | if (len < sizeof(struct sflow_processor_counter_t)) |
||
454 | return 1; |
||
455 | |||
456 | sflow_processor_counter = (const struct sflow_processor_counter_t *)pointer; |
||
457 | ND_PRINT((ndo, "\n\t 5sec %u, 1min %u, 5min %u, total_mem %" PRIu64 |
||
458 | ", total_mem %" PRIu64, |
||
459 | EXTRACT_32BITS(sflow_processor_counter->five_sec_util), |
||
460 | EXTRACT_32BITS(sflow_processor_counter->one_min_util), |
||
461 | EXTRACT_32BITS(sflow_processor_counter->five_min_util), |
||
462 | EXTRACT_64BITS(sflow_processor_counter->total_memory), |
||
463 | EXTRACT_64BITS(sflow_processor_counter->free_memory))); |
||
464 | |||
465 | return 0; |
||
466 | } |
||
467 | |||
468 | static int |
||
469 | sflow_print_counter_records(netdissect_options *ndo, |
||
470 | const u_char *pointer, u_int len, u_int records) |
||
471 | { |
||
472 | u_int nrecords; |
||
473 | const u_char *tptr; |
||
474 | u_int tlen; |
||
475 | u_int counter_type; |
||
476 | u_int counter_len; |
||
477 | u_int enterprise; |
||
478 | const struct sflow_counter_record_t *sflow_counter_record; |
||
479 | |||
480 | nrecords = records; |
||
481 | tptr = pointer; |
||
482 | tlen = len; |
||
483 | |||
484 | while (nrecords > 0) { |
||
485 | /* do we have the "header?" */ |
||
486 | if (tlen < sizeof(struct sflow_counter_record_t)) |
||
487 | return 1; |
||
488 | sflow_counter_record = (const struct sflow_counter_record_t *)tptr; |
||
489 | |||
490 | enterprise = EXTRACT_32BITS(sflow_counter_record->format); |
||
491 | counter_type = enterprise & 0x0FFF; |
||
492 | enterprise = enterprise >> 20; |
||
493 | counter_len = EXTRACT_32BITS(sflow_counter_record->length); |
||
494 | ND_PRINT((ndo, "\n\t enterprise %u, %s (%u) length %u", |
||
495 | enterprise, |
||
496 | (enterprise == 0) ? tok2str(sflow_counter_type_values,"Unknown",counter_type) : "Unknown", |
||
497 | counter_type, |
||
498 | counter_len)); |
||
499 | |||
500 | tptr += sizeof(struct sflow_counter_record_t); |
||
501 | tlen -= sizeof(struct sflow_counter_record_t); |
||
502 | |||
503 | if (tlen < counter_len) |
||
504 | return 1; |
||
505 | if (enterprise == 0) { |
||
506 | switch (counter_type) { |
||
507 | case SFLOW_COUNTER_GENERIC: |
||
508 | if (print_sflow_counter_generic(ndo, tptr, tlen)) |
||
509 | return 1; |
||
510 | break; |
||
511 | case SFLOW_COUNTER_ETHERNET: |
||
512 | if (print_sflow_counter_ethernet(ndo, tptr, tlen)) |
||
513 | return 1; |
||
514 | break; |
||
515 | case SFLOW_COUNTER_TOKEN_RING: |
||
516 | if (print_sflow_counter_token_ring(ndo, tptr,tlen)) |
||
517 | return 1; |
||
518 | break; |
||
519 | case SFLOW_COUNTER_BASEVG: |
||
520 | if (print_sflow_counter_basevg(ndo, tptr, tlen)) |
||
521 | return 1; |
||
522 | break; |
||
523 | case SFLOW_COUNTER_VLAN: |
||
524 | if (print_sflow_counter_vlan(ndo, tptr, tlen)) |
||
525 | return 1; |
||
526 | break; |
||
527 | case SFLOW_COUNTER_PROCESSOR: |
||
528 | if (print_sflow_counter_processor(ndo, tptr, tlen)) |
||
529 | return 1; |
||
530 | break; |
||
531 | default: |
||
532 | if (ndo->ndo_vflag <= 1) |
||
533 | print_unknown_data(ndo, tptr, "\n\t\t", counter_len); |
||
534 | break; |
||
535 | } |
||
536 | } |
||
537 | tptr += counter_len; |
||
538 | tlen -= counter_len; |
||
539 | nrecords--; |
||
540 | |||
541 | } |
||
542 | |||
543 | return 0; |
||
544 | } |
||
545 | |||
546 | static int |
||
547 | sflow_print_counter_sample(netdissect_options *ndo, |
||
548 | const u_char *pointer, u_int len) |
||
549 | { |
||
550 | const struct sflow_counter_sample_t *sflow_counter_sample; |
||
551 | u_int nrecords; |
||
552 | u_int typesource; |
||
553 | u_int type; |
||
554 | u_int index; |
||
555 | |||
556 | |||
557 | if (len < sizeof(struct sflow_counter_sample_t)) |
||
558 | return 1; |
||
559 | |||
560 | sflow_counter_sample = (const struct sflow_counter_sample_t *)pointer; |
||
561 | |||
562 | typesource = EXTRACT_32BITS(sflow_counter_sample->typesource); |
||
563 | nrecords = EXTRACT_32BITS(sflow_counter_sample->records); |
||
564 | type = typesource >> 24; |
||
565 | index = typesource & 0x0FFF; |
||
566 | |||
567 | ND_PRINT((ndo, " seqnum %u, type %u, idx %u, records %u", |
||
568 | EXTRACT_32BITS(sflow_counter_sample->seqnum), |
||
569 | type, |
||
570 | index, |
||
571 | nrecords)); |
||
572 | |||
573 | return sflow_print_counter_records(ndo, pointer + sizeof(struct sflow_counter_sample_t), |
||
574 | len - sizeof(struct sflow_counter_sample_t), |
||
575 | nrecords); |
||
576 | |||
577 | } |
||
578 | |||
579 | static int |
||
580 | sflow_print_expanded_counter_sample(netdissect_options *ndo, |
||
581 | const u_char *pointer, u_int len) |
||
582 | { |
||
583 | const struct sflow_expanded_counter_sample_t *sflow_expanded_counter_sample; |
||
584 | u_int nrecords; |
||
585 | |||
586 | |||
587 | if (len < sizeof(struct sflow_expanded_counter_sample_t)) |
||
588 | return 1; |
||
589 | |||
590 | sflow_expanded_counter_sample = (const struct sflow_expanded_counter_sample_t *)pointer; |
||
591 | |||
592 | nrecords = EXTRACT_32BITS(sflow_expanded_counter_sample->records); |
||
593 | |||
594 | ND_PRINT((ndo, " seqnum %u, type %u, idx %u, records %u", |
||
595 | EXTRACT_32BITS(sflow_expanded_counter_sample->seqnum), |
||
596 | EXTRACT_32BITS(sflow_expanded_counter_sample->type), |
||
597 | EXTRACT_32BITS(sflow_expanded_counter_sample->index), |
||
598 | nrecords)); |
||
599 | |||
600 | return sflow_print_counter_records(ndo, pointer + sizeof(struct sflow_expanded_counter_sample_t), |
||
601 | len - sizeof(struct sflow_expanded_counter_sample_t), |
||
602 | nrecords); |
||
603 | |||
604 | } |
||
605 | |||
606 | static int |
||
607 | print_sflow_raw_packet(netdissect_options *ndo, |
||
608 | const u_char *pointer, u_int len) |
||
609 | { |
||
610 | const struct sflow_expanded_flow_raw_t *sflow_flow_raw; |
||
611 | |||
612 | if (len < sizeof(struct sflow_expanded_flow_raw_t)) |
||
613 | return 1; |
||
614 | |||
615 | sflow_flow_raw = (const struct sflow_expanded_flow_raw_t *)pointer; |
||
616 | ND_PRINT((ndo, "\n\t protocol %s (%u), length %u, stripped bytes %u, header_size %u", |
||
617 | tok2str(sflow_flow_raw_protocol_values,"Unknown",EXTRACT_32BITS(sflow_flow_raw->protocol)), |
||
618 | EXTRACT_32BITS(sflow_flow_raw->protocol), |
||
619 | EXTRACT_32BITS(sflow_flow_raw->length), |
||
620 | EXTRACT_32BITS(sflow_flow_raw->stripped_bytes), |
||
621 | EXTRACT_32BITS(sflow_flow_raw->header_size))); |
||
622 | |||
623 | /* QUESTION - should we attempt to print the raw header itself? |
||
624 | assuming of course there is wnough data present to do so... */ |
||
625 | |||
626 | return 0; |
||
627 | } |
||
628 | |||
629 | static int |
||
630 | print_sflow_ethernet_frame(netdissect_options *ndo, |
||
631 | const u_char *pointer, u_int len) |
||
632 | { |
||
633 | const struct sflow_ethernet_frame_t *sflow_ethernet_frame; |
||
634 | |||
635 | if (len < sizeof(struct sflow_ethernet_frame_t)) |
||
636 | return 1; |
||
637 | |||
638 | sflow_ethernet_frame = (const struct sflow_ethernet_frame_t *)pointer; |
||
639 | |||
640 | ND_PRINT((ndo, "\n\t frame len %u, type %u", |
||
641 | EXTRACT_32BITS(sflow_ethernet_frame->length), |
||
642 | EXTRACT_32BITS(sflow_ethernet_frame->type))); |
||
643 | |||
644 | return 0; |
||
645 | } |
||
646 | |||
647 | static int |
||
648 | print_sflow_extended_switch_data(netdissect_options *ndo, |
||
649 | const u_char *pointer, u_int len) |
||
650 | { |
||
651 | const struct sflow_extended_switch_data_t *sflow_extended_sw_data; |
||
652 | |||
653 | if (len < sizeof(struct sflow_extended_switch_data_t)) |
||
654 | return 1; |
||
655 | |||
656 | sflow_extended_sw_data = (const struct sflow_extended_switch_data_t *)pointer; |
||
657 | ND_PRINT((ndo, "\n\t src vlan %u, src pri %u, dst vlan %u, dst pri %u", |
||
658 | EXTRACT_32BITS(sflow_extended_sw_data->src_vlan), |
||
659 | EXTRACT_32BITS(sflow_extended_sw_data->src_pri), |
||
660 | EXTRACT_32BITS(sflow_extended_sw_data->dst_vlan), |
||
661 | EXTRACT_32BITS(sflow_extended_sw_data->dst_pri))); |
||
662 | |||
663 | return 0; |
||
664 | } |
||
665 | |||
666 | static int |
||
667 | sflow_print_flow_records(netdissect_options *ndo, |
||
668 | const u_char *pointer, u_int len, u_int records) |
||
669 | { |
||
670 | u_int nrecords; |
||
671 | const u_char *tptr; |
||
672 | u_int tlen; |
||
673 | u_int flow_type; |
||
674 | u_int enterprise; |
||
675 | u_int flow_len; |
||
676 | const struct sflow_flow_record_t *sflow_flow_record; |
||
677 | |||
678 | nrecords = records; |
||
679 | tptr = pointer; |
||
680 | tlen = len; |
||
681 | |||
682 | while (nrecords > 0) { |
||
683 | /* do we have the "header?" */ |
||
684 | if (tlen < sizeof(struct sflow_flow_record_t)) |
||
685 | return 1; |
||
686 | |||
687 | sflow_flow_record = (const struct sflow_flow_record_t *)tptr; |
||
688 | |||
689 | /* so, the funky encoding means we cannot blythly mask-off |
||
690 | bits, we must also check the enterprise. */ |
||
691 | |||
692 | enterprise = EXTRACT_32BITS(sflow_flow_record->format); |
||
693 | flow_type = enterprise & 0x0FFF; |
||
694 | enterprise = enterprise >> 12; |
||
695 | flow_len = EXTRACT_32BITS(sflow_flow_record->length); |
||
696 | ND_PRINT((ndo, "\n\t enterprise %u %s (%u) length %u", |
||
697 | enterprise, |
||
698 | (enterprise == 0) ? tok2str(sflow_flow_type_values,"Unknown",flow_type) : "Unknown", |
||
699 | flow_type, |
||
700 | flow_len)); |
||
701 | |||
702 | tptr += sizeof(struct sflow_flow_record_t); |
||
703 | tlen -= sizeof(struct sflow_flow_record_t); |
||
704 | |||
705 | if (tlen < flow_len) |
||
706 | return 1; |
||
707 | |||
708 | if (enterprise == 0) { |
||
709 | switch (flow_type) { |
||
710 | case SFLOW_FLOW_RAW_PACKET: |
||
711 | if (print_sflow_raw_packet(ndo, tptr, tlen)) |
||
712 | return 1; |
||
713 | break; |
||
714 | case SFLOW_FLOW_EXTENDED_SWITCH_DATA: |
||
715 | if (print_sflow_extended_switch_data(ndo, tptr, tlen)) |
||
716 | return 1; |
||
717 | break; |
||
718 | case SFLOW_FLOW_ETHERNET_FRAME: |
||
719 | if (print_sflow_ethernet_frame(ndo, tptr, tlen)) |
||
720 | return 1; |
||
721 | break; |
||
722 | /* FIXME these need a decoder */ |
||
723 | case SFLOW_FLOW_IPV4_DATA: |
||
724 | case SFLOW_FLOW_IPV6_DATA: |
||
725 | case SFLOW_FLOW_EXTENDED_ROUTER_DATA: |
||
726 | case SFLOW_FLOW_EXTENDED_GATEWAY_DATA: |
||
727 | case SFLOW_FLOW_EXTENDED_USER_DATA: |
||
728 | case SFLOW_FLOW_EXTENDED_URL_DATA: |
||
729 | case SFLOW_FLOW_EXTENDED_MPLS_DATA: |
||
730 | case SFLOW_FLOW_EXTENDED_NAT_DATA: |
||
731 | case SFLOW_FLOW_EXTENDED_MPLS_TUNNEL: |
||
732 | case SFLOW_FLOW_EXTENDED_MPLS_VC: |
||
733 | case SFLOW_FLOW_EXTENDED_MPLS_FEC: |
||
734 | case SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC: |
||
735 | case SFLOW_FLOW_EXTENDED_VLAN_TUNNEL: |
||
736 | break; |
||
737 | default: |
||
738 | if (ndo->ndo_vflag <= 1) |
||
739 | print_unknown_data(ndo, tptr, "\n\t\t", flow_len); |
||
740 | break; |
||
741 | } |
||
742 | } |
||
743 | tptr += flow_len; |
||
744 | tlen -= flow_len; |
||
745 | nrecords--; |
||
746 | |||
747 | } |
||
748 | |||
749 | return 0; |
||
750 | } |
||
751 | |||
752 | static int |
||
753 | sflow_print_flow_sample(netdissect_options *ndo, |
||
754 | const u_char *pointer, u_int len) |
||
755 | { |
||
756 | const struct sflow_flow_sample_t *sflow_flow_sample; |
||
757 | u_int nrecords; |
||
758 | u_int typesource; |
||
759 | u_int type; |
||
760 | u_int index; |
||
761 | |||
762 | if (len < sizeof(struct sflow_flow_sample_t)) |
||
763 | return 1; |
||
764 | |||
765 | sflow_flow_sample = (struct sflow_flow_sample_t *)pointer; |
||
766 | |||
767 | typesource = EXTRACT_32BITS(sflow_flow_sample->typesource); |
||
768 | nrecords = EXTRACT_32BITS(sflow_flow_sample->records); |
||
769 | type = typesource >> 24; |
||
770 | index = typesource & 0x0FFF; |
||
771 | |||
772 | ND_PRINT((ndo, " seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, input %u output %u records %u", |
||
773 | EXTRACT_32BITS(sflow_flow_sample->seqnum), |
||
774 | type, |
||
775 | index, |
||
776 | EXTRACT_32BITS(sflow_flow_sample->rate), |
||
777 | EXTRACT_32BITS(sflow_flow_sample->pool), |
||
778 | EXTRACT_32BITS(sflow_flow_sample->drops), |
||
779 | EXTRACT_32BITS(sflow_flow_sample->in_interface), |
||
780 | EXTRACT_32BITS(sflow_flow_sample->out_interface), |
||
781 | nrecords)); |
||
782 | |||
783 | return sflow_print_flow_records(ndo, pointer + sizeof(struct sflow_flow_sample_t), |
||
784 | len - sizeof(struct sflow_flow_sample_t), |
||
785 | nrecords); |
||
786 | |||
787 | } |
||
788 | |||
789 | static int |
||
790 | sflow_print_expanded_flow_sample(netdissect_options *ndo, |
||
791 | const u_char *pointer, u_int len) |
||
792 | { |
||
793 | const struct sflow_expanded_flow_sample_t *sflow_expanded_flow_sample; |
||
794 | u_int nrecords; |
||
795 | |||
796 | if (len < sizeof(struct sflow_expanded_flow_sample_t)) |
||
797 | return 1; |
||
798 | |||
799 | sflow_expanded_flow_sample = (const struct sflow_expanded_flow_sample_t *)pointer; |
||
800 | |||
801 | nrecords = EXTRACT_32BITS(sflow_expanded_flow_sample->records); |
||
802 | |||
803 | ND_PRINT((ndo, " seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, records %u", |
||
804 | EXTRACT_32BITS(sflow_expanded_flow_sample->seqnum), |
||
805 | EXTRACT_32BITS(sflow_expanded_flow_sample->type), |
||
806 | EXTRACT_32BITS(sflow_expanded_flow_sample->index), |
||
807 | EXTRACT_32BITS(sflow_expanded_flow_sample->rate), |
||
808 | EXTRACT_32BITS(sflow_expanded_flow_sample->pool), |
||
809 | EXTRACT_32BITS(sflow_expanded_flow_sample->drops), |
||
810 | EXTRACT_32BITS(sflow_expanded_flow_sample->records))); |
||
811 | |||
812 | return sflow_print_flow_records(ndo, pointer + sizeof(struct sflow_expanded_flow_sample_t), |
||
813 | len - sizeof(struct sflow_expanded_flow_sample_t), |
||
814 | nrecords); |
||
815 | |||
816 | } |
||
817 | |||
818 | void |
||
819 | sflow_print(netdissect_options *ndo, |
||
820 | const u_char *pptr, u_int len) |
||
821 | { |
||
822 | const struct sflow_datagram_t *sflow_datagram; |
||
823 | const struct sflow_sample_header *sflow_sample; |
||
824 | |||
825 | const u_char *tptr; |
||
826 | u_int tlen; |
||
827 | uint32_t sflow_sample_type, sflow_sample_len; |
||
828 | uint32_t nsamples; |
||
829 | |||
830 | |||
831 | tptr = pptr; |
||
832 | tlen = len; |
||
833 | sflow_datagram = (const struct sflow_datagram_t *)pptr; |
||
834 | ND_TCHECK(*sflow_datagram); |
||
835 | |||
836 | /* |
||
837 | * Sanity checking of the header. |
||
838 | */ |
||
839 | if (EXTRACT_32BITS(sflow_datagram->version) != 5) { |
||
840 | ND_PRINT((ndo, "sFlow version %u packet not supported", |
||
841 | EXTRACT_32BITS(sflow_datagram->version))); |
||
842 | return; |
||
843 | } |
||
844 | |||
845 | if (ndo->ndo_vflag < 1) { |
||
846 | ND_PRINT((ndo, "sFlowv%u, %s agent %s, agent-id %u, length %u", |
||
847 | EXTRACT_32BITS(sflow_datagram->version), |
||
848 | EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6", |
||
849 | ipaddr_string(ndo, sflow_datagram->agent), |
||
850 | EXTRACT_32BITS(sflow_datagram->agent_id), |
||
851 | len)); |
||
852 | return; |
||
853 | } |
||
854 | |||
855 | /* ok they seem to want to know everything - lets fully decode it */ |
||
856 | nsamples=EXTRACT_32BITS(sflow_datagram->samples); |
||
857 | ND_PRINT((ndo, "sFlowv%u, %s agent %s, agent-id %u, seqnum %u, uptime %u, samples %u, length %u", |
||
858 | EXTRACT_32BITS(sflow_datagram->version), |
||
859 | EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6", |
||
860 | ipaddr_string(ndo, sflow_datagram->agent), |
||
861 | EXTRACT_32BITS(sflow_datagram->agent_id), |
||
862 | EXTRACT_32BITS(sflow_datagram->seqnum), |
||
863 | EXTRACT_32BITS(sflow_datagram->uptime), |
||
864 | nsamples, |
||
865 | len)); |
||
866 | |||
867 | /* skip Common header */ |
||
868 | tptr += sizeof(const struct sflow_datagram_t); |
||
869 | tlen -= sizeof(const struct sflow_datagram_t); |
||
870 | |||
871 | while (nsamples > 0 && tlen > 0) { |
||
872 | sflow_sample = (const struct sflow_sample_header *)tptr; |
||
873 | ND_TCHECK(*sflow_sample); |
||
874 | |||
875 | sflow_sample_type = (EXTRACT_32BITS(sflow_sample->format)&0x0FFF); |
||
876 | sflow_sample_len = EXTRACT_32BITS(sflow_sample->len); |
||
877 | |||
878 | if (tlen < sizeof(struct sflow_sample_header)) |
||
879 | goto trunc; |
||
880 | |||
881 | tptr += sizeof(struct sflow_sample_header); |
||
882 | tlen -= sizeof(struct sflow_sample_header); |
||
883 | |||
884 | ND_PRINT((ndo, "\n\t%s (%u), length %u,", |
||
885 | tok2str(sflow_format_values, "Unknown", sflow_sample_type), |
||
886 | sflow_sample_type, |
||
887 | sflow_sample_len)); |
||
888 | |||
889 | /* basic sanity check */ |
||
890 | if (sflow_sample_type == 0 || sflow_sample_len ==0) { |
||
891 | return; |
||
892 | } |
||
893 | |||
894 | if (tlen < sflow_sample_len) |
||
895 | goto trunc; |
||
896 | |||
897 | /* did we capture enough for fully decoding the sample ? */ |
||
898 | ND_TCHECK2(*tptr, sflow_sample_len); |
||
899 | |||
900 | switch(sflow_sample_type) { |
||
901 | case SFLOW_FLOW_SAMPLE: |
||
902 | if (sflow_print_flow_sample(ndo, tptr, tlen)) |
||
903 | goto trunc; |
||
904 | break; |
||
905 | |||
906 | case SFLOW_COUNTER_SAMPLE: |
||
907 | if (sflow_print_counter_sample(ndo, tptr,tlen)) |
||
908 | goto trunc; |
||
909 | break; |
||
910 | |||
911 | case SFLOW_EXPANDED_FLOW_SAMPLE: |
||
912 | if (sflow_print_expanded_flow_sample(ndo, tptr, tlen)) |
||
913 | goto trunc; |
||
914 | break; |
||
915 | |||
916 | case SFLOW_EXPANDED_COUNTER_SAMPLE: |
||
917 | if (sflow_print_expanded_counter_sample(ndo, tptr,tlen)) |
||
918 | goto trunc; |
||
919 | break; |
||
920 | |||
921 | default: |
||
922 | if (ndo->ndo_vflag <= 1) |
||
923 | print_unknown_data(ndo, tptr, "\n\t ", sflow_sample_len); |
||
924 | break; |
||
925 | } |
||
926 | tptr += sflow_sample_len; |
||
927 | tlen -= sflow_sample_len; |
||
928 | nsamples--; |
||
929 | } |
||
930 | return; |
||
931 | |||
932 | trunc: |
||
933 | ND_PRINT((ndo, "[|SFLOW]")); |
||
934 | } |
||
935 | |||
936 | /* |
||
937 | * Local Variables: |
||
938 | * c-style: whitesmith |
||
939 | * c-basic-offset: 4 |
||
940 | * End: |
||
941 | */ |