1190203Srpaulo/* 2190203Srpaulo * Copyright (c) 1998-2007 The TCPDUMP project 3190203Srpaulo * 4190203Srpaulo * Redistribution and use in source and binary forms, with or without 5190203Srpaulo * modification, are permitted provided that: (1) source code 6190203Srpaulo * distributions retain the above copyright notice and this paragraph 7190203Srpaulo * in its entirety, and (2) distributions including binary code include 8190203Srpaulo * the above copyright notice and this paragraph in its entirety in 9190203Srpaulo * the documentation or other materials provided with the distribution. 10190203Srpaulo * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 11190203Srpaulo * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 12190203Srpaulo * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 13190203Srpaulo * FOR A PARTICULAR PURPOSE. 14190203Srpaulo * 15190203Srpaulo * The SFLOW protocol as per http://www.sflow.org/developers/specifications.php 16190203Srpaulo * 17190203Srpaulo * Original code by Carles Kishimoto <carles.kishimoto@gmail.com> 18236192Sdelphij * 19236192Sdelphij * Expansion and refactoring by Rick Jones <rick.jones2@hp.com> 20190203Srpaulo */ 21190203Srpaulo 22190203Srpaulo#ifndef lint 23190203Srpaulostatic const char rcsid[] _U_ = 24190203Srpaulo"@(#) $Header: /tcpdump/master/tcpdump/print-sflow.c,v 1.1 2007-08-08 17:20:58 hannes Exp $"; 25190203Srpaulo#endif 26190203Srpaulo 27190203Srpaulo#ifdef HAVE_CONFIG_H 28190203Srpaulo#include "config.h" 29190203Srpaulo#endif 30190203Srpaulo 31190203Srpaulo#include <tcpdump-stdinc.h> 32190203Srpaulo 33190203Srpaulo#include <stdio.h> 34190203Srpaulo#include <stdlib.h> 35190203Srpaulo#include <string.h> 36190203Srpaulo 37190203Srpaulo#include "interface.h" 38190203Srpaulo#include "extract.h" 39190203Srpaulo#include "addrtoname.h" 40190203Srpaulo 41190203Srpaulo/* 42190203Srpaulo * sFlow datagram 43190203Srpaulo * 44190203Srpaulo * 0 1 2 3 45190203Srpaulo * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 46190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 47190203Srpaulo * | Sflow version (2,4,5) | 48190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 49190203Srpaulo * | IP version (1 for IPv4 | 2 for IPv6) | 50190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51190203Srpaulo * | IP Address AGENT (4 or 16 bytes) | 52190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 53190203Srpaulo * | Sub agent ID | 54190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 55190203Srpaulo * | Datagram sequence number | 56190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 57190203Srpaulo * | Switch uptime in ms | 58190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 59190203Srpaulo * | num samples in datagram | 60190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 61190203Srpaulo * 62190203Srpaulo */ 63190203Srpaulo 64190203Srpaulostruct sflow_datagram_t { 65190203Srpaulo u_int8_t version[4]; 66190203Srpaulo u_int8_t ip_version[4]; 67190203Srpaulo u_int8_t agent[4]; 68190203Srpaulo u_int8_t agent_id[4]; 69190203Srpaulo u_int8_t seqnum[4]; 70190203Srpaulo u_int8_t uptime[4]; 71190203Srpaulo u_int8_t samples[4]; 72190203Srpaulo}; 73190203Srpaulo 74190203Srpaulostruct sflow_sample_header { 75190203Srpaulo u_int8_t format[4]; 76190203Srpaulo u_int8_t len[4]; 77190203Srpaulo}; 78190203Srpaulo 79190203Srpaulo#define SFLOW_FLOW_SAMPLE 1 80190203Srpaulo#define SFLOW_COUNTER_SAMPLE 2 81190203Srpaulo#define SFLOW_EXPANDED_FLOW_SAMPLE 3 82190203Srpaulo#define SFLOW_EXPANDED_COUNTER_SAMPLE 4 83190203Srpaulo 84190203Srpaulostatic const struct tok sflow_format_values[] = { 85190203Srpaulo { SFLOW_FLOW_SAMPLE, "flow sample" }, 86190203Srpaulo { SFLOW_COUNTER_SAMPLE, "counter sample" }, 87190203Srpaulo { SFLOW_EXPANDED_FLOW_SAMPLE, "expanded flow sample" }, 88190203Srpaulo { SFLOW_EXPANDED_COUNTER_SAMPLE, "expanded counter sample" }, 89190203Srpaulo { 0, NULL} 90190203Srpaulo}; 91190203Srpaulo 92236192Sdelphijstruct sflow_flow_sample_t { 93236192Sdelphij u_int8_t seqnum[4]; 94236192Sdelphij u_int8_t typesource[4]; 95236192Sdelphij u_int8_t rate[4]; 96236192Sdelphij u_int8_t pool[4]; 97236192Sdelphij u_int8_t drops[4]; 98236192Sdelphij u_int8_t in_interface[4]; 99236192Sdelphij u_int8_t out_interface[4]; 100236192Sdelphij u_int8_t records[4]; 101236192Sdelphij 102236192Sdelphij}; 103236192Sdelphij 104190203Srpaulostruct sflow_expanded_flow_sample_t { 105190203Srpaulo u_int8_t seqnum[4]; 106190203Srpaulo u_int8_t type[4]; 107190203Srpaulo u_int8_t index[4]; 108190203Srpaulo u_int8_t rate[4]; 109190203Srpaulo u_int8_t pool[4]; 110190203Srpaulo u_int8_t drops[4]; 111190203Srpaulo u_int8_t in_interface_format[4]; 112190203Srpaulo u_int8_t in_interface_value[4]; 113190203Srpaulo u_int8_t out_interface_format[4]; 114190203Srpaulo u_int8_t out_interface_value[4]; 115190203Srpaulo u_int8_t records[4]; 116190203Srpaulo}; 117190203Srpaulo 118190203Srpaulo#define SFLOW_FLOW_RAW_PACKET 1 119190203Srpaulo#define SFLOW_FLOW_ETHERNET_FRAME 2 120190203Srpaulo#define SFLOW_FLOW_IPV4_DATA 3 121190203Srpaulo#define SFLOW_FLOW_IPV6_DATA 4 122190203Srpaulo#define SFLOW_FLOW_EXTENDED_SWITCH_DATA 1001 123190203Srpaulo#define SFLOW_FLOW_EXTENDED_ROUTER_DATA 1002 124190203Srpaulo#define SFLOW_FLOW_EXTENDED_GATEWAY_DATA 1003 125190203Srpaulo#define SFLOW_FLOW_EXTENDED_USER_DATA 1004 126190203Srpaulo#define SFLOW_FLOW_EXTENDED_URL_DATA 1005 127190203Srpaulo#define SFLOW_FLOW_EXTENDED_MPLS_DATA 1006 128190203Srpaulo#define SFLOW_FLOW_EXTENDED_NAT_DATA 1007 129190203Srpaulo#define SFLOW_FLOW_EXTENDED_MPLS_TUNNEL 1008 130190203Srpaulo#define SFLOW_FLOW_EXTENDED_MPLS_VC 1009 131190203Srpaulo#define SFLOW_FLOW_EXTENDED_MPLS_FEC 1010 132190203Srpaulo#define SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC 1011 133190203Srpaulo#define SFLOW_FLOW_EXTENDED_VLAN_TUNNEL 1012 134190203Srpaulo 135190203Srpaulostatic const struct tok sflow_flow_type_values[] = { 136190203Srpaulo { SFLOW_FLOW_RAW_PACKET, "Raw packet"}, 137190203Srpaulo { SFLOW_FLOW_ETHERNET_FRAME, "Ethernet frame"}, 138190203Srpaulo { SFLOW_FLOW_IPV4_DATA, "IPv4 Data"}, 139190203Srpaulo { SFLOW_FLOW_IPV6_DATA, "IPv6 Data"}, 140190203Srpaulo { SFLOW_FLOW_EXTENDED_SWITCH_DATA, "Extended Switch data"}, 141190203Srpaulo { SFLOW_FLOW_EXTENDED_ROUTER_DATA, "Extended Router data"}, 142190203Srpaulo { SFLOW_FLOW_EXTENDED_GATEWAY_DATA, "Extended Gateway data"}, 143190203Srpaulo { SFLOW_FLOW_EXTENDED_USER_DATA, "Extended User data"}, 144190203Srpaulo { SFLOW_FLOW_EXTENDED_URL_DATA, "Extended URL data"}, 145190203Srpaulo { SFLOW_FLOW_EXTENDED_MPLS_DATA, "Extended MPLS data"}, 146190203Srpaulo { SFLOW_FLOW_EXTENDED_NAT_DATA, "Extended NAT data"}, 147190203Srpaulo { SFLOW_FLOW_EXTENDED_MPLS_TUNNEL, "Extended MPLS tunnel"}, 148190203Srpaulo { SFLOW_FLOW_EXTENDED_MPLS_VC, "Extended MPLS VC"}, 149190203Srpaulo { SFLOW_FLOW_EXTENDED_MPLS_FEC, "Extended MPLS FEC"}, 150190203Srpaulo { SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC, "Extended MPLS LVP FEC"}, 151190203Srpaulo { SFLOW_FLOW_EXTENDED_VLAN_TUNNEL, "Extended VLAN Tunnel"}, 152190203Srpaulo { 0, NULL} 153190203Srpaulo}; 154190203Srpaulo 155190203Srpaulo#define SFLOW_HEADER_PROTOCOL_ETHERNET 1 156190203Srpaulo#define SFLOW_HEADER_PROTOCOL_IPV4 11 157190203Srpaulo#define SFLOW_HEADER_PROTOCOL_IPV6 12 158190203Srpaulo 159190203Srpaulostatic const struct tok sflow_flow_raw_protocol_values[] = { 160190203Srpaulo { SFLOW_HEADER_PROTOCOL_ETHERNET, "Ethernet"}, 161190203Srpaulo { SFLOW_HEADER_PROTOCOL_IPV4, "IPv4"}, 162190203Srpaulo { SFLOW_HEADER_PROTOCOL_IPV6, "IPv6"}, 163190203Srpaulo { 0, NULL} 164190203Srpaulo}; 165190203Srpaulo 166190203Srpaulostruct sflow_expanded_flow_raw_t { 167190203Srpaulo u_int8_t protocol[4]; 168190203Srpaulo u_int8_t length[4]; 169190203Srpaulo u_int8_t stripped_bytes[4]; 170190203Srpaulo u_int8_t header_size[4]; 171190203Srpaulo}; 172190203Srpaulo 173236192Sdelphijstruct sflow_ethernet_frame_t { 174236192Sdelphij u_int8_t length[4]; 175236192Sdelphij u_int8_t src_mac[8]; 176236192Sdelphij u_int8_t dst_mac[8]; 177236192Sdelphij u_int8_t type[4]; 178236192Sdelphij}; 179236192Sdelphij 180236192Sdelphijstruct sflow_extended_switch_data_t { 181236192Sdelphij u_int8_t src_vlan[4]; 182236192Sdelphij u_int8_t src_pri[4]; 183236192Sdelphij u_int8_t dst_vlan[4]; 184236192Sdelphij u_int8_t dst_pri[4]; 185236192Sdelphij}; 186236192Sdelphij 187236192Sdelphijstruct sflow_counter_record_t { 188236192Sdelphij u_int8_t format[4]; 189236192Sdelphij u_int8_t length[4]; 190236192Sdelphij}; 191236192Sdelphij 192236192Sdelphijstruct sflow_flow_record_t { 193236192Sdelphij u_int8_t format[4]; 194236192Sdelphij u_int8_t length[4]; 195236192Sdelphij}; 196236192Sdelphij 197236192Sdelphijstruct sflow_counter_sample_t { 198236192Sdelphij u_int8_t seqnum[4]; 199236192Sdelphij u_int8_t typesource[4]; 200236192Sdelphij u_int8_t records[4]; 201236192Sdelphij}; 202236192Sdelphij 203190203Srpaulostruct sflow_expanded_counter_sample_t { 204190203Srpaulo u_int8_t seqnum[4]; 205190203Srpaulo u_int8_t type[4]; 206190203Srpaulo u_int8_t index[4]; 207190203Srpaulo u_int8_t records[4]; 208190203Srpaulo}; 209190203Srpaulo 210190203Srpaulo#define SFLOW_COUNTER_GENERIC 1 211190203Srpaulo#define SFLOW_COUNTER_ETHERNET 2 212190203Srpaulo#define SFLOW_COUNTER_TOKEN_RING 3 213190203Srpaulo#define SFLOW_COUNTER_BASEVG 4 214190203Srpaulo#define SFLOW_COUNTER_VLAN 5 215190203Srpaulo#define SFLOW_COUNTER_PROCESSOR 1001 216190203Srpaulo 217190203Srpaulostatic const struct tok sflow_counter_type_values[] = { 218190203Srpaulo { SFLOW_COUNTER_GENERIC, "Generic counter"}, 219190203Srpaulo { SFLOW_COUNTER_ETHERNET, "Ethernet counter"}, 220190203Srpaulo { SFLOW_COUNTER_TOKEN_RING, "Token ring counter"}, 221190203Srpaulo { SFLOW_COUNTER_BASEVG, "100 BaseVG counter"}, 222190203Srpaulo { SFLOW_COUNTER_VLAN, "Vlan counter"}, 223190203Srpaulo { SFLOW_COUNTER_PROCESSOR, "Processor counter"}, 224190203Srpaulo { 0, NULL} 225190203Srpaulo}; 226190203Srpaulo 227190203Srpaulo#define SFLOW_IFACE_DIRECTION_UNKNOWN 0 228190203Srpaulo#define SFLOW_IFACE_DIRECTION_FULLDUPLEX 1 229190203Srpaulo#define SFLOW_IFACE_DIRECTION_HALFDUPLEX 2 230190203Srpaulo#define SFLOW_IFACE_DIRECTION_IN 3 231190203Srpaulo#define SFLOW_IFACE_DIRECTION_OUT 4 232190203Srpaulo 233190203Srpaulostatic const struct tok sflow_iface_direction_values[] = { 234190203Srpaulo { SFLOW_IFACE_DIRECTION_UNKNOWN, "unknown"}, 235190203Srpaulo { SFLOW_IFACE_DIRECTION_FULLDUPLEX, "full-duplex"}, 236190203Srpaulo { SFLOW_IFACE_DIRECTION_HALFDUPLEX, "half-duplex"}, 237190203Srpaulo { SFLOW_IFACE_DIRECTION_IN, "in"}, 238190203Srpaulo { SFLOW_IFACE_DIRECTION_OUT, "out"}, 239190203Srpaulo { 0, NULL} 240190203Srpaulo}; 241190203Srpaulo 242190203Srpaulostruct sflow_generic_counter_t { 243190203Srpaulo u_int8_t ifindex[4]; 244190203Srpaulo u_int8_t iftype[4]; 245190203Srpaulo u_int8_t ifspeed[8]; 246190203Srpaulo u_int8_t ifdirection[4]; 247190203Srpaulo u_int8_t ifstatus[4]; 248190203Srpaulo u_int8_t ifinoctets[8]; 249190203Srpaulo u_int8_t ifinunicastpkts[4]; 250190203Srpaulo u_int8_t ifinmulticastpkts[4]; 251190203Srpaulo u_int8_t ifinbroadcastpkts[4]; 252190203Srpaulo u_int8_t ifindiscards[4]; 253190203Srpaulo u_int8_t ifinerrors[4]; 254190203Srpaulo u_int8_t ifinunkownprotos[4]; 255190203Srpaulo u_int8_t ifoutoctets[8]; 256190203Srpaulo u_int8_t ifoutunicastpkts[4]; 257190203Srpaulo u_int8_t ifoutmulticastpkts[4]; 258190203Srpaulo u_int8_t ifoutbroadcastpkts[4]; 259190203Srpaulo u_int8_t ifoutdiscards[4]; 260190203Srpaulo u_int8_t ifouterrors[4]; 261190203Srpaulo u_int8_t ifpromiscmode[4]; 262190203Srpaulo}; 263190203Srpaulo 264190203Srpaulostruct sflow_ethernet_counter_t { 265190203Srpaulo u_int8_t alignerrors[4]; 266190203Srpaulo u_int8_t fcserrors[4]; 267190203Srpaulo u_int8_t single_collision_frames[4]; 268190203Srpaulo u_int8_t multiple_collision_frames[4]; 269190203Srpaulo u_int8_t test_errors[4]; 270190203Srpaulo u_int8_t deferred_transmissions[4]; 271190203Srpaulo u_int8_t late_collisions[4]; 272190203Srpaulo u_int8_t excessive_collisions[4]; 273190203Srpaulo u_int8_t mac_transmit_errors[4]; 274190203Srpaulo u_int8_t carrier_sense_errors[4]; 275190203Srpaulo u_int8_t frame_too_longs[4]; 276190203Srpaulo u_int8_t mac_receive_errors[4]; 277190203Srpaulo u_int8_t symbol_errors[4]; 278190203Srpaulo}; 279190203Srpaulo 280190203Srpaulostruct sflow_100basevg_counter_t { 281190203Srpaulo u_int8_t in_highpriority_frames[4]; 282190203Srpaulo u_int8_t in_highpriority_octets[8]; 283190203Srpaulo u_int8_t in_normpriority_frames[4]; 284190203Srpaulo u_int8_t in_normpriority_octets[8]; 285190203Srpaulo u_int8_t in_ipmerrors[4]; 286190203Srpaulo u_int8_t in_oversized[4]; 287190203Srpaulo u_int8_t in_data_errors[4]; 288190203Srpaulo u_int8_t in_null_addressed_frames[4]; 289190203Srpaulo u_int8_t out_highpriority_frames[4]; 290190203Srpaulo u_int8_t out_highpriority_octets[8]; 291190203Srpaulo u_int8_t transitioninto_frames[4]; 292190203Srpaulo u_int8_t hc_in_highpriority_octets[8]; 293190203Srpaulo u_int8_t hc_in_normpriority_octets[8]; 294190203Srpaulo u_int8_t hc_out_highpriority_octets[8]; 295190203Srpaulo}; 296190203Srpaulo 297190203Srpaulostruct sflow_vlan_counter_t { 298190203Srpaulo u_int8_t vlan_id[4]; 299190203Srpaulo u_int8_t octets[8]; 300190203Srpaulo u_int8_t unicast_pkt[4]; 301190203Srpaulo u_int8_t multicast_pkt[4]; 302190203Srpaulo u_int8_t broadcast_pkt[4]; 303190203Srpaulo u_int8_t discards[4]; 304190203Srpaulo}; 305190203Srpaulo 306236192Sdelphijstatic int 307236192Sdelphijprint_sflow_counter_generic(const u_char *pointer, u_int len) { 308190203Srpaulo 309190203Srpaulo const struct sflow_generic_counter_t *sflow_gen_counter; 310236192Sdelphij 311236192Sdelphij if (len < sizeof(struct sflow_generic_counter_t)) 312236192Sdelphij return 1; 313236192Sdelphij 314236192Sdelphij 315236192Sdelphij sflow_gen_counter = (const struct sflow_generic_counter_t *)pointer; 316236192Sdelphij printf("\n\t ifindex %u, iftype %u, ifspeed %" PRIu64 ", ifdirection %u (%s)", 317236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifindex), 318236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->iftype), 319236192Sdelphij EXTRACT_64BITS(sflow_gen_counter->ifspeed), 320236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifdirection), 321236192Sdelphij tok2str(sflow_iface_direction_values, "Unknown", 322236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifdirection))); 323236192Sdelphij printf("\n\t ifstatus %u, adminstatus: %s, operstatus: %s", 324236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifstatus), 325236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifstatus)&1 ? "up" : "down", 326236192Sdelphij (EXTRACT_32BITS(sflow_gen_counter->ifstatus)>>1)&1 ? "up" : "down"); 327236192Sdelphij printf("\n\t In octets %" PRIu64 328236192Sdelphij ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u", 329236192Sdelphij EXTRACT_64BITS(sflow_gen_counter->ifinoctets), 330236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifinunicastpkts), 331236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifinmulticastpkts), 332236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifinbroadcastpkts), 333236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifindiscards)); 334236192Sdelphij printf("\n\t In errors %u, unknown protos %u", 335236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifinerrors), 336236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifinunkownprotos)); 337236192Sdelphij printf("\n\t Out octets %" PRIu64 338236192Sdelphij ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u", 339236192Sdelphij EXTRACT_64BITS(sflow_gen_counter->ifoutoctets), 340236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifoutunicastpkts), 341236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifoutmulticastpkts), 342236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifoutbroadcastpkts), 343236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifoutdiscards)); 344236192Sdelphij printf("\n\t Out errors %u, promisc mode %u", 345236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifouterrors), 346236192Sdelphij EXTRACT_32BITS(sflow_gen_counter->ifpromiscmode)); 347236192Sdelphij 348236192Sdelphij return 0; 349236192Sdelphij} 350236192Sdelphij 351236192Sdelphijstatic int 352236192Sdelphijprint_sflow_counter_ethernet(const u_char *pointer, u_int len){ 353236192Sdelphij 354190203Srpaulo const struct sflow_ethernet_counter_t *sflow_eth_counter; 355236192Sdelphij 356236192Sdelphij if (len < sizeof(struct sflow_ethernet_counter_t)) 357236192Sdelphij return 1; 358236192Sdelphij 359236192Sdelphij sflow_eth_counter = (const struct sflow_ethernet_counter_t *)pointer; 360236192Sdelphij printf("\n\t align errors %u, fcs errors %u, single collision %u, multiple collision %u, test error %u", 361236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->alignerrors), 362236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->fcserrors), 363236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->single_collision_frames), 364236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->multiple_collision_frames), 365236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->test_errors)); 366236192Sdelphij printf("\n\t deferred %u, late collision %u, excessive collision %u, mac trans error %u", 367236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->deferred_transmissions), 368236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->late_collisions), 369236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->excessive_collisions), 370236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->mac_transmit_errors)); 371236192Sdelphij printf("\n\t carrier error %u, frames too long %u, mac receive errors %u, symbol errors %u", 372236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->carrier_sense_errors), 373236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->frame_too_longs), 374236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->mac_receive_errors), 375236192Sdelphij EXTRACT_32BITS(sflow_eth_counter->symbol_errors)); 376236192Sdelphij 377236192Sdelphij return 0; 378236192Sdelphij} 379236192Sdelphij 380236192Sdelphijstatic int 381236192Sdelphijprint_sflow_counter_token_ring(const u_char *pointer _U_, u_int len _U_) { 382236192Sdelphij 383236192Sdelphij return 0; 384236192Sdelphij} 385236192Sdelphij 386236192Sdelphijstatic int 387236192Sdelphijprint_sflow_counter_basevg(const u_char *pointer, u_int len) { 388236192Sdelphij 389190203Srpaulo const struct sflow_100basevg_counter_t *sflow_100basevg_counter; 390236192Sdelphij 391236192Sdelphij if (len < sizeof(struct sflow_100basevg_counter_t)) 392236192Sdelphij return 1; 393236192Sdelphij 394236192Sdelphij sflow_100basevg_counter = (const struct sflow_100basevg_counter_t *)pointer; 395236192Sdelphij printf("\n\t in high prio frames %u, in high prio octets %" PRIu64, 396236192Sdelphij EXTRACT_32BITS(sflow_100basevg_counter->in_highpriority_frames), 397236192Sdelphij EXTRACT_64BITS(sflow_100basevg_counter->in_highpriority_octets)); 398236192Sdelphij printf("\n\t in norm prio frames %u, in norm prio octets %" PRIu64, 399236192Sdelphij EXTRACT_32BITS(sflow_100basevg_counter->in_normpriority_frames), 400236192Sdelphij EXTRACT_64BITS(sflow_100basevg_counter->in_normpriority_octets)); 401236192Sdelphij printf("\n\t in ipm errors %u, oversized %u, in data errors %u, null addressed frames %u", 402236192Sdelphij EXTRACT_32BITS(sflow_100basevg_counter->in_ipmerrors), 403236192Sdelphij EXTRACT_32BITS(sflow_100basevg_counter->in_oversized), 404236192Sdelphij EXTRACT_32BITS(sflow_100basevg_counter->in_data_errors), 405236192Sdelphij EXTRACT_32BITS(sflow_100basevg_counter->in_null_addressed_frames)); 406236192Sdelphij printf("\n\t out high prio frames %u, out high prio octets %" PRIu64 407236192Sdelphij ", trans into frames %u", 408236192Sdelphij EXTRACT_32BITS(sflow_100basevg_counter->out_highpriority_frames), 409236192Sdelphij EXTRACT_64BITS(sflow_100basevg_counter->out_highpriority_octets), 410236192Sdelphij EXTRACT_32BITS(sflow_100basevg_counter->transitioninto_frames)); 411236192Sdelphij printf("\n\t in hc high prio octets %" PRIu64 412236192Sdelphij ", in hc norm prio octets %" PRIu64 413236192Sdelphij ", out hc high prio octets %" PRIu64, 414236192Sdelphij EXTRACT_64BITS(sflow_100basevg_counter->hc_in_highpriority_octets), 415236192Sdelphij EXTRACT_64BITS(sflow_100basevg_counter->hc_in_normpriority_octets), 416236192Sdelphij EXTRACT_64BITS(sflow_100basevg_counter->hc_out_highpriority_octets)); 417236192Sdelphij 418236192Sdelphij return 0; 419236192Sdelphij} 420236192Sdelphij 421236192Sdelphijstatic int 422236192Sdelphijprint_sflow_counter_vlan(const u_char *pointer, u_int len) { 423236192Sdelphij 424190203Srpaulo const struct sflow_vlan_counter_t *sflow_vlan_counter; 425236192Sdelphij 426236192Sdelphij if (len < sizeof(struct sflow_vlan_counter_t)) 427236192Sdelphij return 1; 428236192Sdelphij 429236192Sdelphij sflow_vlan_counter = (const struct sflow_vlan_counter_t *)pointer; 430236192Sdelphij printf("\n\t vlan_id %u, octets %" PRIu64 431236192Sdelphij ", unicast_pkt %u, multicast_pkt %u, broadcast_pkt %u, discards %u", 432236192Sdelphij EXTRACT_32BITS(sflow_vlan_counter->vlan_id), 433236192Sdelphij EXTRACT_64BITS(sflow_vlan_counter->octets), 434236192Sdelphij EXTRACT_32BITS(sflow_vlan_counter->unicast_pkt), 435236192Sdelphij EXTRACT_32BITS(sflow_vlan_counter->multicast_pkt), 436236192Sdelphij EXTRACT_32BITS(sflow_vlan_counter->broadcast_pkt), 437236192Sdelphij EXTRACT_32BITS(sflow_vlan_counter->discards)); 438236192Sdelphij 439236192Sdelphij return 0; 440236192Sdelphij} 441236192Sdelphij 442236192Sdelphijstruct sflow_processor_counter_t { 443236192Sdelphij u_int8_t five_sec_util[4]; 444236192Sdelphij u_int8_t one_min_util[4]; 445236192Sdelphij u_int8_t five_min_util[4]; 446236192Sdelphij u_int8_t total_memory[8]; 447236192Sdelphij u_int8_t free_memory[8]; 448236192Sdelphij}; 449236192Sdelphij 450236192Sdelphijstatic int 451236192Sdelphijprint_sflow_counter_processor(const u_char *pointer, u_int len) { 452236192Sdelphij 453236192Sdelphij const struct sflow_processor_counter_t *sflow_processor_counter; 454236192Sdelphij 455236192Sdelphij if (len < sizeof(struct sflow_processor_counter_t)) 456236192Sdelphij return 1; 457236192Sdelphij 458236192Sdelphij sflow_processor_counter = (const struct sflow_processor_counter_t *)pointer; 459236192Sdelphij printf("\n\t 5sec %u, 1min %u, 5min %u, total_mem %" PRIu64 460236192Sdelphij ", total_mem %" PRIu64, 461236192Sdelphij EXTRACT_32BITS(sflow_processor_counter->five_sec_util), 462236192Sdelphij EXTRACT_32BITS(sflow_processor_counter->one_min_util), 463236192Sdelphij EXTRACT_32BITS(sflow_processor_counter->five_min_util), 464236192Sdelphij EXTRACT_64BITS(sflow_processor_counter->total_memory), 465236192Sdelphij EXTRACT_64BITS(sflow_processor_counter->free_memory)); 466236192Sdelphij 467236192Sdelphij return 0; 468236192Sdelphij} 469236192Sdelphij 470236192Sdelphijstatic int 471236192Sdelphijsflow_print_counter_records(const u_char *pointer, u_int len, u_int records) { 472236192Sdelphij 473236192Sdelphij u_int nrecords; 474190203Srpaulo const u_char *tptr; 475236192Sdelphij u_int tlen; 476236192Sdelphij u_int counter_type; 477236192Sdelphij u_int counter_len; 478236192Sdelphij u_int enterprise; 479236192Sdelphij const struct sflow_counter_record_t *sflow_counter_record; 480236192Sdelphij 481236192Sdelphij nrecords = records; 482236192Sdelphij tptr = pointer; 483236192Sdelphij tlen = len; 484236192Sdelphij 485236192Sdelphij while (nrecords > 0) { 486236192Sdelphij /* do we have the "header?" */ 487236192Sdelphij if (tlen < sizeof(struct sflow_counter_record_t)) 488236192Sdelphij return 1; 489236192Sdelphij sflow_counter_record = (const struct sflow_counter_record_t *)tptr; 490236192Sdelphij 491236192Sdelphij enterprise = EXTRACT_32BITS(sflow_counter_record->format); 492236192Sdelphij counter_type = enterprise & 0x0FFF; 493236192Sdelphij enterprise = enterprise >> 20; 494236192Sdelphij counter_len = EXTRACT_32BITS(sflow_counter_record->length); 495236192Sdelphij printf("\n\t enterprise %u, %s (%u) length %u", 496236192Sdelphij enterprise, 497236192Sdelphij (enterprise == 0) ? tok2str(sflow_counter_type_values,"Unknown",counter_type) : "Unknown", 498236192Sdelphij counter_type, 499236192Sdelphij counter_len); 500236192Sdelphij 501236192Sdelphij tptr += sizeof(struct sflow_counter_record_t); 502236192Sdelphij tlen -= sizeof(struct sflow_counter_record_t); 503236192Sdelphij 504236192Sdelphij if (tlen < counter_len) 505236192Sdelphij return 1; 506236192Sdelphij if (enterprise == 0) { 507236192Sdelphij switch (counter_type) { 508236192Sdelphij case SFLOW_COUNTER_GENERIC: 509236192Sdelphij if (print_sflow_counter_generic(tptr,tlen)) 510236192Sdelphij return 1; 511236192Sdelphij break; 512236192Sdelphij case SFLOW_COUNTER_ETHERNET: 513236192Sdelphij if (print_sflow_counter_ethernet(tptr,tlen)) 514236192Sdelphij return 1; 515236192Sdelphij break; 516236192Sdelphij case SFLOW_COUNTER_TOKEN_RING: 517236192Sdelphij if (print_sflow_counter_token_ring(tptr,tlen)) 518236192Sdelphij return 1; 519236192Sdelphij break; 520236192Sdelphij case SFLOW_COUNTER_BASEVG: 521236192Sdelphij if (print_sflow_counter_basevg(tptr,tlen)) 522236192Sdelphij return 1; 523236192Sdelphij break; 524236192Sdelphij case SFLOW_COUNTER_VLAN: 525236192Sdelphij if (print_sflow_counter_vlan(tptr,tlen)) 526236192Sdelphij return 1; 527236192Sdelphij break; 528236192Sdelphij case SFLOW_COUNTER_PROCESSOR: 529236192Sdelphij if (print_sflow_counter_processor(tptr,tlen)) 530236192Sdelphij return 1; 531236192Sdelphij break; 532236192Sdelphij default: 533236192Sdelphij if (vflag <= 1) 534236192Sdelphij print_unknown_data(tptr, "\n\t\t", counter_len); 535236192Sdelphij break; 536236192Sdelphij } 537236192Sdelphij } 538236192Sdelphij tptr += counter_len; 539236192Sdelphij tlen -= counter_len; 540236192Sdelphij nrecords--; 541236192Sdelphij 542236192Sdelphij } 543236192Sdelphij 544236192Sdelphij return 0; 545236192Sdelphij} 546236192Sdelphij 547236192Sdelphij 548236192Sdelphijstatic int 549236192Sdelphijsflow_print_counter_sample(const u_char *pointer, u_int len) { 550236192Sdelphij 551236192Sdelphij const struct sflow_counter_sample_t *sflow_counter_sample; 552236192Sdelphij u_int nrecords; 553236192Sdelphij u_int typesource; 554236192Sdelphij u_int type; 555236192Sdelphij u_int index; 556236192Sdelphij 557236192Sdelphij 558236192Sdelphij if (len < sizeof(struct sflow_counter_sample_t)) 559236192Sdelphij return 1; 560236192Sdelphij 561236192Sdelphij sflow_counter_sample = (const struct sflow_counter_sample_t *)pointer; 562236192Sdelphij 563236192Sdelphij typesource = EXTRACT_32BITS(sflow_counter_sample->typesource); 564236192Sdelphij nrecords = EXTRACT_32BITS(sflow_counter_sample->records); 565236192Sdelphij type = typesource >> 24; 566236192Sdelphij index = typesource & 0x0FFF; 567236192Sdelphij 568236192Sdelphij printf(" seqnum %u, type %u, idx %u, records %u", 569236192Sdelphij EXTRACT_32BITS(sflow_counter_sample->seqnum), 570236192Sdelphij type, 571236192Sdelphij index, 572236192Sdelphij nrecords); 573236192Sdelphij 574236192Sdelphij return sflow_print_counter_records(pointer + sizeof(struct sflow_counter_sample_t), 575236192Sdelphij len - sizeof(struct sflow_counter_sample_t), 576236192Sdelphij nrecords); 577236192Sdelphij 578236192Sdelphij} 579236192Sdelphij 580236192Sdelphijstatic int 581236192Sdelphijsflow_print_expanded_counter_sample(const u_char *pointer, u_int len) { 582236192Sdelphij 583236192Sdelphij const struct sflow_expanded_counter_sample_t *sflow_expanded_counter_sample; 584236192Sdelphij u_int nrecords; 585236192Sdelphij 586236192Sdelphij 587236192Sdelphij if (len < sizeof(struct sflow_expanded_counter_sample_t)) 588236192Sdelphij return 1; 589236192Sdelphij 590236192Sdelphij sflow_expanded_counter_sample = (const struct sflow_expanded_counter_sample_t *)pointer; 591236192Sdelphij 592236192Sdelphij nrecords = EXTRACT_32BITS(sflow_expanded_counter_sample->records); 593236192Sdelphij 594236192Sdelphij printf(" seqnum %u, type %u, idx %u, records %u", 595236192Sdelphij EXTRACT_32BITS(sflow_expanded_counter_sample->seqnum), 596236192Sdelphij EXTRACT_32BITS(sflow_expanded_counter_sample->type), 597236192Sdelphij EXTRACT_32BITS(sflow_expanded_counter_sample->index), 598236192Sdelphij nrecords); 599236192Sdelphij 600236192Sdelphij return sflow_print_counter_records(pointer + sizeof(struct sflow_expanded_counter_sample_t), 601236192Sdelphij len - sizeof(struct sflow_expanded_counter_sample_t), 602236192Sdelphij nrecords); 603236192Sdelphij 604236192Sdelphij} 605236192Sdelphij 606236192Sdelphijstatic int 607236192Sdelphijprint_sflow_raw_packet(const u_char *pointer, u_int len) { 608236192Sdelphij 609236192Sdelphij const struct sflow_expanded_flow_raw_t *sflow_flow_raw; 610236192Sdelphij 611236192Sdelphij if (len < sizeof(struct sflow_expanded_flow_raw_t)) 612236192Sdelphij return 1; 613236192Sdelphij 614236192Sdelphij sflow_flow_raw = (const struct sflow_expanded_flow_raw_t *)pointer; 615236192Sdelphij printf("\n\t protocol %s (%u), length %u, stripped bytes %u, header_size %u", 616236192Sdelphij tok2str(sflow_flow_raw_protocol_values,"Unknown",EXTRACT_32BITS(sflow_flow_raw->protocol)), 617236192Sdelphij EXTRACT_32BITS(sflow_flow_raw->protocol), 618236192Sdelphij EXTRACT_32BITS(sflow_flow_raw->length), 619236192Sdelphij EXTRACT_32BITS(sflow_flow_raw->stripped_bytes), 620236192Sdelphij EXTRACT_32BITS(sflow_flow_raw->header_size)); 621236192Sdelphij 622236192Sdelphij /* QUESTION - should we attempt to print the raw header itself? 623236192Sdelphij assuming of course there is wnough data present to do so... */ 624236192Sdelphij 625236192Sdelphij return 0; 626236192Sdelphij} 627236192Sdelphij 628236192Sdelphijstatic int 629236192Sdelphijprint_sflow_ethernet_frame(const u_char *pointer, u_int len) { 630236192Sdelphij 631236192Sdelphij const struct sflow_ethernet_frame_t *sflow_ethernet_frame; 632236192Sdelphij 633236192Sdelphij if (len < sizeof(struct sflow_ethernet_frame_t)) 634236192Sdelphij return 1; 635236192Sdelphij 636236192Sdelphij sflow_ethernet_frame = (const struct sflow_ethernet_frame_t *)pointer; 637236192Sdelphij 638236192Sdelphij printf("\n\t frame len %u, type %u", 639236192Sdelphij EXTRACT_32BITS(sflow_ethernet_frame->length), 640236192Sdelphij EXTRACT_32BITS(sflow_ethernet_frame->type)); 641236192Sdelphij 642236192Sdelphij return 0; 643236192Sdelphij} 644236192Sdelphij 645236192Sdelphijstatic int 646236192Sdelphijprint_sflow_extended_switch_data(const u_char *pointer, u_int len) { 647236192Sdelphij 648236192Sdelphij const struct sflow_extended_switch_data_t *sflow_extended_sw_data; 649236192Sdelphij 650236192Sdelphij if (len < sizeof(struct sflow_extended_switch_data_t)) 651236192Sdelphij return 1; 652236192Sdelphij 653236192Sdelphij sflow_extended_sw_data = (const struct sflow_extended_switch_data_t *)pointer; 654236192Sdelphij printf("\n\t src vlan %u, src pri %u, dst vlan %u, dst pri %u", 655236192Sdelphij EXTRACT_32BITS(sflow_extended_sw_data->src_vlan), 656236192Sdelphij EXTRACT_32BITS(sflow_extended_sw_data->src_pri), 657236192Sdelphij EXTRACT_32BITS(sflow_extended_sw_data->dst_vlan), 658236192Sdelphij EXTRACT_32BITS(sflow_extended_sw_data->dst_pri)); 659236192Sdelphij 660236192Sdelphij return 0; 661236192Sdelphij} 662236192Sdelphij 663236192Sdelphijstatic int 664236192Sdelphijsflow_print_flow_records(const u_char *pointer, u_int len, u_int records) { 665236192Sdelphij 666236192Sdelphij u_int nrecords; 667236192Sdelphij const u_char *tptr; 668236192Sdelphij u_int tlen; 669236192Sdelphij u_int flow_type; 670236192Sdelphij u_int enterprise; 671236192Sdelphij u_int flow_len; 672236192Sdelphij const struct sflow_flow_record_t *sflow_flow_record; 673236192Sdelphij 674236192Sdelphij nrecords = records; 675236192Sdelphij tptr = pointer; 676236192Sdelphij tlen = len; 677236192Sdelphij 678236192Sdelphij while (nrecords > 0) { 679236192Sdelphij /* do we have the "header?" */ 680236192Sdelphij if (tlen < sizeof(struct sflow_flow_record_t)) 681236192Sdelphij return 1; 682236192Sdelphij 683236192Sdelphij sflow_flow_record = (const struct sflow_flow_record_t *)tptr; 684236192Sdelphij 685236192Sdelphij /* so, the funky encoding means we cannot blythly mask-off 686236192Sdelphij bits, we must also check the enterprise. */ 687236192Sdelphij 688236192Sdelphij enterprise = EXTRACT_32BITS(sflow_flow_record->format); 689236192Sdelphij flow_type = enterprise & 0x0FFF; 690236192Sdelphij enterprise = enterprise >> 12; 691236192Sdelphij flow_len = EXTRACT_32BITS(sflow_flow_record->length); 692236192Sdelphij printf("\n\t enterprise %u %s (%u) length %u", 693236192Sdelphij enterprise, 694236192Sdelphij (enterprise == 0) ? tok2str(sflow_flow_type_values,"Unknown",flow_type) : "Unknown", 695236192Sdelphij flow_type, 696236192Sdelphij flow_len); 697236192Sdelphij 698236192Sdelphij tptr += sizeof(struct sflow_flow_record_t); 699236192Sdelphij tlen -= sizeof(struct sflow_flow_record_t); 700236192Sdelphij 701236192Sdelphij if (tlen < flow_len) 702236192Sdelphij return 1; 703236192Sdelphij 704236192Sdelphij if (enterprise == 0) { 705236192Sdelphij switch (flow_type) { 706236192Sdelphij case SFLOW_FLOW_RAW_PACKET: 707236192Sdelphij if (print_sflow_raw_packet(tptr,tlen)) 708236192Sdelphij return 1; 709236192Sdelphij break; 710236192Sdelphij case SFLOW_FLOW_EXTENDED_SWITCH_DATA: 711236192Sdelphij if (print_sflow_extended_switch_data(tptr,tlen)) 712236192Sdelphij return 1; 713236192Sdelphij break; 714236192Sdelphij case SFLOW_FLOW_ETHERNET_FRAME: 715236192Sdelphij if (print_sflow_ethernet_frame(tptr,tlen)) 716236192Sdelphij return 1; 717236192Sdelphij break; 718236192Sdelphij /* FIXME these need a decoder */ 719236192Sdelphij case SFLOW_FLOW_IPV4_DATA: 720236192Sdelphij case SFLOW_FLOW_IPV6_DATA: 721236192Sdelphij case SFLOW_FLOW_EXTENDED_ROUTER_DATA: 722236192Sdelphij case SFLOW_FLOW_EXTENDED_GATEWAY_DATA: 723236192Sdelphij case SFLOW_FLOW_EXTENDED_USER_DATA: 724236192Sdelphij case SFLOW_FLOW_EXTENDED_URL_DATA: 725236192Sdelphij case SFLOW_FLOW_EXTENDED_MPLS_DATA: 726236192Sdelphij case SFLOW_FLOW_EXTENDED_NAT_DATA: 727236192Sdelphij case SFLOW_FLOW_EXTENDED_MPLS_TUNNEL: 728236192Sdelphij case SFLOW_FLOW_EXTENDED_MPLS_VC: 729236192Sdelphij case SFLOW_FLOW_EXTENDED_MPLS_FEC: 730236192Sdelphij case SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC: 731236192Sdelphij case SFLOW_FLOW_EXTENDED_VLAN_TUNNEL: 732236192Sdelphij break; 733236192Sdelphij default: 734236192Sdelphij if (vflag <= 1) 735236192Sdelphij print_unknown_data(tptr, "\n\t\t", flow_len); 736236192Sdelphij break; 737236192Sdelphij } 738236192Sdelphij } 739236192Sdelphij tptr += flow_len; 740236192Sdelphij tlen -= flow_len; 741236192Sdelphij nrecords--; 742236192Sdelphij 743236192Sdelphij } 744236192Sdelphij 745236192Sdelphij return 0; 746236192Sdelphij} 747236192Sdelphij 748236192Sdelphijstatic int 749236192Sdelphijsflow_print_flow_sample(const u_char *pointer, u_int len) { 750236192Sdelphij 751236192Sdelphij const struct sflow_flow_sample_t *sflow_flow_sample; 752236192Sdelphij u_int nrecords; 753236192Sdelphij u_int typesource; 754236192Sdelphij u_int type; 755236192Sdelphij u_int index; 756236192Sdelphij 757236192Sdelphij if (len < sizeof(struct sflow_flow_sample_t)) 758236192Sdelphij return 1; 759236192Sdelphij 760236192Sdelphij sflow_flow_sample = (struct sflow_flow_sample_t *)pointer; 761236192Sdelphij 762236192Sdelphij typesource = EXTRACT_32BITS(sflow_flow_sample->typesource); 763236192Sdelphij nrecords = EXTRACT_32BITS(sflow_flow_sample->records); 764236192Sdelphij type = typesource >> 24; 765236192Sdelphij index = typesource & 0x0FFF; 766236192Sdelphij 767236192Sdelphij printf(" seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, input %u output %u records %u", 768236192Sdelphij EXTRACT_32BITS(sflow_flow_sample->seqnum), 769236192Sdelphij type, 770236192Sdelphij index, 771236192Sdelphij EXTRACT_32BITS(sflow_flow_sample->rate), 772236192Sdelphij EXTRACT_32BITS(sflow_flow_sample->pool), 773236192Sdelphij EXTRACT_32BITS(sflow_flow_sample->drops), 774236192Sdelphij EXTRACT_32BITS(sflow_flow_sample->in_interface), 775236192Sdelphij EXTRACT_32BITS(sflow_flow_sample->out_interface), 776236192Sdelphij nrecords); 777236192Sdelphij 778236192Sdelphij return sflow_print_flow_records(pointer + sizeof(struct sflow_flow_sample_t), 779236192Sdelphij len - sizeof(struct sflow_flow_sample_t), 780236192Sdelphij nrecords); 781236192Sdelphij 782236192Sdelphij} 783236192Sdelphij 784236192Sdelphijstatic int 785236192Sdelphijsflow_print_expanded_flow_sample(const u_char *pointer, u_int len) { 786236192Sdelphij 787236192Sdelphij const struct sflow_expanded_flow_sample_t *sflow_expanded_flow_sample; 788236192Sdelphij u_int nrecords; 789236192Sdelphij 790236192Sdelphij if (len < sizeof(struct sflow_expanded_flow_sample_t)) 791236192Sdelphij return 1; 792236192Sdelphij 793236192Sdelphij sflow_expanded_flow_sample = (const struct sflow_expanded_flow_sample_t *)pointer; 794236192Sdelphij 795236192Sdelphij nrecords = EXTRACT_32BITS(sflow_expanded_flow_sample->records); 796236192Sdelphij 797236192Sdelphij printf(" seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, records %u", 798236192Sdelphij EXTRACT_32BITS(sflow_expanded_flow_sample->seqnum), 799236192Sdelphij EXTRACT_32BITS(sflow_expanded_flow_sample->type), 800236192Sdelphij EXTRACT_32BITS(sflow_expanded_flow_sample->index), 801236192Sdelphij EXTRACT_32BITS(sflow_expanded_flow_sample->rate), 802236192Sdelphij EXTRACT_32BITS(sflow_expanded_flow_sample->pool), 803236192Sdelphij EXTRACT_32BITS(sflow_expanded_flow_sample->drops), 804236192Sdelphij EXTRACT_32BITS(sflow_expanded_flow_sample->records)); 805236192Sdelphij 806236192Sdelphij return sflow_print_flow_records(pointer + sizeof(struct sflow_expanded_flow_sample_t), 807236192Sdelphij len - sizeof(struct sflow_expanded_flow_sample_t), 808236192Sdelphij nrecords); 809236192Sdelphij 810236192Sdelphij} 811236192Sdelphij 812236192Sdelphijvoid 813236192Sdelphijsflow_print(const u_char *pptr, u_int len) { 814236192Sdelphij 815236192Sdelphij const struct sflow_datagram_t *sflow_datagram; 816236192Sdelphij const struct sflow_sample_header *sflow_sample; 817236192Sdelphij 818236192Sdelphij const u_char *tptr; 819236192Sdelphij u_int tlen; 820190203Srpaulo u_int32_t sflow_sample_type, sflow_sample_len; 821236192Sdelphij u_int32_t nsamples; 822190203Srpaulo 823236192Sdelphij 824236192Sdelphij tptr = pptr; 825190203Srpaulo tlen = len; 826190203Srpaulo sflow_datagram = (const struct sflow_datagram_t *)pptr; 827190203Srpaulo TCHECK(*sflow_datagram); 828190203Srpaulo 829190203Srpaulo /* 830190203Srpaulo * Sanity checking of the header. 831190203Srpaulo */ 832190203Srpaulo if (EXTRACT_32BITS(sflow_datagram->version) != 5) { 833190203Srpaulo printf("sFlow version %u packet not supported", 834190203Srpaulo EXTRACT_32BITS(sflow_datagram->version)); 835190203Srpaulo return; 836190203Srpaulo } 837190203Srpaulo 838190203Srpaulo if (vflag < 1) { 839190203Srpaulo printf("sFlowv%u, %s agent %s, agent-id %u, length %u", 840190203Srpaulo EXTRACT_32BITS(sflow_datagram->version), 841190203Srpaulo EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6", 842190203Srpaulo ipaddr_string(sflow_datagram->agent), 843190203Srpaulo EXTRACT_32BITS(sflow_datagram->samples), 844190203Srpaulo len); 845190203Srpaulo return; 846190203Srpaulo } 847190203Srpaulo 848190203Srpaulo /* ok they seem to want to know everything - lets fully decode it */ 849190203Srpaulo nsamples=EXTRACT_32BITS(sflow_datagram->samples); 850190203Srpaulo printf("sFlowv%u, %s agent %s, agent-id %u, seqnum %u, uptime %u, samples %u, length %u", 851190203Srpaulo EXTRACT_32BITS(sflow_datagram->version), 852190203Srpaulo EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6", 853190203Srpaulo ipaddr_string(sflow_datagram->agent), 854190203Srpaulo EXTRACT_32BITS(sflow_datagram->agent_id), 855190203Srpaulo EXTRACT_32BITS(sflow_datagram->seqnum), 856190203Srpaulo EXTRACT_32BITS(sflow_datagram->uptime), 857190203Srpaulo nsamples, 858190203Srpaulo len); 859190203Srpaulo 860190203Srpaulo /* skip Common header */ 861236192Sdelphij tptr += sizeof(const struct sflow_datagram_t); 862236192Sdelphij tlen -= sizeof(const struct sflow_datagram_t); 863190203Srpaulo 864190203Srpaulo while (nsamples > 0 && tlen > 0) { 865190203Srpaulo sflow_sample = (const struct sflow_sample_header *)tptr; 866236192Sdelphij TCHECK(*sflow_sample); 867236192Sdelphij 868190203Srpaulo sflow_sample_type = (EXTRACT_32BITS(sflow_sample->format)&0x0FFF); 869190203Srpaulo sflow_sample_len = EXTRACT_32BITS(sflow_sample->len); 870190203Srpaulo 871236192Sdelphij if (tlen < sizeof(struct sflow_sample_header)) 872236192Sdelphij goto trunc; 873236192Sdelphij 874236192Sdelphij tptr += sizeof(struct sflow_sample_header); 875236192Sdelphij tlen -= sizeof(struct sflow_sample_header); 876190203Srpaulo 877190203Srpaulo printf("\n\t%s (%u), length %u,", 878190203Srpaulo tok2str(sflow_format_values, "Unknown", sflow_sample_type), 879190203Srpaulo sflow_sample_type, 880190203Srpaulo sflow_sample_len); 881190203Srpaulo 882190203Srpaulo /* basic sanity check */ 883190203Srpaulo if (sflow_sample_type == 0 || sflow_sample_len ==0) { 884190203Srpaulo return; 885190203Srpaulo } 886190203Srpaulo 887236192Sdelphij if (tlen < sflow_sample_len) 888236192Sdelphij goto trunc; 889236192Sdelphij 890190203Srpaulo /* did we capture enough for fully decoding the sample ? */ 891236192Sdelphij TCHECK2(*tptr, sflow_sample_len); 892190203Srpaulo 893190203Srpaulo switch(sflow_sample_type) { 894236192Sdelphij case SFLOW_FLOW_SAMPLE: 895236192Sdelphij if (sflow_print_flow_sample(tptr,tlen)) 896236192Sdelphij goto trunc; 897190203Srpaulo break; 898190203Srpaulo 899236192Sdelphij case SFLOW_COUNTER_SAMPLE: 900236192Sdelphij if (sflow_print_counter_sample(tptr,tlen)) 901236192Sdelphij goto trunc; 902190203Srpaulo break; 903190203Srpaulo 904190203Srpaulo case SFLOW_EXPANDED_FLOW_SAMPLE: 905236192Sdelphij if (sflow_print_expanded_flow_sample(tptr,tlen)) 906236192Sdelphij goto trunc; 907236192Sdelphij break; 908190203Srpaulo 909190203Srpaulo case SFLOW_EXPANDED_COUNTER_SAMPLE: 910236192Sdelphij if (sflow_print_expanded_counter_sample(tptr,tlen)) 911236192Sdelphij goto trunc; 912236192Sdelphij break; 913190203Srpaulo 914190203Srpaulo default: 915190203Srpaulo if (vflag <= 1) 916190203Srpaulo print_unknown_data(tptr, "\n\t ", sflow_sample_len); 917190203Srpaulo break; 918190203Srpaulo } 919190203Srpaulo tptr += sflow_sample_len; 920190203Srpaulo tlen -= sflow_sample_len; 921190203Srpaulo nsamples--; 922190203Srpaulo } 923190203Srpaulo return; 924190203Srpaulo 925190203Srpaulo trunc: 926190203Srpaulo printf("[|SFLOW]"); 927190203Srpaulo} 928190203Srpaulo 929190203Srpaulo/* 930190203Srpaulo * Local Variables: 931190203Srpaulo * c-style: whitesmith 932190203Srpaulo * c-basic-offset: 4 933190203Srpaulo * End: 934190203Srpaulo */ 935