xref: /minix3/external/bsd/tcpdump/dist/print-sflow.c (revision b636d99d91c3d54204248f643c14627405d4afd1)
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