summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-aruba-papi.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-aruba-papi.c')
-rw-r--r--epan/dissectors/packet-aruba-papi.c966
1 files changed, 966 insertions, 0 deletions
diff --git a/epan/dissectors/packet-aruba-papi.c b/epan/dissectors/packet-aruba-papi.c
new file mode 100644
index 00000000..5d5e6ab4
--- /dev/null
+++ b/epan/dissectors/packet-aruba-papi.c
@@ -0,0 +1,966 @@
+/* packet-aruba-papi.c
+ * Routines for Aruba PAPI dissection
+ * Copyright 2010, Alexis La Goutte <alexis.lagoutte at gmail dot com>
+ *
+ * Real name of PAPI : Protocol Application Program Interface
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/expert.h>
+#include <epan/addr_resolv.h>
+#include <wsutil/inet_ipv4.h>
+#include <wsutil/inet_ipv6.h>
+
+/* This is not IANA assigned nor registered */
+#define UDP_PORT_PAPI 8211
+
+void proto_register_papi(void);
+void proto_reg_handoff_papi(void);
+
+static dissector_handle_t papi_handle;
+
+/* Initialize the protocol and registered fields */
+static int proto_papi = -1;
+static int hf_papi_hdr_magic = -1;
+static int hf_papi_hdr_version = -1;
+static int hf_papi_hdr_dest_ip = -1;
+static int hf_papi_hdr_src_ip = -1;
+static int hf_papi_hdr_nat_port_number = -1;
+static int hf_papi_hdr_garbage = -1;
+static int hf_papi_hdr_dest_port = -1;
+static int hf_papi_hdr_src_port = -1;
+static int hf_papi_hdr_packet_type = -1;
+static int hf_papi_hdr_packet_size = -1;
+static int hf_papi_hdr_seq_number = -1;
+static int hf_papi_hdr_message_code = -1;
+static int hf_papi_hdr_checksum = -1;
+
+static int hf_papi_hdr_srcipv6 = -1;
+static int hf_papi_hdr_destipv6 = -1;
+
+static int hf_papi_debug = -1;
+static int hf_papi_debug_text = -1;
+static int hf_papi_debug_text_length = -1;
+static int hf_papi_debug_48bits = -1;
+static int hf_papi_debug_8bits = -1;
+static int hf_papi_debug_16bits = -1;
+static int hf_papi_debug_32bits = -1;
+static int hf_papi_debug_ipv4 = -1;
+static int hf_papi_debug_64bits = -1;
+static int hf_papi_debug_bytes = -1;
+static int hf_papi_debug_bytes_length = -1;
+
+static int hf_papi_licmgr = -1;
+static int hf_papi_licmgr_payload_len = -1;
+static int hf_papi_licmgr_tlv = -1;
+static int hf_papi_licmgr_type = -1;
+static int hf_papi_licmgr_length = -1;
+static int hf_papi_licmgr_value = -1;
+static int hf_papi_licmgr_ip = -1;
+static int hf_papi_licmgr_serial_number = -1;
+static int hf_papi_licmgr_hostname = -1;
+static int hf_papi_licmgr_mac_address = -1;
+static int hf_papi_licmgr_license_ap_remaining = -1;
+static int hf_papi_licmgr_license_pef_remaining = -1;
+static int hf_papi_licmgr_license_rfp_remaining = -1;
+static int hf_papi_licmgr_license_xsec_remaining = -1;
+static int hf_papi_licmgr_license_acr_remaining = -1;
+static int hf_papi_licmgr_license_ap_used = -1;
+static int hf_papi_licmgr_license_pef_used = -1;
+static int hf_papi_licmgr_license_rfp_used = -1;
+static int hf_papi_licmgr_license_xsec_used = -1;
+static int hf_papi_licmgr_license_acr_used = -1;
+static int hf_papi_licmgr_padding = -1;
+
+static expert_field ei_papi_debug_unknown = EI_INIT;
+
+/* variable for dissector table for subdissectors */
+static dissector_table_t papi_dissector_table;
+
+/* Global PAPI Debug Preference */
+static gboolean g_papi_debug = FALSE;
+
+/* Initialize the subtree pointers */
+static gint ett_papi = -1;
+static gint ett_papi_licmgr = -1;
+static gint ett_papi_licmgr_tlv = -1;
+
+#define SAMBA_WRAPPER 8442
+#define RESOLVER_PORT 8392
+#define PB_INT_TASK 8448
+#define STATION_MANAGEMENT_LOPRI 8419
+#define MOBILE_IP 8383
+#define SIBYTE_FASTPATH_PORT 8355
+#define WLAN_MANAGEMENT_SERVER 8224
+#define SIBYTE_CONSOLE_CLIENT2 8357
+#define AUTH_SERVER_LOPRI 8420
+#define MOB_FASTPATH_PORT 8354
+#define SAP_RRAD_PORT 8382
+#define REPGEN 8418
+#define RAPPER_PORT2 8424
+#define IKE_DAEMON_RAW 8232
+#define STATION_MANAGEMENT 8345
+#define PPPD_START 8241
+#define SETUP_DIALOG 8434
+#define WEB_GRAPHGEN1 8346
+#define SNMP_TRAP_RAW 8402
+#define ARUBA_NTPD 8377
+#define STATION_MANAGEMENT_LOPRI_AP 8452
+#define CLI_LOG_RAW 8364
+#define AUTH_SERVER_RAW 8227
+#define RAPPER_PORT5 8427
+#define MESH_DAEMON 8433
+#define PHONE_HOME 8437
+#define FPCLI_SIBYTE_CONSOLE2 8368
+#define FASTPATH_WEB_CLIENT 8218
+#define SERVER_LOAD_BALANCING 8384
+#define IKE_DAEMON 8231
+#define CPSEC 8453
+#define MOBILITY_CLIENT 8217
+#define SNMP_TRAPMGR 8363
+#define PIM_TOSIBYTE 8416
+#define RAPPER_PORT9 8431
+#define CERT_MANAGER_MASTER 8353
+#define MISC_PROC 8445
+#define PPPD_END 8340
+#define SYSMGR 8450
+#define RAPPER_PORT6 8428
+#define RRA_SERVER 8238
+#define NANNY_PORT_MEM_MON 8371
+#define SYS_MAPPER_LOPRI 8435
+#define RAPPER_PORT4 8426
+#define SAPM_HYBRID_AP 8436
+#define FASTPATH_CLI_CLIENT 8213
+#define CFGM_RAW 8362
+#define SPOTMGR 8398
+#define SYSLOGDWRAP 8407
+#define WEBS_AM_PORT 8352
+#define QPDQ_STANDALONE 8401
+#define FPCLI_RAW 8361
+#define VRRP_DAEMON 8391
+#define AMAP_MGMT_PORT 8395
+#define CAP_MGMT_PORT 8351
+#define SAPM_SERVER 8222
+#define PPPD_DAEMON 8234
+#define LAST_SERVICE 8999
+#define DHCP_SERVER 8390
+#define ADMINSERVER 8403
+#define SYS_MAPPER 8396
+#define PUBSUB_SERVER 8378
+#define AMAPI_SNMP_TRAP_CLIENT 8440
+#define PPTPD 8341
+#define SIBYTE_CONSOLE_PORT 8348
+#define SNMP_DAEMON 8219
+#define SIBYTE_DNLD_FILE 8374
+#define UTILITY_PROCESS 8449
+#define SAPM_RAPCP 8438
+#define SIBYTE_MACH_INFO 8386
+#define SIBYTE_CONSOLE_CLIENT1 8356
+#define SWKEY 8373
+#define RF_CLIENT 8410
+#define HAMGR 8408
+#define FASTPATH_CLI_SERVER 8239
+#define FASTPATH_AUTH_CLIENT 8360
+#define CRYPTO_POST_PORT 8400
+#define HTTPD_WRAP 8404
+#define MMSCONFIGMGR 8412
+#define FPAPPS_AUTH_PORT 8381
+#define FPWEB_RAW 8415
+#define L2TPD 8342
+#define CERT_CLIENT 8349
+#define SIBYTE_RAW 8228
+#define FPAPPS_VRRP_PORT 8379
+#define AIR_MONITOR 8225
+#define ANOMALY_DETECTION 8387
+#define ARUBA_FILTER 8388
+#define MSGH_HELPER 8446
+#define FASTPATH_SERVER 8212
+#define MOBILITY_AGENT 8229
+#define OSPF_DAEMON 8441
+#define PIM 8385
+#define MOBILITY_SERVER 8216
+#define SIBYTE_CONSOLE_CLIENT3 8358
+#define FPCLI_SIBYTE_CONSOLE1 8367
+#define AUTH_CLIENT 8215
+#define FPCLI_SIBYTE_CONSOLE3 8369
+#define AMAPI_SAMPLE_CLIENT 8221
+#define PPPOE_DAEMON 8411
+#define UDB_SERVER 8344
+#define RAPPER_PORT1 8423
+#define PAPI_EPHEMERAL 65535
+#define MVC_SERVER 8422
+#define RAPPER_PORT3 8425
+#define DHCP_DAEMON 8359
+#define EMWEB_RAW 8365
+#define STATSMGR 8397
+#define FASTPATH_ADD_SERVER 8240
+#define AMAPI_CLI_CLIENT 8220
+#define AUTH_SERVER 8214
+#define MESSAGE_HANDLER 8999
+#define AMAP_PROC 8394
+#define CTS 8413
+#define CFGMANAGER 8226
+#define RAPPER_PORT8 8430
+#define L2TPD_DAEMON_RAW 8233
+#define WLAN_MANAGEMENT_SERVER_LOPRI 8421
+#define NANNY_PORT 8370
+#define RAPPER_PORT10 8432
+#define RAPPER_PORT7 8429
+#define AMAPI_WEB_CLIENT 8235
+#define WEB_CLI_RAW 8375
+#define CERT_MANAGER 8343
+#define NCFGTEST_APP 8406
+#define REM_DSLMGR 8439
+#define PROFILE_MANAGER 8405
+#define LICENSE_MANAGER 8389
+#define MMSWEBSVC 8414
+#define SSH_AUTH_PORT 8393
+#define STATION_MANAGEMENT_AP 8451
+#define AMP_SERVER 8444
+#define HTTPD_WRAP_AUTH_PORT 8417
+#define FAULTMGR 8399
+#define SIBYTE_HEARTBEAT 8237
+#define USBHELPER_CLIENT 8447
+#define SAPM_CLIENT 8223
+#define RF_MANAGER 8409
+#define WEB_GRAPHGEN2 8347
+#define HARDWARE_MONITOR_PORT 8366
+#define P8MGR 8454
+#define WIRED_MAC_LOOKUP 8376
+#define CDP_PROC 8350
+#define AAA_MGMT_PORT 8372
+#define DBSYNC_PORT 8380
+#define AMAPI_SNMP_CLIENT 8236
+#define PORT_UBT 15560
+
+/* defining Packet Size & HDR version no for PAPI */
+#define PAPI_PACKET_SIZE 76
+#define V4V6_HDR_VERSION 0x03
+
+static const value_string papi_port_vals[] = {
+ { FASTPATH_SERVER, "FASTPATH_SERVER" },
+ { FASTPATH_CLI_CLIENT, "FASTPATH_CLI_CLIENT" },
+ { AUTH_SERVER, "AUTH_SERVER" },
+ { AUTH_CLIENT, "AUTH_CLIENT" },
+ { MOBILITY_SERVER, "MOBILITY_SERVER" },
+ { MOBILITY_CLIENT, "MOBILITY_CLIENT" },
+ { FASTPATH_WEB_CLIENT, "FASTPATH_WEB_CLIENT" },
+ { SNMP_DAEMON, "SNMP_DAEMON" },
+ { AMAPI_CLI_CLIENT, "AMAPI_CLI_CLIENT" },
+ { AMAPI_SAMPLE_CLIENT, "AMAPI_SAMPLE_CLIENT" },
+ { SAPM_SERVER, "SAPM_SERVER" },
+ { SAPM_CLIENT, "SAPM_CLIENT" },
+ { WLAN_MANAGEMENT_SERVER, "WLAN_MANAGEMENT_SERVER" },
+ { AIR_MONITOR, "AIR_MONITOR" },
+ { CFGMANAGER, "CFGMANAGER" },
+ { AUTH_SERVER_RAW, "AUTH_SERVER_RAW" },
+ { SIBYTE_RAW, "SIBYTE_RAW" },
+ { MOBILITY_AGENT, "MOBILITY_AGENT" },
+ { IKE_DAEMON, "IKE_DAEMON" },
+ { IKE_DAEMON_RAW, "IKE_DAEMON_RAW" },
+ { L2TPD_DAEMON_RAW, "L2TPD_DAEMON_RAW" },
+ { PPPD_DAEMON, "PPPD_DAEMON" },
+ { AMAPI_WEB_CLIENT, "AMAPI_WEB_CLIENT" },
+ { AMAPI_SNMP_CLIENT, "AMAPI_SNMP_CLIENT" },
+ { SIBYTE_HEARTBEAT, "SIBYTE_HEARTBEAT" },
+ { RRA_SERVER, "RRA_SERVER" },
+ { FASTPATH_CLI_SERVER, "FASTPATH_CLI_SERVER" },
+ { FASTPATH_ADD_SERVER, "FASTPATH_ADD_SERVER" },
+ { PPPD_START, "PPPD_START" },
+ { PPPD_END, "PPPD_END" },
+ { PPTPD, "PPTPD" },
+ { L2TPD, "L2TPD" },
+ { CERT_MANAGER, "CERT_MANAGER" },
+ { UDB_SERVER, "UDB_SERVER" },
+ { STATION_MANAGEMENT, "STATION_MANAGEMENT" },
+ { WEB_GRAPHGEN1, "WEB_GRAPHGEN1" },
+ { WEB_GRAPHGEN2, "WEB_GRAPHGEN2" },
+ { SIBYTE_CONSOLE_PORT, "SIBYTE_CONSOLE_PORT" },
+ { CERT_CLIENT, "CERT_CLIENT" },
+ { CDP_PROC, "CDP_PROC" },
+ { CAP_MGMT_PORT, "CAP_MGMT_PORT" },
+ { WEBS_AM_PORT, "WEBS_AM_PORT" },
+ { CERT_MANAGER_MASTER, "CERT_MANAGER_MASTER" },
+ { MOB_FASTPATH_PORT, "MOB_FASTPATH_PORT" },
+ { SIBYTE_FASTPATH_PORT, "SIBYTE_FASTPATH_PORT" },
+ { SIBYTE_CONSOLE_CLIENT1, "SIBYTE_CONSOLE_CLIENT1" },
+ { SIBYTE_CONSOLE_CLIENT2, "SIBYTE_CONSOLE_CLIENT2" },
+ { SIBYTE_CONSOLE_CLIENT3, "SIBYTE_CONSOLE_CLIENT3" },
+ { DHCP_DAEMON, "DHCP_DAEMON" },
+ { FASTPATH_AUTH_CLIENT, "FASTPATH_AUTH_CLIENT" },
+ { FPCLI_RAW, "FPCLI_RAW" },
+ { CFGM_RAW, "CFGM_RAW" },
+ { SNMP_TRAPMGR, "SNMP_TRAPMGR" },
+ { CLI_LOG_RAW, "CLI_LOG_RAW" },
+ { EMWEB_RAW, "EMWEB_RAW" },
+ { HARDWARE_MONITOR_PORT, "HARDWARE_MONITOR_PORT" },
+ { FPCLI_SIBYTE_CONSOLE1, "FPCLI_SIBYTE_CONSOLE1" },
+ { FPCLI_SIBYTE_CONSOLE2, "FPCLI_SIBYTE_CONSOLE2" },
+ { FPCLI_SIBYTE_CONSOLE3, "FPCLI_SIBYTE_CONSOLE3" },
+ { NANNY_PORT, "NANNY_PORT" },
+ { NANNY_PORT_MEM_MON, "NANNY_PORT_MEM_MON" },
+ { AAA_MGMT_PORT, "AAA_MGMT_PORT" },
+ { SWKEY, "SWKEY" },
+ { SIBYTE_DNLD_FILE, "SIBYTE_DNLD_FILE" },
+ { WEB_CLI_RAW, "WEB_CLI_RAW" },
+ { WIRED_MAC_LOOKUP, "WIRED_MAC_LOOKUP" },
+ { ARUBA_NTPD, "ARUBA_NTPD" },
+ { PUBSUB_SERVER, "PUBSUB_SERVER" },
+ { FPAPPS_VRRP_PORT, "FPAPPS_VRRP_PORT" },
+ { DBSYNC_PORT, "DBSYNC_PORT" },
+ { FPAPPS_AUTH_PORT, "FPAPPS_AUTH_PORT" },
+ { SAP_RRAD_PORT, "SAP_RRAD_PORT" },
+ { MOBILE_IP, "MOBILE_IP" },
+ { SERVER_LOAD_BALANCING, "SERVER_LOAD_BALANCING" },
+ { PIM, "PIM" },
+ { SIBYTE_MACH_INFO, "SIBYTE_MACH_INFO" },
+ { ANOMALY_DETECTION, "ANOMALY_DETECTION" },
+ { ARUBA_FILTER, "ARUBA_FILTER" },
+ { LICENSE_MANAGER, "LICENSE_MANAGER" },
+ { DHCP_SERVER, "DHCP_SERVER" },
+ { VRRP_DAEMON, "VRRP_DAEMON" },
+ { RESOLVER_PORT, "RESOLVER_PORT" },
+ { SSH_AUTH_PORT, "SSH_AUTH_PORT" },
+ { AMAP_PROC, "AMAP_PROC" },
+ { AMAP_MGMT_PORT, "AMAP_MGMT_PORT" },
+ { SYS_MAPPER, "SYS_MAPPER" },
+ { STATSMGR, "STATSMGR" },
+ { SPOTMGR, "SPOTMGR" },
+ { FAULTMGR, "FAULTMGR" },
+ { CRYPTO_POST_PORT, "CRYPTO_POST_PORT" },
+ { QPDQ_STANDALONE, "QPDQ_STANDALONE" },
+ { SNMP_TRAP_RAW, "SNMP_TRAP_RAW" },
+ { ADMINSERVER, "ADMINSERVER" },
+ { HTTPD_WRAP, "HTTPD_WRAP" },
+ { PROFILE_MANAGER, "PROFILE_MANAGER" },
+ { NCFGTEST_APP, "NCFGTEST_APP" },
+ { SYSLOGDWRAP, "SYSLOGDWRAP" },
+ { HAMGR, "HAMGR" },
+ { RF_MANAGER, "RF_MANAGER" },
+ { RF_CLIENT, "RF_CLIENT" },
+ { PPPOE_DAEMON, "PPPOE_DAEMON" },
+ { MMSCONFIGMGR, "MMSCONFIGMGR" },
+ { CTS, "CTS" },
+ { MMSWEBSVC, "MMSWEBSVC" },
+ { FPWEB_RAW, "FPWEB_RAW" },
+ { PIM_TOSIBYTE, "PIM_TOSIBYTE" },
+ { HTTPD_WRAP_AUTH_PORT, "HTTPD_WRAP_AUTH_PORT" },
+ { REPGEN, "REPGEN" },
+ { STATION_MANAGEMENT_LOPRI, "STATION_MANAGEMENT_LOPRI" },
+ { AUTH_SERVER_LOPRI, "AUTH_SERVER_LOPRI" },
+ { WLAN_MANAGEMENT_SERVER_LOPRI, "WLAN_MANAGEMENT_SERVER_LOPRI" },
+ { MVC_SERVER, "MVC_SERVER" },
+ { RAPPER_PORT1, "RAPPER_PORT1" },
+ { RAPPER_PORT2, "RAPPER_PORT2" },
+ { RAPPER_PORT3, "RAPPER_PORT3" },
+ { RAPPER_PORT4, "RAPPER_PORT4" },
+ { RAPPER_PORT5, "RAPPER_PORT5" },
+ { RAPPER_PORT6, "RAPPER_PORT6" },
+ { RAPPER_PORT7, "RAPPER_PORT7" },
+ { RAPPER_PORT8, "RAPPER_PORT8" },
+ { RAPPER_PORT9, "RAPPER_PORT9" },
+ { RAPPER_PORT10, "RAPPER_PORT10" },
+ { MESH_DAEMON, "MESH_DAEMON" },
+ { SETUP_DIALOG, "SETUP_DIALOG" },
+ { SYS_MAPPER_LOPRI, "SYS_MAPPER_LOPRI" },
+ { SAPM_HYBRID_AP, "SAPM_HYBRID_AP" },
+ { PHONE_HOME, "PHONE_HOME" },
+ { SAPM_RAPCP, "SAPM_RAPCP" },
+ { REM_DSLMGR, "REM_DSLMGR" },
+ { AMAPI_SNMP_TRAP_CLIENT, "AMAPI_SNMP_TRAP_CLIENT" },
+ { OSPF_DAEMON, "OSPF_DAEMON" },
+ { SAMBA_WRAPPER, "SAMBA_WRAPPER" },
+ { AMP_SERVER, "AMP_SERVER" },
+ { MISC_PROC, "MISC_PROC" },
+ { MSGH_HELPER, "MSGH_HELPER" },
+ { USBHELPER_CLIENT, "USBHELPER_CLIENT" },
+ { PB_INT_TASK, "PB_INT_TASK" },
+ { UTILITY_PROCESS, "UTILITY_PROCESS" },
+ { SYSMGR, "SYSMGR" },
+ { STATION_MANAGEMENT_AP, "STATION_MANAGEMENT_AP" },
+ { STATION_MANAGEMENT_LOPRI_AP, "STATION_MANAGEMENT_LOPRI_AP" },
+ { CPSEC, "CPSEC" },
+ { P8MGR, "P8MGR" },
+ { LAST_SERVICE, "LAST_SERVICE / MESSAGE_HANDLER" },
+ //{ MESSAGE_HANDLER, "MESSAGE_HANDLER" },
+ { PORT_UBT, "PORT_UBT" },
+ { PAPI_EPHEMERAL, "PAPI_EPHEMERAL" },
+ { 0, NULL }
+};
+
+static value_string_ext papi_port_vals_ext = VALUE_STRING_EXT_INIT(papi_port_vals);
+
+/* PAPI License Manager ! */
+static const value_string licmgr_type_vals[] = {
+ { 1, "IP Address" },
+ { 2, "Serial Number" },
+ { 3, "Hostname" },
+ { 5, "Mac Address" },
+ { 7, "License AP Remaining" },
+ { 8, "License PEF Remaining" },
+ { 9, "License RFP Remaining" },
+ { 10, "License xSec Remaining " },
+ { 11, "License ACR Remaining " },
+ { 12, "License AP Used" },
+ { 13, "License PEF Used" },
+ { 14, "License AP Used" },
+ { 15, "License xSec Used" },
+ { 16, "License ACR Used" },
+ { 17, "License WebCC Key ?" },
+ { 18, "License WebCC Remaining ?" },
+ { 19, "License WebCC Used ?" },
+ { 0, NULL }
+};
+static int
+dissect_papi_license_manager(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_item *ti;
+ proto_tree *licmgr_tree, *licmgr_subtree;
+ guint offset_end, payload_len, offset = 0;
+
+ ti = proto_tree_add_item(tree, hf_papi_licmgr, tvb, offset, -1, ENC_NA);
+ licmgr_tree = proto_item_add_subtree(ti, ett_papi_licmgr);
+
+ proto_tree_add_item_ret_uint(licmgr_tree, hf_papi_licmgr_payload_len, tvb, offset, 2, ENC_BIG_ENDIAN, &payload_len);
+ offset += 2;
+ col_set_str(pinfo->cinfo, COL_INFO, "PAPI - Licence Manager");
+
+ offset_end = offset + payload_len;
+
+ while (offset< offset_end) {
+ guint optlen, type;
+ proto_item *tlv_item;
+
+ type = tvb_get_ntohs(tvb, offset);
+ optlen = tvb_get_ntohs(tvb, offset+2);
+ tlv_item = proto_tree_add_item(licmgr_tree, hf_papi_licmgr_tlv, tvb, offset, 2+2+optlen, ENC_NA );
+
+ proto_item_append_text(tlv_item, ": (t=%d,l=%d) %s", type, optlen, val_to_str(type, licmgr_type_vals, "Unknown Type (%02d)") );
+
+ licmgr_subtree = proto_item_add_subtree(tlv_item, ett_papi_licmgr_tlv);
+
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_type, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_value, tvb, offset, optlen, ENC_NA);
+
+ switch (type) {
+ case 1: /* IP Address */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_ip, tvb, offset, 4, ENC_NA);
+ proto_item_append_text(tlv_item, ": %s", tvb_ip_to_str(pinfo->pool, tvb, offset));
+ break;
+ case 2: /* Serial Number */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_serial_number, tvb, offset, 32, ENC_ASCII);
+ proto_item_append_text(tlv_item, ": %s", tvb_get_string_enc(pinfo->pool,tvb, offset, optlen, ENC_ASCII));
+ break;
+ case 3: /* Hostname */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_hostname, tvb, offset, optlen, ENC_ASCII);
+ proto_item_append_text(tlv_item, ": %s", tvb_get_string_enc(pinfo->pool,tvb, offset, optlen, ENC_ASCII));
+ break;
+ case 5: /* MAC Address */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_mac_address, tvb, offset, optlen, ENC_NA);
+ proto_item_append_text(tlv_item, ": %s", tvb_get_ether_name(tvb, offset));
+ break;
+ case 7: /* License AP remaining */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_license_ap_remaining, tvb, offset, 4, ENC_NA);
+ proto_item_append_text(tlv_item, ": %u", tvb_get_ntohl(tvb, offset));
+ break;
+ case 8: /* License PEF remaining */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_license_pef_remaining, tvb, offset, 4, ENC_NA);
+ proto_item_append_text(tlv_item, ": %u", tvb_get_ntohl(tvb, offset));
+ break;
+ case 9: /* License RFP remaining */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_license_rfp_remaining, tvb, offset, 4, ENC_NA);
+ proto_item_append_text(tlv_item, ": %u", tvb_get_ntohl(tvb, offset));
+ break;
+ case 10: /* License xSec remaining */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_license_xsec_remaining, tvb, offset, 4, ENC_NA);
+ proto_item_append_text(tlv_item, ": %u", tvb_get_ntohl(tvb, offset));
+ break;
+ case 11: /* License ACR remaining */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_license_acr_remaining, tvb, offset, 4, ENC_NA);
+ proto_item_append_text(tlv_item, ": %u", tvb_get_ntohl(tvb, offset));
+ break;
+ case 12: /* License AP used */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_license_ap_used, tvb, offset, 4, ENC_NA);
+ proto_item_append_text(tlv_item, ": %u", tvb_get_ntohl(tvb, offset));
+ break;
+ case 13: /* License PEF used */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_license_pef_used, tvb, offset, 4, ENC_NA);
+ proto_item_append_text(tlv_item, ": %u", tvb_get_ntohl(tvb, offset));
+ break;
+ case 14: /* License RFP used */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_license_rfp_used, tvb, offset, 4, ENC_NA);
+ proto_item_append_text(tlv_item, ": %u", tvb_get_ntohl(tvb, offset));
+ break;
+ case 15: /* License xSec used */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_license_xsec_used, tvb, offset, 4, ENC_NA);
+ proto_item_append_text(tlv_item, ": %u", tvb_get_ntohl(tvb, offset));
+ break;
+ case 16: /* License ACR used */
+ proto_tree_add_item(licmgr_subtree, hf_papi_licmgr_license_acr_used, tvb, offset, 4, ENC_NA);
+ proto_item_append_text(tlv_item, ": %u", tvb_get_ntohl(tvb, offset));
+ break;
+ }
+ offset += optlen;
+ }
+
+ proto_tree_add_item(licmgr_tree, hf_papi_licmgr_padding, tvb, offset, -1, ENC_NA);
+ offset += tvb_reported_length_remaining(tvb, offset);
+
+ return offset;
+}
+
+/* PAPI Debug loop ! */
+static int
+dissect_papi_debug(tvbuff_t *tvb, packet_info *pinfo, guint offset, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *debug_tree, *debug_sub_tree;
+
+
+ ti = proto_tree_add_item(tree, hf_papi_debug, tvb, offset, -1, ENC_NA);
+ debug_tree = proto_item_add_subtree(ti, ett_papi);
+
+ while(offset < tvb_reported_length(tvb)) {
+ switch(tvb_get_guint8(tvb,offset)) {
+ case 0x00:
+ ti = proto_tree_add_item(debug_tree, hf_papi_debug_text, tvb, offset+3, tvb_get_ntohs(tvb,offset+1), ENC_ASCII);
+ debug_sub_tree = proto_item_add_subtree(ti, ett_papi);
+ proto_tree_add_item(debug_sub_tree, hf_papi_debug_text_length, tvb, offset+1, 2, ENC_BIG_ENDIAN);
+ offset += tvb_get_ntohs(tvb, offset+1) + 3;
+ break;
+ case 0x01:
+ proto_tree_add_item(debug_tree, hf_papi_debug_48bits, tvb, offset+1, 6, ENC_BIG_ENDIAN);
+ offset += 7;
+ break;
+ case 0x02:
+ proto_tree_add_item(debug_tree, hf_papi_debug_8bits, tvb, offset+1, 1, ENC_BIG_ENDIAN);
+ offset += 2;
+ break;
+ case 0x03:
+ proto_tree_add_item(debug_tree, hf_papi_debug_16bits, tvb, offset+1, 2, ENC_BIG_ENDIAN);
+ offset += 3;
+ break;
+ case 0x04:
+ proto_tree_add_item(debug_tree, hf_papi_debug_32bits, tvb, offset+1, 4, ENC_BIG_ENDIAN);
+ offset += 5;
+ break;
+ case 0x05:
+ proto_tree_add_item(debug_tree, hf_papi_debug_ipv4, tvb, offset+1, 4, ENC_BIG_ENDIAN);
+ offset += 5;
+ break;
+ case 0x07:
+ proto_tree_add_item(debug_tree, hf_papi_debug_16bits, tvb, offset+1, 2, ENC_BIG_ENDIAN);
+ offset += 3;
+ break;
+ case 0x08:
+ ti = proto_tree_add_item(debug_tree, hf_papi_debug_bytes, tvb, offset+3, tvb_get_ntohs(tvb,offset+1), ENC_NA);
+ debug_sub_tree = proto_item_add_subtree(ti, ett_papi);
+ proto_tree_add_item(debug_sub_tree, hf_papi_debug_bytes_length, tvb, offset+1, 2, ENC_BIG_ENDIAN);
+ offset += tvb_get_ntohs(tvb,offset+1) + 3;
+ break;
+ case 0x09:
+ proto_tree_add_item(debug_tree, hf_papi_debug_64bits, tvb, offset+1, 8, ENC_BIG_ENDIAN);
+ offset += 9;
+ break;
+ default:
+ proto_tree_add_expert_format(debug_tree, pinfo, &ei_papi_debug_unknown, tvb, offset, 1, "Unknown (%d)", tvb_get_guint8(tvb, offset));
+ offset +=1;
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_papi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ proto_item *ti;
+ proto_tree *papi_tree;
+ guint offset = 0;
+ guint32 dest_port, src_port, hdr_version;
+ tvbuff_t *next_tvb;
+
+
+ /* All PAPI packet start with 0x4972 ! */
+ if ( tvb_get_ntohs(tvb, offset) != 0x4972 )
+ return FALSE;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PAPI");
+ col_set_str(pinfo->cinfo, COL_INFO, "PAPI - Aruba AP Control Protocol");
+
+ ti = proto_tree_add_item(tree, proto_papi, tvb, 0, PAPI_PACKET_SIZE, ENC_NA);
+ papi_tree = proto_item_add_subtree(ti, ett_papi);
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_magic, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item_ret_uint(papi_tree, hf_papi_hdr_version, tvb, offset, 2, ENC_BIG_ENDIAN, &hdr_version);
+ offset += 2;
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_dest_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_src_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_nat_port_number, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_garbage, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item_ret_uint(papi_tree, hf_papi_hdr_dest_port, tvb, offset, 2, ENC_BIG_ENDIAN, &dest_port);
+ offset += 2;
+
+ proto_tree_add_item_ret_uint(papi_tree, hf_papi_hdr_src_port, tvb, offset, 2, ENC_BIG_ENDIAN, &src_port);
+ offset += 2;
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_packet_type, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_packet_size, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_seq_number, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_message_code, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_checksum, tvb, offset, 16, ENC_NA);
+ offset += 16;
+
+ if (hdr_version == V4V6_HDR_VERSION) {
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_destipv6, tvb, offset, IPv6_ADDR_SIZE, ENC_NA);
+ offset += IPv6_ADDR_SIZE;
+
+ proto_tree_add_item(papi_tree, hf_papi_hdr_srcipv6, tvb, offset, IPv6_ADDR_SIZE, ENC_NA);
+ offset += IPv6_ADDR_SIZE;
+
+ }
+
+ if(g_papi_debug)
+ {
+ offset = dissect_papi_debug(tvb, pinfo, offset, papi_tree);
+ }
+
+ next_tvb = tvb_new_subset_remaining(tvb, offset);
+ if (!dissector_try_uint_new(papi_dissector_table, dest_port, next_tvb, pinfo, tree, TRUE, NULL)) {
+ if (!dissector_try_uint_new(papi_dissector_table, src_port, next_tvb, pinfo, tree, TRUE, NULL)) {
+ call_data_dissector(next_tvb, pinfo, tree);
+ }
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+void
+proto_register_papi(void)
+{
+ module_t *papi_module;
+
+ static hf_register_info hf[] = {
+ { &hf_papi_hdr_magic,
+ { "Magic", "papi.hdr.magic",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "PAPI Header Magic Number", HFILL }
+ },
+ { &hf_papi_hdr_version,
+ { "Version", "papi.hdr.version",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "PAPI Protocol Version", HFILL }
+ },
+ { &hf_papi_hdr_dest_ip,
+ { "Destination IP", "papi.hdr.dest.ip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_src_ip,
+ { "Source IP", "papi.hdr.src.ip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_nat_port_number,
+ { "NAT Port Number", "papi.hdr.nat_port_number",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_garbage,
+ { "Garbage", "papi.hdr.garbage",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_dest_port,
+ { "Destination Port", "papi.hdr.dest.port",
+ FT_UINT16, BASE_DEC|BASE_EXT_STRING, &papi_port_vals_ext, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_src_port,
+ { "Source Port", "papi.hdr.src.port",
+ FT_UINT16, BASE_DEC|BASE_EXT_STRING, &papi_port_vals_ext, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_packet_type,
+ { "Packet Type", "papi.hdr.packet.type",
+ FT_UINT16, BASE_DEC|BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_packet_size,
+ { "Packet Size", "papi.hdr.packet.size",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_seq_number,
+ { "Sequence Number", "papi.hdr.seq_number",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_message_code,
+ { "Message Code", "papi.hdr.message_code",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_checksum,
+ { "Checksum", "papi.hdr.checksum",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_destipv6,/* IPv6 address of Destination */
+ { "Destination IPv6", "papi.hdr.dest.ipv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_hdr_srcipv6,/* IPv6 address of Source */
+ { "Source IPv6", "papi.hdr.src.ipv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_debug,
+ { "Debug", "papi.debug",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_debug_text,
+ { "Debug (Text)", "papi.debug.text",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_debug_text_length,
+ { "Debug Text Length", "papi.debug.text_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_debug_bytes,
+ { "Debug (Bytes)", "papi.debug.bytes",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_debug_bytes_length,
+ { "Debug Bytes Length", "papi.debug.bytes_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_debug_48bits,
+ { "Debug (48 Bits)", "papi.debug.48bits",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_debug_8bits,
+ { "Debug (8 Bits)", "papi.debug.8bits",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_debug_16bits,
+ { "Debug (16 Bits)", "papi.debug.16bits",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_debug_32bits,
+ { "Debug (32 Bits)", "papi.debug.32bits",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_debug_ipv4,
+ { "Debug (IPv4)", "papi.debug.ipv4",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_debug_64bits,
+ { "Debug (64 Bits)", "papi.debug.64bits",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+
+ { &hf_papi_licmgr,
+ { "License Manager", "papi.licmgr",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_payload_len,
+ { "Payload Length", "papi.licmgr.payload_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_tlv,
+ { "TLV", "papi.licmgr.tlv",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_type,
+ { "Type", "papi.licmgr.type",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_length,
+ { "Length", "papi.licmgr.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_value,
+ { "Value", "papi.licmgr.value",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_ip,
+ { "License Manager IP Address", "papi.licmgr.ip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_serial_number,
+ { "Serial Number", "papi.licmgr.serial_number",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_hostname,
+ { "Hostname", "papi.licmgr.hostname",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_mac_address,
+ { "MAC Address", "papi.licmgr.mac_address",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_license_ap_remaining,
+ { "License AP remaining", "papi.licmgr.license.ap.remaining",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_license_pef_remaining,
+ { "License PEF remaining", "papi.licmgr.license.pef.remaining",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_license_rfp_remaining,
+ { "License RFP remaining", "papi.licmgr.license.rfp.remaining",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_license_xsec_remaining,
+ { "License xSEC remaining", "papi.licmgr.license.xsec.remaining",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_license_acr_remaining,
+ { "License ACR remaining", "papi.licmgr.license.acr.remaining",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_license_ap_used,
+ { "License AP used", "papi.licmgr.license.ap.used",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_license_pef_used,
+ { "License PEF used", "papi.licmgr.license.pef.used",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_license_rfp_used,
+ { "License RFP used", "papi.licmgr.license.rfp.used",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_license_xsec_used,
+ { "License xSec used", "papi.licmgr.license.xsec.used",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_license_acr_used,
+ { "License ACR used", "papi.licmgr.license.acr.used",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_papi_licmgr_padding,
+ { "Padding", "papi.licmgr.padding",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_papi,
+ &ett_papi_licmgr,
+ &ett_papi_licmgr_tlv
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_papi_debug_unknown, { "papi.debug.unknown", PI_PROTOCOL, PI_WARN, "Unknown", EXPFILL }},
+ };
+
+ expert_module_t* expert_papi;
+
+ proto_papi = proto_register_protocol("Aruba PAPI", "PAPI", "papi");
+
+ proto_register_field_array(proto_papi, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_papi = expert_register_protocol(proto_papi);
+ expert_register_field_array(expert_papi, ei, array_length(ei));
+
+ papi_module = prefs_register_protocol(proto_papi, NULL);
+
+ /* creating a dissector table for the protocol & registering the same */
+ papi_dissector_table = register_dissector_table("papi.port", "PAPI protocol", proto_papi, FT_UINT16, BASE_DEC);
+
+ prefs_register_bool_preference(papi_module, "experimental_decode",
+ "Do experimental decode",
+ "Attempt to decode parts of the message that aren't fully understood yet",
+ &g_papi_debug);
+
+ papi_handle = register_dissector("papi", dissect_papi, proto_papi);
+}
+
+
+void
+proto_reg_handoff_papi(void)
+{
+ dissector_add_uint("papi.port", LICENSE_MANAGER, create_dissector_handle(dissect_papi_license_manager, -1));
+ dissector_add_uint_with_preference("udp.port", UDP_PORT_PAPI, papi_handle);
+}
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */