17797969af63ff204633c427dc3995ffd725ec80
[obnox/wireshark/wip.git] / epan / dissectors / packet-sflow.c
1 /* packet-sflow.c
2  * Routines for sFlow v5 dissection implemented according to the specifications
3  * at http://www.sflow.org/sflow_version_5.txt
4  *
5  * Additional 802.11 structures support implemented according to the
6  * specifications at http://www.sflow.org/sflow_80211.txt
7  *
8  * By Yi Yu <yiyu.inbox@gmail.com>
9  *
10  * $Id$
11  *
12  * TODO:
13  *   802.11 aggregation data dissection                         (sFlow v5)
14  *   improve TCP bitwise flags dissection display               (sFlow v5)
15  *
16  *
17  * Based on Jeff Rizzo's <riz@boogers.sf.ca.us> dissector for sFlow v2/4
18  * in Wireshark 1.0.8 public release.
19  *
20  * Wireshark - Network traffic analyzer
21  * By Gerald Combs <gerald@wireshark.org>
22  * Copyright 1998 Gerald Combs
23  *
24  * This program is free software; you can redistribute it and/or
25  * modify it under the terms of the GNU General Public License
26  * as published by the Free Software Foundation; either version 2
27  * of the License, or (at your option) any later version.
28  *
29  * This program is distributed in the hope that it will be useful,
30  * but WITHOUT ANY WARRANTY; without even the implied warranty of
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32  * GNU General Public License for more details.
33  *
34  * You should have received a copy of the GNU General Public License
35  * along with this program; if not, write to the Free Software
36  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37  *
38  *
39  * This file (mostly) implements a dissector for sFlow (RFC3176),
40  * from the version 4 spec at http://www.sflow.org/SFLOW-DATAGRAM.txt .
41  *
42  * TODO:
43  *   Fix the highlighting of the datastream when bits are selected
44  *   split things out into packet-sflow.h ?
45  *   make routines more consistent as to whether they return
46  *     'offset' or bytes consumed ('len')                       (sFlow v2/4)
47  *   implement sampled_ipv4 and sampled_ipv6 packet data types  (sFlow v2/4)
48  *   implement extended_user                                    (sFlow v2/4)
49  *   implement extended_url                                     (sFlow v2/4)
50  *   implement non-generic counters sampling                    (sFlow v2/4)
51  */
52
53 #ifdef HAVE_CONFIG_H
54 #include "config.h"
55 #endif
56
57 #include <glib.h>
58
59 #include <epan/packet.h>
60 #include <epan/prefs.h>
61
62 #define SFLOW_UDP_PORTS "6343"
63
64 static dissector_handle_t sflow_handle;
65
66 /*
67  *  global_sflow_ports : holds the configured range of ports for sflow
68  */
69 static range_t *global_sflow_ports = NULL;
70
71 /*
72  *  sflow_245_ports : holds the currently used range of ports for sflow
73  */
74 static gboolean global_dissect_samp_headers = TRUE;
75 static gboolean global_analyze_samp_ip_headers = FALSE;
76
77 #define ENTERPRISE_DEFAULT 0
78
79 #define ADDR_TYPE_IPV4 1
80 #define ADDR_TYPE_IPV6 2
81
82 #define FLOWSAMPLE 1
83 #define COUNTERSSAMPLE 2
84 #define EXPANDED_FLOWSAMPLE 3
85 #define EXPANDED_COUNTERSSAMPLE 4
86
87 static const value_string sflow_245_sampletype[] = {
88     { FLOWSAMPLE, "Flow sample"},
89     { COUNTERSSAMPLE, "Counters sample"},
90     { EXPANDED_FLOWSAMPLE, "Expanded flow sample"},
91     { EXPANDED_COUNTERSSAMPLE, "Expanded counters sample"},
92     { 0, NULL}
93 };
94
95 #define SFLOW_5_IEEE80211_VERSION_A 1
96 #define SFLOW_5_IEEE80211_VERSION_B 2
97 #define SFLOW_5_IEEE80211_VERSION_G 3
98 #define SFLOW_5_IEEE80211_VERSION_N 4
99
100 static const value_string sflow_5_ieee80211_versions [] = {
101     { SFLOW_5_IEEE80211_VERSION_A, "802.11a"},
102     { SFLOW_5_IEEE80211_VERSION_B, "802.11b"},
103     { SFLOW_5_IEEE80211_VERSION_G, "802.11g"},
104     { SFLOW_5_IEEE80211_VERSION_N, "802.11n"},
105     { 0, NULL}
106 };
107
108 /* interface counter types */
109 #define SFLOW_245_COUNTERS_GENERIC 1
110 #define SFLOW_245_COUNTERS_ETHERNET 2
111 #define SFLOW_245_COUNTERS_TOKENRING 3
112 #define SFLOW_245_COUNTERS_FDDI 4
113 #define SFLOW_245_COUNTERS_VG 5
114 #define SFLOW_245_COUNTERS_WAN 6
115 #define SFLOW_245_COUNTERS_VLAN 7
116
117 static const value_string sflow_245_counterstype[] = {
118     { SFLOW_245_COUNTERS_GENERIC, "Generic counters"},
119     { SFLOW_245_COUNTERS_ETHERNET, "Ethernet counters"},
120     { SFLOW_245_COUNTERS_FDDI, "FDDI counters"},
121     { SFLOW_245_COUNTERS_VG, "100baseVG counters"},
122     { SFLOW_245_COUNTERS_WAN, "WAN counters"},
123     { SFLOW_245_COUNTERS_VLAN, "VLAN counters"},
124     { 0, NULL}
125 };
126
127 #define MAX_HEADER_SIZE 256
128
129 #define SFLOW_245_PACKET_DATA_TYPE_HEADER 1
130 #define SFLOW_245_PACKET_DATA_TYPE_IPV4 2
131 #define SFLOW_245_PACKET_DATA_TYPE_IPV6 3
132
133 static const value_string sflow_245_packet_information_type[] = {
134     { SFLOW_245_PACKET_DATA_TYPE_HEADER, "Packet headers are sampled"},
135     { SFLOW_245_PACKET_DATA_TYPE_IPV4, "IP Version 4 data"},
136     { SFLOW_245_PACKET_DATA_TYPE_IPV6, "IP Version 6 data"},
137     { 0, NULL}
138 };
139
140 #define SFLOW_245_HEADER_ETHERNET 1
141 #define SFLOW_245_HEADER_TOKENBUS 2
142 #define SFLOW_245_HEADER_TOKENRING 3
143 #define SFLOW_245_HEADER_FDDI 4
144 #define SFLOW_245_HEADER_FRAME_RELAY 5
145 #define SFLOW_245_HEADER_X25 6
146 #define SFLOW_245_HEADER_PPP 7
147 #define SFLOW_245_HEADER_SMDS 8
148 #define SFLOW_245_HEADER_AAL5 9
149 #define SFLOW_245_HEADER_AAL5_IP 10
150 #define SFLOW_245_HEADER_IPv4 11
151 #define SFLOW_245_HEADER_IPv6 12
152 #define SFLOW_245_HEADER_MPLS 13
153 #define SFLOW_5_HEADER_POS 14
154 #define SFLOW_5_HEADER_80211_MAC 15
155 #define SFLOW_5_HEADER_80211_AMPDU 16
156 #define SFLOW_5_HEADER_80211_AMSDU_SUBFRAME 17
157
158 static const value_string sflow_245_header_protocol[] = {
159     { SFLOW_245_HEADER_ETHERNET, "Ethernet"},
160     { SFLOW_245_HEADER_TOKENBUS, "Token Bus"},
161     { SFLOW_245_HEADER_TOKENRING, "Token Ring"},
162     { SFLOW_245_HEADER_FDDI, "FDDI"},
163     { SFLOW_245_HEADER_FRAME_RELAY, "Frame Relay"},
164     { SFLOW_245_HEADER_X25, "X.25"},
165     { SFLOW_245_HEADER_PPP, "PPP"},
166     { SFLOW_245_HEADER_SMDS, "SMDS"},
167     { SFLOW_245_HEADER_AAL5, "ATM AAL5"},
168     { SFLOW_245_HEADER_AAL5_IP, "ATM AAL5-IP (e.g., Cisco AAL5 mux)"},
169     { SFLOW_245_HEADER_IPv4, "IPv4"},
170     { SFLOW_245_HEADER_IPv6, "IPv6"},
171     { SFLOW_245_HEADER_MPLS, "MPLS"},
172     { SFLOW_5_HEADER_POS, "PPP over SONET/SDH (RFC 1662, 2615)"},
173     { SFLOW_5_HEADER_80211_MAC, "802.11 MAC"},
174     { SFLOW_5_HEADER_80211_AMPDU, "802.11n Aggregated MPDU"},
175     { SFLOW_5_HEADER_80211_AMSDU_SUBFRAME, "A-MSDU Subframe"},
176     { 0, NULL}
177 };
178
179 /* extended packet data types */
180 #define SFLOW_245_EXTENDED_SWITCH 1
181 #define SFLOW_245_EXTENDED_ROUTER 2
182 #define SFLOW_245_EXTENDED_GATEWAY 3
183 #define SFLOW_245_EXTENDED_USER 4
184 #define SFLOW_245_EXTENDED_URL 5
185
186 static const value_string sflow_245_extended_data_types[] = {
187     { SFLOW_245_EXTENDED_SWITCH, "Extended switch information"},
188     { SFLOW_245_EXTENDED_ROUTER, "Extended router information"},
189     { SFLOW_245_EXTENDED_GATEWAY, "Extended gateway information"},
190     { SFLOW_245_EXTENDED_USER, "Extended user information"},
191     { SFLOW_245_EXTENDED_URL, "Extended URL information"},
192     { 0, NULL}
193 };
194
195
196 #define SFLOW_245_AS_SET 1
197 #define SFLOW_245_AS_SEQUENCE 2
198
199 static const value_string sflow_245_as_types[] = {
200     { SFLOW_245_AS_SET, "AS Set"},
201     { SFLOW_245_AS_SEQUENCE, "AS Sequence"},
202     { 0, NULL}
203 };
204
205 #define SFLOW_245_IPV4_PRECEDENCE_ROUTINE 0
206 #define SFLOW_245_IPV4_PRECEDENCE_PRIORITY 1
207 #define SFLOW_245_IPV4_PRECEDENCE_IMMEDIATE 2
208 #define SFLOW_245_IPV4_PRECEDENCE_FLASH 3
209 #define SFLOW_245_IPV4_PRECEDENCE_FLASH_OVERRIDE 4
210 #define SFLOW_245_IPV4_PRECEDENCE_CRITIC_ECP 5
211 #define SFLOW_245_IPV4_PRECEDENCE_INTERNETWORK_CONTROL 6
212 #define SFLOW_245_IPV4_PRECEDENCE_NETWORK_CONTROL 7
213
214 static const value_string sflow_245_ipv4_precedence_types[] = {
215     { SFLOW_245_IPV4_PRECEDENCE_ROUTINE, "Routine"},
216     { SFLOW_245_IPV4_PRECEDENCE_PRIORITY, "Priority"},
217     { SFLOW_245_IPV4_PRECEDENCE_IMMEDIATE, "Immediate"},
218     { SFLOW_245_IPV4_PRECEDENCE_FLASH, "Flash"},
219     { SFLOW_245_IPV4_PRECEDENCE_FLASH_OVERRIDE, "Flash Override"},
220     { SFLOW_245_IPV4_PRECEDENCE_CRITIC_ECP, "CRITIC/ECP"},
221     { SFLOW_245_IPV4_PRECEDENCE_INTERNETWORK_CONTROL, "Internetwork Control"},
222     { SFLOW_245_IPV4_PRECEDENCE_NETWORK_CONTROL, "Network Control"},
223     { 0, NULL}
224 };
225
226 /* sFlow v5 flow record formats */
227 #define SFLOW_5_RAW_PACKET_HEADER 1
228 #define SFLOW_5_ETHERNET_FRAME 2
229 #define SFLOW_5_IPV4 3
230 #define SFLOW_5_IPV6 4
231 #define SFLOW_5_SWITCH 1001
232 #define SFLOW_5_ROUTER 1002
233 #define SFLOW_5_GATEWAY 1003
234 #define SFLOW_5_USER 1004
235 #define SFLOW_5_URL 1005
236 #define SFLOW_5_MPLS_DATA 1006
237 #define SFLOW_5_NAT 1007
238 #define SFLOW_5_MPLS_TUNNEL 1008
239 #define SFLOW_5_MPLS_VC 1009
240 #define SFLOW_5_MPLS_FEC 1010
241 #define SFLOW_5_MPLS_LVP_FEC 1011
242 #define SFLOW_5_VLAN_TUNNEL 1012
243 #define SFLOW_5_80211_PAYLOAD 1013
244 #define SFLOW_5_80211_RX 1014
245 #define SFLOW_5_80211_TX 1015
246 #define SFLOW_5_80211_AGGREGATION 1016
247
248
249 static const value_string sflow_5_flow_record_type[] = {
250     { SFLOW_5_RAW_PACKET_HEADER, "Raw packet header"},
251     { SFLOW_5_ETHERNET_FRAME, "Ethernet frame data"},
252     { SFLOW_5_IPV4, "IPv4 data"},
253     { SFLOW_5_IPV6, "IPv6 data"},
254     { SFLOW_5_SWITCH, "Extended switch data"},
255     { SFLOW_5_ROUTER, "Extended router data"},
256     { SFLOW_5_GATEWAY, "Extended gateway data"},
257     { SFLOW_5_USER, "Extended user data"},
258     { SFLOW_5_URL, "Extended URL data"},
259     { SFLOW_5_MPLS_DATA, "Extended MPLS data"},
260     { SFLOW_5_NAT, "Extended NAT data"},
261     { SFLOW_5_MPLS_TUNNEL, "Extended MPLS tunnel data"},
262     { SFLOW_5_MPLS_VC, "Extended MPLS VC data"},
263     { SFLOW_5_MPLS_FEC, "Extended MPLS FEC data"},
264     { SFLOW_5_MPLS_LVP_FEC, "Extended MPLS LVP FEC data"},
265     { SFLOW_5_VLAN_TUNNEL, "Extended VLAN tunnel"},
266     { SFLOW_5_80211_PAYLOAD, "Extended 802.11 payload"},
267     { SFLOW_5_80211_RX, "Extended 802.11 RX"},
268     { SFLOW_5_80211_TX, "Extended 802.11 TX"},
269     { SFLOW_5_80211_AGGREGATION, "Extended 802.11 aggregation"},
270     { 0, NULL}
271 };
272
273 /* sFlow v5 counters record formats */
274 #define SFLOW_5_GENERIC_INTERFACE 1
275 #define SFLOW_5_ETHERNET_INTERFACE 2
276 #define SFLOW_5_TOKEN_RING 3
277 #define SFLOW_5_100BASE_VG_INTERFACE 4
278 #define SFLOW_5_VLAN 5
279 #define SFLOW_5_80211_COUNTERS 6
280 #define SFLOW_5_PROCESSOR 1001
281 #define SFLOW_5_RADIO_UTILIZATION 1002
282
283 static const value_string sflow_5_counters_record_type[] = {
284     { SFLOW_5_GENERIC_INTERFACE, "Generic interface counters"},
285     { SFLOW_5_ETHERNET_INTERFACE, "Ethernet interface counters"},
286     { SFLOW_5_TOKEN_RING, "Token ring counters"},
287     { SFLOW_5_100BASE_VG_INTERFACE, "100 Base VG interface counters"},
288     { SFLOW_5_VLAN, "VLAN counters"},
289     { SFLOW_5_80211_COUNTERS, "IEEE 802.11 counters"},
290     { SFLOW_5_PROCESSOR, "Processor information"},
291     { SFLOW_5_RADIO_UTILIZATION, "Radio utilization"},
292     { 0, NULL}
293 };
294
295 /* flow sample header v24 */
296 struct sflow_24_flow_sample_header {
297     guint32 sequence_number;
298     guint32 source_id;
299     guint32 sampling_rate;
300     guint32 sample_pool;
301     guint32 drops;
302     guint32 input;
303     guint32 output;
304 };
305
306 /* flow sample header v5 */
307 struct sflow_5_flow_sample_header {
308     guint32 sequence_number;
309     guint32 source_id;
310     guint32 sampling_rate;
311     guint32 sample_pool;
312     guint32 drops;
313     guint32 input;
314     guint32 output;
315     guint32 records;
316 };
317
318 /* flow sample header v5 expanded */
319 struct sflow_5_expanded_flow_sample_header {
320     guint32 sequence_number;
321     guint32 source_id_type;
322     guint32 source_id_index;
323     guint32 sampling_rate;
324     guint32 sample_pool;
325     guint32 drops;
326     guint32 input_format;
327     guint32 input_value;
328     guint32 output_format;
329     guint32 output_value;
330     guint32 records;
331 };
332
333 /* counters sample header v24 */
334 struct sflow_24_counters_sample_header {
335     guint32 sequence_number;
336     guint32 source_id;
337     guint32 sampling_interval;
338     guint32 counters_type;
339 };
340
341 /* counters sample header v5 */
342 struct sflow_5_counters_sample_header {
343     guint32 sequence_number;
344     guint32 source_id;
345     guint32 records;
346 };
347
348 /* counters sample header v5 expanded */
349 struct sflow_5_expanded_counters_sample_header {
350     guint32 sequence_number;
351     guint32 source_id_type;
352     guint32 source_id_index;
353     guint32 records;
354 };
355
356 /* generic interface counters */
357 struct if_counters {
358     guint32 ifIndex;
359     guint32 ifType;
360     guint64 ifSpeed;
361     guint32 ifDirection;
362     guint32 ifStatus;
363     guint64 ifInOctets;
364     guint32 ifInUcastPkts;
365     guint32 ifInMulticastPkts;
366     guint32 ifInBroadcastPkts;
367     guint32 ifInDiscards;
368     guint32 ifInErrors;
369     guint32 ifInUnknownProtos;
370     guint64 ifOutOctets;
371     guint32 ifOutUcastPkts;
372     guint32 ifOutMulticastPkts;
373     guint32 ifOutBroadcastPkts;
374     guint32 ifOutDiscards;
375     guint32 ifOutErrors;
376     guint32 ifPromiscuousMode;
377 };
378
379 /* ethernet counters.  These will be preceded by generic counters. */
380 struct ethernet_counters {
381     guint32 dot3StatsAlignmentErrors;
382     guint32 dot3StatsFCSErrors;
383     guint32 dot3StatsSingleCollisionFrames;
384     guint32 dot3StatsMultipleCollisionFrames;
385     guint32 dot3StatsSQETestErrors;
386     guint32 dot3StatsDeferredTransmissions;
387     guint32 dot3StatsLateCollisions;
388     guint32 dot3StatsExcessiveCollisions;
389     guint32 dot3StatsInternalMacTransmitErrors;
390     guint32 dot3StatsCarrierSenseErrors;
391     guint32 dot3StatsFrameTooLongs;
392     guint32 dot3StatsInternalMacReceiveErrors;
393     guint32 dot3StatsSymbolErrors;
394 };
395
396 /* Token Ring counters */
397 struct token_ring_counters {
398     guint32 dot5StatsLineErrors;
399     guint32 dot5StatsBurstErrors;
400     guint32 dot5StatsACErrors;
401     guint32 dot5StatsAbortTransErrors;
402     guint32 dot5StatsInternalErrors;
403     guint32 dot5StatsLostFrameErrors;
404     guint32 dot5StatsReceiveCongestions;
405     guint32 dot5StatsFrameCopiedErrors;
406     guint32 dot5StatsTokenErrors;
407     guint32 dot5StatsSoftErrors;
408     guint32 dot5StatsHardErrors;
409     guint32 dot5StatsSignalLoss;
410     guint32 dot5StatsTransmitBeacons;
411     guint32 dot5StatsRecoverys;
412     guint32 dot5StatsLobeWires;
413     guint32 dot5StatsRemoves;
414     guint32 dot5StatsSingles;
415     guint32 dot5StatsFreqErrors;
416 };
417
418 /* 100BaseVG counters */
419
420 struct vg_counters {
421     guint32 dot12InHighPriorityFrames;
422     guint64 dot12InHighPriorityOctets;
423     guint32 dot12InNormPriorityFrames;
424     guint64 dot12InNormPriorityOctets;
425     guint32 dot12InIPMErrors;
426     guint32 dot12InOversizeFrameErrors;
427     guint32 dot12InDataErrors;
428     guint32 dot12InNullAddressedFrames;
429     guint32 dot12OutHighPriorityFrames;
430     guint64 dot12OutHighPriorityOctets;
431     guint32 dot12TransitionIntoTrainings;
432     guint64 dot12HCInHighPriorityOctets;
433     guint64 dot12HCInNormPriorityOctets;
434     guint64 dot12HCOutHighPriorityOctets;
435 };
436
437 /* VLAN counters */
438
439 struct vlan_counters {
440     guint32 vlan_id;
441     guint32 octets;
442     guint32 ucastPkts;
443     guint32 multicastPkts;
444     guint32 broadcastPkts;
445     guint32 discards;
446 };
447
448 /* 802.11 counters */
449
450 struct ieee80211_if_counters {
451     guint32 dot11TransmittedFragmentCount;
452     guint32 dot11MulticastTransmittedFrameCount;
453     guint32 dot11FailedCount;
454     guint32 dot11RetryCount;
455     guint32 dot11MultipleRetryCount;
456     guint32 dot11FrameDuplicateCount;
457     guint32 dot11RTSSuccessCount;
458     guint32 dot11RTSFailureCount;
459     guint32 dot11ACKFailureCount;
460     guint32 dot11ReceivedFragmentCount;
461     guint32 dot11MulticastReceivedFrameCount;
462     guint32 dot11FCSErrorCount;
463     guint32 dot11TransmittedFrameCount;
464     guint32 dot11WEPUndecryptableCount;
465     guint32 dot11QoSDiscardedFragmentCount;
466     guint32 dot11AssociatedStationCount;
467     guint32 dot11QoSCFPollsReceivedCount;
468     guint32 dot11QoSCFPollsUnusedCount;
469     guint32 dot11QoSCFPollsUnusableCount;
470     guint32 dot11QoSCFPollsLostCount;
471 };
472
473 /* processor information */
474
475 struct processor {
476     guint32 cpu_5s;
477     guint32 cpu_1m;
478     guint32 cpu_5m;
479     guint64 total_memory;
480     guint64 free_memory;
481 };
482
483 /* radio utilization */
484
485 struct radio_utilization {
486     guint32 elapsed_time;
487     guint32 on_channel_time;
488     guint32 on_channel_busy_time;
489 };
490
491 struct sflow_address_type {
492     int hf_addr_v4;
493     int hf_addr_v6;
494 };
495
496 struct sflow_address_details {
497     int addr_type;              /* ADDR_TYPE_IPV4 | ADDR_TYPE_IPV6 */
498     union {
499         guint8 v4[4];
500         guint8 v6[16];
501     } agent_address;
502 };
503
504 /* Initialize the protocol and registered fields */
505 static int proto_sflow = -1;
506 static int hf_sflow_version = -1;
507 /*static int hf_sflow_245_agent_address_type = -1; */
508 static int hf_sflow_agent_address_v4 = -1;
509 static int hf_sflow_agent_address_v6 = -1;
510 static int hf_sflow_5_sub_agent_id = -1;
511 static int hf_sflow_5_sample_length = -1;
512 static int hf_sflow_5_flow_data_length = -1;
513 static int hf_sflow_5_counters_data_length = -1;
514 static int hf_sflow_245_seqnum = -1;
515 static int hf_sflow_245_sysuptime = -1;
516 static int hf_sflow_245_numsamples = -1;
517 static int hf_sflow_245_header_protocol = -1;
518 static int hf_sflow_245_sampletype = -1;
519 static int hf_sflow_245_ipv4_precedence_type = -1;
520 static int hf_sflow_5_flow_record_format = -1;
521 static int hf_sflow_5_counters_record_format = -1;
522 static int hf_sflow_245_header = -1;
523 static int hf_sflow_245_packet_information_type = -1;
524 static int hf_sflow_245_extended_information_type = -1;
525 static int hf_sflow_245_vlan_in = -1; /* incoming 802.1Q VLAN ID */
526 static int hf_sflow_245_vlan_out = -1; /* outgoing 802.1Q VLAN ID */
527 static int hf_sflow_245_pri_in = -1; /* incominging 802.1p priority */
528 static int hf_sflow_245_pri_out = -1; /* outgoing 802.1p priority */
529 static int hf_sflow_245_nexthop_v4 = -1; /* nexthop address */
530 static int hf_sflow_245_nexthop_v6 = -1; /* nexthop address */
531 static int hf_sflow_245_ipv4_src = -1;
532 static int hf_sflow_245_ipv4_dst = -1;
533 static int hf_sflow_245_ipv6_src = -1;
534 static int hf_sflow_245_ipv6_dst = -1;
535 static int hf_sflow_245_nexthop_src_mask = -1;
536 static int hf_sflow_245_nexthop_dst_mask = -1;
537
538
539 /* extended gateway (all versions) */
540 static int hf_sflow_245_as = -1;
541 static int hf_sflow_245_src_as = -1;
542 static int hf_sflow_245_src_peer_as = -1;
543 static int hf_sflow_245_dst_as_entries = -1; /* aka length */
544 static int hf_sflow_245_dst_as = -1;
545 /* extended gateway (>= version 4) */
546 static int hf_sflow_245_community_entries = -1;
547 static int hf_sflow_245_community = -1;
548 static int hf_sflow_245_localpref = -1;
549
550 /* generic interface counter */
551 static int hf_sflow_245_ifindex = -1;
552 static int hf_sflow_245_iftype = -1;
553 static int hf_sflow_245_ifspeed = -1;
554 static int hf_sflow_245_ifdirection = -1;
555 static int hf_sflow_245_ifstatus = -1;
556 static int hf_sflow_245_ifinoct = -1;
557 static int hf_sflow_245_ifinpkt = -1;
558 static int hf_sflow_245_ifinmcast = -1;
559 static int hf_sflow_245_ifinbcast = -1;
560 static int hf_sflow_245_ifinerr = -1;
561 static int hf_sflow_245_ifindisc = -1;
562 static int hf_sflow_245_ifinunk = -1;
563 static int hf_sflow_245_ifoutoct = -1;
564 static int hf_sflow_245_ifoutpkt = -1;
565 static int hf_sflow_245_ifoutmcast = -1;
566 static int hf_sflow_245_ifoutbcast = -1;
567 static int hf_sflow_245_ifoutdisc = -1;
568 static int hf_sflow_245_ifouterr = -1;
569 static int hf_sflow_245_ifpromisc = -1;
570
571 /* ethernet interface counter */
572 static int hf_sflow_245_dot3StatsAlignmentErrors = -1;
573 static int hf_sflow_245_dot3StatsFCSErrors = -1;
574 static int hf_sflow_245_dot3StatsSingleCollisionFrames = -1;
575 static int hf_sflow_245_dot3StatsMultipleCollisionFrames = -1;
576 static int hf_sflow_245_dot3StatsSQETestErrors = -1;
577 static int hf_sflow_245_dot3StatsDeferredTransmissions = -1;
578 static int hf_sflow_245_dot3StatsLateCollisions = -1;
579 static int hf_sflow_245_dot3StatsExcessiveCollisions = -1;
580 static int hf_sflow_245_dot3StatsInternalMacTransmitErrors = -1;
581 static int hf_sflow_245_dot3StatsCarrierSenseErrors = -1;
582 static int hf_sflow_245_dot3StatsFrameTooLongs = -1;
583 static int hf_sflow_245_dot3StatsInternalMacReceiveErrors = -1;
584 static int hf_sflow_245_dot3StatsSymbolErrors = -1;
585
586 /* token ring counter */
587 static int hf_sflow_245_dot5StatsLineErrors = -1;
588 static int hf_sflow_245_dot5StatsBurstErrors = -1;
589 static int hf_sflow_245_dot5StatsACErrors = -1;
590 static int hf_sflow_245_dot5StatsAbortTransErrors = -1;
591 static int hf_sflow_245_dot5StatsInternalErrors = -1;
592 static int hf_sflow_245_dot5StatsLostFrameErrors = -1;
593 static int hf_sflow_245_dot5StatsReceiveCongestions = -1;
594 static int hf_sflow_245_dot5StatsFrameCopiedErrors = -1;
595 static int hf_sflow_245_dot5StatsTokenErrors = -1;
596 static int hf_sflow_245_dot5StatsSoftErrors = -1;
597 static int hf_sflow_245_dot5StatsHardErrors = -1;
598 static int hf_sflow_245_dot5StatsSignalLoss = -1;
599 static int hf_sflow_245_dot5StatsTransmitBeacons = -1;
600 static int hf_sflow_245_dot5StatsRecoveries = -1;
601 static int hf_sflow_245_dot5StatsLobeWires = -1;
602 static int hf_sflow_245_dot5StatsRemoves = -1;
603 static int hf_sflow_245_dot5StatsSingles = -1;
604 static int hf_sflow_245_dot5StatsFreqErrors = -1;
605
606 /* 100 BaseVG interface counters */
607 static int hf_sflow_245_dot12InHighPriorityFrames = -1;
608 static int hf_sflow_245_dot12InHighPriorityOctets = -1;
609 static int hf_sflow_245_dot12InNormPriorityFrames = -1;
610 static int hf_sflow_245_dot12InNormPriorityOctets = -1;
611 static int hf_sflow_245_dot12InIPMErrors = -1;
612 static int hf_sflow_245_dot12InOversizeFrameErrors = -1;
613 static int hf_sflow_245_dot12InDataErrors = -1;
614 static int hf_sflow_245_dot12InNullAddressedFrames = -1;
615 static int hf_sflow_245_dot12OutHighPriorityFrames = -1;
616 static int hf_sflow_245_dot12OutHighPriorityOctets = -1;
617 static int hf_sflow_245_dot12TransitionIntoTrainings = -1;
618 static int hf_sflow_245_dot12HCInHighPriorityOctets = -1;
619 static int hf_sflow_245_dot12HCInNormPriorityOctets = -1;
620 static int hf_sflow_245_dot12HCOutHighPriorityOctets = -1;
621
622 /* VLAN counters */
623 static int hf_sflow_245_vlan_id = -1;
624 static int hf_sflow_245_octets = -1;
625 static int hf_sflow_245_ucastPkts = -1;
626 static int hf_sflow_245_multicastPkts = -1;
627 static int hf_sflow_245_broadcastPkts = -1;
628 static int hf_sflow_245_discards = -1;
629
630 /* 802.11 interface counters */
631 static int hf_sflow_5_dot11TransmittedFragmentCount = -1;
632 static int hf_sflow_5_dot11MulticastTransmittedFrameCount = -1;
633 static int hf_sflow_5_dot11FailedCount = -1;
634 static int hf_sflow_5_dot11RetryCount = -1;
635 static int hf_sflow_5_dot11MultipleRetryCount = -1;
636 static int hf_sflow_5_dot11FrameDuplicateCount = -1;
637 static int hf_sflow_5_dot11RTSSuccessCount = -1;
638 static int hf_sflow_5_dot11RTSFailureCount = -1;
639 static int hf_sflow_5_dot11ACKFailureCount = -1;
640 static int hf_sflow_5_dot11ReceivedFragmentCount = -1;
641 static int hf_sflow_5_dot11MulticastReceivedFrameCount = -1;
642 static int hf_sflow_5_dot11FCSErrorCount = -1;
643 static int hf_sflow_5_dot11TransmittedFrameCount = -1;
644 static int hf_sflow_5_dot11WEPUndecryptableCount = -1;
645 static int hf_sflow_5_dot11QoSDiscardedFragmentCount = -1;
646 static int hf_sflow_5_dot11AssociatedStationCount = -1;
647 static int hf_sflow_5_dot11QoSCFPollsReceivedCount = -1;
648 static int hf_sflow_5_dot11QoSCFPollsUnusedCount = -1;
649 static int hf_sflow_5_dot11QoSCFPollsUnusableCount = -1;
650 static int hf_sflow_5_dot11QoSCFPollsLostCount = -1;
651 static int hf_sflow_5_ieee80211_version = -1;
652
653
654 /* processor information */
655 static int hf_sflow_5_cpu_5s = -1;
656 static int hf_sflow_5_cpu_1m = -1;
657 static int hf_sflow_5_cpu_5m = -1;
658 static int hf_sflow_5_total_memory = -1;
659 static int hf_sflow_5_free_memory = -1;
660
661 /* radio utilisation */
662 static int hf_sflow_5_elapsed_time = -1;
663 static int hf_sflow_5_on_channel_time = -1;
664 static int hf_sflow_5_on_channel_busy_time = -1;
665
666 /* Initialize the subtree pointers */
667 static gint ett_sflow_245 = -1;
668 static gint ett_sflow_245_sample = -1;
669 static gint ett_sflow_5_flow_record = -1;
670 static gint ett_sflow_5_counters_record = -1;
671 static gint ett_sflow_5_mpls_in_label_stack = -1;
672 static gint ett_sflow_5_mpls_out_label_stack = -1;
673 static gint ett_sflow_245_extended_data = -1;
674 static gint ett_sflow_245_gw_as_dst = -1;
675 static gint ett_sflow_245_gw_as_dst_seg = -1;
676 static gint ett_sflow_245_gw_community = -1;
677 static gint ett_sflow_245_sampled_header = -1;
678
679 /* dissectors for other protocols */
680 static dissector_handle_t eth_withoutfcs_handle;
681 static dissector_handle_t tr_handle;
682 static dissector_handle_t fddi_handle;
683 static dissector_handle_t fr_handle;
684 static dissector_handle_t x25_handle;
685 static dissector_handle_t ppp_hdlc_handle;
686 static dissector_handle_t smds_handle;
687 static dissector_handle_t aal5_handle;
688 static dissector_handle_t ipv4_handle;
689 static dissector_handle_t ipv6_handle;
690 static dissector_handle_t mpls_handle;
691 static dissector_handle_t pos_handle;
692 static dissector_handle_t ieee80211_mac_handle;
693 static dissector_handle_t ieee80211_ampdu_handle;
694 static dissector_handle_t ieee80211_amsdu_subframe_handle;
695 /* don't dissect */
696 static dissector_handle_t data_handle;
697
698 void proto_reg_handoff_sflow_245(void);
699
700 /* dissect a sampled header - layer 2 protocols */
701 static gint
702 dissect_sflow_245_sampled_header(tvbuff_t *tvb, packet_info *pinfo,
703                                  proto_tree *tree, volatile gint offset) {
704     guint32 version, header_proto, frame_length, stripped;
705     volatile guint32 header_length;
706     tvbuff_t *next_tvb;
707     proto_tree *sflow_245_header_tree;
708     proto_item *ti;
709     /* stuff for saving column state before calling other dissectors.
710      * Thanks to Guy Harris for the tip. */
711     gboolean save_writable;
712     gboolean save_in_error_pkt;
713     address save_dl_src;
714     address save_dl_dst;
715     address save_net_src;
716     address save_net_dst;
717     address save_src;
718     address save_dst;
719     void *pd_save;
720
721     version = tvb_get_ntohl(tvb, 0);
722     header_proto = tvb_get_ntohl(tvb, offset);
723     proto_tree_add_item(tree, hf_sflow_245_header_protocol, tvb, offset, 4, ENC_BIG_ENDIAN);
724     offset += 4;
725     frame_length = tvb_get_ntohl(tvb, offset);
726     proto_tree_add_text(tree, tvb, offset, 4, "Frame Length: %u bytes", frame_length);
727     offset += 4;
728
729     if (version == 5) {
730         stripped = tvb_get_ntohl(tvb, offset);
731         proto_tree_add_text(tree, tvb, offset, 4, "Payload removed: %u bytes", stripped);
732         offset += 4;
733     }
734
735     header_length = tvb_get_ntohl(tvb, offset);
736     offset += 4;
737
738     if (header_length % 4) /* XDR requires 4-byte alignment */
739         header_length += 4 - (header_length % 4);
740
741
742     ti = proto_tree_add_item(tree, hf_sflow_245_header, tvb, offset, header_length, ENC_NA);
743     sflow_245_header_tree = proto_item_add_subtree(ti, ett_sflow_245_sampled_header);
744
745     /* hand the header off to the appropriate dissector.  It's probably
746      * a short frame, so ignore any exceptions. */
747     next_tvb = tvb_new_subset(tvb, offset, header_length, frame_length);
748
749     /* save some state */
750     save_writable = col_get_writable(pinfo->cinfo);
751
752     /*
753        If sFlow samples a TCP packet it is very likely that the
754        TCP analysis will flag the packet as having some error with
755        the sequence numbers.  sFlow only report on a "sample" of
756        traffic so many packets will not be reported on.  This is
757        most obvious if the colorizing rules are on, but will also
758        cause confusion if you attempt to filter on
759        "tcp.analysis.flags".
760
761        The following only works to suppress IP/TCP errors, but
762        it is a start anyway.  Other protocols carried as payloads
763        may exhibit similar issues.
764
765        I think what is really needed is a more general
766        "protocol_as_payload" flag.  Of course then someone has to
767        play whack-a-mole and add code to implement it to any
768        protocols that could be carried as a payload.  In the case
769        of sFlow that pretty much means anything on your network.
770      */
771     save_in_error_pkt = pinfo->in_error_pkt;
772     if (!global_analyze_samp_ip_headers) {
773         pinfo->in_error_pkt = TRUE;
774     }
775
776     col_set_writable(pinfo->cinfo, FALSE);
777     save_dl_src = pinfo->dl_src;
778     save_dl_dst = pinfo->dl_dst;
779     save_net_src = pinfo->net_src;
780     save_net_dst = pinfo->net_dst;
781     save_src = pinfo->src;
782     save_dst = pinfo->dst;
783     pd_save = pinfo->private_data;
784
785     TRY
786     {
787         switch (header_proto) {
788             case SFLOW_245_HEADER_ETHERNET:
789                 call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, sflow_245_header_tree);
790                 break;
791             case SFLOW_245_HEADER_TOKENRING:
792                 call_dissector(tr_handle, next_tvb, pinfo, sflow_245_header_tree);
793                 break;
794             case SFLOW_245_HEADER_FDDI:
795                 call_dissector(fddi_handle, next_tvb, pinfo, sflow_245_header_tree);
796                 break;
797             case SFLOW_245_HEADER_FRAME_RELAY:
798                 call_dissector(fr_handle, next_tvb, pinfo, sflow_245_header_tree);
799                 break;
800             case SFLOW_245_HEADER_X25:
801                 call_dissector(x25_handle, next_tvb, pinfo, sflow_245_header_tree);
802                 break;
803             case SFLOW_245_HEADER_PPP:
804                 call_dissector(ppp_hdlc_handle, next_tvb, pinfo, sflow_245_header_tree);
805                 break;
806             case SFLOW_245_HEADER_SMDS:
807                 call_dissector(smds_handle, next_tvb, pinfo, sflow_245_header_tree);
808                 break;
809             case SFLOW_245_HEADER_AAL5:
810             case SFLOW_245_HEADER_AAL5_IP:
811                 /* I'll be surprised if this works! I have no AAL5 captures
812                  * to test with, and I'm not sure how the encapsulation goes */
813                 call_dissector(aal5_handle, next_tvb, pinfo, sflow_245_header_tree);
814                 break;
815             case SFLOW_245_HEADER_IPv4:
816                 call_dissector(ipv4_handle, next_tvb, pinfo, sflow_245_header_tree);
817                 break;
818             case SFLOW_245_HEADER_IPv6:
819                 call_dissector(ipv6_handle, next_tvb, pinfo, sflow_245_header_tree);
820                 break;
821             case SFLOW_245_HEADER_MPLS:
822                 call_dissector(mpls_handle, next_tvb, pinfo, sflow_245_header_tree);
823                 break;
824             case SFLOW_5_HEADER_POS:
825                 call_dissector(pos_handle, next_tvb, pinfo, sflow_245_header_tree);
826                 break;
827             case SFLOW_5_HEADER_80211_MAC:
828                 call_dissector(ieee80211_mac_handle, next_tvb, pinfo, sflow_245_header_tree);
829                 break;
830             case SFLOW_5_HEADER_80211_AMPDU:
831                 call_dissector(ieee80211_ampdu_handle, next_tvb, pinfo, sflow_245_header_tree);
832                 break;
833             case SFLOW_5_HEADER_80211_AMSDU_SUBFRAME:
834                 call_dissector(ieee80211_amsdu_subframe_handle, next_tvb, pinfo, sflow_245_header_tree);
835                 break;
836             default:
837                 /* some of the protocols, I have no clue where to begin. */
838                 break;
839         }
840     }
841
842     CATCH2(BoundsError, ReportedBoundsError) {
843         /*  Restore the private_data structure in case one of the
844          *  called dissectors modified it (and, due to the exception,
845          *  was unable to restore it).
846          */
847         pinfo->private_data = pd_save;
848     }
849     ENDTRY;
850
851     /* restore saved state */
852     col_set_writable(pinfo->cinfo, save_writable);
853     pinfo->in_error_pkt = save_in_error_pkt;
854
855     pinfo->dl_src = save_dl_src;
856     pinfo->dl_dst = save_dl_dst;
857     pinfo->net_src = save_net_src;
858     pinfo->net_dst = save_net_dst;
859     pinfo->src = save_src;
860     pinfo->dst = save_dst;
861
862     offset += header_length;
863     return offset;
864 }
865
866 static gint
867 dissect_sflow_245_address_type(tvbuff_t *tvb, proto_tree *tree, gint offset,
868                                struct sflow_address_type *hf_type,
869                                struct sflow_address_details *addr_detail) {
870     guint32 addr_type;
871     int len;
872
873     addr_type = tvb_get_ntohl(tvb, offset);
874     offset += 4;
875
876     switch (addr_type) {
877     case ADDR_TYPE_IPV4:
878         len = 4;
879         proto_tree_add_item(tree, hf_type->hf_addr_v4, tvb, offset, 4, FALSE);
880         break;
881     case ADDR_TYPE_IPV6:
882         len = 16;
883         proto_tree_add_item(tree, hf_type->hf_addr_v6, tvb, offset, 16, FALSE);
884         break;
885     default:
886         /* acferen:  November 10, 2010
887          *
888          * We should never get here, but if we do we don't know
889          * the length for this address type.  Not knowing the
890          * length this default case is doomed to failure.  Might
891          * as well acknowledge that as soon as possible.
892          */
893         proto_tree_add_text(tree, tvb, offset - 4, 4, "Unknown address type (%u)", addr_type);
894         return 0;               /* malformed packet */
895     }
896
897     if (addr_detail) {
898         addr_detail->addr_type = addr_type;
899         switch (len) {
900         case 4:
901             tvb_memcpy(tvb, addr_detail->agent_address.v4, offset, len);
902             break;
903         case 16:
904             tvb_memcpy(tvb, addr_detail->agent_address.v6, offset, len);
905             break;
906         }
907     }
908
909     return offset + len;
910 }
911
912 /* extended switch data, after the packet data */
913 static gint
914 dissect_sflow_245_extended_switch(tvbuff_t *tvb, proto_tree *tree, gint offset) {
915     proto_tree_add_item(tree, hf_sflow_245_vlan_in, tvb, offset, 4, ENC_BIG_ENDIAN);
916     offset += 4;
917     proto_tree_add_item(tree, hf_sflow_245_pri_in, tvb, offset, 4, ENC_BIG_ENDIAN);
918     offset += 4;
919     proto_tree_add_item(tree, hf_sflow_245_vlan_out, tvb, offset, 4, ENC_BIG_ENDIAN);
920     offset += 4;
921     proto_tree_add_item(tree, hf_sflow_245_pri_out, tvb, offset, 4, ENC_BIG_ENDIAN);
922     offset += 4;
923
924     return offset;
925 }
926
927 /* extended router data, after the packet data */
928 static gint
929 dissect_sflow_245_extended_router(tvbuff_t *tvb, proto_tree *tree, gint offset) {
930     struct sflow_address_type addr_type = {hf_sflow_245_nexthop_v4, hf_sflow_245_nexthop_v6};
931
932     offset = dissect_sflow_245_address_type(tvb, tree, offset, &addr_type, NULL);
933     proto_tree_add_item(tree, hf_sflow_245_nexthop_src_mask, tvb, offset, 4, ENC_BIG_ENDIAN);
934     offset += 4;
935     proto_tree_add_item(tree, hf_sflow_245_nexthop_dst_mask, tvb, offset, 4, ENC_BIG_ENDIAN);
936     offset += 4;
937     return offset;
938 }
939
940 /* extended MPLS data */
941 static gint
942 dissect_sflow_5_extended_mpls_data(tvbuff_t *tvb, proto_tree *tree, gint offset) {
943     guint32 in_label_count, out_label_count, i, j;
944     proto_tree *in_stack;
945     proto_item *ti_in;
946     proto_tree *out_stack;
947     proto_item *ti_out;
948
949     struct sflow_address_type addr_type = {hf_sflow_245_nexthop_v4, hf_sflow_245_nexthop_v6};
950     offset = dissect_sflow_245_address_type(tvb, tree, offset, &addr_type, NULL);
951
952     in_label_count = tvb_get_ntohl(tvb, offset);
953     proto_tree_add_text(tree, tvb, offset, 4, "In Label Stack Entries: %u", in_label_count);
954     offset += 4;
955
956     ti_in = proto_tree_add_text(tree, tvb, offset, -1, "In Label Stack");
957     in_stack = proto_item_add_subtree(ti_in, ett_sflow_5_mpls_in_label_stack);
958
959     /* by applying the mask, we avoid possible corrupted data that causes huge number of loops
960      * 255 is a sensible limit of label count */
961     for (i = 0, j = 0; i < (in_label_count & 0x000000ff); i++, j += 4) {
962         proto_tree_add_text(in_stack, tvb, offset, 4, "Label %u: %u", i + 1, tvb_get_ntohl(tvb, offset + j));
963     }
964     offset = offset + in_label_count * 4;
965
966     out_label_count = tvb_get_ntohl(tvb, offset);
967     proto_tree_add_text(tree, tvb, offset, 4, "Out Label Stack Entries: %u", out_label_count);
968     offset += 4;
969
970     ti_out = proto_tree_add_text(tree, tvb, offset, -1, "Out Label Stack");
971     out_stack = proto_item_add_subtree(ti_out, ett_sflow_5_mpls_in_label_stack);
972
973     /* by applying the mask, we avoid possible corrupted data that causes huge number of loops
974      * 255 is a sensible limit of label count */
975     for (i = 0, j = 0; i < (out_label_count & 0x000000ff); i++, j += 4) {
976         proto_tree_add_text(out_stack, tvb, offset, 4, "Label %u: %u", i + 1, tvb_get_ntohl(tvb, offset + j));
977     }
978     offset = offset + out_label_count * 4;
979
980     return offset;
981 }
982
983 /* extended NAT data */
984 static gint
985 dissect_sflow_5_extended_nat(tvbuff_t *tvb, proto_tree *tree, gint offset) {
986     struct sflow_address_type addr_type = {hf_sflow_245_ipv4_src,
987                                            hf_sflow_245_ipv6_src};
988     offset = dissect_sflow_245_address_type(tvb, tree, offset, &addr_type, NULL);
989
990     addr_type.hf_addr_v4 = hf_sflow_245_ipv4_dst;
991     addr_type.hf_addr_v6 = hf_sflow_245_ipv6_dst;
992
993     offset = dissect_sflow_245_address_type(tvb, tree, offset, &addr_type, NULL);
994
995     return offset;
996 }
997
998 /* extended gateway data, after the packet data */
999 static gint
1000 dissect_sflow_245_extended_gateway(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1001     gint32 len = 0;
1002     gint32 i, j, comm_len, dst_len, dst_seg_len;
1003     guint32 path_type;
1004     gint32 kludge;
1005
1006     guint32 version = tvb_get_ntohl(tvb, 0); /* get sFlow version */
1007     proto_item *ti;
1008     proto_tree *sflow_245_dst_as_tree;
1009     proto_tree *sflow_245_comm_tree;
1010     proto_tree *sflow_245_dst_as_seg_tree;
1011
1012     /* sFlow v5 contains next hop router IP address */
1013     if (version == 5) {
1014         struct sflow_address_type addr_type = {hf_sflow_245_nexthop_v4, hf_sflow_245_nexthop_v6};
1015
1016         offset = dissect_sflow_245_address_type(tvb, tree, offset, &addr_type, NULL);
1017     }
1018
1019     proto_tree_add_item(tree, hf_sflow_245_as, tvb, offset + len, 4, ENC_BIG_ENDIAN);
1020     len += 4;
1021
1022     proto_tree_add_item(tree, hf_sflow_245_src_as, tvb, offset + len, 4, ENC_BIG_ENDIAN);
1023     len += 4;
1024
1025     proto_tree_add_item(tree, hf_sflow_245_src_peer_as, tvb, offset + len, 4, ENC_BIG_ENDIAN);
1026     len += 4;
1027
1028     dst_len = tvb_get_ntohl(tvb, offset + len);
1029     ti = proto_tree_add_uint(tree, hf_sflow_245_dst_as_entries, tvb, offset + len, 4, dst_len);
1030     sflow_245_dst_as_tree = proto_item_add_subtree(ti, ett_sflow_245_gw_as_dst);
1031     len += 4;
1032
1033     for (i = 0; i < dst_len; i++) {
1034         if (version < 4) {
1035             /* Version 2 AS paths are different than versions >= 4 as
1036                follows:
1037
1038                There is no type encoded in the packet.
1039
1040                The destination ASs are encoded as an array of integers
1041                rather as an array of arrays of integers.  I just
1042                pretended they were encoded as an array of arrays with
1043                an implicit length of 1 to not have to do two
1044                completely separate blocks for the different versions.
1045
1046                Having a subtree for "arrays" guaranteed to have only a
1047                single element proved cumbersome to navigate so I moved
1048                the creation of the subtree to only happen for versions
1049                >= 4.
1050              */
1051             dst_seg_len = 1;
1052             path_type = 0;
1053             kludge = 0;
1054             sflow_245_dst_as_seg_tree = sflow_245_dst_as_tree;
1055         } else {
1056             path_type = tvb_get_ntohl(tvb, offset + len);
1057             len += 4;
1058             dst_seg_len = tvb_get_ntohl(tvb, offset + len);
1059             len += 4;
1060             kludge = 8;
1061             ti = proto_tree_add_text(tree, tvb, offset + len - kludge, kludge,
1062                     "%s, (%u entries)", val_to_str(path_type, sflow_245_as_types, "Unknown AS type"), dst_seg_len);
1063             sflow_245_dst_as_seg_tree = proto_item_add_subtree(ti, ett_sflow_245_gw_as_dst_seg);
1064         }
1065
1066         for (j = 0; j < dst_seg_len; j++) {
1067             proto_tree_add_item(sflow_245_dst_as_seg_tree, hf_sflow_245_dst_as, tvb, offset + len, 4, ENC_BIG_ENDIAN);
1068             len += 4;
1069         }
1070     }
1071
1072
1073     if (version >= 4) {
1074         comm_len = tvb_get_ntohl(tvb, offset + len);
1075
1076         ti = proto_tree_add_uint(tree, hf_sflow_245_community_entries, tvb, offset + len, 4, comm_len);
1077         sflow_245_comm_tree = proto_item_add_subtree(ti, ett_sflow_245_gw_community);
1078         len += 4;
1079         for (i = 0; i < comm_len; i++) {
1080             proto_tree_add_item(sflow_245_comm_tree,
1081                     hf_sflow_245_dst_as, tvb, offset + len,
1082                     4, ENC_BIG_ENDIAN);
1083             len += 4;
1084         }
1085
1086         proto_tree_add_item(tree, hf_sflow_245_localpref, tvb, offset + len, 4, ENC_BIG_ENDIAN);
1087         len += 4;
1088
1089     }
1090
1091     return offset + len;
1092 }
1093
1094 /* sflow v5 ethernet frame data */
1095 static gint
1096 dissect_sflow_5_ethernet_frame(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1097     guint32 length, type;
1098     guint64 src, dest;
1099
1100     length = tvb_get_ntohl(tvb, offset);
1101     proto_tree_add_text(tree, tvb, offset, 4, "Length of MAC Packet: %u bytes", length);
1102     offset += 4;
1103
1104     src = tvb_get_ntoh64(tvb, offset) >> 16;
1105     proto_tree_add_text(tree, tvb, offset, 8, "Source MAC Address: 0x%" G_GINT64_MODIFIER "X", src);
1106     offset += 8;
1107
1108     dest = tvb_get_ntoh64(tvb, offset) >> 16;
1109     proto_tree_add_text(tree, tvb, offset, 8, "Destination MAC Address: 0x%" G_GINT64_MODIFIER "X", dest);
1110     offset += 8;
1111
1112     type = tvb_get_ntohl(tvb, offset);
1113     proto_tree_add_text(tree, tvb, offset, 4, "Ethernet Packet Type: %u", type);
1114     offset += 4;
1115
1116     return offset;
1117 }
1118
1119 /* sflow v5 IPv4 data */
1120 static gint
1121 dissect_sflow_5_ipv4(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1122     guint32 length, protocol, src_port, dest_port;
1123     guint8 flags, tos;
1124
1125     length = tvb_get_ntohl(tvb, offset);
1126     proto_tree_add_text(tree, tvb, offset, 4, "Length of IP Packet: %u bytes", length);
1127     offset += 4;
1128
1129     protocol = tvb_get_ntohl(tvb, offset);
1130
1131     switch (protocol) {
1132         case 6:
1133             proto_tree_add_text(tree, tvb, offset, 4, "IP Protocol: %s (%u)", "TCP", protocol);
1134             break;
1135         case 17:
1136             proto_tree_add_text(tree, tvb, offset, 4, "IP Protocol: %s (%u)", "UDP", protocol);
1137             break;
1138         default:
1139             proto_tree_add_text(tree, tvb, offset, 4, "IP Protocol: %u (look up against protocol numbers)", protocol);
1140             break;
1141     }
1142     offset += 4;
1143
1144     proto_tree_add_item(tree, hf_sflow_245_ipv4_src, tvb, offset, 4, ENC_BIG_ENDIAN);
1145     offset += 4;
1146
1147     proto_tree_add_item(tree, hf_sflow_245_ipv4_dst, tvb, offset, 4, ENC_BIG_ENDIAN);
1148     offset += 4;
1149
1150     src_port = tvb_get_ntohl(tvb, offset);
1151     proto_tree_add_text(tree, tvb, offset, 4, "Source Port: %u", src_port);
1152     offset += 4;
1153
1154     dest_port = tvb_get_ntohl(tvb, offset);
1155     proto_tree_add_text(tree, tvb, offset, 4, "Destination Port: %u", dest_port);
1156     offset += 4;
1157
1158     /* dissect tcp flags bit-by-bit */
1159     /* 8 flags are included here, plus 24-bit 0-padding */
1160     flags = tvb_get_guint8(tvb, offset);
1161     flags >> 7 ?
1162             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (CWR): 1....... (Set)") :
1163             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (CWR): 0....... (Not Set)");
1164     (flags & 0x40) >> 6 ?
1165             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (ECE): .1...... (Set)") :
1166             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (ECE): .0...... (Not Set)");
1167     (flags & 0x20) >> 5 ?
1168             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (URG): ..1..... (Set)") :
1169             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (URG): ..0..... (Not Set)");
1170     (flags & 0x10) >> 4 ?
1171             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (ACK): ...1.... (Set)") :
1172             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (ACK): ...0.... (Not Set)");
1173     (flags & 0x08) >> 3 ?
1174             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (PSH): ....1... (Set)") :
1175             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (PSH): ....0... (Not Set)");
1176     (flags & 0x04) >> 2 ?
1177             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (RST): .....1.. (Set)") :
1178             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (RST): .....0.. (Not Set)");
1179     (flags & 0x02) >> 1 ?
1180             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (SYN): ......1. (Set)") :
1181             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (SYN): ......0. (Not Set)");
1182     flags & 0x01 ?
1183             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (FIN): .......1 (Set)") :
1184             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (FIN): .......0 (Not Set)");
1185
1186     offset += 4;
1187
1188     /* 7 bits for type of service, plus 1 reserved bit */
1189     tos = tvb_get_guint8(tvb, offset);
1190     proto_tree_add_text(tree, tvb, offset, 1, "%s",
1191             val_to_str(tos >> 5, sflow_245_ipv4_precedence_types, "Unknown precedence type"));
1192     (tos & 0x10) >> 4 ?
1193             proto_tree_add_text(tree, tvb, offset, 1, "Delay: ...1... (Low)") :
1194             proto_tree_add_text(tree, tvb, offset, 1, "Delay: ...0... (Normal)");
1195     (tos & 0x08) >> 3 ?
1196             proto_tree_add_text(tree, tvb, offset, 1, "Throughput: ....1.. (High)") :
1197             proto_tree_add_text(tree, tvb, offset, 1, "Throughput: ....0.. (Normal)");
1198     (tos & 0x04) >> 2 ?
1199             proto_tree_add_text(tree, tvb, offset, 1, "Reliability: .....1. (High)") :
1200             proto_tree_add_text(tree, tvb, offset, 1, "Reliability: .....0. (Normal)");
1201     (tos & 0x02) >> 1 ?
1202             proto_tree_add_text(tree, tvb, offset, 1, "Cost (RFC1349): ......1 (Minimize Monetary)") :
1203             proto_tree_add_text(tree, tvb, offset, 1, "Cost (RFC1349): ......0 (Normal)");
1204
1205     offset += 4;
1206
1207     return offset;
1208 }
1209
1210 /* sflow v5 IPv6 data */
1211 static gint
1212 dissect_sflow_5_ipv6(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1213     guint32 length, protocol, src_port, dest_port, priority;
1214     guint8 flags;
1215
1216     length = tvb_get_ntohl(tvb, offset);
1217     proto_tree_add_text(tree, tvb, offset, 4, "Length of IP Packet: %u bytes", length);
1218     offset += 4;
1219
1220     protocol = tvb_get_ntohl(tvb, offset);
1221     switch (protocol) {
1222         case 6:
1223             proto_tree_add_text(tree, tvb, offset, 4, "IP Protocol: %s (%u)", "TCP", protocol);
1224             break;
1225         case 17:
1226             proto_tree_add_text(tree, tvb, offset, 4, "IP Protocol: %s (%u)", "UDP", protocol);
1227             break;
1228         default:
1229             proto_tree_add_text(tree, tvb, offset, 4, "IP Protocol: %u (look up against protocol numbers)", protocol);
1230             break;
1231     }
1232     offset += 4;
1233
1234     proto_tree_add_item(tree, hf_sflow_245_ipv6_src, tvb, offset, 16, ENC_NA);
1235     offset += 16;
1236
1237     proto_tree_add_item(tree, hf_sflow_245_ipv6_dst, tvb, offset, 16, ENC_NA);
1238     offset += 16;
1239
1240     src_port = tvb_get_ntohl(tvb, offset);
1241     proto_tree_add_text(tree, tvb, offset, 4, "Source Port: %u", src_port);
1242     offset += 4;
1243
1244     dest_port = tvb_get_ntohl(tvb, offset);
1245     proto_tree_add_text(tree, tvb, offset, 4, "Destination Port: %u", dest_port);
1246     offset += 4;
1247
1248     /* dissect tcp flags bit-by-bit */
1249     /* 8 flags are included here, plus 24-bit 0-padding */
1250     flags = tvb_get_guint8(tvb, offset);
1251     flags >> 7 ?
1252             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (CWR): 1....... (Set)") :
1253             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (CWR): 0....... (Not Set)");
1254     (flags & 0x40) >> 6 ?
1255             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (ECE): .1...... (Set)") :
1256             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (ECE): .0...... (Not Set)");
1257     (flags & 0x20) >> 5 ?
1258             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (URG): ..1..... (Set)") :
1259             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (URG): ..0..... (Not Set)");
1260     (flags & 0x10) >> 4 ?
1261             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (ACK): ...1.... (Set)") :
1262             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (ACK): ...0.... (Not Set)");
1263     (flags & 0x08) >> 3 ?
1264             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (PSH): ....1... (Set)") :
1265             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (PSH): ....0... (Not Set)");
1266     (flags & 0x04) >> 2 ?
1267             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (RST): .....1.. (Set)") :
1268             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (RST): .....0.. (Not Set)");
1269     (flags & 0x02) >> 1 ?
1270             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (SYN): ......1. (Set)") :
1271             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (SYN): ......0. (Not Set)");
1272     flags & 0x01 ?
1273             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (FIN): .......1 (Set)") :
1274             proto_tree_add_text(tree, tvb, offset, 1, "TCP Flag (FIN): .......0 (Not Set)");
1275
1276     offset += 4;
1277
1278     /* Priority -- Traffic class field enables a source to identify the desired
1279        delivery priority of the packets. Priority values are divided into
1280        ranges: traffic where the source provides congestion control and
1281        non-congestion control traffic.
1282
1283        It is displayed as unsigned integer here according to sFlow specification */
1284
1285     priority = tvb_get_ntohl(tvb, offset);
1286     proto_tree_add_text(tree, tvb, offset, 4, "Priority: %u", priority);
1287     offset += 4;
1288
1289     return offset;
1290 }
1291
1292 /* sflow v5 user data */
1293 static gint
1294 dissect_sflow_5_extended_user(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1295     guint32 src_charset, src_length, dest_charset, dest_length, i;
1296     proto_item *src;
1297     proto_item *dest;
1298
1299     src_charset = tvb_get_ntohl(tvb, offset);
1300     /* charset is not processed here, all chars are assumed to be ASCII */
1301     proto_tree_add_text(tree, tvb, offset, 4, "Source Character Set: %u", src_charset);
1302     offset += 4;
1303
1304     src_length = tvb_get_ntohl(tvb, offset);
1305     proto_tree_add_text(tree, tvb, offset, 4, "Source User String Length: %u bytes", src_length);
1306     offset += 4;
1307
1308     /* extract source user info char by char */
1309     src = proto_tree_add_text(tree, tvb, offset, src_length, "Source User: ");
1310     for (i = 0; i < src_length; i++) {
1311         proto_item_append_text(src, "%c", tvb_get_guint8(tvb, offset++));
1312     }
1313
1314     /* get the correct offset by adding padding byte count */
1315     if (src_length % 4)
1316         offset = offset + (4 - src_length % 4);
1317
1318     dest_charset = tvb_get_ntohl(tvb, offset);
1319     /* charset is not processed here, all chars are assumed to be ASCII */
1320     proto_tree_add_text(tree, tvb, offset, 4, "Destination Character Set: %u", dest_charset);
1321     offset += 4;
1322
1323     dest_length = tvb_get_ntohl(tvb, offset);
1324     proto_tree_add_text(tree, tvb, offset, 4, "Destination User String Length: %u bytes", dest_length);
1325     offset += 4;
1326
1327     /* extract destination user info char by char */
1328     dest = proto_tree_add_text(tree, tvb, offset, dest_length, "Destination User: ");
1329     for (i = 0; i < dest_length; i++) {
1330         proto_item_append_text(dest, "%c", tvb_get_guint8(tvb, offset++));
1331     }
1332
1333     /* get the correct offset by adding padding byte count */
1334     if (dest_length % 4)
1335         offset = offset + (4 - dest_length % 4);
1336
1337     return offset;
1338 }
1339
1340 /* sflow v5 URL data */
1341 static gint
1342 dissect_sflow_5_extended_url(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1343     guint32 direction, url_length, host_length, i;
1344     proto_item *url;
1345     proto_item *host;
1346
1347     direction = tvb_get_ntohl(tvb, offset);
1348     switch (direction) {
1349         case 1:
1350             proto_tree_add_text(tree, tvb, offset, 4, "Source Address is Server(%u)", direction);
1351             break;
1352         case 2:
1353             proto_tree_add_text(tree, tvb, offset, 4, "Destination Address is Server (%u)", direction);
1354             break;
1355         default:
1356             proto_tree_add_text(tree, tvb, offset, 4, "Server Unspecified (%u)", direction);
1357             break;
1358     }
1359     offset += 4;
1360
1361     url_length = tvb_get_ntohl(tvb, offset);
1362     proto_tree_add_text(tree, tvb, offset, 4, "URL Length: %u bytes", url_length);
1363     offset += 4;
1364
1365     /* extract URL char by char */
1366     url = proto_tree_add_text(tree, tvb, offset, url_length, "URL: ");
1367     for (i = 0; i < url_length; i++) {
1368         proto_item_append_text(url, "%c", tvb_get_guint8(tvb, offset++));
1369     }
1370
1371     /* get the correct offset by adding padding byte count */
1372     if (url_length % 4)
1373         offset = offset + (4 - url_length % 4);
1374
1375     host_length = tvb_get_ntohl(tvb, offset);
1376     proto_tree_add_text(tree, tvb, offset, 4, "Host Length: %u bytes", host_length);
1377     offset += 4;
1378
1379     /* extract host info char by char */
1380     host = proto_tree_add_text(tree, tvb, offset, host_length, "Host: ");
1381     for (i = 0; i < host_length; i++) {
1382         proto_item_append_text(host, "%c", tvb_get_guint8(tvb, offset++));
1383     }
1384
1385     /* get the correct offset by adding padding byte count */
1386     if (host_length % 4)
1387         offset = offset + (4 - host_length % 4);
1388
1389     return offset;
1390 }
1391
1392 /* sflow v5 MPLS tunnel */
1393 static gint
1394 dissect_sflow_5_extended_mpls_tunnel(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1395     guint32 name_length, id, cos, i;
1396     proto_item *tunnel;
1397
1398     name_length = tvb_get_ntohl(tvb, offset);
1399     proto_tree_add_text(tree, tvb, offset, 4, "Tunnel Name Length: %u bytes", name_length);
1400     offset += 4;
1401
1402     /* extract tunnel name char by char */
1403     tunnel = proto_tree_add_text(tree, tvb, offset, name_length, "Tunnel Name: ");
1404     for (i = 0; i < name_length; i++) {
1405         proto_item_append_text(tunnel, "%c", tvb_get_guint8(tvb, offset++));
1406     }
1407
1408     /* get the correct offset by adding padding byte count */
1409     if (name_length % 4)
1410         offset = offset + (4 - name_length % 4);
1411
1412     id = tvb_get_ntohl(tvb, offset);
1413     proto_tree_add_text(tree, tvb, offset, 4, "Tunnel ID: %u", id);
1414     offset += 4;
1415
1416     cos = tvb_get_ntohl(tvb, offset);
1417     proto_tree_add_text(tree, tvb, offset, 4, "Tunnel COS Value: %u", cos);
1418     offset += 4;
1419
1420     return offset;
1421 }
1422
1423 /* sflow v5 MPLS VC */
1424 static gint
1425 dissect_sflow_5_extended_mpls_vc(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1426     guint32 name_length, id, cos, i;
1427     proto_item *vc_name;
1428
1429     name_length = tvb_get_ntohl(tvb, offset);
1430     proto_tree_add_text(tree, tvb, offset, 4, "VC Instance Name Length: %u bytes", name_length);
1431     offset += 4;
1432
1433     /* extract source user info char by char */
1434     vc_name = proto_tree_add_text(tree, tvb, offset, name_length, "VC Instance Name: ");
1435     for (i = 0; i < name_length; i++) {
1436         proto_item_append_text(vc_name, "%c", tvb_get_guint8(tvb, offset++));
1437     }
1438
1439     /* get the correct offset by adding padding byte count */
1440     if (name_length % 4)
1441         offset = offset + (4 - name_length % 4);
1442
1443     id = tvb_get_ntohl(tvb, offset);
1444     proto_tree_add_text(tree, tvb, offset, 4, "VLL/VC ID: %u", id);
1445     offset += 4;
1446
1447     cos = tvb_get_ntohl(tvb, offset);
1448     proto_tree_add_text(tree, tvb, offset, 4, "VC Label COS Value: %u", cos);
1449     offset += 4;
1450
1451     return offset;
1452 }
1453
1454 /* sflow v5 MPLS FEC */
1455 static gint
1456 dissect_sflow_5_extended_mpls_fec(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1457     guint32 length, mask, i;
1458     proto_item *desc;
1459
1460     length = tvb_get_ntohl(tvb, offset);
1461     proto_tree_add_text(tree, tvb, offset, 4, "MPLS FTN Description Length: %u bytes", length);
1462     offset += 4;
1463
1464     /* extract MPLS FTN description char by char */
1465     desc = proto_tree_add_text(tree, tvb, offset, length, "MPLS FTN Description: ");
1466     for (i = 0; i < length; i++) {
1467         proto_item_append_text(desc, "%c", tvb_get_guint8(tvb, offset++));
1468     }
1469
1470     /* get the correct offset by adding padding byte count */
1471     if (length % 4)
1472         offset = offset + (4 - length % 4);
1473
1474     mask = tvb_get_ntohl(tvb, offset);
1475     proto_tree_add_text(tree, tvb, offset, 4, "MPLS FTN Mask: %u", mask);
1476     offset += 4;
1477
1478     return offset;
1479 }
1480
1481 /* sflow v5 MPLS LVP FEC */
1482 static gint
1483 dissect_sflow_5_extended_mpls_lvp_fec(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1484     guint32 length;
1485
1486     length = tvb_get_ntohl(tvb, offset);
1487     proto_tree_add_text(tree, tvb, offset, 4, "MPLS FEC Address Prefix Length: %u bytes", length);
1488     offset += 4;
1489     return offset;
1490 }
1491
1492 /* sflow v5 extended VLAN tunnel */
1493 static gint
1494 dissect_sflow_5_extended_vlan_tunnel(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1495     guint32 num, i, pair;
1496
1497     num = tvb_get_ntohl(tvb, offset);
1498     proto_tree_add_text(tree, tvb, offset, 4, "Number of Layers: %u", num);
1499     offset += 4;
1500
1501     /* loop strip 802.1Q TPID/TCI layers. each TPID/TCI pair is represented as a
1502        single 32 bit integer layers listed from outermost to innermost */
1503     for (i = 0; i < num; i++) {
1504
1505         pair = tvb_get_ntohl(tvb, offset);
1506         proto_tree_add_text(tree, tvb, offset, 4, "TPID/TCI Pair as Integer: %u", pair);
1507         offset += 4;
1508     }
1509
1510     return offset;
1511 }
1512
1513 /* sflow v5 extended 802.11 payload */
1514 static gint
1515 dissect_sflow_5_extended_80211_payload(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1516     guint32 cipher_suite, OUI, suite_type, length, i;
1517     proto_item *data;
1518
1519     cipher_suite = tvb_get_ntohl(tvb, offset);
1520     OUI = cipher_suite >> 8;
1521     suite_type = cipher_suite & 0x000000ff;
1522
1523     if (OUI == 0x000FAC) {
1524         proto_tree_add_text(tree, tvb, offset, 3, "OUI: Default (0x%X)", OUI);
1525         offset += 3;
1526         switch (suite_type) {
1527             case 0:
1528                 proto_tree_add_text(tree, tvb, offset, 1, "Suite Type: Use group cipher suite (%u)", suite_type);
1529                 break;
1530             case 1:
1531                 proto_tree_add_text(tree, tvb, offset, 1, "Suite Type: WEP-40 (%u)", suite_type);
1532                 break;
1533             case 2:
1534                 proto_tree_add_text(tree, tvb, offset, 1, "Suite Type: TKIP (%u)", suite_type);
1535                 break;
1536             case 4:
1537                 proto_tree_add_text(tree, tvb, offset, 1, "Suite Type: CCMP (%u)", suite_type);
1538                 break;
1539             case 5:
1540                 proto_tree_add_text(tree, tvb, offset, 1, "Suite Type: WEP-104 (%u)", suite_type);
1541                 break;
1542             default: /* 3, 6-255 = reserved */
1543                 proto_tree_add_text(tree, tvb, offset, 1, "Suite Type: Reserved (%u)", suite_type);
1544                 break;
1545         }
1546     } else {
1547         proto_tree_add_text(tree, tvb, offset, 3, "OUI: Other vender (0x%X)", OUI);
1548         offset += 3;
1549         proto_tree_add_text(tree, tvb, offset, 1, "Suite Type: Vender specific (%u)", suite_type);
1550     }
1551     offset++;
1552
1553     length = tvb_get_ntohl(tvb, offset);
1554     proto_tree_add_text(tree, tvb, offset, 4, "Payload Length: %u bytes", length);
1555     offset += 4;
1556
1557     /* extract data byte by byte */
1558     data = proto_tree_add_text(tree, tvb, offset, length, "Payload: 0x");
1559     for (i = 0; i < length; i++) {
1560         proto_item_append_text(data, "%X", tvb_get_guint8(tvb, offset++));
1561     }
1562
1563     /* get the correct offset by adding padding byte count */
1564     if (length % 4)
1565         offset = offset + (4 - length % 4);
1566
1567     return offset;
1568 }
1569
1570 /* sflow v5 extended 802.11 rx */
1571 static gint
1572 dissect_sflow_5_extended_80211_rx(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1573     guint32 ssid_length, i, version, channel, rsni, rcpi, duration;
1574     guint64 bssid, speed;
1575     proto_item *ssid;
1576
1577     /* extract SSID char by char. max char count = 32 */
1578     ssid_length = tvb_get_ntohl(tvb, offset);
1579     offset += 4;
1580     ssid = proto_tree_add_text(tree, tvb, offset, ssid_length, "SSID: ");
1581     for (i = 0; i < ssid_length; i++) {
1582         proto_item_append_text(ssid, "%c", tvb_get_guint8(tvb, offset++));
1583     }
1584
1585     /* get the correct offset by adding padding byte count */
1586     if (ssid_length % 4)
1587         offset = offset + (4 - ssid_length % 4);
1588
1589     bssid = tvb_get_ntoh64(tvb, offset) >> 16;
1590     proto_tree_add_text(tree, tvb, offset, 8, "BSSID: 0x%" G_GINT64_MODIFIER "X", bssid);
1591     offset += 8;
1592
1593     version = tvb_get_ntohl(tvb, offset);
1594     proto_tree_add_text(tree, tvb, offset, 4, "Version: %s",
1595             val_to_str(version, sflow_5_ieee80211_versions, "Unknown"));
1596     offset += 4;
1597
1598     channel = tvb_get_ntohl(tvb, offset);
1599     proto_tree_add_text(tree, tvb, offset, 4, "Channel: %u", channel);
1600     offset += 4;
1601
1602     speed = tvb_get_ntoh64(tvb, offset);
1603     proto_tree_add_text(tree, tvb, offset, 8, "Speed: %" G_GINT64_MODIFIER "u", speed);
1604     offset += 8;
1605
1606     rsni = tvb_get_ntohl(tvb, offset);
1607     proto_tree_add_text(tree, tvb, offset, 4, "RSNI: %u", rsni);
1608     offset += 4;
1609
1610     rcpi = tvb_get_ntohl(tvb, offset);
1611     proto_tree_add_text(tree, tvb, offset, 4, "RCPI: %u", rcpi);
1612     offset += 4;
1613
1614     duration = tvb_get_ntohl(tvb, offset);
1615     duration == 0 ?
1616             proto_tree_add_text(tree, tvb, offset, 4, "Packet Duration: Unknown") :
1617             proto_tree_add_text(tree, tvb, offset, 4, "Packet Duration: %u (ms)", duration);
1618     offset += 4;
1619
1620     return offset;
1621 }
1622
1623 /* sflow v5 extended 802.11 tx */
1624 static gint
1625 dissect_sflow_5_extended_80211_tx(tvbuff_t *tvb, proto_tree *tree, gint offset) {
1626     guint32 ssid_length, version, transmissions, packet_duration, retrans_duration,
1627             channel, power, i;
1628     guint64 bssid, speed;
1629     proto_item *ssid;
1630
1631     /* extract SSID char by char. max char count = 32 */
1632     ssid_length = tvb_get_ntohl(tvb, offset);
1633     if (ssid_length > 32)
1634         ssid_length = 32;
1635     offset += 4;
1636     ssid = proto_tree_add_text(tree, tvb, offset, ssid_length, "SSID: ");
1637     for (i = 0; i < ssid_length; i++) {
1638         proto_item_append_text(ssid, "%c", tvb_get_guint8(tvb, offset++));
1639     }
1640
1641     /* get the correct offset by adding padding byte count */
1642     if (ssid_length % 4)
1643         offset = offset + (4 - ssid_length % 4);
1644
1645     bssid = tvb_get_ntoh64(tvb, offset) >> 16;
1646     proto_tree_add_text(tree, tvb, offset, 8, "BSSID: 0x%" G_GINT64_MODIFIER "X", bssid);
1647     offset += 8;
1648
1649     version = tvb_get_ntohl(tvb, offset);
1650     proto_tree_add_text(tree, tvb, offset, 4, "Version: %s",
1651             val_to_str(version, sflow_5_ieee80211_versions, "Unknown"));
1652     offset += 4;
1653
1654     transmissions = tvb_get_ntohl(tvb, offset);
1655     switch (transmissions) {
1656         case 0:
1657             proto_tree_add_text(tree, tvb, offset, 4, "Retransmission: Unknown");
1658             break;
1659         case 1:
1660             proto_tree_add_text(tree, tvb, offset, 4,
1661                     "Retransmission: Packet transmitted sucessfully on first attempt");
1662             break;
1663         default:
1664             proto_tree_add_text(tree, tvb, offset, 4, "Retransmissions: %u", transmissions - 1);
1665             break;
1666     }
1667     offset += 4;
1668
1669     packet_duration = tvb_get_ntohl(tvb, offset);
1670     packet_duration == 0 ?
1671             proto_tree_add_text(tree, tvb, offset, 4, "Packet Duration: Unknown") :
1672             proto_tree_add_text(tree, tvb, offset, 4, "Packet Duration: %u (ms)", packet_duration);
1673     offset += 4;
1674
1675     retrans_duration = tvb_get_ntohl(tvb, offset);
1676     retrans_duration == 0 ?
1677             proto_tree_add_text(tree, tvb, offset, 4, "Retransmission Duration: Unknown") :
1678             proto_tree_add_text(tree, tvb, offset, 4, "Retransmission Duration: %u (ms)", retrans_duration);
1679     offset += 4;
1680
1681     channel = tvb_get_ntohl(tvb, offset);
1682     proto_tree_add_text(tree, tvb, offset, 4, "Channel: %u", channel);
1683     offset += 4;
1684
1685     speed = tvb_get_ntoh64(tvb, offset);
1686     proto_tree_add_text(tree, tvb, offset, 8, "Speed: %" G_GINT64_MODIFIER "u", speed);
1687     offset += 8;
1688
1689     power = tvb_get_ntohl(tvb, offset);
1690     proto_tree_add_text(tree, tvb, offset, 4, "Power: %u (mW)", power);
1691     offset += 4;
1692
1693     return offset;
1694 }
1695
1696 /* sflow v5 extended 802.11 aggregation */
1697 static gint
1698 dissect_sflow_5_extended_80211_aggregation(tvbuff_t *tvb _U_, proto_tree *tree _U_, gint offset) {
1699
1700     return offset;
1701 }
1702
1703 /* dissect an sflow v2/4 flow sample */
1704 static gint
1705 dissect_sflow_24_flow_sample(tvbuff_t *tvb, packet_info *pinfo,
1706         proto_tree *tree, gint offset, proto_item *parent) {
1707     struct sflow_24_flow_sample_header flow_header;
1708     proto_tree *extended_data_tree;
1709     proto_item *ti;
1710     guint32 packet_type, extended_data, ext_type, i, output;
1711
1712     /* grab the flow header.  This will remain in network byte
1713        order, so must convert each item before use */
1714     tvb_memcpy(tvb, (guint8 *) & flow_header, offset, sizeof (flow_header));
1715     proto_tree_add_text(tree, tvb, offset, 4,
1716             "Sequence number: %u", g_ntohl(flow_header.sequence_number));
1717     proto_item_append_text(parent, ", seq %u", g_ntohl(flow_header.sequence_number));
1718     proto_tree_add_text(tree, tvb, offset + 4, 4,
1719             "Source ID class: %u index: %u",
1720             g_ntohl(flow_header.source_id) >> 24,
1721             g_ntohl(flow_header.source_id) & 0x00ffffff);
1722     proto_tree_add_text(tree, tvb, offset + 8, 4,
1723             "Sampling rate: 1 out of %u packets",
1724             g_ntohl(flow_header.sampling_rate));
1725     proto_tree_add_text(tree, tvb, offset + 12, 4,
1726             "Sample pool: %u total packets",
1727             g_ntohl(flow_header.sample_pool));
1728     proto_tree_add_text(tree, tvb, offset + 16, 4,
1729             "Dropped packets: %u",
1730             g_ntohl(flow_header.drops));
1731     proto_tree_add_text(tree, tvb, offset + 20, 4,
1732             "Input interface: ifIndex %u",
1733             g_ntohl(flow_header.input));
1734     output = g_ntohl(flow_header.output);
1735     if (output >> 31) {
1736         output & 0x7fffffff ?
1737                 proto_tree_add_text(tree, tvb, offset + 24, 4,
1738                 "Multiple outputs: %u interfaces", output & 0x7fffffff) :
1739                 proto_tree_add_text(tree, tvb, offset + 24, 4,
1740                 "Multiple outputs: unknown number");
1741     } else {
1742         proto_tree_add_text(tree, tvb, offset + 24, 4,
1743                 "Output interface: ifIndex %u", output & 0x7fffffff);
1744     }
1745     offset += sizeof (flow_header);
1746
1747     /* what kind of flow sample is it? */
1748     packet_type = tvb_get_ntohl(tvb, offset);
1749     proto_tree_add_uint(tree, hf_sflow_245_packet_information_type, tvb, offset, 4, packet_type);
1750     offset += 4;
1751     switch (packet_type) {
1752         case SFLOW_245_PACKET_DATA_TYPE_HEADER:
1753             offset = dissect_sflow_245_sampled_header(tvb, pinfo, tree, offset);
1754             break;
1755         case SFLOW_245_PACKET_DATA_TYPE_IPV4:
1756         case SFLOW_245_PACKET_DATA_TYPE_IPV6:
1757         default:
1758             break;
1759     }
1760     /* still need to dissect extended data */
1761     extended_data = tvb_get_ntohl(tvb, offset);
1762     offset += 4;
1763
1764     for (i = 0; i < extended_data; i++) {
1765         /* figure out what kind of extended data it is */
1766         ext_type = tvb_get_ntohl(tvb, offset);
1767
1768         /* create a subtree.  Might want to move this to
1769          * the end, so more info can be correct.
1770          */
1771         ti = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1772                 val_to_str(ext_type, sflow_245_extended_data_types, "Unknown extended information"));
1773         extended_data_tree = proto_item_add_subtree(ti, ett_sflow_245_extended_data);
1774         proto_tree_add_uint(extended_data_tree, hf_sflow_245_extended_information_type, tvb, offset, 4, ext_type);
1775         offset += 4;
1776
1777         switch (ext_type) {
1778             case SFLOW_245_EXTENDED_SWITCH:
1779                 offset = dissect_sflow_245_extended_switch(tvb, extended_data_tree, offset);
1780                 break;
1781             case SFLOW_245_EXTENDED_ROUTER:
1782                 offset = dissect_sflow_245_extended_router(tvb, extended_data_tree, offset);
1783                 break;
1784             case SFLOW_245_EXTENDED_GATEWAY:
1785                 offset = dissect_sflow_245_extended_gateway(tvb, extended_data_tree, offset);
1786                 break;
1787             case SFLOW_245_EXTENDED_USER:
1788                 break;
1789             case SFLOW_245_EXTENDED_URL:
1790                 break;
1791             default:
1792                 break;
1793         }
1794         proto_item_set_end(ti, tvb, offset);
1795     }
1796     return offset;
1797
1798 }
1799
1800 /* dissect an sflow v5 flow record */
1801 static gint
1802 dissect_sflow_5_flow_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset) {
1803     proto_tree *flow_data_tree;
1804     proto_item *ti;
1805     guint32 enterprise_format, enterprise, format;
1806
1807
1808     /* what kind of flow sample is it? */
1809     enterprise_format = tvb_get_ntohl(tvb, offset);
1810     enterprise = enterprise_format >> 12;
1811     format = enterprise_format & 0x00000fff;
1812
1813     /* only accept default enterprise 0 (InMon sFlow) */
1814     if (enterprise == ENTERPRISE_DEFAULT) {
1815         ti = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1816                 val_to_str(format, sflow_5_flow_record_type, "Unknown sample format"));
1817         flow_data_tree = proto_item_add_subtree(ti, ett_sflow_5_flow_record);
1818
1819         proto_tree_add_text(flow_data_tree, tvb, offset, 4, "Enterprise: standard sFlow (%u)", enterprise);
1820         proto_tree_add_item(flow_data_tree, hf_sflow_5_flow_record_format, tvb, offset, 4, ENC_BIG_ENDIAN);
1821         offset += 4;
1822
1823         proto_tree_add_item(flow_data_tree, hf_sflow_5_flow_data_length, tvb, offset, 4, ENC_BIG_ENDIAN);
1824         offset += 4;
1825
1826         switch (format) {
1827             case SFLOW_5_RAW_PACKET_HEADER:
1828                 offset = dissect_sflow_245_sampled_header(tvb, pinfo, flow_data_tree, offset);
1829                 break;
1830             case SFLOW_5_ETHERNET_FRAME:
1831                 offset = dissect_sflow_5_ethernet_frame(tvb, flow_data_tree, offset);
1832                 break;
1833             case SFLOW_5_IPV4:
1834                 offset = dissect_sflow_5_ipv4(tvb, flow_data_tree, offset);
1835                 break;
1836             case SFLOW_5_IPV6:
1837                 offset = dissect_sflow_5_ipv6(tvb, flow_data_tree, offset);
1838                 break;
1839             case SFLOW_5_SWITCH:
1840                 offset = dissect_sflow_245_extended_switch(tvb, flow_data_tree, offset);
1841                 break;
1842             case SFLOW_5_ROUTER:
1843                 offset = dissect_sflow_245_extended_router(tvb, flow_data_tree, offset);
1844                 break;
1845             case SFLOW_5_GATEWAY:
1846                 offset = dissect_sflow_245_extended_gateway(tvb, flow_data_tree, offset);
1847                 break;
1848             case SFLOW_5_USER:
1849                 offset = dissect_sflow_5_extended_user(tvb, flow_data_tree, offset);
1850                 break;
1851             case SFLOW_5_URL:
1852                 offset = dissect_sflow_5_extended_url(tvb, flow_data_tree, offset);
1853                 break;
1854             case SFLOW_5_MPLS_DATA:
1855                 offset = dissect_sflow_5_extended_mpls_data(tvb, flow_data_tree, offset);
1856                 break;
1857             case SFLOW_5_NAT:
1858                 offset = dissect_sflow_5_extended_nat(tvb, flow_data_tree, offset);
1859                 break;
1860             case SFLOW_5_MPLS_TUNNEL:
1861                 offset = dissect_sflow_5_extended_mpls_tunnel(tvb, flow_data_tree, offset);
1862                 break;
1863             case SFLOW_5_MPLS_VC:
1864                 offset = dissect_sflow_5_extended_mpls_vc(tvb, flow_data_tree, offset);
1865                 break;
1866             case SFLOW_5_MPLS_FEC:
1867                 offset = dissect_sflow_5_extended_mpls_fec(tvb, flow_data_tree, offset);
1868                 break;
1869             case SFLOW_5_MPLS_LVP_FEC:
1870                 offset = dissect_sflow_5_extended_mpls_lvp_fec(tvb, flow_data_tree, offset);
1871                 break;
1872             case SFLOW_5_VLAN_TUNNEL:
1873                 offset = dissect_sflow_5_extended_vlan_tunnel(tvb, flow_data_tree, offset);
1874                 break;
1875             case SFLOW_5_80211_PAYLOAD:
1876                 offset = dissect_sflow_5_extended_80211_payload(tvb, flow_data_tree, offset);
1877                 break;
1878             case SFLOW_5_80211_RX:
1879                 offset = dissect_sflow_5_extended_80211_rx(tvb, flow_data_tree, offset);
1880                 break;
1881             case SFLOW_5_80211_TX:
1882                 offset = dissect_sflow_5_extended_80211_tx(tvb, flow_data_tree, offset);
1883                 break;
1884             case SFLOW_5_80211_AGGREGATION:
1885                 offset = dissect_sflow_5_extended_80211_aggregation(tvb, flow_data_tree, offset);
1886                 break;
1887             default:
1888                 break;
1889         }
1890     } else {
1891         /* unknown enterprise format, what to do?? */
1892         ti = proto_tree_add_text(tree, tvb, offset, -1, "Unknown enterprise format");
1893         flow_data_tree = proto_item_add_subtree(ti, ett_sflow_5_flow_record);
1894         proto_tree_add_text(flow_data_tree, tvb, offset, -1, "Enterprise: Non-standard sFlow (%u)", enterprise);
1895     }
1896     proto_item_set_end(ti, tvb, offset);
1897
1898     return offset;
1899 }
1900
1901 /* dissect generic interface counters */
1902 static gint
1903 dissect_sflow_5_generic_interface(proto_tree *counter_data_tree, tvbuff_t *tvb, gint offset) {
1904     struct if_counters ifc;
1905     tvb_memcpy(tvb, (guint8 *) & ifc, offset, sizeof (ifc));
1906     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifindex, tvb, offset, 4, ENC_BIG_ENDIAN);
1907     offset += 4;
1908     proto_tree_add_item(counter_data_tree, hf_sflow_245_iftype, tvb, offset, 4, ENC_BIG_ENDIAN);
1909     offset += 4;
1910     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifspeed, tvb, offset, 8, ENC_BIG_ENDIAN);
1911     offset += 8;
1912     switch (tvb_get_ntohl(tvb, offset)) {
1913         case 1:
1914             proto_tree_add_text(counter_data_tree, tvb, offset, 4, "IfDirection: Full-Duplex");
1915             break;
1916         case 2:
1917             proto_tree_add_text(counter_data_tree, tvb, offset, 4, "IfDirection: Half-Duplex");
1918             break;
1919         case 3:
1920             proto_tree_add_text(counter_data_tree, tvb, offset, 4, "IfDirection: In");
1921             break;
1922         case 4:
1923             proto_tree_add_text(counter_data_tree, tvb, offset, 4, "IfDirection: Out");
1924             break;
1925         default:
1926             proto_tree_add_text(counter_data_tree, tvb, offset, 4, "IfDirection: Unknown");
1927             break;
1928     }
1929     offset += 4;
1930     if (tvb_get_ntohl(tvb, offset)&0x00000001) { /* check bit 0 (host order) */
1931         proto_tree_add_text(counter_data_tree, tvb, offset, 4, "IfAdminStatus: Up");
1932     } else {
1933         proto_tree_add_text(counter_data_tree, tvb, offset, 4, "IfAdminStatus: Down");
1934     }
1935     if (tvb_get_ntohl(tvb, offset)&0x00000002) { /* check bit 1 (host order) */
1936         proto_tree_add_text(counter_data_tree, tvb, offset, 4, "IfOperStatus: Up");
1937     } else {
1938         proto_tree_add_text(counter_data_tree, tvb, offset, 4, "IfOperStatus: Down");
1939     }
1940     offset += 4;
1941     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifinoct, tvb, offset, 8, ENC_BIG_ENDIAN);
1942     offset += 8;
1943     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifinpkt, tvb, offset, 4, ENC_BIG_ENDIAN);
1944     offset += 4;
1945     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifinmcast, tvb, offset, 4, ENC_BIG_ENDIAN);
1946     offset += 4;
1947     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifinbcast, tvb, offset, 4, ENC_BIG_ENDIAN);
1948     offset += 4;
1949     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifindisc, tvb, offset, 4, ENC_BIG_ENDIAN);
1950     offset += 4;
1951     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifinerr, tvb, offset, 4, ENC_BIG_ENDIAN);
1952     offset += 4;
1953     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifinunk, tvb, offset, 4, ENC_BIG_ENDIAN);
1954     offset += 4;
1955     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifoutoct, tvb, offset, 8, ENC_BIG_ENDIAN);
1956     offset += 8;
1957     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifoutpkt, tvb, offset, 4, ENC_BIG_ENDIAN);
1958     offset += 4;
1959     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifoutmcast, tvb, offset, 4, ENC_BIG_ENDIAN);
1960     offset += 4;
1961     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifoutbcast, tvb, offset, 4, ENC_BIG_ENDIAN);
1962     offset += 4;
1963     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifoutdisc, tvb, offset, 4, ENC_BIG_ENDIAN);
1964     offset += 4;
1965     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifouterr, tvb, offset, 4, ENC_BIG_ENDIAN);
1966     offset += 4;
1967     proto_tree_add_item(counter_data_tree, hf_sflow_245_ifpromisc, tvb, offset, 4, ENC_BIG_ENDIAN);
1968     offset += 4;
1969
1970     return offset;
1971 }
1972
1973 /* dissect ethernet interface counters */
1974 static gint
1975 dissect_sflow_5_ethernet_interface(proto_tree *counter_data_tree, tvbuff_t *tvb, gint offset) {
1976     struct ethernet_counters ethc;
1977
1978     tvb_memcpy(tvb, (guint8 *) & ethc, offset, sizeof (ethc));
1979     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsAlignmentErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
1980     offset += 4;
1981     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsFCSErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
1982     offset += 4;
1983     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsSingleCollisionFrames, tvb, offset, 4, ENC_BIG_ENDIAN);
1984     offset += 4;
1985     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsMultipleCollisionFrames, tvb, offset, 4, ENC_BIG_ENDIAN);
1986     offset += 4;
1987     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsSQETestErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
1988     offset += 4;
1989     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsDeferredTransmissions, tvb, offset, 4, ENC_BIG_ENDIAN);
1990     offset += 4;
1991     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsLateCollisions, tvb, offset, 4, ENC_BIG_ENDIAN);
1992     offset += 4;
1993     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsExcessiveCollisions, tvb, offset, 4, ENC_BIG_ENDIAN);
1994     offset += 4;
1995     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsInternalMacTransmitErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
1996     offset += 4;
1997     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsCarrierSenseErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
1998     offset += 4;
1999     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsFrameTooLongs, tvb, offset, 4, ENC_BIG_ENDIAN);
2000     offset += 4;
2001     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsInternalMacReceiveErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2002     offset += 4;
2003     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot3StatsSymbolErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2004     offset += 4;
2005
2006     return offset;
2007 }
2008
2009 /* dissect token ring counters */
2010 static gint
2011 dissect_sflow_5_token_ring(proto_tree *counter_data_tree, tvbuff_t *tvb, gint offset) {
2012     struct token_ring_counters tokc;
2013
2014     tvb_memcpy(tvb, (guint8 *) & tokc, offset, sizeof (tokc));
2015     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsLineErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2016     offset += 4;
2017     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsBurstErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2018     offset += 4;
2019     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsACErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2020     offset += 4;
2021     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsAbortTransErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2022     offset += 4;
2023     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsInternalErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2024     offset += 4;
2025     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsLostFrameErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2026     offset += 4;
2027     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsReceiveCongestions, tvb, offset, 4, ENC_BIG_ENDIAN);
2028     offset += 4;
2029     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsFrameCopiedErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2030     offset += 4;
2031     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsTokenErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2032     offset += 4;
2033     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsSoftErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2034     offset += 4;
2035     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsHardErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2036     offset += 4;
2037     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsSignalLoss, tvb, offset, 4, ENC_BIG_ENDIAN);
2038     offset += 4;
2039     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsTransmitBeacons, tvb, offset, 4, ENC_BIG_ENDIAN);
2040     offset += 4;
2041     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsRecoveries, tvb, offset, 4, ENC_BIG_ENDIAN);
2042     offset += 4;
2043     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsLobeWires, tvb, offset, 4, ENC_BIG_ENDIAN);
2044     offset += 4;
2045     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsRemoves, tvb, offset, 4, ENC_BIG_ENDIAN);
2046     offset += 4;
2047     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsSingles, tvb, offset, 4, ENC_BIG_ENDIAN);
2048     offset += 4;
2049     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot5StatsFreqErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2050     offset += 4;
2051
2052     return offset;
2053 }
2054
2055 /* dissect 100 BaseVG interface counters */
2056 static gint
2057 dissect_sflow_5_vg_interface(proto_tree *counter_data_tree, tvbuff_t *tvb, gint offset) {
2058     struct vg_counters vgc;
2059
2060     tvb_memcpy(tvb, (guint8 *) & vgc, offset, sizeof (vgc));
2061     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12InHighPriorityFrames, tvb, offset, 4, ENC_BIG_ENDIAN);
2062     offset += 4;
2063     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12InHighPriorityOctets, tvb, offset, 8, ENC_BIG_ENDIAN);
2064     offset += 8;
2065     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12InNormPriorityFrames, tvb, offset, 4, ENC_BIG_ENDIAN);
2066     offset += 4;
2067     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12InNormPriorityOctets, tvb, offset, 8, ENC_BIG_ENDIAN);
2068     offset += 8;
2069     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12InIPMErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2070     offset += 4;
2071     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12InOversizeFrameErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2072     offset += 4;
2073     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12InDataErrors, tvb, offset, 4, ENC_BIG_ENDIAN);
2074     offset += 4;
2075     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12InNullAddressedFrames, tvb, offset, 4, ENC_BIG_ENDIAN);
2076     offset += 4;
2077     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12OutHighPriorityFrames, tvb, offset, 4, ENC_BIG_ENDIAN);
2078     offset += 4;
2079     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12OutHighPriorityOctets, tvb, offset, 8, ENC_BIG_ENDIAN);
2080     offset += 8;
2081     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12TransitionIntoTrainings, tvb, offset, 4, ENC_BIG_ENDIAN);
2082     offset += 4;
2083     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12HCInHighPriorityOctets, tvb, offset, 8, ENC_BIG_ENDIAN);
2084     offset += 8;
2085     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12HCInNormPriorityOctets, tvb, offset, 8, ENC_BIG_ENDIAN);
2086     offset += 8;
2087     proto_tree_add_item(counter_data_tree, hf_sflow_245_dot12HCOutHighPriorityOctets, tvb, offset, 8, ENC_BIG_ENDIAN);
2088     offset += 8;
2089
2090     return offset;
2091 }
2092
2093 /* dissect VLAN counters */
2094 static gint
2095 dissect_sflow_5_vlan(proto_tree *counter_data_tree, tvbuff_t *tvb, gint offset) {
2096     struct vlan_counters vlanc;
2097
2098     tvb_memcpy(tvb, (guint8 *) & vlanc, offset, sizeof (vlanc));
2099     proto_tree_add_item(counter_data_tree, hf_sflow_245_vlan_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2100     offset += 4;
2101     proto_tree_add_item(counter_data_tree, hf_sflow_245_octets, tvb, offset, 8, ENC_BIG_ENDIAN);
2102     offset += 8;
2103     proto_tree_add_item(counter_data_tree, hf_sflow_245_ucastPkts, tvb, offset, 4, ENC_BIG_ENDIAN);
2104     offset += 4;
2105     proto_tree_add_item(counter_data_tree, hf_sflow_245_multicastPkts, tvb, offset, 4, ENC_BIG_ENDIAN);
2106     offset += 4;
2107     proto_tree_add_item(counter_data_tree, hf_sflow_245_broadcastPkts, tvb, offset, 4, ENC_BIG_ENDIAN);
2108     offset += 4;
2109     proto_tree_add_item(counter_data_tree, hf_sflow_245_discards, tvb, offset, 4, ENC_BIG_ENDIAN);
2110     offset += 4;
2111
2112     return offset;
2113 }
2114
2115 /* dissect 802.11 counters */
2116 static gint
2117 dissect_sflow_5_80211_counters(proto_tree *counter_data_tree, tvbuff_t *tvb, gint offset) {
2118     struct ieee80211_if_counters ieee80211;
2119
2120     tvb_memcpy(tvb, (guint8 *) & ieee80211, offset, sizeof (ieee80211));
2121     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11TransmittedFragmentCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2122     offset += 4;
2123     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11MulticastTransmittedFrameCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2124     offset += 4;
2125     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11FailedCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2126     offset += 4;
2127     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11RetryCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2128     offset += 4;
2129     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11MultipleRetryCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2130     offset += 4;
2131     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11FrameDuplicateCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2132     offset += 4;
2133     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11RTSSuccessCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2134     offset += 4;
2135     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11RTSFailureCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2136     offset += 4;
2137     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11ACKFailureCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2138     offset += 4;
2139     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11ReceivedFragmentCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2140     offset += 4;
2141     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11MulticastReceivedFrameCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2142     offset += 4;
2143     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11FCSErrorCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2144     offset += 4;
2145     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11TransmittedFrameCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2146     offset += 4;
2147     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11WEPUndecryptableCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2148     offset += 4;
2149     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11QoSDiscardedFragmentCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2150     offset += 4;
2151     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11AssociatedStationCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2152     offset += 4;
2153     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11QoSCFPollsReceivedCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2154     offset += 4;
2155     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11QoSCFPollsUnusedCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2156     offset += 4;
2157     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11QoSCFPollsUnusableCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2158     offset += 4;
2159     proto_tree_add_item(counter_data_tree, hf_sflow_5_dot11QoSCFPollsLostCount, tvb, offset, 4, ENC_BIG_ENDIAN);
2160     offset += 4;
2161
2162     return offset;
2163 }
2164
2165 /* dissect processor information */
2166 static gint
2167 dissect_sflow_5_processor_information(proto_tree *counter_data_tree, tvbuff_t *tvb, gint offset) {
2168     struct processor proc;
2169
2170     tvb_memcpy(tvb, (guint8 *) & proc, offset, sizeof (proc));
2171     proto_tree_add_item(counter_data_tree, hf_sflow_5_cpu_5s, tvb, offset, 4, ENC_BIG_ENDIAN);
2172     offset += 4;
2173     proto_tree_add_item(counter_data_tree, hf_sflow_5_cpu_1m, tvb, offset, 4, ENC_BIG_ENDIAN);
2174     offset += 4;
2175     proto_tree_add_item(counter_data_tree, hf_sflow_5_cpu_5m, tvb, offset, 4, ENC_BIG_ENDIAN);
2176     offset += 4;
2177     proto_tree_add_item(counter_data_tree, hf_sflow_5_total_memory, tvb, offset, 8, ENC_BIG_ENDIAN);
2178     offset += 8;
2179     proto_tree_add_item(counter_data_tree, hf_sflow_5_free_memory, tvb, offset, 8, ENC_BIG_ENDIAN);
2180     offset += 8;
2181
2182     return offset;
2183 }
2184
2185 /* dissect radio utilization */
2186 static gint
2187 dissect_sflow_5_radio_utilization(proto_tree *counter_data_tree, tvbuff_t *tvb, gint offset) {
2188     struct radio_utilization radio;
2189
2190     tvb_memcpy(tvb, (guint8 *) & radio, offset, sizeof (radio));
2191     proto_tree_add_item(counter_data_tree, hf_sflow_5_elapsed_time, tvb, offset, 4, ENC_BIG_ENDIAN);
2192     offset += 4;
2193     proto_tree_add_item(counter_data_tree, hf_sflow_5_on_channel_time, tvb, offset, 4, ENC_BIG_ENDIAN);
2194     offset += 4;
2195     proto_tree_add_item(counter_data_tree, hf_sflow_5_on_channel_busy_time, tvb, offset, 4, ENC_BIG_ENDIAN);
2196     offset += 4;
2197
2198     return offset;
2199 }
2200
2201 /* dissect an sflow v5 counters record */
2202 static gint
2203 dissect_sflow_5_counters_record(tvbuff_t *tvb, proto_tree *tree, gint offset) {
2204     proto_tree *counter_data_tree;
2205     proto_item *ti;
2206     guint32 enterprise_format, enterprise, format;
2207
2208     /* what kind of flow sample is it? */
2209     enterprise_format = tvb_get_ntohl(tvb, offset);
2210     enterprise = enterprise_format >> 12;
2211     format = enterprise_format & 0x00000fff;
2212
2213     if (enterprise == ENTERPRISE_DEFAULT) { /* only accept default enterprise 0 (InMon sFlow) */
2214         ti = proto_tree_add_text(tree, tvb, offset, -1, "%s",
2215                 val_to_str(format, sflow_5_counters_record_type, "Unknown sample format"));
2216         counter_data_tree = proto_item_add_subtree(ti, ett_sflow_5_counters_record);
2217
2218         proto_tree_add_text(counter_data_tree, tvb, offset, 4, "Enterprise: standard sFlow (%u)", enterprise);
2219
2220         proto_tree_add_item(counter_data_tree, hf_sflow_5_counters_record_format, tvb, offset, 4, ENC_BIG_ENDIAN);
2221         offset += 4;
2222
2223
2224         proto_tree_add_item(counter_data_tree, hf_sflow_5_flow_data_length, tvb, offset, 4, ENC_BIG_ENDIAN);
2225         offset += 4;
2226
2227         switch (format) {
2228             case SFLOW_5_GENERIC_INTERFACE:
2229                 offset = dissect_sflow_5_generic_interface(counter_data_tree, tvb, offset);
2230                 break;
2231             case SFLOW_5_ETHERNET_INTERFACE:
2232                 offset = dissect_sflow_5_ethernet_interface(counter_data_tree, tvb, offset);
2233                 break;
2234             case SFLOW_5_TOKEN_RING:
2235                 offset = dissect_sflow_5_token_ring(counter_data_tree, tvb, offset);
2236                 break;
2237             case SFLOW_5_100BASE_VG_INTERFACE:
2238                 offset = dissect_sflow_5_vg_interface(counter_data_tree, tvb, offset);
2239                 break;
2240             case SFLOW_5_VLAN:
2241                 offset = dissect_sflow_5_vlan(counter_data_tree, tvb, offset);
2242                 break;
2243             case SFLOW_5_80211_COUNTERS:
2244                 offset = dissect_sflow_5_80211_counters(counter_data_tree, tvb, offset);
2245                 break;
2246             case SFLOW_5_PROCESSOR:
2247                 offset = dissect_sflow_5_processor_information(counter_data_tree, tvb, offset);
2248                 break;
2249             case SFLOW_5_RADIO_UTILIZATION:
2250                 offset = dissect_sflow_5_radio_utilization(counter_data_tree, tvb, offset);
2251                 break;
2252             default:
2253                 break;
2254         }
2255     } else { /* unknown enterprise format, what to do?? */
2256         ti = proto_tree_add_text(tree, tvb, offset, -1, "%s", "Unknown enterprise format");
2257         counter_data_tree = proto_item_add_subtree(ti, ett_sflow_5_counters_record);
2258         proto_tree_add_text(counter_data_tree, tvb, offset, -1, "Enterprise: Non-standard sFlow (%u)", enterprise);
2259     }
2260     proto_item_set_end(ti, tvb, offset);
2261
2262     return offset;
2263 }
2264
2265 /* dissect an sflow v5 flow sample */
2266 static void
2267 dissect_sflow_5_flow_sample(tvbuff_t *tvb, packet_info *pinfo,
2268         proto_tree *tree, gint offset, proto_item *parent) {
2269     struct sflow_5_flow_sample_header flow_header;
2270     guint32 i, output;
2271
2272     /* grab the flow header.  This will remain in network byte
2273        order, so must convert each item before use */
2274     tvb_memcpy(tvb, (guint8 *) & flow_header, offset, sizeof (flow_header));
2275     proto_tree_add_text(tree, tvb, offset, 4,
2276             "Sequence number: %u", g_ntohl(flow_header.sequence_number));
2277     offset += 4;
2278     proto_item_append_text(parent, ", seq %u", g_ntohl(flow_header.sequence_number));
2279     proto_tree_add_text(tree, tvb, offset, 4,
2280             "Source ID class: %u index: %u",
2281             g_ntohl(flow_header.source_id) >> 24,
2282             g_ntohl(flow_header.source_id) & 0x00ffffff);
2283     offset += 4;
2284     proto_tree_add_text(tree, tvb, offset, 4,
2285             "Sampling rate: 1 out of %u packets",
2286             g_ntohl(flow_header.sampling_rate));
2287     offset += 4;
2288     proto_tree_add_text(tree, tvb, offset, 4,
2289             "Sample pool: %u total packets",
2290             g_ntohl(flow_header.sample_pool));
2291     offset += 4;
2292     proto_tree_add_text(tree, tvb, offset, 4,
2293             "Dropped packets: %u",
2294             g_ntohl(flow_header.drops));
2295     offset += 4;
2296     proto_tree_add_text(tree, tvb, offset, 4,
2297             "Input interface: ifIndex %u",
2298             g_ntohl(flow_header.input));
2299     offset += 4;
2300     output = g_ntohl(flow_header.output);
2301     if (output >> 31) {
2302         output & 0x7fffffff ?
2303                 proto_tree_add_text(tree, tvb, offset, 4,
2304                 "Multiple outputs: %u interfaces", output & 0x7fffffff) :
2305                 proto_tree_add_text(tree, tvb, offset, 4,
2306                 "Multiple outputs: unknown number");
2307     } else {
2308         proto_tree_add_text(tree, tvb, offset, 4,
2309                 "Output interface: ifIndex %u", output & 0x7fffffff);
2310     }
2311     offset += 4;
2312     proto_tree_add_text(tree, tvb, offset, 4,
2313             "Flow record: %u",
2314             g_ntohl(flow_header.records));
2315     offset += 4;
2316
2317     /* start loop processing flow records */
2318     /* we set an upper records limit to 255 in case corrupted data causes
2319      * huge number of loops! */
2320     for (i = 0; i < (g_ntohl(flow_header.records)&0x000000ff); i++) {
2321
2322         offset = dissect_sflow_5_flow_record(tvb, pinfo, tree, offset);
2323
2324     }
2325
2326 }
2327
2328 /* dissect an expanded flow sample */
2329 static void
2330 dissect_sflow_5_expanded_flow_sample(tvbuff_t *tvb, packet_info *pinfo,
2331         proto_tree *tree, gint offset, proto_item *parent) {
2332     struct sflow_5_expanded_flow_sample_header flow_header;
2333     guint32 i;
2334
2335     /* grab the flow header.  This will remain in network byte
2336        order, so must convert each item before use */
2337     tvb_memcpy(tvb, (guint8 *) & flow_header, offset, sizeof (flow_header));
2338     proto_tree_add_text(tree, tvb, offset, 4,
2339             "Sequence number: %u", g_ntohl(flow_header.sequence_number));
2340     offset += 4;
2341     proto_item_append_text(parent, ", seq %u", g_ntohl(flow_header.sequence_number));
2342     proto_tree_add_text(tree, tvb, offset, 4,
2343             "Source ID type: %u",
2344             g_ntohl(flow_header.source_id_type));
2345     offset += 4;
2346     proto_tree_add_text(tree, tvb, offset, 4,
2347             "Source ID index: %u",
2348             g_ntohl(flow_header.source_id_index));
2349     offset += 4;
2350     proto_tree_add_text(tree, tvb, offset, 4,
2351             "Sampling rate: 1 out of %u packets",
2352             g_ntohl(flow_header.sampling_rate));
2353     offset += 4;
2354     proto_tree_add_text(tree, tvb, offset, 4,
2355             "Sample pool: %u total packets",
2356             g_ntohl(flow_header.sample_pool));
2357     offset += 4;
2358     proto_tree_add_text(tree, tvb, offset, 4,
2359             "Dropped packets: %u",
2360             g_ntohl(flow_header.drops));
2361     offset += 4;
2362     proto_tree_add_text(tree, tvb, offset, 4,
2363             "Input interface format: %u",
2364             g_ntohl(flow_header.input_format));
2365     offset += 4;
2366     proto_tree_add_text(tree, tvb, offset, 4,
2367             "Input interface value: %u",
2368             g_ntohl(flow_header.input_value));
2369     offset += 4;
2370     proto_tree_add_text(tree, tvb, offset, 4,
2371             "Output interface format: %u",
2372             g_ntohl(flow_header.output_format));
2373     offset += 4;
2374     proto_tree_add_text(tree, tvb, offset, 4,
2375             "Output interface value: %u",
2376             g_ntohl(flow_header.output_value));
2377     offset += 4;
2378     proto_tree_add_text(tree, tvb, offset, 4,
2379             "Flow record: %u",
2380             g_ntohl(flow_header.records));
2381     offset += 4;
2382
2383     /* start loop processing flow records
2384      * we limit record count to 255 in case corrupted data may cause huge number of loops */
2385     for (i = 0; i < (g_ntohl(flow_header.records)&0x000000ff); i++) {
2386
2387         offset = dissect_sflow_5_flow_record(tvb, pinfo, tree, offset);
2388
2389     }
2390 }
2391
2392 /* dissect an sflow v2/4 counters sample */
2393 static gint
2394 dissect_sflow_24_counters_sample(tvbuff_t *tvb, proto_tree *tree, gint offset, proto_item *parent) {
2395     struct sflow_24_counters_sample_header counters_header;
2396     struct if_counters ifc;
2397     struct ethernet_counters ethc;
2398     struct token_ring_counters tokc;
2399     struct vg_counters vgc;
2400     struct vlan_counters vlanc;
2401
2402     /* grab the flow header.  This will remain in network byte
2403        order, so must convert each item before use */
2404     tvb_memcpy(tvb, (guint8 *) & counters_header, offset, sizeof (counters_header));
2405     proto_tree_add_text(tree, tvb, offset, 4,
2406             "Sequence number: %u",
2407             g_ntohl(counters_header.sequence_number));
2408     proto_item_append_text(parent, ", seq %u", g_ntohl(counters_header.sequence_number));
2409     proto_tree_add_text(tree, tvb, offset + 4, 4,
2410             "Source ID class: %u index: %u",
2411             g_ntohl(counters_header.source_id) >> 24,
2412             g_ntohl(counters_header.source_id) & 0x00ffffff);
2413     proto_tree_add_text(tree, tvb, offset + 8, 4,
2414             "Sampling Interval: %u",
2415             g_ntohl(counters_header.sampling_interval));
2416     proto_tree_add_text(tree, tvb, offset + 12, 4, "Counters type: %s",
2417             val_to_str(g_ntohl(counters_header.counters_type),
2418             sflow_245_counterstype, "Unknown type"));
2419
2420     offset += sizeof (counters_header);
2421
2422     /* most counters types have the "generic" counters first */
2423     switch (g_ntohl(counters_header.counters_type)) {
2424         case SFLOW_245_COUNTERS_GENERIC:
2425         case SFLOW_245_COUNTERS_ETHERNET:
2426         case SFLOW_245_COUNTERS_TOKENRING:
2427         case SFLOW_245_COUNTERS_FDDI:
2428         case SFLOW_245_COUNTERS_VG:
2429         case SFLOW_245_COUNTERS_WAN:
2430             tvb_memcpy(tvb, (guint8 *) & ifc, offset, sizeof (ifc));
2431             proto_item_append_text(parent, ", ifIndex %u", g_ntohl(ifc.ifIndex));
2432             proto_tree_add_item(tree, hf_sflow_245_ifindex, tvb, offset, 4, ENC_BIG_ENDIAN);
2433             offset += 4;
2434             proto_tree_add_item(tree, hf_sflow_245_iftype, tvb, offset, 4, ENC_BIG_ENDIAN);
2435             offset += 4;
2436             proto_tree_add_item(tree, hf_sflow_245_ifspeed, tvb, offset, 8, ENC_BIG_ENDIAN);
2437             offset += 8;
2438             /* IfDirection, IfAdminStatus, IfOperStatus fixed by Yi Yu */
2439             switch (tvb_get_ntohl(tvb, offset)) {
2440                 case 1:
2441                     proto_tree_add_text(tree, tvb, offset, 4, "IfDirection: Full-Duplex");
2442                     break;
2443                 case 2:
2444                     proto_tree_add_text(tree, tvb, offset, 4, "IfDirection: Half-Duplex");
2445                     break;
2446                 case 3:
2447                     proto_tree_add_text(tree, tvb, offset, 4, "IfDirection: In");
2448                     break;
2449                 case 4:
2450                     proto_tree_add_text(tree, tvb, offset, 4, "IfDirection: Out");
2451                     break;
2452                 default:
2453                     proto_tree_add_text(tree, tvb, offset, 4, "IfDirection: Unknown");
2454                     break;
2455             }
2456             offset += 4;
2457             if (tvb_get_ntohl(tvb, offset)&0x00000001) { /* check bit 0 (host order) */
2458                 proto_tree_add_text(tree, tvb, offset, 4, "IfAdminStatus: Up");
2459             } else {
2460                 proto_tree_add_text(tree, tvb, offset, 4, "IfAdminStatus: Down");
2461             }
2462             if (tvb_get_ntohl(tvb, offset)&0x00000002) { /* check bit 1 (host order) */
2463                 proto_tree_add_text(tree, tvb, offset, 4, "IfOperStatus: Up");
2464             } else {
2465                 proto_tree_add_text(tree, tvb, offset, 4, "IfOperStatus: Down");
2466             }
2467             offset += 4;
2468             proto_tree_add_item(tree, hf_sflow_245_ifinoct, tvb, offset, 8, ENC_BIG_ENDIAN);
2469             offset += 8;
2470             proto_tree_add_item(tree, hf_sflow_245_ifinpkt, tvb, offset, 4, ENC_BIG_ENDIAN);
2471             offset += 4;
2472             proto_tree_add_item(tree, hf_sflow_245_ifinmcast, tvb, offset, 4, ENC_BIG_ENDIAN);
2473             offset += 4;
2474             proto_tree_add_item(tree, hf_sflow_245_ifinbcast, tvb, offset, 4, ENC_BIG_ENDIAN);
2475             offset += 4;
2476             proto_tree_add_item(tree, hf_sflow_245_ifindisc, tvb, offset, 4, ENC_BIG_ENDIAN);
2477             offset += 4;
2478             proto_tree_add_item(tree, hf_sflow_245_ifinerr, tvb, offset, 4, ENC_BIG_ENDIAN);
2479             offset += 4;
2480             proto_tree_add_item(tree, hf_sflow_245_ifinunk, tvb, offset, 4, ENC_BIG_ENDIAN);
2481             offset += 4;
2482             proto_tree_add_item(tree, hf_sflow_245_ifoutoct, tvb, offset, 8, ENC_BIG_ENDIAN);
2483             offset += 8;
2484             proto_tree_add_item(tree, hf_sflow_245_ifoutpkt, tvb, offset, 4, ENC_BIG_ENDIAN);
2485             offset += 4;
2486             proto_tree_add_item(tree, hf_sflow_245_ifoutmcast, tvb, offset, 4, ENC_BIG_ENDIAN);
2487             offset += 4;
2488             proto_tree_add_item(tree, hf_sflow_245_ifoutbcast, tvb, offset, 4, ENC_BIG_ENDIAN);
2489             offset += 4;
2490             proto_tree_add_item(tree, hf_sflow_245_ifoutdisc, tvb, offset, 4, ENC_BIG_ENDIAN);
2491             offset += 4;
2492             proto_tree_add_item(tree, hf_sflow_245_ifouterr, tvb, offset, 4, ENC_BIG_ENDIAN);
2493             offset += 4;
2494             proto_tree_add_item(tree, hf_sflow_245_ifpromisc, tvb, offset, 4, ENC_BIG_ENDIAN);
2495             offset += 4;
2496             break;
2497     }
2498
2499     /* Some counter types have other info to gather */
2500     switch (g_ntohl(counters_header.counters_type)) {
2501         case SFLOW_245_COUNTERS_ETHERNET:
2502             tvb_memcpy(tvb, (guint8 *) & ethc, offset, sizeof (ethc));
2503             offset += sizeof (ethc);
2504             break;
2505         case SFLOW_245_COUNTERS_TOKENRING:
2506             tvb_memcpy(tvb, (guint8 *) & tokc, offset, sizeof (tokc));
2507             offset += sizeof (tokc);
2508             break;
2509         case SFLOW_245_COUNTERS_VG:
2510             tvb_memcpy(tvb, (guint8 *) & vgc, offset, sizeof (vgc));
2511             offset += sizeof (vgc);
2512             break;
2513         case SFLOW_245_COUNTERS_VLAN:
2514             tvb_memcpy(tvb, (guint8 *) & vlanc, offset, sizeof (vlanc));
2515             offset += sizeof (vlanc);
2516
2517             break;
2518         default:
2519             break;
2520     }
2521     return offset;
2522 }
2523
2524 /* dissect an sflow v5 counters sample */
2525 static void
2526 dissect_sflow_5_counters_sample(tvbuff_t *tvb, proto_tree *tree, gint offset, proto_item *parent) {
2527     struct sflow_5_counters_sample_header counters_header;
2528     guint32 i;
2529
2530     /* grab the flow header.  This will remain in network byte
2531        order, so must convert each item before use */
2532     tvb_memcpy(tvb, (guint8 *) & counters_header, offset, sizeof (counters_header));
2533     proto_tree_add_text(tree, tvb, offset, 4, "Sequence number: %u", g_ntohl(counters_header.sequence_number));
2534     proto_item_append_text(parent, ", seq %u", g_ntohl(counters_header.sequence_number));
2535     offset += 4;
2536     proto_tree_add_text(tree, tvb, offset, 4, "Source ID type: %u", g_ntohl(counters_header.source_id) >> 24);
2537     proto_tree_add_text(tree, tvb, offset, 4, "Source ID index: %u", g_ntohl(counters_header.source_id) & 0x00ffffff);
2538     offset += 4;
2539     proto_tree_add_text(tree, tvb, offset, 4, "Counters records: %u", g_ntohl(counters_header.records));
2540     offset += 4;
2541
2542     /* start loop processing counters records
2543      * limit record count to 255 in case corrupted data may cause huge number of loops */
2544     for (i = 0; i < (g_ntohl(counters_header.records)&0x000000ff); i++) {
2545
2546         offset = dissect_sflow_5_counters_record(tvb, tree, offset);
2547
2548     }
2549 }
2550
2551 /* dissect an expanded counters sample */
2552 static void
2553 dissect_sflow_5_expanded_counters_sample(tvbuff_t *tvb, proto_tree *tree, gint offset, proto_item *parent) {
2554     struct sflow_5_expanded_counters_sample_header counters_header;
2555     guint32 i;
2556
2557     /* grab the flow header.  This will remain in network byte
2558        order, so must convert each item before use */
2559     tvb_memcpy(tvb, (guint8 *) & counters_header, offset, sizeof (counters_header));
2560     proto_tree_add_text(tree, tvb, offset, 4, "Sequence number: %u", g_ntohl(counters_header.sequence_number));
2561     proto_item_append_text(parent, ", seq %u", g_ntohl(counters_header.sequence_number));
2562     offset += 4;
2563     proto_tree_add_text(tree, tvb, offset, 4, "Source ID type: %u", g_ntohl(counters_header.source_id_type));
2564     offset += 4;
2565     proto_tree_add_text(tree, tvb, offset, 4, "Source ID index: %u", g_ntohl(counters_header.source_id_index));
2566     offset += 4;
2567     proto_tree_add_text(tree, tvb, offset, 4, "Counters records: %u", g_ntohl(counters_header.records));
2568     offset += 4;
2569
2570     /* start loop processing counters records
2571      * limit record count to 255 in case corrupted data may cause huge number of loops */
2572     for (i = 0; i < (g_ntohl(counters_header.records)&0x000000ff); i++) {
2573
2574         offset = dissect_sflow_5_counters_record(tvb, tree, offset);
2575
2576     }
2577 }
2578
2579 /* Code to dissect the sflow v2/4/5 samples */
2580 static gint
2581 dissect_sflow_245_samples(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, guint32 version) {
2582     proto_tree *sflow_245_sample_tree;
2583     proto_item *ti; /* tree item */
2584     guint32 sample_type, enterprise, format, length;
2585
2586     /* decide what kind of sample it is. */
2587     sample_type = tvb_get_ntohl(tvb, offset);
2588     if (version == 5) {
2589         enterprise = sample_type >> 12;
2590         format = sample_type & 0x00000fff;
2591
2592         if (enterprise == ENTERPRISE_DEFAULT) { /* only accept default enterprise 0 (InMon sFlow) */
2593             ti = proto_tree_add_text(tree, tvb, offset, -1, "%s",
2594                     val_to_str(format, sflow_245_sampletype, "Unknown sample format"));
2595             sflow_245_sample_tree = proto_item_add_subtree(ti, ett_sflow_245_sample);
2596
2597             proto_tree_add_text(sflow_245_sample_tree, tvb, offset, 4, "Enterprise: standard sFlow (%u)", enterprise);
2598             proto_tree_add_item(sflow_245_sample_tree, hf_sflow_245_sampletype, tvb, offset, 4, ENC_BIG_ENDIAN);
2599             offset += 4;
2600
2601             length = tvb_get_ntohl(tvb, offset);
2602             proto_tree_add_item(sflow_245_sample_tree, hf_sflow_5_sample_length, tvb, offset, 4, ENC_BIG_ENDIAN);
2603             offset += 4;
2604
2605             switch (format) {
2606                 case FLOWSAMPLE:
2607                     dissect_sflow_5_flow_sample(tvb, pinfo, sflow_245_sample_tree, offset, ti);
2608                     break;
2609                 case COUNTERSSAMPLE:
2610                     dissect_sflow_5_counters_sample(tvb, sflow_245_sample_tree, offset, ti);
2611                     break;
2612                 case EXPANDED_FLOWSAMPLE:
2613                     dissect_sflow_5_expanded_flow_sample(tvb, pinfo, sflow_245_sample_tree, offset, ti);
2614                     break;
2615                 case EXPANDED_COUNTERSSAMPLE:
2616                     dissect_sflow_5_expanded_counters_sample(tvb, sflow_245_sample_tree, offset, ti);
2617                     break;
2618                 default:
2619                     break;
2620             }
2621             /* Make sure the length doesn't run past the end of the packet */
2622             tvb_ensure_bytes_exist(tvb, offset, length);
2623             /* current offset points to sample length field, which is 4 bytes from the beginning of the packet*/
2624             offset += length;
2625         } else { /* unknown enterprise format, what to do?? */
2626             ti = proto_tree_add_text(tree, tvb, offset, -1, "%s", "Unknown enterprise format");
2627             sflow_245_sample_tree = proto_item_add_subtree(ti, ett_sflow_245_sample);
2628             proto_tree_add_text(sflow_245_sample_tree, tvb, offset, -1, "Enterprise: Non-standard sFlow (%u)", enterprise);
2629         }
2630
2631     } else { /* version 2 or 4 */
2632         ti = proto_tree_add_text(tree, tvb, offset, -1, "%s",
2633                 val_to_str(sample_type, sflow_245_sampletype, "Unknown sample type"));
2634         sflow_245_sample_tree = proto_item_add_subtree(ti, ett_sflow_245_sample);
2635
2636         proto_tree_add_item(sflow_245_sample_tree, hf_sflow_245_sampletype, tvb, offset, 4, ENC_BIG_ENDIAN);
2637         offset += 4;
2638
2639         switch (sample_type) {
2640             case FLOWSAMPLE:
2641                 offset = dissect_sflow_24_flow_sample(tvb, pinfo, sflow_245_sample_tree, offset, ti);
2642                 break;
2643             case COUNTERSSAMPLE:
2644                 offset = dissect_sflow_24_counters_sample(tvb, sflow_245_sample_tree, offset, ti);
2645                 break;
2646             default:
2647                 break;
2648         }
2649     }
2650     proto_item_set_end(ti, tvb, offset);
2651
2652     return offset;
2653 }
2654
2655 /* Code to actually dissect the packets */
2656 static int
2657 dissect_sflow_245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
2658
2659     /* Set up structures needed to add the protocol subtree and manage it */
2660     proto_item *ti;
2661     proto_tree *sflow_245_tree;
2662     guint32 version, sub_agent_id, seqnum;
2663     struct sflow_address_details addr_details;
2664     struct sflow_address_type addr_type = {hf_sflow_agent_address_v4, hf_sflow_agent_address_v6};
2665
2666     guint32 numsamples;
2667     volatile guint offset = 0;
2668     guint i = 0;
2669
2670     /* Make entries in Protocol column and Info column on summary display */
2671     col_set_str(pinfo->cinfo, COL_PROTOCOL, "sFlow");
2672
2673
2674     /* create display subtree for the protocol */
2675     ti = proto_tree_add_item(tree, proto_sflow, tvb, 0, -1, ENC_NA);
2676
2677     sflow_245_tree = proto_item_add_subtree(ti, ett_sflow_245);
2678
2679     version = tvb_get_ntohl(tvb, offset);
2680     col_add_fstr(pinfo->cinfo, COL_INFO, "V%u", version);
2681     proto_tree_add_item(sflow_245_tree, hf_sflow_version, tvb, offset, 4, ENC_BIG_ENDIAN);
2682     offset += 4;
2683
2684     offset = dissect_sflow_245_address_type(tvb, sflow_245_tree, offset,
2685                                             &addr_type, &addr_details);
2686     switch (addr_details.addr_type) {
2687         case ADDR_TYPE_IPV4:
2688             col_append_fstr(pinfo->cinfo, COL_INFO, ", agent %s", ip_to_str(addr_details.agent_address.v4));
2689             break;
2690         case ADDR_TYPE_IPV6:
2691             col_append_fstr(pinfo->cinfo, COL_INFO, ", agent %s",
2692                     ip6_to_str((struct e_in6_addr *) addr_details.agent_address.v6));
2693             break;
2694         default:
2695             /* unknown address.  this will cause a malformed packet.  */
2696             return 0;
2697     }
2698
2699     if (version == 5) {
2700         sub_agent_id = tvb_get_ntohl(tvb, offset);
2701         col_append_fstr(pinfo->cinfo, COL_INFO, ", sub-agent ID %u", sub_agent_id);
2702         proto_tree_add_uint(sflow_245_tree, hf_sflow_5_sub_agent_id, tvb, offset, 4, sub_agent_id);
2703         offset += 4;
2704     }
2705     seqnum = tvb_get_ntohl(tvb, offset);
2706     col_append_fstr(pinfo->cinfo, COL_INFO, ", seq %u", seqnum);
2707     proto_tree_add_uint(sflow_245_tree, hf_sflow_245_seqnum, tvb, offset, 4, seqnum);
2708     offset += 4;
2709     proto_tree_add_item(sflow_245_tree, hf_sflow_245_sysuptime, tvb, offset, 4, ENC_BIG_ENDIAN);
2710     offset += 4;
2711     numsamples = tvb_get_ntohl(tvb, offset);
2712     col_append_fstr(pinfo->cinfo, COL_INFO, ", %u samples", numsamples);
2713     proto_tree_add_uint(sflow_245_tree, hf_sflow_245_numsamples, tvb, offset, 4, numsamples);
2714     offset += 4;
2715
2716     /* Ok, we're now at the end of the sflow_245 datagram header;
2717      * everything from here out should be samples. Loop over
2718      * the expected number of samples, and pass them to the appropriate
2719      * dissectors.
2720      */
2721
2722     /* limit number of samples to 255 to avoid huge number of loops
2723      * caused by corrupted data */
2724     for (i = 0; i < (numsamples & 0x000000ff); i++) {
2725
2726         offset = dissect_sflow_245_samples(tvb, pinfo, sflow_245_tree, offset, version);
2727     }
2728
2729     return tvb_length(tvb);
2730 }
2731
2732 /* Register the protocol with Wireshark */
2733
2734 /* this format is require because a script is used to build the C function
2735    that calls all the protocol registration.
2736  */
2737
2738 void
2739 proto_register_sflow(void) {
2740
2741     module_t *sflow_245_module;
2742
2743     /* Setup list of header fields  See Section 1.6.1 for details*/
2744     static hf_register_info hf[] = {
2745         { &hf_sflow_version,
2746             { "Datagram version", "sflow_245.version",
2747                 FT_UINT32, BASE_DEC, NULL, 0x0,
2748                 "sFlow datagram version", HFILL}},
2749         { &hf_sflow_agent_address_v4,
2750             { "Agent address", "sflow_245.agent",
2751                 FT_IPv4, BASE_NONE, NULL, 0x0,
2752                 "sFlow Agent IP address", HFILL}},
2753         { &hf_sflow_agent_address_v6,
2754             { "Agent address", "sflow_245.agent.v6",
2755                 FT_IPv6, BASE_NONE, NULL, 0x0,
2756                 "sFlow Agent IPv6 address", HFILL}},
2757         { &hf_sflow_5_sub_agent_id,
2758             { "Sub-agent ID", "sflow_245.sub_agent_id",
2759                 FT_UINT32, BASE_DEC, NULL, 0x0,
2760                 "sFlow sub-agent ID", HFILL}},
2761         { &hf_sflow_5_sample_length,
2762             { "Sample length (byte)", "sflow_5.sample_length",
2763                 FT_UINT32, BASE_DEC, NULL, 0x0,
2764                 "sFlow sample length", HFILL}},
2765         { &hf_sflow_5_flow_data_length,
2766             { "Flow data length (byte)", "sflow_5.flow_data_length",
2767                 FT_UINT32, BASE_DEC, NULL, 0x0,
2768                 "sFlow flow data length", HFILL}},
2769         { &hf_sflow_5_counters_data_length,
2770             { "Counters data length (byte)", "sflow_5.counter_data_length",
2771                 FT_UINT32, BASE_DEC, NULL, 0x0,
2772                 "sFlow counters data length", HFILL}},
2773         { &hf_sflow_245_seqnum,
2774             { "Sequence number", "sflow_245.sequence_number",
2775                 FT_UINT32, BASE_DEC, NULL, 0x0,
2776                 "sFlow datagram sequence number", HFILL}},
2777         { &hf_sflow_245_sysuptime,
2778             { "SysUptime", "sflow_245.sysuptime",
2779                 FT_UINT32, BASE_DEC, NULL, 0x0,
2780                 "System Uptime", HFILL}},
2781         { &hf_sflow_245_numsamples,
2782             { "NumSamples", "sflow_245.numsamples",
2783                 FT_UINT32, BASE_DEC, NULL, 0x0,
2784                 "Number of samples in sFlow datagram", HFILL}},
2785         { &hf_sflow_245_sampletype,
2786             { "sFlow sample type", "sflow_245.sampletype",
2787                 FT_UINT32, BASE_DEC, VALS(sflow_245_sampletype), 0x0,
2788                 "Type of sFlow sample", HFILL}},
2789         { &hf_sflow_5_ieee80211_version,
2790             { "Version", "sflow_245.ieee80211_version",
2791                 FT_UINT32, BASE_DEC, VALS(sflow_5_ieee80211_versions), 0x0,
2792                 "IEEE 802.11 Version", HFILL}},
2793         { &hf_sflow_245_ipv4_precedence_type,
2794             { "Precedence", "sflow_245.ipv4_precedence_type",
2795                 FT_UINT8, BASE_DEC, VALS(sflow_245_ipv4_precedence_types), 0x0,
2796                 "IPv4 Precedence Type", HFILL}},
2797         { &hf_sflow_5_flow_record_format,
2798             { "Format", "sflow_245.flow_record_format",
2799                 FT_UINT32, BASE_DEC, VALS(sflow_5_flow_record_type), 0x0,
2800                 "Format of sFlow flow record", HFILL}},
2801         { &hf_sflow_5_counters_record_format,
2802             { "Format", "sflow_245.counters_record_format",
2803                 FT_UINT32, BASE_DEC, VALS(sflow_5_counters_record_type), 0x0,
2804                 "Format of sFlow counters record", HFILL}},
2805         { &hf_sflow_245_header_protocol,
2806             { "Header protocol", "sflow_245.header_protocol",
2807                 FT_UINT32, BASE_DEC, VALS(sflow_245_header_protocol), 0x0,
2808                 "Protocol of sampled header", HFILL}},
2809         { &hf_sflow_245_header,
2810             { "Header of sampled packet", "sflow_245.header",
2811                 FT_BYTES, BASE_NONE, NULL, 0x0,
2812                 "Data from sampled header", HFILL}},
2813         { &hf_sflow_245_packet_information_type,
2814             { "Sample type", "sflow_245.packet_information_type",
2815                 FT_UINT32, BASE_DEC, VALS(sflow_245_packet_information_type), 0x0,
2816                 "Type of sampled information", HFILL}},
2817         { &hf_sflow_245_extended_information_type,
2818             { "Extended information type", "sflow_245.extended_information_type",
2819                 FT_UINT32, BASE_DEC, VALS(sflow_245_extended_data_types), 0x0,
2820                 "Type of extended information", HFILL}},
2821         { &hf_sflow_245_vlan_in,
2822             { "Incoming 802.1Q VLAN", "sflow_245.vlan.in",
2823                 FT_UINT32, BASE_DEC, NULL, 0x0,
2824                 "Incoming VLAN ID", HFILL}},
2825         { &hf_sflow_245_vlan_out,
2826             { "Outgoing 802.1Q VLAN", "sflow_245.vlan.out",
2827                 FT_UINT32, BASE_DEC, NULL, 0x0,
2828                 "Outgoing VLAN ID", HFILL}},
2829         { &hf_sflow_245_pri_in,
2830             { "Incoming 802.1p priority", "sflow_245.pri.in",
2831                 FT_UINT32, BASE_DEC, NULL, 0x0,
2832                 NULL, HFILL}},
2833         { &hf_sflow_245_pri_out,
2834             { "Outgoing 802.1p priority", "sflow_245.pri.out",
2835                 FT_UINT32, BASE_DEC, NULL, 0x0,
2836                 NULL, HFILL}},
2837         { &hf_sflow_245_nexthop_v4,
2838             { "Next hop", "sflow_245.nexthop",
2839                 FT_IPv4, BASE_NONE, NULL, 0x0,
2840                 "Next hop address", HFILL}},
2841         { &hf_sflow_245_ipv4_src,
2842             { "Source IP address", "sflow_245.ipv4_src",
2843                 FT_IPv4, BASE_NONE, NULL, 0x0,
2844                 "Source IPv4 address", HFILL}},
2845         { &hf_sflow_245_ipv4_dst,
2846             { "Destination IP address", "sflow_245.ipv4_dst",
2847                 FT_IPv4, BASE_NONE, NULL, 0x0,
2848                 "Destination IPv4 address", HFILL}},
2849         { &hf_sflow_245_nexthop_v6,
2850             { "Next hop", "sflow_245.nexthop",
2851                 FT_IPv6, BASE_NONE, NULL, 0x0,
2852                 "Next hop address", HFILL}},
2853         { &hf_sflow_245_ipv6_src,
2854             { "Source IP address", "sflow_245.ipv6_src",
2855                 FT_IPv6, BASE_NONE, NULL, 0x0,
2856                 "Source IPv6 address", HFILL}},
2857         { &hf_sflow_245_ipv6_dst,
2858             { "Destination IP address", "sflow_245.ipv6_dst",
2859                 FT_IPv6, BASE_NONE, NULL, 0x0,
2860                 "Destination IPv6 address", HFILL}},
2861         { &hf_sflow_245_nexthop_src_mask,
2862             { "Next hop source mask", "sflow_245.nexthop.src_mask",
2863                 FT_UINT32, BASE_DEC, NULL, 0x0,
2864                 "Next hop source mask bits", HFILL}},
2865         { &hf_sflow_245_nexthop_dst_mask,
2866             { "Next hop destination mask", "sflow_245.nexthop.dst_mask",
2867                 FT_UINT32, BASE_DEC, NULL, 0x0,
2868                 "Next hop destination mask bits", HFILL}},
2869         { &hf_sflow_245_ifindex,
2870             { "Interface index", "sflow_245.ifindex",
2871                 FT_UINT32, BASE_DEC, NULL, 0x0,
2872                 NULL, HFILL}},
2873         { &hf_sflow_245_as,
2874             { "AS Router", "sflow_245.as",
2875                 FT_UINT32, BASE_DEC, NULL, 0x0,
2876                 "Autonomous System of Router", HFILL}},
2877         { &hf_sflow_245_src_as,
2878             { "AS Source", "sflow_245.srcAS",
2879                 FT_UINT32, BASE_DEC, NULL, 0x0,
2880                 "Autonomous System of Source", HFILL}},
2881         { &hf_sflow_245_src_peer_as,
2882             { "AS Peer", "sflow_245.peerAS",
2883                 FT_UINT32, BASE_DEC, NULL, 0x0,
2884                 "Autonomous System of Peer", HFILL}},
2885         { &hf_sflow_245_dst_as_entries,
2886             { "AS Destinations", "sflow_245.dstASentries",
2887                 FT_UINT32, BASE_DEC, NULL, 0x0,
2888                 "Autonomous System destinations", HFILL}},
2889         { &hf_sflow_245_dst_as,
2890             { "AS Destination", "sflow_245.dstAS",
2891                 FT_UINT32, BASE_DEC, NULL, 0x0,
2892                 "Autonomous System destination", HFILL}},
2893         /* Needed for sFlow >= 4.  If I had a capture to test... */
2894         { &hf_sflow_245_community_entries,
2895             { "Gateway Communities", "sflow_245.communityEntries",
2896                 FT_UINT32, BASE_DEC, NULL, 0x0,
2897                 NULL, HFILL}},
2898         { &hf_sflow_245_community,
2899             { "Gateway Community", "sflow_245.community",
2900                 FT_UINT32, BASE_DEC, NULL, 0x0,
2901                 "Gateway Communities", HFILL}},
2902         { &hf_sflow_245_localpref,
2903             { "localpref", "sflow_245.localpref",
2904                 FT_UINT32, BASE_DEC, NULL, 0x0,
2905                 "Local preferences of AS route", HFILL}},
2906         /**/
2907         { &hf_sflow_245_iftype,
2908             { "Interface Type", "sflow_245.iftype",
2909                 FT_UINT32, BASE_DEC, NULL, 0x0,
2910                 NULL, HFILL}},
2911         { &hf_sflow_245_ifspeed,
2912             { "Interface Speed", "sflow_245.ifspeed",
2913                 FT_UINT64, BASE_DEC, NULL, 0x0,
2914                 NULL, HFILL}},
2915         { &hf_sflow_245_ifdirection,
2916             { "Interface Direction", "sflow_245.ifdirection",
2917                 FT_UINT32, BASE_DEC, NULL, 0x0,
2918                 NULL, HFILL}},
2919         { &hf_sflow_245_ifstatus,
2920             { "Interface Status", "sflow_245.ifstatus",
2921                 FT_UINT32, BASE_DEC, NULL, 0x0,
2922                 NULL, HFILL}},
2923         { &hf_sflow_245_ifinoct,
2924             { "Input Octets", "sflow_245.ifinoct",
2925                 FT_UINT64, BASE_DEC, NULL, 0x0,
2926                 "Interface Input Octets", HFILL}},
2927         { &hf_sflow_245_ifinpkt,
2928             { "Input Packets", "sflow_245.ifinpkt",
2929                 FT_UINT32, BASE_DEC, NULL, 0x0,
2930                 "Interface Input Packets", HFILL}},
2931         { &hf_sflow_245_ifinmcast,
2932             { "Input Multicast Packets", "sflow_245.ifinmcast",
2933                 FT_UINT32, BASE_DEC, NULL, 0x0,
2934                 "Interface Input Multicast Packets", HFILL}},
2935         { &hf_sflow_245_ifinbcast,
2936             { "Input Broadcast Packets", "sflow_245.ifinbcast",
2937                 FT_UINT32, BASE_DEC, NULL, 0x0,
2938                 "Interface Input Broadcast Packets", HFILL}},
2939         { &hf_sflow_245_ifindisc,
2940             { "Input Discarded Packets", "sflow_245.ifindisc",
2941                 FT_UINT32, BASE_DEC, NULL, 0x0,
2942                 "Interface Input Discarded Packets", HFILL}},
2943         { &hf_sflow_245_ifinerr,
2944             { "Input Errors", "sflow_245.ifinerr",
2945                 FT_UINT32, BASE_DEC, NULL, 0x0,
2946                 "Interface Input Errors", HFILL}},
2947         { &hf_sflow_245_ifinunk,
2948             { "Input Unknown Protocol Packets", "sflow_245.ifinunk",
2949                 FT_UINT32, BASE_DEC, NULL, 0x0,
2950                 "Interface Input Unknown Protocol Packets", HFILL}},
2951         { &hf_sflow_245_ifoutoct,
2952             { "Output Octets", "sflow_245.ifoutoct",
2953                 FT_UINT64, BASE_DEC, NULL, 0x0,
2954                 "Outterface Output Octets", HFILL}},
2955         { &hf_sflow_245_ifoutpkt,
2956             { "Output Packets", "sflow_245.ifoutpkt",
2957                 FT_UINT32, BASE_DEC, NULL, 0x0,
2958                 "Interface Output Packets", HFILL}},
2959         { &hf_sflow_245_ifoutmcast,
2960             { "Output Multicast Packets", "sflow_245.ifoutmcast",
2961                 FT_UINT32, BASE_DEC, NULL, 0x0,
2962                 "Interface Output Multicast Packets", HFILL}},
2963         { &hf_sflow_245_ifoutbcast,
2964             { "Output Broadcast Packets", "sflow_245.ifoutbcast",
2965                 FT_UINT32, BASE_DEC, NULL, 0x0,
2966                 "Interface Output Broadcast Packets", HFILL}},
2967         { &hf_sflow_245_ifoutdisc,
2968             { "Output Discarded Packets", "sflow_245.ifoutdisc",
2969                 FT_UINT32, BASE_DEC, NULL, 0x0,
2970                 "Interface Output Discarded Packets", HFILL}},
2971         { &hf_sflow_245_ifouterr,
2972             { "Output Errors", "sflow_245.ifouterr",
2973                 FT_UINT32, BASE_DEC, NULL, 0x0,
2974                 "Interface Output Errors", HFILL}},
2975         { &hf_sflow_245_ifpromisc,
2976             { "Promiscuous Mode", "sflow_245.ifpromisc",
2977                 FT_UINT32, BASE_DEC, NULL, 0x0,
2978                 "Interface Promiscuous Mode", HFILL}},
2979         { &hf_sflow_245_dot3StatsAlignmentErrors,
2980             { "Alignment Errors", "sflow_245.dot3StatsAlignmentErrors",
2981                 FT_UINT32, BASE_DEC, NULL, 0x0,
2982                 "dot3 Stats Alignment Errors", HFILL}},
2983         { &hf_sflow_245_dot3StatsFCSErrors,
2984             { "FCS Errors", "sflow_245.dot3StatsFCSErrors",
2985                 FT_UINT32, BASE_DEC, NULL, 0x0,
2986                 "dot3 Stats FCS Errors", HFILL}},
2987         { &hf_sflow_245_dot3StatsSingleCollisionFrames,
2988             { "Single Collision Frames", "sflow_245.dot3StatsSingleCollisionFrames",
2989                 FT_UINT32, BASE_DEC, NULL, 0x0,
2990                 "dot3 Stats Single Collision Frames", HFILL}},
2991         { &hf_sflow_245_dot3StatsMultipleCollisionFrames,
2992             { "Multiple Collision Frames", "sflow_245.dot3StatsMultipleCollisionFrames",
2993                 FT_UINT32, BASE_DEC, NULL, 0x0,
2994                 "dot3 Stats Multiple Collision Frames", HFILL}},
2995         { &hf_sflow_245_dot3StatsSQETestErrors,
2996             { "SQE Test Errors", "sflow_245.dot3StatsSQETestErrors",
2997                 FT_UINT32, BASE_DEC, NULL, 0x0,
2998                 "dot3 Stats SQE Test Errors", HFILL}},
2999         { &hf_sflow_245_dot3StatsDeferredTransmissions,
3000             { "Deferred Transmissions", "sflow_245.dot3StatsDeferredTransmissions",
3001                 FT_UINT32, BASE_DEC, NULL, 0x0,
3002                 "dot3 Stats Deferred Transmissions", HFILL}},
3003         { &hf_sflow_245_dot3StatsLateCollisions,
3004             { "Late Collisions", "sflow_245.dot3StatsLateCollisions",
3005                 FT_UINT32, BASE_DEC, NULL, 0x0,
3006                 "dot3 Stats Late Collisions", HFILL}},
3007         { &hf_sflow_245_dot3StatsExcessiveCollisions,
3008             { "Excessive Collisions", "sflow_245.dot3StatsExcessiveCollisions",
3009                 FT_UINT32, BASE_DEC, NULL, 0x0,
3010                 "dot3 Stats Excessive Collisions", HFILL}},
3011         { &hf_sflow_245_dot3StatsInternalMacTransmitErrors,
3012             { "Internal Mac Transmit Errors", "sflow_245.dot3StatsInternalMacTransmitErrors",
3013                 FT_UINT32, BASE_DEC, NULL, 0x0,
3014                 "dot3 Stats Internal Mac Transmit Errors", HFILL}},
3015         { &hf_sflow_245_dot3StatsCarrierSenseErrors,
3016             { "Carrier Sense Errors", "sflow_245.dot3StatsCarrierSenseErrors",
3017                 FT_UINT32, BASE_DEC, NULL, 0x0,
3018                 "dot3 Stats Carrier Sense Errors", HFILL}},
3019         { &hf_sflow_245_dot3StatsFrameTooLongs,
3020             { "Frame Too Longs", "sflow_245.dot3StatsFrameTooLongs",
3021                 FT_UINT32, BASE_DEC, NULL, 0x0,
3022                 "dot3 Stats Frame Too Longs", HFILL}},
3023         { &hf_sflow_245_dot3StatsInternalMacReceiveErrors,
3024             { "Internal Mac Receive Errors", "sflow_245.dot3StatsInternalMacReceiveErrors",
3025                 FT_UINT32, BASE_DEC, NULL, 0x0,
3026                 "dot3 Stats Internal Mac Receive Errors", HFILL}},
3027         { &hf_sflow_245_dot3StatsSymbolErrors,
3028             { "Symbol Errors", "sflow_245.dot3StatsSymbolErrors",
3029                 FT_UINT32, BASE_DEC, NULL, 0x0,
3030                 "dot3 Stats Symbol Errors", HFILL}},
3031         { &hf_sflow_245_dot5StatsLineErrors,
3032             { "Line Errors", "sflow_245.dot5StatsLineErrors",
3033                 FT_UINT32, BASE_DEC, NULL, 0x0,
3034                 "dot5 Stats Line Errors", HFILL}},
3035         { &hf_sflow_245_dot5StatsBurstErrors,
3036             { "Burst Errors", "sflow_245.dot5StatsBurstErrors",
3037                 FT_UINT32, BASE_DEC, NULL, 0x0,
3038                 "dot5 Stats Burst Errors", HFILL}},
3039         { &hf_sflow_245_dot5StatsACErrors,
3040             { "AC Errors", "sflow_245.dot5StatsACErrors",
3041                 FT_UINT32, BASE_DEC, NULL, 0x0,
3042                 "dot5 Stats AC Errors", HFILL}},
3043         { &hf_sflow_245_dot5StatsAbortTransErrors,
3044             { "Abort Trans Errors", "sflow_245.dot5StatsAbortTransErrors",
3045                 FT_UINT32, BASE_DEC, NULL, 0x0,
3046                 "dot5 Stats Abort Trans Errors", HFILL}},
3047         { &hf_sflow_245_dot5StatsInternalErrors,
3048             { "Internal Errors", "sflow_245.dot5StatsInternalErrors",
3049                 FT_UINT32, BASE_DEC, NULL, 0x0,
3050                 "dot5 Stats Internal Errors", HFILL}},
3051         { &hf_sflow_245_dot5StatsLostFrameErrors,
3052             { "Lost Frame Errors", "sflow_245.dot5StatsLostFrameErrors",
3053                 FT_UINT32, BASE_DEC, NULL, 0x0,
3054                 "dot5 Stats Lost Frame Errors", HFILL}},
3055         { &hf_sflow_245_dot5StatsReceiveCongestions,
3056             { "Receive Congestions", "sflow_245.dot5StatsReceiveCongestions",
3057                 FT_UINT32, BASE_DEC, NULL, 0x0,
3058                 "dot5 Stats Receive Congestions", HFILL}},
3059         { &hf_sflow_245_dot5StatsFrameCopiedErrors,
3060             { "Frame Copied Errors", "sflow_245.dot5StatsFrameCopiedErrors",
3061                 FT_UINT32, BASE_DEC, NULL, 0x0,
3062                 "dot5 Stats Frame Copied Errors", HFILL}},
3063         { &hf_sflow_245_dot5StatsTokenErrors,
3064             { "Token Errors", "sflow_245.dot5StatsTokenErrors",
3065                 FT_UINT32, BASE_DEC, NULL, 0x0,
3066                 "dot5 Stats Token Errors", HFILL}},
3067         { &hf_sflow_245_dot5StatsSoftErrors,
3068             { "Soft Errors", "sflow_245.dot5StatsSoftErrors",
3069                 FT_UINT32, BASE_DEC, NULL, 0x0,
3070                 "dot5 Stats Soft Errors", HFILL}},
3071         { &hf_sflow_245_dot5StatsHardErrors,
3072             { "Hard Errors", "sflow_245.dot5StatsHardErrors",
3073                 FT_UINT32, BASE_DEC, NULL, 0x0,
3074                 "dot5 Stats Hard Errors", HFILL}},
3075         { &hf_sflow_245_dot5StatsSignalLoss,
3076             { "Signal Loss", "sflow_245.dot5StatsSignalLoss",
3077                 FT_UINT32, BASE_DEC, NULL, 0x0,
3078                 "dot5 Stats Signal Loss", HFILL}},
3079         { &hf_sflow_245_dot5StatsTransmitBeacons,
3080             { "Transmit Beacons", "sflow_245.dot5StatsTransmitBeacons",
3081                 FT_UINT32, BASE_DEC, NULL, 0x0,
3082                 "dot5 Stats Transmit Beacons", HFILL}},
3083         { &hf_sflow_245_dot5StatsRecoveries,
3084             { "Recoveries", "sflow_245.dot5StatsRecoveries",
3085                 FT_UINT32, BASE_DEC, NULL, 0x0,
3086                 "dot5 Stats Recoveries", HFILL}},
3087         { &hf_sflow_245_dot5StatsLobeWires,
3088             { "Lobe Wires", "sflow_245.dot5StatsLobeWires",
3089                 FT_UINT32, BASE_DEC, NULL, 0x0,
3090                 "dot5 Stats Lobe Wires", HFILL}},
3091         { &hf_sflow_245_dot5StatsRemoves,
3092             { "Removes", "sflow_245.dot5StatsRemoves",
3093                 FT_UINT32, BASE_DEC, NULL, 0x0,
3094                 "dot5 Stats Removes", HFILL}},
3095         { &hf_sflow_245_dot5StatsSingles,
3096             { "Singles", "sflow_245.dot5StatsSingles",
3097                 FT_UINT32, BASE_DEC, NULL, 0x0,
3098                 "dot5 Stats Singles", HFILL}},
3099         { &hf_sflow_245_dot5StatsFreqErrors,
3100             { "Freq Errors", "sflow_245.dot5StatsFreqErrors",
3101                 FT_UINT32, BASE_DEC, NULL, 0x0,
3102                 "dot5 Stats Freq Errors", HFILL}},
3103         { &hf_sflow_245_dot12InHighPriorityFrames,
3104             { "In High Priority Frames", "sflow_245.dot12InHighPriorityFrames",
3105                 FT_UINT32, BASE_DEC, NULL, 0x0,
3106                 "dot12 Input High Priority Frames", HFILL}},
3107         { &hf_sflow_245_dot12InHighPriorityOctets,
3108             { "In High Priority Octets", "sflow_245.dot12InHighPriorityOctets",
3109                 FT_UINT64, BASE_DEC, NULL, 0x0,
3110                 "dot12 Input High Priority Octets", HFILL}},
3111         { &hf_sflow_245_dot12InNormPriorityFrames,
3112             { "In Normal Priority Frames", "sflow_245.dot12InNormPriorityFrames",
3113                 FT_UINT32, BASE_DEC, NULL, 0x0,
3114                 "dot12 Input Normal Priority Frames", HFILL}},
3115         { &hf_sflow_245_dot12InNormPriorityOctets,
3116             { "In Normal Priority Octets", "sflow_245.dot12InNormPriorityOctets",
3117                 FT_UINT64, BASE_DEC, NULL, 0x0,
3118                 "dot12 Input Normal Priority Octets", HFILL}},
3119         { &hf_sflow_245_dot12InIPMErrors,
3120             { "In IPM Errors", "sflow_245.dot12InIPMErrors",
3121                 FT_UINT32, BASE_DEC, NULL, 0x0,
3122                 "dot12 Input IPM Errors", HFILL}},
3123         { &hf_sflow_245_dot12InOversizeFrameErrors,
3124             { "In Oversize Frame Errors", "sflow_245.dot12InOversizeFrameErrors",
3125                 FT_UINT32, BASE_DEC, NULL, 0x0,
3126                 "dot12 Input Oversize Frame Errors", HFILL}},
3127         { &hf_sflow_245_dot12InDataErrors,
3128             { "In Data Errors", "sflow_245.dot12InDataErrors",
3129                 FT_UINT32, BASE_DEC, NULL, 0x0,
3130                 "dot12 Input Data Errors", HFILL}},
3131         { &hf_sflow_245_dot12InNullAddressedFrames,
3132             { "In Null Addressed Frames", "sflow_245.dot12InNullAddressedFrames",
3133                 FT_UINT32, BASE_DEC, NULL, 0x0,
3134                 "dot12 Input Null Addressed Frames", HFILL}},
3135         { &hf_sflow_245_dot12OutHighPriorityFrames,
3136             { "Out High Priority Frames", "sflow_245.dot12OutHighPriorityFrames",
3137                 FT_UINT32, BASE_DEC, NULL, 0x0,
3138                 "dot12 Output High Priority Frames", HFILL}},
3139         { &hf_sflow_245_dot12OutHighPriorityOctets,
3140             { "Out High Priority Octets", "sflow_245.dot12OutHighPriorityOctets",
3141                 FT_UINT64, BASE_DEC, NULL, 0x0,
3142                 "dot12 Out High Priority Octets", HFILL}},
3143         { &hf_sflow_245_dot12TransitionIntoTrainings,
3144             { "Transition Into Trainings", "sflow_245.dot12TransitionIntoTrainings",
3145                 FT_UINT32, BASE_DEC, NULL, 0x0,
3146                 "dot12 Transition Into Trainings", HFILL}},
3147         { &hf_sflow_245_dot12HCInHighPriorityOctets,
3148             { "HC In High Priority Octets", "sflow_245.dot12HCInHighPriorityOctets",
3149                 FT_UINT64, BASE_DEC, NULL, 0x0,
3150                 "dot12 HC Input High Priority Octets", HFILL}},
3151         { &hf_sflow_245_dot12HCInNormPriorityOctets,
3152             { "HC In Normal Priority Octets", "sflow_245.dot12HCInNormPriorityOctets",
3153                 FT_UINT64, BASE_DEC, NULL, 0x0,
3154                 "dot12 HC Input Normal Priority Octets", HFILL}},
3155         { &hf_sflow_245_dot12HCOutHighPriorityOctets,
3156             { "HC Out High Priority Octets", "sflow_245.dot12HCOutHighPriorityOctets",
3157                 FT_UINT64, BASE_DEC, NULL, 0x0,
3158                 "dot12 HC Output High Priority Octets", HFILL}},
3159         { &hf_sflow_245_vlan_id,
3160             { "VLAN ID", "sflow_245.vlan_id",
3161                 FT_UINT32, BASE_DEC, NULL, 0x0,
3162                 NULL, HFILL}},
3163         { &hf_sflow_245_octets,
3164             { "Octets", "sflow_245.octets",
3165                 FT_UINT64, BASE_DEC, NULL, 0x0,
3166                 NULL, HFILL}},
3167         { &hf_sflow_245_ucastPkts,
3168             { "Unicast Packets", "sflow_245.ucastPkts",
3169                 FT_UINT32, BASE_DEC, NULL, 0x0,
3170                 NULL, HFILL}},
3171         { &hf_sflow_245_multicastPkts,
3172             { "Multicast Packets", "sflow_245.multicastPkts",
3173                 FT_UINT32, BASE_DEC, NULL, 0x0,
3174                 NULL, HFILL}},
3175         { &hf_sflow_245_broadcastPkts,
3176             { "Broadcast Packets", "sflow_245.broadcastPkts",
3177                 FT_UINT32, BASE_DEC, NULL, 0x0,
3178                 NULL, HFILL}},
3179         { &hf_sflow_245_discards,
3180             { "Discards", "sflow_245.discards",
3181                 FT_UINT32, BASE_DEC, NULL, 0x0,
3182                 NULL, HFILL}},
3183         { &hf_sflow_5_dot11TransmittedFragmentCount,
3184             { "Transmitted Fragment Count", "sflow_5.dot11TransmittedFragmentCount",
3185                 FT_UINT32, BASE_DEC, NULL, 0x0,
3186                 NULL, HFILL}},
3187         { &hf_sflow_5_dot11MulticastTransmittedFrameCount,
3188             { "Multicast Transmitted Frame Count", "sflow_5.dot11MulticastTransmittedFrameCount",
3189                 FT_UINT32, BASE_DEC, NULL, 0x0,
3190                 NULL, HFILL}},
3191         { &hf_sflow_5_dot11FailedCount,
3192             { "Failed Count", "sflow_5.dot11FailedCount",
3193                 FT_UINT32, BASE_DEC, NULL, 0x0,
3194                 NULL, HFILL}},
3195         { &hf_sflow_5_dot11RetryCount,
3196             { "Retry Count", "sflow_5.dot11RetryCount",
3197                 FT_UINT32, BASE_DEC, NULL, 0x0,
3198                 NULL, HFILL}},
3199         { &hf_sflow_5_dot11MultipleRetryCount,
3200             { "Multiple Retry Count", "sflow_5.dot11MultipleRetryCount",
3201                 FT_UINT32, BASE_DEC, NULL, 0x0,
3202                 NULL, HFILL}},
3203         { &hf_sflow_5_dot11FrameDuplicateCount,
3204             { "Frame Duplicate Count", "sflow_5.dot11FrameDuplicateCount",
3205                 FT_UINT32, BASE_DEC, NULL, 0x0,
3206                 NULL, HFILL}},
3207         { &hf_sflow_5_dot11RTSSuccessCount,
3208             { "RTS Success Count", "sflow_5.dot11RTSSuccessCount",
3209                 FT_UINT32, BASE_DEC, NULL, 0x0,
3210                 NULL, HFILL}},
3211         { &hf_sflow_5_dot11RTSFailureCount,
3212             { "Failure Count", "sflow_5.dot11RTSFailureCount",
3213                 FT_UINT32, BASE_DEC, NULL, 0x0,
3214                 NULL, HFILL}},
3215         { &hf_sflow_5_dot11ACKFailureCount,
3216             { "ACK Failure Count", "sflow_5.dot11ACKFailureCount",
3217                 FT_UINT32, BASE_DEC, NULL, 0x0,
3218                 NULL, HFILL}},
3219         { &hf_sflow_5_dot11ReceivedFragmentCount,
3220             { "Received Fragment Count", "sflow_5.dot11ReceivedFragmentCount",
3221                 FT_UINT32, BASE_DEC, NULL, 0x0,
3222                 NULL, HFILL}},
3223         { &hf_sflow_5_dot11MulticastReceivedFrameCount,
3224             { "Multicast Received Frame Count", "sflow_5.dot11MulticastReceivedFrameCount",
3225                 FT_UINT32, BASE_DEC, NULL, 0x0,
3226                 NULL, HFILL}},
3227         { &hf_sflow_5_dot11FCSErrorCount,
3228             { "FCS Error Count", "sflow_5.dot11FCSErrorCount",
3229                 FT_UINT32, BASE_DEC, NULL, 0x0,
3230                 NULL, HFILL}},
3231         { &hf_sflow_5_dot11TransmittedFrameCount,
3232             { "Transmitted Frame Count", "sflow_5.dot11TransmittedFrameCount",
3233                 FT_UINT32, BASE_DEC, NULL, 0x0,
3234                 NULL, HFILL}},
3235         { &hf_sflow_5_dot11WEPUndecryptableCount,
3236             { "WEP Undecryptable Count", "sflow_5.dot11WEPUndecryptableCount",
3237                 FT_UINT32, BASE_DEC, NULL, 0x0,
3238                 NULL, HFILL}},
3239         { &hf_sflow_5_dot11QoSDiscardedFragmentCount,
3240             { "QoS Discarded Fragment Count", "sflow_5.dot11QoSDiscardedFragmentCount",
3241                 FT_UINT32, BASE_DEC, NULL, 0x0,
3242                 NULL, HFILL}},
3243         { &hf_sflow_5_dot11AssociatedStationCount,
3244             { "Associated Station Count", "sflow_5.dot11AssociatedStationCount",
3245                 FT_UINT32, BASE_DEC, NULL, 0x0,
3246                 NULL, HFILL}},
3247         { &hf_sflow_5_dot11QoSCFPollsReceivedCount,
3248             { "QoS CF Polls Received Count", "sflow_5.dot11QoSCFPollsReceivedCount",
3249                 FT_UINT32, BASE_DEC, NULL, 0x0,
3250                 NULL, HFILL}},
3251         { &hf_sflow_5_dot11QoSCFPollsUnusedCount,
3252             { "QoS CF Polls Unused Count", "sflow_5.dot11QoSCFPollsUnusedCount",
3253                 FT_UINT32, BASE_DEC, NULL, 0x0,
3254                 NULL, HFILL}},
3255         { &hf_sflow_5_dot11QoSCFPollsUnusableCount,
3256             { "QoS CF Polls Unusable Count", "sflow_5.dot11QoSCFPollsUnusableCount",
3257                 FT_UINT32, BASE_DEC, NULL, 0x0,
3258                 NULL, HFILL}},
3259         { &hf_sflow_5_dot11QoSCFPollsLostCount,
3260             { "QoS CF Polls Lost Count", "sflow_5.dot11QoSCFPollsLostCount",
3261                 FT_UINT32, BASE_DEC, NULL, 0x0,
3262                 NULL, HFILL}},
3263         { &hf_sflow_5_cpu_5s,
3264             { "5s CPU Load (100 = 1%)", "sflow_5.cpu_5s",
3265                 FT_UINT32, BASE_DEC, NULL, 0x0,
3266                 "Average CPU Load Over 5 Seconds (100 = 1%)", HFILL}},
3267         { &hf_sflow_5_cpu_1m,
3268             { "1m CPU Load (100 = 1%)", "sflow_5.cpu_1m",
3269                 FT_UINT32, BASE_DEC, NULL, 0x0,
3270                 "Average CPU Load Over 1 Minute (100 = 1%)", HFILL}},
3271         { &hf_sflow_5_cpu_5m,
3272             { "5m CPU Load (100 = 1%)", "sflow_5.cpu_5m",
3273                 FT_UINT32, BASE_DEC, NULL, 0x0,
3274                 "Average CPU Load Over 5 Minutes (100 = 1%)", HFILL}},
3275         { &hf_sflow_5_total_memory,
3276             { "Total Memory", "sflow_5.total_memory",
3277                 FT_UINT64, BASE_DEC, NULL, 0x0,
3278                 NULL, HFILL}},
3279         { &hf_sflow_5_free_memory,
3280             { "Free Memory", "sflow_5.free_memory",
3281                 FT_UINT64, BASE_DEC, NULL, 0x0,
3282                 NULL, HFILL}},
3283         { &hf_sflow_5_elapsed_time,
3284             { "Elapsed Time (ms)", "sflow_5.elapsed_time",
3285                 FT_UINT32, BASE_DEC, NULL, 0x0,
3286                 "Elapsed Time in ms", HFILL}},
3287         { &hf_sflow_5_on_channel_time,
3288             { "On Channel (ms)", "sflow_5.on_channel_time",
3289                 FT_UINT32, BASE_DEC, NULL, 0x0,
3290                 "Time in ms Spent on Channel", HFILL}},
3291         { &hf_sflow_5_on_channel_busy_time,
3292             { "On Channel Busy (ms)", "sflow_5.channel_busy_time",
3293                 FT_UINT32, BASE_DEC, NULL, 0x0,
3294                 "Time in ms Spent on Channel and Busy", HFILL}},
3295     };
3296
3297     /* Setup protocol subtree array */
3298     static gint * ett[] = {
3299         &ett_sflow_245,
3300         &ett_sflow_245_sample,
3301         &ett_sflow_5_flow_record,
3302         &ett_sflow_5_counters_record,
3303         &ett_sflow_5_mpls_in_label_stack,
3304         &ett_sflow_5_mpls_out_label_stack,
3305         &ett_sflow_245_extended_data,
3306         &ett_sflow_245_gw_as_dst,
3307         &ett_sflow_245_gw_as_dst_seg,
3308         &ett_sflow_245_gw_community,
3309         &ett_sflow_245_sampled_header,
3310     };
3311
3312     /* Register the protocol name and description */
3313     proto_sflow = proto_register_protocol(
3314             "InMon sFlow", /* name       */
3315             "sFlow", /* short name */
3316             "sflow" /* abbrev     */
3317             );
3318
3319     /* Required function calls to register the header fields and subtrees used */
3320     proto_register_field_array(proto_sflow, hf, array_length(hf));
3321     proto_register_subtree_array(ett, array_length(ett));
3322
3323     /* Register our configuration options for sFlow */
3324     sflow_245_module = prefs_register_protocol(proto_sflow, proto_reg_handoff_sflow_245);
3325
3326     /* Set default Neflow port(s) */
3327     range_convert_str(&global_sflow_ports, SFLOW_UDP_PORTS, MAX_UDP_PORT);
3328
3329     prefs_register_obsolete_preference(sflow_245_module, "udp.port");
3330
3331     prefs_register_range_preference(sflow_245_module, "ports",
3332             "sFlow UDP Port(s)",
3333             "Set the port(s) for sFlow messages"
3334             " (default: " SFLOW_UDP_PORTS ")",
3335             &global_sflow_ports, MAX_UDP_PORT);
3336
3337     /*
3338        If I use a filter like "ip.src == 10.1.1.1" this will, in
3339        addition to the usual suspects, find every sFlow packet
3340        where *any* of the payload headers contain 10.1.1.1 as a
3341        src addr.  I think this may not be the desired behavior.
3342        It can certainly be confusing since the ip.src being found
3343        is buried about 3 subtrees deep and the subtrees might be
3344        under any one of the sampled (payload) header trees. It is
3345        certainly not quickly obvious why the filter matched.
3346      */
3347     prefs_register_bool_preference(sflow_245_module, "enable_dissection",
3348             "Dissect data in sampled headers",
3349             "Enabling dissection makes it easy to view protocol details in each of the sampled headers.  Disabling dissection may reduce noise caused when display filters match the contents of any sampled header(s).",
3350             &global_dissect_samp_headers);
3351     /*
3352        It is not clear to me that it *ever* makes sense to enable
3353        this option.  However, it was previously the default
3354        behavior so I'll leave it as an option if someone thinks
3355        they have a use for it.
3356      */
3357     prefs_register_bool_preference(sflow_245_module, "enable_analysis",
3358             "Analyze data in sampled IP headers",
3359             "This option only makes sense if dissection of sampled headers is enabled and probably not even then.",
3360             &global_analyze_samp_ip_headers);
3361 }
3362
3363
3364 static void
3365 sflow_245_delete_callback(guint32 port) {
3366     if (port) {
3367         dissector_delete_uint("udp.port", port, sflow_handle);
3368     }
3369 }
3370
3371 static void
3372 sflow_245_add_callback(guint32 port) {
3373     if (port) {
3374         dissector_add_uint("udp.port", port, sflow_handle);
3375     }
3376 }
3377
3378 void
3379 proto_reg_handoff_sflow_245(void) {
3380     static range_t *sflow_ports;
3381     static gboolean sflow_245_prefs_initialized = FALSE;
3382
3383     if (!sflow_245_prefs_initialized) {
3384         sflow_handle = new_create_dissector_handle(dissect_sflow_245, proto_sflow);
3385         data_handle = find_dissector("data");
3386         sflow_245_prefs_initialized = TRUE;
3387     } else {
3388         range_foreach(sflow_ports, sflow_245_delete_callback);
3389         g_free(sflow_ports);
3390     }
3391
3392     sflow_ports = range_copy(global_sflow_ports);
3393     range_foreach(sflow_ports, sflow_245_add_callback);
3394
3395     /*dissector_handle_t sflow_245_handle;*/
3396
3397     /*
3398      * XXX - should this be done with a dissector table?
3399      */
3400
3401     if (global_dissect_samp_headers) {
3402         eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
3403         tr_handle = find_dissector("tr");
3404         fddi_handle = find_dissector("fddi");
3405         fr_handle = find_dissector("fr");
3406         x25_handle = find_dissector("x.25");
3407         ppp_hdlc_handle = find_dissector("ppp_hdlc");
3408 #if 0
3409         smds_handle = find_dissector("smds");
3410 #else
3411         /* We don't have an SMDS dissector yet
3412          *
3413          *Switched multimegabit data service (SMDS) was a connectionless service
3414          *used to connect LANs, MANs and WANs to exchange data. SMDS was based on
3415          *the IEEE 802.6 DQDB standard. SMDS fragmented its datagrams into smaller
3416          *"cells" for transport, and can be viewed as a technological precursor of ATM.
3417          */
3418         smds_handle = data_handle;
3419 #endif
3420 #if 0
3421         aal5_handle = find_dissector("aal5");
3422 #else
3423         /*
3424          * No AAL5 (ATM Adaptation Layer 5) dissector available.
3425          * What does the packet look like?  An AAL5 PDU?  Where
3426          * do the VPI/VCI pair appear, if anywhere?
3427          */
3428         aal5_handle = data_handle;
3429 #endif
3430         ipv4_handle = find_dissector("ip");
3431         ipv6_handle = find_dissector("ipv6");
3432         mpls_handle = find_dissector("mpls");
3433 #if 0
3434         pos_handle = find_dissector("pos");
3435 #else
3436         /* wireshark does not have POS dissector yet */
3437         pos_handle = data_handle;
3438 #endif
3439         ieee80211_mac_handle = find_dissector("wlan");
3440 #if 0
3441         ieee80211_ampdu_handle = find_dissector("ampdu");
3442         ieee80211_amsdu_subframe_handle = find_dissector("wlan_aggregate");
3443 #else
3444         /* No handles for these */
3445         ieee80211_ampdu_handle = data_handle;
3446         ieee80211_amsdu_subframe_handle = data_handle;
3447 #endif
3448     } else {
3449         eth_withoutfcs_handle = data_handle;
3450         tr_handle = data_handle;
3451         fddi_handle = data_handle;
3452         fr_handle = data_handle;
3453         x25_handle = data_handle;
3454         ppp_hdlc_handle = data_handle;
3455         smds_handle = data_handle;
3456         aal5_handle = data_handle;
3457         ipv4_handle = data_handle;
3458         ipv6_handle = data_handle;
3459         mpls_handle = data_handle;
3460         pos_handle = data_handle;
3461         ieee80211_mac_handle = data_handle;
3462         ieee80211_ampdu_handle = data_handle;
3463         ieee80211_amsdu_subframe_handle = data_handle;
3464     }
3465
3466 }
3467
3468
3469 /*
3470  * Editor modelines
3471  *
3472  * Local Variables:
3473  * c-basic-offset: 4
3474  * tab-width: 4
3475  * indent-tabs-mode: nil
3476  * End:
3477  *
3478  * ex: set shiftwidth=4 tabstop=4 noexpandtab
3479  * :indentSize=4:tabSize=4:noTabs=true:
3480  */