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