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