/* * packet-3g-a11.c * Routines for CDMA2000 A11 packet trace * Copyright 2002, Ryuji Somegawa * packet-3g-a11.c was written based on 'packet-mip.c'. * * packet-3g-a11.c updated by Ravi Valmikam for 3GPP2 TIA-878-A * Copyright 2005, Ravi Valmikam * * packet-mip.c * Routines for Mobile IP dissection * Copyright 2000, Stefan Raab * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later * *Ref: * https://www.3gpp2.org/Public_html/Specs/A.S0009-C_v3.0_100621.pdf * https://www.3gpp2.org/Public_html/Specs/A.S0017-D_v1.0_070624.pdf (IOS 5.1) * https://www.3gpp2.org/Public_html/Specs/A.S0017-D_v2.0_090825.pdf * https://www.3gpp2.org/Public_html/Specs/A.S0017-D%20v3.0_Interoperability%20Specification%20%28IOS%29%20for%20cdma2000%20Access%20Network%20Interfaces%20-%20Part%207%20%28A10%20and%20A11%20Interfaces%29_20110701.pdf * https://www.3gpp2.org/Public_html/Specs/A00-20110419-002Er0%20A.S0008-C%20v4.0%20HRPD%20IOS-Pub_20110513.pdf * https://www.3gpp2.org/Public_html/Specs/A.S0022-0_v2.0_100426.pdf * * https://web.archive.org/web/20070812071100/http://3gpp2.org:80/Public_html/specs/A.S0017-0_v2.0.pdf */ #include "config.h" #include #include /* Include vendor id translation */ #include #include #include #include "packet-radius.h" /* Forward declarations */ void proto_register_a11(void); void proto_reg_handoff_a11(void); static int registration_request_msg; /* Initialize the protocol and registered fields */ static int proto_a11; static int hf_a11_type; static int hf_a11_flags; static int hf_a11_s; static int hf_a11_b; static int hf_a11_d; static int hf_a11_m; static int hf_a11_g; static int hf_a11_v; static int hf_a11_t; static int hf_a11_code; static int hf_a11_status; static int hf_a11_life; static int hf_a11_homeaddr; static int hf_a11_haaddr; static int hf_a11_coa; static int hf_a11_ident; static int hf_a11_ext_type; static int hf_a11_ext_stype; static int hf_a11_ext_len; static int hf_a11_ext; static int hf_a11_aext_spi; static int hf_a11_aext_auth; static int hf_a11_next_nai; static int hf_a11_ses_key; static int hf_a11_ses_mnsrid; static int hf_a11_ses_sidver; static int hf_a11_ses_msid_type; static int hf_a11_ses_msid_len; static int hf_a11_ses_msid; static int hf_a11_ses_ptype; static int hf_a11_vse_vid; static int hf_a11_vse_apptype; static int hf_a11_vse_canid; static int hf_a11_vse_panid; static int hf_a11_vse_srvopt; static int hf_a11_vse_qosmode; static int hf_a11_vse_pdit; static int hf_a11_vse_session_parameter; static int hf_a11_vse_code; static int hf_a11_vse_dormant; static int hf_a11_vse_ehrpd_mode; static int hf_a11_vse_ehrpd_pmk; static int hf_a11_vse_ehrpd_handoff_info; static int hf_a11_vse_ehrpd_tunnel_mode; static int hf_a11_vse_ppaddr; /* Additional Session Information */ static int hf_a11_ase_len_type; static int hf_a11_ase_srid_type; static int hf_a11_ase_servopt_type; static int hf_a11_ase_gre_proto_type; static int hf_a11_ase_gre_key; static int hf_a11_ase_pcf_addr_key; static int hf_a11_ase_forward_rohc_info_len; static int hf_a11_ase_forward_maxcid; static int hf_a11_ase_forward_mrru; static int hf_a11_ase_forward_large_cids; static int hf_a11_ase_forward_profile_count; static int hf_a11_ase_forward_profile; static int hf_a11_ase_reverse_rohc_info_len; static int hf_a11_ase_reverse_maxcid; static int hf_a11_ase_reverse_mrru; static int hf_a11_ase_reverse_large_cids; static int hf_a11_ase_reverse_profile_count; static int hf_a11_ase_reverse_profile; static int hf_a11_aut_flow_prof_sub_type; static int hf_a11_aut_flow_prof_sub_type_len; static int hf_a11_aut_flow_prof_sub_type_value; static int hf_a11_serv_opt_prof_max_serv; static int hf_a11_sub_type; static int hf_a11_sub_type_length; static int hf_a11_serv_opt; static int hf_a11_max_num_serv_opt; static int hf_a11_bcmcs_stype; static int hf_a11_bcmcs_entry_len; /* Forward QoS Information */ static int hf_a11_fqi_srid; static int hf_a11_fqi_flags; static int hf_a11_fqi_flags_ip_flow; static int hf_a11_fqi_flags_dscp; static int hf_a11_fqi_entry_flag; static int hf_a11_fqi_entry_flag_dscp; static int hf_a11_fqi_entry_flag_flow_state; static int hf_a11_fqi_flowcount; static int hf_a11_fqi_flowid; static int hf_a11_fqi_entrylen; /* static int hf_a11_fqi_flowstate; */ static int hf_a11_fqi_requested_qoslen; static int hf_a11_fqi_flow_priority; static int hf_a11_fqi_num_qos_attribute_set; static int hf_a11_fqi_qos_attribute_setlen; static int hf_a11_fqi_qos_attribute_setid; static int hf_a11_fqi_qos_granted_attribute_setid; static int hf_a11_fqi_verbose; static int hf_a11_fqi_flow_profileid; static int hf_a11_fqi_granted_qoslen; /* Reverse QoS Information */ static int hf_a11_rqi_srid; static int hf_a11_rqi_flowcount; static int hf_a11_rqi_flowid; static int hf_a11_rqi_entrylen; static int hf_a11_rqi_entry_flag; static int hf_a11_rqi_entry_flag_flow_state; /* static int hf_a11_rqi_flowstate; */ static int hf_a11_rqi_requested_qoslen; static int hf_a11_rqi_flow_priority; static int hf_a11_rqi_num_qos_attribute_set; static int hf_a11_rqi_qos_attribute_setlen; static int hf_a11_rqi_qos_attribute_setid; static int hf_a11_rqi_qos_granted_attribute_setid; static int hf_a11_rqi_verbose; static int hf_a11_rqi_flow_profileid; /* static int hf_a11_rqi_requested_qos; */ static int hf_a11_rqi_granted_qoslen; /* static int hf_a11_rqi_granted_qos; */ /* QoS Update Information */ static int hf_a11_fqui_flowcount; static int hf_a11_rqui_flowcount; static int hf_a11_fqui_updated_qoslen; static int hf_a11_fqui_updated_qos; static int hf_a11_rqui_updated_qoslen; static int hf_a11_rqui_updated_qos; static int hf_a11_subscriber_profile; /* static int hf_a11_subscriber_profile_len; */ /* Initialize the subtree pointers */ static int ett_a11; static int ett_a11_flags; static int ett_a11_ext; static int ett_a11_exts; static int ett_a11_radius; static int ett_a11_radiuses; static int ett_a11_ase; static int ett_a11_fqi_flowentry; static int ett_a11_fqi_requestedqos; static int ett_a11_fqi_qos_attribute_set; static int ett_a11_fqi_grantedqos; static int ett_a11_rqi_flowentry; static int ett_a11_rqi_requestedqos; static int ett_a11_rqi_qos_attribute_set; static int ett_a11_rqi_grantedqos; static int ett_a11_fqi_flags; static int ett_a11_fqi_entry_flags; static int ett_a11_rqi_entry_flags; static int ett_a11_fqui_flowentry; static int ett_a11_rqui_flowentry; static int ett_a11_subscriber_profile; static int ett_a11_forward_rohc; static int ett_a11_reverse_rohc; static int ett_a11_forward_profile; static int ett_a11_reverse_profile; static int ett_a11_aut_flow_profile_ids; static int ett_a11_bcmcs_entry; static expert_field ei_a11_sub_type_length_not2; static expert_field ei_a11_sse_too_short; static expert_field ei_a11_bcmcs_too_short; static expert_field ei_a11_entry_data_not_dissected; static expert_field ei_a11_session_data_not_dissected; static dissector_handle_t a11_handle; /* Port used for Mobile IP based Tunneling Protocol (A11) */ #define UDP_PORT_3GA11 699 /* Not IANA registered */ typedef enum { REGISTRATION_REQUEST = 1, REGISTRATION_REPLY = 3, REGISTRATION_UPDATE = 20, REGISTRATION_ACK = 21, SESSION_UPDATE = 22, SESSION_ACK = 23, CAPABILITIES_INFO = 24, CAPABILITIES_INFO_ACK = 25, BC_SERVICE_REQUEST = 0xb0, /* 3GPP2 A.S0019-A v2.0 */ BC_SERVICE_REPLY = 0xb1, BC_REGISTRATION_REQUEST = 0xb2, BC_REGISTRATION_REPLY = 0xb3, BC_REGISTRATION_UPDATE = 0xb4, BC_REGISTRATION_ACK = 0xb5 } a11MessageTypes; static const value_string a11_types[] = { {REGISTRATION_REQUEST, "Registration Request"}, {REGISTRATION_REPLY, "Registration Reply"}, {REGISTRATION_UPDATE, "Registration Update"}, {REGISTRATION_ACK, "Registration Ack"}, {SESSION_UPDATE, "Session Update"}, {SESSION_ACK, "Session Update Ack"}, {CAPABILITIES_INFO, "Capabilities Info"}, {CAPABILITIES_INFO_ACK, "Capabilities Info Ack"}, {BC_SERVICE_REQUEST, "BC Service Request"}, {BC_SERVICE_REPLY, "BC Service Response"}, {BC_REGISTRATION_REQUEST, "BC Registration RequestT"}, {BC_REGISTRATION_REPLY, "BC Registration Reply"}, {BC_REGISTRATION_UPDATE, "BC Registration Update"}, {BC_REGISTRATION_ACK, "BC Registration Acknowledge"}, {0, NULL}, }; static value_string_ext a11_types_ext = VALUE_STRING_EXT_INIT(a11_types); static const value_string a11_ses_ptype_vals[] = { {0x8881, "Unstructured Byte Stream"}, {0x88D2, "3GPP2 Packet"}, {0, NULL}, }; static const value_string a11_reply_codes[]= { {0, "Reg Accepted"}, {9, "Connection Update"}, #if 0 {1, "Reg Accepted, but Simultaneous Bindings Unsupported."}, {64, "Reg Deny (FA)- Unspecified Reason"}, {65, "Reg Deny (FA)- Administratively Prohibited"}, {66, "Reg Deny (FA)- Insufficient Resources"}, {67, "Reg Deny (FA)- MN failed Authentication"}, {68, "Reg Deny (FA)- HA failed Authentication"}, {69, "Reg Deny (FA)- Requested Lifetime too Long"}, {70, "Reg Deny (FA)- Poorly Formed Request"}, {71, "Reg Deny (FA)- Poorly Formed Reply"}, {72, "Reg Deny (FA)- Requested Encapsulation Unavailable"}, {73, "Reg Deny (FA)- VJ Compression Unavailable"}, {74, "Reg Deny (FA)- Requested Reverse Tunnel Unavailable"}, {75, "Reg Deny (FA)- Reverse Tunnel is Mandatory and 'T' Bit Not Set"}, {76, "Reg Deny (FA)- Mobile Node Too Distant"}, {79, "Reg Deny (FA)- Delivery Style Not Supported"}, {80, "Reg Deny (FA)- Home Network Unreachable"}, {81, "Reg Deny (FA)- HA Host Unreachable"}, {82, "Reg Deny (FA)- HA Port Unreachable"}, {88, "Reg Deny (FA)- HA Unreachable"}, {96, "Reg Deny (FA)(NAI) - Non Zero Home Address Required"}, {97, "Reg Deny (FA)(NAI) - Missing NAI"}, {98, "Reg Deny (FA)(NAI) - Missing Home Agent"}, {99, "Reg Deny (FA)(NAI) - Missing Home Address"}, #endif {128, "Registration Denied - Unspecified"}, /* 3GPP2 A.S0017-D v4.0 */ {129, "Registration Denied - Administratively Prohibited"}, {130, "Registration Denied - Insufficient Resources"}, {131, "Registration Denied - PCF Failed Authentication"}, /* {132, "Reg Deny (HA)- FA Failed Authentication"}, */ {133, "Registration Denied - Identification Mismatch"}, {134, "Registration Denied - Poorly Formed Request"}, /* {135, "Reg Deny (HA)- Too Many Simultaneous Bindings"}, */ {136, "Registration Denied - Unknown PDSN Address"}, {137, "Registration Denied - Requested Reverse Tunnel Unavailable"}, {138, "Registration Denied - Reverse Tunnel is Mandatory and 'T' Bit Not Set"}, {139, "Registration Denied - service option not supported"}, {140, "Registration Denied - no CID available"}, {141, "Registration Denied - unsupported Vendor ID / Application Type in CVSE"}, {142, "Registration Denied - nonexistent A10 or IP flow"}, {0, NULL}, }; static value_string_ext a11_reply_codes_ext = VALUE_STRING_EXT_INIT(a11_reply_codes); static const value_string a11_ack_status[]= { {0x00, "Update Accepted"}, {0x01, "Partial QoS updated"}, {0x80, "Update Denied - reason unspecified"}, {0x83, "Update Denied - sending node failed authentication"}, {0x85, "Update Denied - identification mismatch)"}, {0x86, "Update Denied - poorly formed registration update"}, {0xc9, "Update Denied - Session Parameter Not Updated"}, {0xca, "Update Denied - PMK not requested"}, {0xfd, "Update Denied - QoS profileID not supported"}, {0xfe, "Update Denied - insufficient resources"}, {0xff, "Update Denied - handoff in progress"}, {0, NULL}, }; static value_string_ext a11_ack_status_ext = VALUE_STRING_EXT_INIT(a11_ack_status); typedef enum { MH_AUTH_EXT = 32, MF_AUTH_EXT = 33, FH_AUTH_EXT = 34, GEN_AUTH_EXT = 36, /* RFC 3012 */ OLD_CVSE_EXT = 37, /* RFC 3115 */ CVSE_EXT = 38, /* RFC 3115 */ SS_EXT = 39, /* 3GPP2 IOS4.2 */ RU_AUTH_EXT = 40, /* 3GPP2 IOS4.2 */ MN_NAI_EXT = 131, MF_CHALLENGE_EXT = 132, /* RFC 3012 */ OLD_NVSE_EXT = 133, /* RFC 3115 */ NVSE_EXT = 134, /* RFC 3115 */ BCMCS_EXT = 0xb0 /* 3GPP2 A.S0019-A v2.0 */ } MIP_EXTS; static const value_string a11_ext_types[]= { {MH_AUTH_EXT, "Mobile-Home Authentication Extension"}, {MF_AUTH_EXT, "Mobile-Foreign Authentication Extension"}, {FH_AUTH_EXT, "Foreign-Home Authentication Extension"}, {GEN_AUTH_EXT, "Generalized Mobile-IP Authentication Extension"}, {OLD_CVSE_EXT, "Critical Vendor/Organization Specific Extension (OLD)"}, {CVSE_EXT, "Critical Vendor/Organization Specific Extension"}, {SS_EXT, "Session Specific Extension"}, {RU_AUTH_EXT, "Registration Update Authentication Extension"}, {MN_NAI_EXT, "Mobile Node NAI Extension"}, {MF_CHALLENGE_EXT, "MN-FA Challenge Extension"}, {OLD_NVSE_EXT, "Normal Vendor/Organization Specific Extension (OLD)"}, {NVSE_EXT, "Normal Vendor/Organization Specific Extension"}, {BCMCS_EXT, "BCMCS Session Extension"}, {0, NULL}, }; static value_string_ext a11_ext_types_ext = VALUE_STRING_EXT_INIT(a11_ext_types); static const value_string a11_ext_stypes[]= { {1, "MN AAA Extension"}, {0, NULL}, }; static const value_string a11_ext_nvose_qosmode[]= { {0x00, "QoS Disabled"}, {0x01, "QoS Enabled"}, {0, NULL}, }; static const value_string a11_ext_nvose_srvopt[]= { {0x0021, "3G High Speed Packet Data"}, {0x003B, "HRPD Main Service Connection"}, {0x003C, "Link Layer Assisted Header Removal"}, {0x003D, "Link Layer Assisted Robust Header Compression"}, {0x0040, "HRPD Accounting Records Identifier"}, /* 3GPP2 A.S0009-C v4.0 */ {0x0043, "HRPD Packet Data IP Service where Higher Layer Protocol is IP or ROHC"}, /* 3GPP2 A.S0009-C v4.0 */ {0x0047, "HRPD AltPPP operation"}, /* 3GPP2 A.S0009-C v4.0 */ {0, NULL}, }; static const value_string a11_ext_nvose_pdsn_code[]= { {0xc1, "Connection Release - reason unspecified"}, {0xc2, "Connection Release - PPP time-out"}, {0xc3, "Connection Release - registration time-out"}, {0xc4, "Connection Release - PDSN error"}, {0xc5, "Connection Release - inter-PCF handoff"}, {0xc6, "Connection Release - inter-PDSN handoff"}, {0xc7, "Connection Release - PDSN OAM&P intervention"}, {0xc8, "Connection Release - accounting error"}, {0xca, "Connection Release - user (NAI) failed authentication"}, {0x00, NULL}, }; static const value_string a11_ext_dormant[]= { {0x0000, "all MS packet data service instances are dormant"}, {0, NULL}, }; static const true_false_string a11_tfs_ehrpd_mode = { "eAT is operating in evolved mode", "eAT is operating in legacy mode" }; /* 3GPP2 A.S0022-0 v2.0, section 4.2.14 */ static const true_false_string a11_tfs_ehrpd_pmk = { "eAT is requesting PMK information", "eAT is not requesting PMK information", }; /* 3GPP2 A.S0022-0 v2.0, section 4.2.14 */ static const true_false_string a11_tfs_ehrpd_handoff_info = { "eAT is requesting information for E-UTRAN handoff", "eAT is not requesting information for E-UTRAN handoff", }; /* 3GPP2 A.S0022-0 v2.0, section 4.2.14 */ static const true_false_string a11_tfs_ehrpd_tunnel_mode = { "eAT is communicating via tunnel from non-eHRPD", "eAT is communicating directly via eHRPD", }; static const value_string a11_ext_app[]= { {0x0101, "Accounting (RADIUS)"}, {0x0102, "Accounting (DIAMETER)"}, {0x0201, "Mobility Event Indicator (Mobility)"}, {0x0301, "Data Available Indicator (Data Ready to Send)"}, {0x0401, "Access Network Identifiers (ANID)"}, {0x0501, "PDSN Identifiers (Anchor P-P Address)"}, {0x0601, "Indicators (All Dormant Indicator)"}, {0x0602, "Indicators (eHRPD Mode)"}, /* 3GPP2 A.S0022-B v1.0 */ {0x0603, "Indicators (eHRPD Indicators)"}, /* 3GPP2 A.S0009-C v4.0 */ {0x0701, "PDSN Code (PDSN Code)"}, {0x0801, "Session Parameter (RN-PDIT:Radio Network Packet Data Inactivity Timer)"}, {0x0802, "Session Parameter (Always On)"}, {0x0803, "Session Parameter (QoS Mode)"}, {0x0901, "Service Option (Service Option Value)"}, {0x0A01, "PDSN Enabled Features (Flow Control Enabled)"}, {0x0A02, "PDSN Enabled Features (Packet Boundary Enabled)"}, {0x0A03, "PDSN Enabled Features (GRE Segmentation Enabled)"}, {0x0B01, "PCF Enabled Features (Short Data Indication Supported)"}, {0x0B02, "PCF Enabled Features (GRE Segmentation Enabled)"}, {0x0C01, "Additional Session Info"}, {0x0D01, "QoS Information (Forward QoS Information)"}, {0x0D02, "QoS Information (Reverse QoS Information)"}, {0x0D03, "QoS Information (Subscriber QoS Profile)"}, {0x0D04, "QoS Information (Forward Flow Priority Update Information)"}, {0x0D05, "QoS Information (Reverse Flow Priority Update Information)"}, {0x0DFE, "QoS Information (Forward QoS Update Information)"}, {0x0DFF, "QoS Information (Reverse QoS Update Information)"}, {0x0E01, "Header Compression (ROHC Configuration Parameters)"}, {0x0F01, "Information (Cause Code)"}, {0x0F04, "Information (Additional HSGW Information)"}, {0x1001, "HRPD Indicators (Emergency Services)"}, {0xB001, "System Identifiers (BSID / HRPD Subnet)"}, {0, NULL}, }; static value_string_ext a11_ext_app_ext = VALUE_STRING_EXT_INIT(a11_ext_app); #if 0 static const value_string a11_airlink_types[]= { {1, "Session Setup (Y=1)"}, {2, "Active Start (Y=2)"}, {3, "Active Stop (Y=3)"}, {4, "Short Data Burst (Y=4)"}, {0, NULL}, }; #endif static const value_string a11_bcmcs_stype_vals[] = { {1, "BCMCS Flow and Registration Information"}, {2, "Session Information"}, {3, "BCMCS Registration Result"}, {4, "Enhanced Session Information"}, {0, NULL}, }; #define A11_MSG_MSID_ELEM_LEN_MAX 8 #define A11_MSG_MSID_LEN_MAX 15 /* XXXX ToDo This should be imported from packet-rohc.h */ static const value_string a11_rohc_profile_vals[] = { { 0x0000, "ROHC uncompressed" }, /*RFC 5795*/ { 0x0001, "ROHC RTP" }, /*RFC 3095*/ { 0x0002, "ROHC UDP" }, /*RFC 3095*/ { 0x0003, "ROHC ESP" }, /*RFC 3095*/ { 0x0004, "ROHC IP" }, /*RFC 3843*/ { 0x0005, "ROHC LLA" }, /*RFC 3242*/ { 0x0006, "ROHC TCP" }, /*RFC 4996*/ { 0x0007, "ROHC RTP/UDP-Lite" }, /*RFC 4019*/ { 0x0008, "ROHC UDP-Lite" }, /*RFC 4019*/ { 0x0101, "ROHCv2 RTP" }, /*RFC 5225*/ { 0x0102, "ROHCv2 UDP" }, /*RFC 5225*/ { 0x0103, "ROHCv2 ESP" }, /*RFC 5225*/ { 0x0104, "ROHCv2 IP" }, /*RFC 5225*/ { 0x0105, "ROHC LLA with R-mode" }, /*RFC 3408*/ { 0x0107, "ROHCv2 RTP/UDP-Lite" }, /*RFC 5225*/ { 0x0108, "ROHCv2 UDP-Lite" }, /*RFC 5225*/ { 0, NULL }, }; static value_string_ext a11_rohc_profile_vals_ext = VALUE_STRING_EXT_INIT(a11_rohc_profile_vals); /* decode MSID from SSE */ /* MSID is encoded in Binary Coded Decimal format First Byte: [odd-indicator] [Digit 1] Second Byte: [Digit 3] [Digit 2] .. if[odd] Last Byte: [Digit N] [Digit N-1] else Last Byte: [F] [Digit N] */ /* 3GPP2 A.S0008-C v4.0, 3GPP2 A.S0019-A v2.0 */ static const value_string a11_ses_msid_type_vals[] = { { 0x0000, "No Identity Code" }, { 0x0001, "MEID" }, { 0x0005, "ESN" }, { 0x0006, "IMSI" }, { 0x0008, "BCMCS Flow ID" }, { 0, NULL }, }; static int * const a11_flags[] = { &hf_a11_s, &hf_a11_b, &hf_a11_d, &hf_a11_m, &hf_a11_g, &hf_a11_v, &hf_a11_t, NULL }; static void decode_sse(proto_tree *ext_tree, packet_info *pinfo, tvbuff_t *tvb, int offset, unsigned ext_len, proto_item *ext_len_item) { uint8_t msid_len; uint8_t msid_start_offset; uint8_t msid_num_digits; uint8_t msid_index; char *msid_digits; const char *p_msid; bool odd_even_ind; /* Decode Protocol Type */ if (ext_len < 2) { expert_add_info_format(pinfo, ext_len_item, &ei_a11_sse_too_short, "Cannot decode Protocol Type - SSE too short"); return; } proto_tree_add_item(ext_tree, hf_a11_ses_ptype, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; ext_len -= 2; /* Decode Session Key */ if (ext_len < 4) { expert_add_info_format(pinfo, ext_len_item, &ei_a11_sse_too_short, "Cannot decode Session Key - SSE too short"); return; } proto_tree_add_item(ext_tree, hf_a11_ses_key, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; ext_len -= 4; /* Decode Session Id Version */ if (ext_len < 2) { expert_add_info_format(pinfo, ext_len_item, &ei_a11_sse_too_short, "Cannot decode Session Id Version - SSE too short"); return; } proto_tree_add_item(ext_tree, hf_a11_ses_sidver, tvb, offset+1, 1, ENC_BIG_ENDIAN); offset += 2; ext_len -= 2; /* Decode SRID */ if (ext_len < 2) { expert_add_info_format(pinfo, ext_len_item, &ei_a11_sse_too_short, "Cannot decode SRID - SSE too short"); return; } proto_tree_add_item(ext_tree, hf_a11_ses_mnsrid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; ext_len -= 2; /* MSID Type */ if (ext_len < 2) { expert_add_info_format(pinfo, ext_len_item, &ei_a11_sse_too_short, "Cannot decode MSID Type - SSE too short"); return; } proto_tree_add_item(ext_tree, hf_a11_ses_msid_type, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; ext_len -= 2; /* MSID Len */ if (ext_len < 1) { expert_add_info_format(pinfo, ext_len_item, &ei_a11_sse_too_short, "Cannot decode MSID Length - SSE too short"); return; } msid_len = tvb_get_uint8(tvb, offset); proto_tree_add_item(ext_tree, hf_a11_ses_msid_len, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; ext_len -= 1; /* Decode MSID */ if (ext_len < msid_len) { expert_add_info_format(pinfo, ext_len_item, &ei_a11_sse_too_short, "Cannot decode MSID - SSE too short"); return; } msid_digits = (char *)wmem_alloc(pinfo->pool, A11_MSG_MSID_LEN_MAX+2); msid_start_offset = offset; if (msid_len > A11_MSG_MSID_ELEM_LEN_MAX) { p_msid = "MSID is too long"; } else if (msid_len == 0) { p_msid = "MSID is too short"; } else { /* Decode the BCD digits */ for (msid_index=0; msid_index> 4) + '0'; } odd_even_ind = (msid_digits[0] == '1'); if (odd_even_ind) { msid_num_digits = ((msid_len-1) * 2) + 1; } else { msid_num_digits = (msid_len-1) * 2; } msid_digits[msid_num_digits + 1] = '\0'; p_msid = msid_digits + 1; } proto_tree_add_string(ext_tree, hf_a11_ses_msid, tvb, msid_start_offset, msid_len, p_msid); } static void decode_bcmcs(proto_tree* ext_tree, packet_info *pinfo, tvbuff_t* tvb, int offset, unsigned ext_len, proto_item *ext_len_item) { uint8_t bc_stype, entry_len; /* Decode Protocol Type */ if (ext_len < 2) { expert_add_info_format(pinfo, ext_len_item, &ei_a11_bcmcs_too_short, "Cannot decode Protocol Type - BCMCS too short"); return; } bc_stype=tvb_get_uint8(tvb, offset); proto_tree_add_item(ext_tree, hf_a11_bcmcs_stype, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; ext_len -= 1; switch (bc_stype) { case 1: { int i = 0; proto_tree *entry_tree; while (ext_len > 0) { i++; entry_len = tvb_get_uint8(tvb, offset); if (entry_len == 0) { ext_len -= 1; entry_len = 1; } else { ext_len = ext_len - entry_len; } entry_tree = proto_tree_add_subtree_format(ext_tree, tvb, offset, entry_len, ett_a11_bcmcs_entry, NULL, "BCMCS Information Entry %u", i); proto_tree_add_item(entry_tree, hf_a11_bcmcs_entry_len, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_expert(ext_tree, pinfo, &ei_a11_entry_data_not_dissected, tvb, offset, entry_len -1); offset = offset+entry_len; } } break; default: proto_tree_add_expert_format(ext_tree, pinfo, &ei_a11_session_data_not_dissected, tvb, offset, -1, "Session Data Type %u Not dissected yet", bc_stype); return; } } /* RADIUS attributed */ static void dissect_a11_radius( tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, int app_len) { proto_tree *radius_tree; /* None of this really matters if we don't have a tree */ if (!tree) return; /* return if length of extension is not valid */ if (tvb_reported_length_remaining(tvb, offset) < 12) { return; } radius_tree = proto_tree_add_subtree(tree, tvb, offset - 2, app_len, ett_a11_radiuses, NULL, "Airlink Record"); dissect_attribute_value_pairs(radius_tree, pinfo, tvb, offset, app_len-2, NULL); } /* X.S0011-005-D v2.0 Service Option Profile */ static const char * dissect_3gpp2_service_option_profile(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo) { int offset = 0; uint8_t sub_type, sub_type_length; proto_item *pi; /* Maximum service connections/Link Flows total 32 bit*/ proto_tree_add_item(tree, hf_a11_serv_opt_prof_max_serv, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; while (tvb_reported_length_remaining(tvb,offset) > 0) { sub_type_length = tvb_get_uint8(tvb,offset+1); sub_type = tvb_get_uint8(tvb,offset); proto_tree_add_item(tree, hf_a11_sub_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; pi = proto_tree_add_item(tree, hf_a11_sub_type_length, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (sub_type_length < 2) { expert_add_info(pinfo, pi, &ei_a11_sub_type_length_not2); sub_type_length = 2; } if (sub_type == 1) { proto_tree_add_item(tree, hf_a11_serv_opt, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Max number of service instances of Service Option n */ proto_tree_add_item(tree, hf_a11_max_num_serv_opt, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } offset = offset + sub_type_length-2; } return ""; } static const value_string a11_aut_flow_prof_subtype_vals[] = { {0x1, "ProfileID-Forward"}, {0x2, "ProfileID-Reverse"}, {0x3, "ProfileID-Bi-direction"}, {0, NULL}, }; /* X.S0011-005-D v2.0 Authorized Flow Profile IDs for the User */ static const char * dissect_3gpp2_radius_aut_flow_profile_ids(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo) { proto_tree *sub_tree; int offset = 0; proto_item *item; uint8_t sub_type, sub_type_length; uint32_t value; while (tvb_reported_length_remaining(tvb,offset) > 0) { sub_type = tvb_get_uint8(tvb,offset); sub_type_length = tvb_get_uint8(tvb,offset+1); /* value is 2 octets */ value = tvb_get_ntohs(tvb,offset+2); sub_tree = proto_tree_add_subtree_format(tree, tvb, offset, sub_type_length, ett_a11_aut_flow_profile_ids, &item, "%s = %u", val_to_str_const(sub_type, a11_aut_flow_prof_subtype_vals, "Unknown"), value); proto_tree_add_item(sub_tree, hf_a11_aut_flow_prof_sub_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; item = proto_tree_add_item(sub_tree, hf_a11_aut_flow_prof_sub_type_len, tvb, offset, 1, ENC_BIG_ENDIAN); if (sub_type_length < 2) { expert_add_info(pinfo, item, &ei_a11_sub_type_length_not2); sub_type_length = 2; } offset += 1; proto_tree_add_item(sub_tree, hf_a11_aut_flow_prof_sub_type_value, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset+sub_type_length - 2; } return ""; } /* Code to dissect Additional Session Info */ static void dissect_ase(tvbuff_t *tvb, int offset, unsigned ase_len, proto_tree *ext_tree) { unsigned clen = 0; /* consumed length */ while (clen < ase_len) { proto_tree *exts_tree; uint8_t srid = tvb_get_uint8(tvb, offset+1); uint16_t service_option = tvb_get_ntohs(tvb, offset+2); uint8_t entry_length; int entry_start_offset; /* Entry Length */ entry_start_offset = offset; entry_length = tvb_get_uint8(tvb, offset); if (registration_request_msg && ((service_option == 64) || (service_option == 67))) exts_tree = proto_tree_add_subtree_format(ext_tree, tvb, offset, entry_length+1, ett_a11_ase, NULL, "GRE Key Entry (SRID: %d)", srid); else exts_tree = proto_tree_add_subtree_format(ext_tree, tvb, offset, entry_length, ett_a11_ase, NULL, "GRE Key Entry (SRID: %d)", srid); proto_tree_add_item(exts_tree, hf_a11_ase_len_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* SRID */ proto_tree_add_item(exts_tree, hf_a11_ase_srid_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Service Option */ proto_tree_add_item(exts_tree, hf_a11_ase_servopt_type, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* GRE Protocol Type*/ proto_tree_add_item(exts_tree, hf_a11_ase_gre_proto_type, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* GRE Key */ proto_tree_add_item(exts_tree, hf_a11_ase_gre_key, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* PCF IP Address */ proto_tree_add_item(exts_tree, hf_a11_ase_pcf_addr_key, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; if ((entry_length>14)&&(registration_request_msg)) { if (service_option == 0x0043) { proto_tree *extv_tree; uint8_t profile_count = tvb_get_uint8(tvb, offset+6); uint8_t profile_index = 0; uint8_t reverse_profile_count; proto_tree *extt_tree = proto_tree_add_subtree(exts_tree, tvb, offset,6+(profile_count*2)+1, ett_a11_forward_rohc, NULL, "Forward ROHC Info"); proto_tree_add_item(extt_tree, hf_a11_ase_forward_rohc_info_len, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(extt_tree, hf_a11_ase_forward_maxcid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(extt_tree, hf_a11_ase_forward_mrru, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(extt_tree, hf_a11_ase_forward_large_cids, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; profile_count=tvb_get_uint8(tvb, offset); proto_tree_add_item(extt_tree, hf_a11_ase_forward_profile_count, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; for (profile_index=0; profile_index 0) { /* Get our extension info */ ext_type = tvb_get_uint8(tvb, offset); if (ext_type == GEN_AUTH_EXT) { /* * Very nasty . . breaks normal extensions, since the length is * in the wrong place :( */ ext_subtype = tvb_get_uint8(tvb, offset + 1); ext_len = tvb_get_ntohs(tvb, offset + 2); hdrLen = 4; } else if ((ext_type == CVSE_EXT) || (ext_type == OLD_CVSE_EXT)) { ext_len = tvb_get_ntohs(tvb, offset + 2); ext_subtype = tvb_get_uint8(tvb, offset + 8); hdrLen = 4; } else { ext_len = tvb_get_uint8(tvb, offset + 1); hdrLen = 2; } ext_tree = proto_tree_add_subtree_format(exts_tree, tvb, offset, ext_len + hdrLen, ett_a11_ext, NULL, "Extension: %s", val_to_str_ext(ext_type, &a11_ext_types_ext, "Unknown Extension %u")); proto_tree_add_uint(ext_tree, hf_a11_ext_type, tvb, offset, 1, ext_type); offset += 1; if (ext_type == SS_EXT) { ext_len_item = proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 1, ext_len); offset += 1; } else if ((ext_type == CVSE_EXT) || (ext_type == OLD_CVSE_EXT)) { offset += 1; ext_len_item = proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 2, ext_len); offset += 2; } else if (ext_type != GEN_AUTH_EXT) { /* Another nasty hack since GEN_AUTH_EXT broke everything */ ext_len_item = proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 1, ext_len); offset += 1; } switch (ext_type) { case SS_EXT: decode_sse(ext_tree, pinfo, tvb, offset, ext_len, ext_len_item); offset += ext_len; ext_len = 0; break; case MH_AUTH_EXT: case MF_AUTH_EXT: case FH_AUTH_EXT: case RU_AUTH_EXT: /* All these extensions look the same. 4 byte SPI followed by a key */ if (ext_len < 4) break; proto_tree_add_item(ext_tree, hf_a11_aext_spi, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; ext_len -= 4; if (ext_len == 0) break; proto_tree_add_item(ext_tree, hf_a11_aext_auth, tvb, offset, ext_len, ENC_NA); break; case MN_NAI_EXT: if (ext_len == 0) break; /* * RFC 2486 speaks only of ASCII; RFC 4282 expands that to * UTF-8. */ proto_tree_add_item(ext_tree, hf_a11_next_nai, tvb, offset, ext_len, ENC_UTF_8); break; case GEN_AUTH_EXT: /* RFC 3012 */ /* * Very nasty . . breaks normal extensions, since the length is * in the wrong place :( */ proto_tree_add_uint(ext_tree, hf_a11_ext_stype, tvb, offset, 1, ext_subtype); offset += 1; proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 2, ext_len); offset += 2; /* SPI */ if (ext_len < 4) break; proto_tree_add_item(ext_tree, hf_a11_aext_spi, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; ext_len -= 4; /* Key */ if (ext_len == 0) break; proto_tree_add_item(ext_tree, hf_a11_aext_auth, tvb, offset, ext_len, ENC_NA); break; case OLD_CVSE_EXT: /* RFC 3115 */ case CVSE_EXT: /* RFC 3115 */ if (ext_len < 4) break; proto_tree_add_item(ext_tree, hf_a11_vse_vid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; ext_len -= 4; if (ext_len < 2) break; apptype = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(ext_tree, hf_a11_vse_apptype, tvb, offset, 2, apptype); offset += 2; ext_len -= 2; if (apptype == 0x0101) { if (tvb_reported_length_remaining(tvb, offset) > 0) { dissect_a11_radius(tvb, pinfo, offset, ext_tree, ext_len + 2); } } break; case OLD_NVSE_EXT: /* RFC 3115 */ case NVSE_EXT: /* RFC 3115 */ if (ext_len < 6) break; proto_tree_add_item(ext_tree, hf_a11_vse_vid, tvb, offset+2, 4, ENC_BIG_ENDIAN); offset += 6; ext_len -= 6; proto_tree_add_item(ext_tree, hf_a11_vse_apptype, tvb, offset, 2, ENC_BIG_ENDIAN); if (ext_len < 2) break; apptype = tvb_get_ntohs(tvb, offset); offset += 2; ext_len -= 2; switch (apptype) { case 0x0401: if (ext_len < 5) break; proto_tree_add_item(ext_tree, hf_a11_vse_panid, tvb, offset, 5, ENC_NA); offset += 5; ext_len -= 5; if (ext_len < 5) break; proto_tree_add_item(ext_tree, hf_a11_vse_canid, tvb, offset, 5, ENC_NA); break; case 0x0501: if (ext_len < 4) break; proto_tree_add_item(ext_tree, hf_a11_vse_ppaddr, tvb, offset, 4, ENC_BIG_ENDIAN); break; case 0x0601: if (ext_len < 2) break; proto_tree_add_item(ext_tree, hf_a11_vse_dormant, tvb, offset, 2, ENC_BIG_ENDIAN); break; case 0x0602: /* eHRPD Mode */ if (ext_len < 1) break; proto_tree_add_item(ext_tree, hf_a11_vse_ehrpd_mode, tvb, offset, 1, ENC_BIG_ENDIAN); break; case 0x0603: /* eHRPD Indicators */ if (ext_len < 1) break; proto_tree_add_item(ext_tree, hf_a11_vse_ehrpd_pmk, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ext_tree, hf_a11_vse_ehrpd_handoff_info, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ext_tree, hf_a11_vse_ehrpd_tunnel_mode, tvb, offset, 1, ENC_BIG_ENDIAN); break; case 0x0701: if (ext_len < 1) break; proto_tree_add_item(ext_tree, hf_a11_vse_code, tvb, offset, 1, ENC_BIG_ENDIAN); break; case 0x0801: if (ext_len < 1) break; proto_tree_add_item(ext_tree, hf_a11_vse_pdit, tvb, offset, 1, ENC_BIG_ENDIAN); break; case 0x0802: proto_tree_add_item(ext_tree, hf_a11_vse_session_parameter, tvb, offset, -1, ENC_NA); break; case 0x0803: proto_tree_add_item(ext_tree, hf_a11_vse_qosmode, tvb, offset, 1, ENC_BIG_ENDIAN); break; case 0x0901: if (ext_len < 2) break; proto_tree_add_item(ext_tree, hf_a11_vse_srvopt, tvb, offset, 2, ENC_BIG_ENDIAN); break; case 0x0C01: dissect_ase(tvb, offset, ext_len, ext_tree); break; case 0x0D01: dissect_fwd_qosinfo(tvb, offset, ext_tree); break; case 0x0D02: dissect_rev_qosinfo(tvb, offset, ext_tree); break; case 0x0D03: dissect_subscriber_qos_profile(tvb, pinfo, offset, ext_len, ext_tree); break; case 0x0DFE: dissect_fwd_qosupdate_info(tvb, offset, ext_tree); break; case 0x0DFF: dissect_rev_qosupdate_info(tvb, offset, ext_tree); break; } break; case BCMCS_EXT: decode_bcmcs(ext_tree, pinfo, tvb, offset, ext_len, ext_len_item); offset += ext_len; ext_len = 0; break; case MF_CHALLENGE_EXT: /* RFC 3012 */ /* The default dissector is good here. The challenge is all hex anyway. */ default: proto_tree_add_item(ext_tree, hf_a11_ext, tvb, offset, ext_len, ENC_NA); break; } /* ext type */ offset += ext_len; } /* while data remaining */ } /* dissect_a11_extensions */ /* Code to actually dissect the packets */ static int dissect_a11( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { /* Set up structures we will need to add the protocol subtree and manage it */ proto_item *ti; proto_tree *a11_tree = NULL; uint8_t type; unsigned offset = 0; if (!tvb_bytes_exist(tvb, offset, 1)) return 0; /* not enough data to check message type */ type = tvb_get_uint8(tvb, offset); if (try_val_to_str_ext(type, &a11_types_ext) == NULL) return 0; /* not a known message type */ /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "3GPP2 A11"); col_clear(pinfo->cinfo, COL_INFO); if (type == REGISTRATION_REQUEST) registration_request_msg =1; else registration_request_msg =0; switch (type) { case REGISTRATION_REQUEST: registration_request_msg = 1; col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Request: PDSN=%s PCF=%s", tvb_ip_to_str(pinfo->pool, tvb, 8), tvb_ip_to_str(pinfo->pool, tvb, 12)); if (tree) { ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* flags */ proto_tree_add_bitmask(a11_tree, tvb, offset, hf_a11_flags, ett_a11_flags, a11_flags, ENC_NA); offset += 1; /* lifetime */ proto_tree_add_item(a11_tree, hf_a11_life, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2; /* home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* home agent address */ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Care of Address */ proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case REGISTRATION_REPLY: col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Reply: PDSN=%s, Code=%u", tvb_ip_to_str(pinfo->pool, tvb, 8), tvb_get_uint8(tvb,1)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* Type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* Reply Code */ proto_tree_add_item(a11_tree, hf_a11_code, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Registration Lifetime */ proto_tree_add_item(a11_tree, hf_a11_life, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Home Agent Address */ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case REGISTRATION_UPDATE: col_add_fstr(pinfo->cinfo, COL_INFO,"Reg Update: PDSN=%s", tvb_ip_to_str(pinfo->pool, tvb, 8)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* Type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* Reserved */ offset += 3; /* Home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Home Agent Address */ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case REGISTRATION_ACK: col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Ack: PCF=%s Status=%u", tvb_ip_to_str(pinfo->pool, tvb, 8), tvb_get_uint8(tvb,3)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* Type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* Reserved */ offset += 2; /* Ack Status */ proto_tree_add_item(a11_tree, hf_a11_status, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Care of Address */ proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case SESSION_UPDATE: /* IOS4.3 */ col_add_fstr(pinfo->cinfo, COL_INFO,"Ses Update: PDSN=%s", tvb_ip_to_str(pinfo->pool, tvb, 8)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* Type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* Reserved */ offset += 3; /* Home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Home Agent Address */ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case SESSION_ACK: /* IOS4.3 */ col_add_fstr(pinfo->cinfo, COL_INFO, "Ses Upd Ack: PCF=%s, Status=%u", tvb_ip_to_str(pinfo->pool, tvb, 8), tvb_get_uint8(tvb,3)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* Type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* Reserved */ offset += 2; /* Ack Status */ proto_tree_add_item(a11_tree, hf_a11_status, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Care of Address */ proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case CAPABILITIES_INFO: /* IOS5.1 */ col_add_fstr(pinfo->cinfo, COL_INFO, "Cap Info: PDSN=%s, PCF=%s", tvb_ip_to_str(pinfo->pool, tvb, 8), tvb_ip_to_str(pinfo->pool, tvb, 12)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* Type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* Reserved */ offset += 3; /* Home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Home Agent Address */ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Care of Address */ proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case CAPABILITIES_INFO_ACK: /* IOS5.1 */ col_add_fstr(pinfo->cinfo, COL_INFO, "Cap Info Ack: PCF=%s", tvb_ip_to_str(pinfo->pool, tvb, 8)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* Type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* Reserved */ offset += 3; /* Home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Care of Address */ proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case BC_SERVICE_REQUEST: col_add_fstr(pinfo->cinfo, COL_INFO, "Service Request: PCF=%s ", tvb_ip_to_str(pinfo->pool, tvb, offset + 8)); if (tree) { ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 4; /* home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Care-of-Address */ proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case BC_SERVICE_REPLY: col_add_fstr(pinfo->cinfo, COL_INFO, "Service Response: BSN=%s ", tvb_ip_to_str(pinfo->pool, tvb, offset + 8)); if (tree) { ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 3; /* Reply Code */ proto_tree_add_item(a11_tree, hf_a11_code, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Home Agent */ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case BC_REGISTRATION_REQUEST: col_add_fstr(pinfo->cinfo, COL_INFO, "BC Reg Request: BSN=%s ", tvb_ip_to_str(pinfo->pool, tvb, offset + 8)); if (tree) { ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* flags */ proto_tree_add_bitmask(a11_tree, tvb, offset, hf_a11_flags, ett_a11_flags, a11_flags, ENC_NA); offset += 1; /* lifetime */ proto_tree_add_item(a11_tree, hf_a11_life, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2; /* home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Home Agent */ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Care-of-Address */ proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case BC_REGISTRATION_REPLY: col_add_fstr(pinfo->cinfo, COL_INFO, "BC Reg Reply: BSN=%s, Code=%u", tvb_ip_to_str(pinfo->pool, tvb, offset + 8), tvb_get_uint8(tvb, offset + 1)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* Type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* Reply Code */ proto_tree_add_item(a11_tree, hf_a11_code, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Registration Lifetime */ proto_tree_add_item(a11_tree, hf_a11_life, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Home Agent */ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case BC_REGISTRATION_UPDATE: col_add_fstr(pinfo->cinfo, COL_INFO,"BC Reg Update: BSN=%s", tvb_ip_to_str(pinfo->pool, tvb, offset + 8)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* Type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* Reserved */ offset += 3; /* Home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Home Agent */ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; case BC_REGISTRATION_ACK: col_add_fstr(pinfo->cinfo, COL_INFO, "BC Reg Acknowledge: PCF=%s Status=%u", tvb_ip_to_str(pinfo->pool, tvb, offset + 8), tvb_get_uint8(tvb, offset + 3)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, ENC_NA); a11_tree = proto_item_add_subtree(ti, ett_a11); /* Type */ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type); offset += 1; /* Reserved */ offset += 2; /* Ack Status */ proto_tree_add_item(a11_tree, hf_a11_status, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Home address */ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Care-of-Address */ proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Identifier - assumed to be an NTP time here */ proto_tree_add_item(a11_tree, hf_a11_ident, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); offset += 8; } /* if tree */ break; default: DISSECTOR_ASSERT_NOT_REACHED(); break; } /* End switch */ if (tree && a11_tree) { if (tvb_reported_length_remaining(tvb, offset) > 0) dissect_a11_extensions(tvb, pinfo, offset, a11_tree); } return tvb_reported_length(tvb); } /* dissect_a11 */ /* Register the protocol with Wireshark */ void proto_register_a11(void) { /* Setup list of header fields */ static hf_register_info hf[] = { { &hf_a11_type, { "Message Type", "a11.type", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &a11_types_ext, 0, "A11 Message Type", HFILL } }, { &hf_a11_flags, { "Flags", "a11.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} }, { &hf_a11_s, { "Simultaneous Bindings", "a11.s", FT_BOOLEAN, 8, NULL, 128, "Simultaneous Bindings Allowed", HFILL } }, { &hf_a11_b, { "Broadcast Datagrams", "a11.b", FT_BOOLEAN, 8, NULL, 64, "Broadcast Datagrams requested", HFILL } }, { &hf_a11_d, { "Co-located Care-of Address", "a11.d", FT_BOOLEAN, 8, NULL, 32, "MN using Co-located Care-of address", HFILL } }, { &hf_a11_m, { "Minimal Encapsulation", "a11.m", FT_BOOLEAN, 8, NULL, 16, "MN wants Minimal encapsulation", HFILL } }, { &hf_a11_g, { "GRE", "a11.g", FT_BOOLEAN, 8, NULL, 8, "MN wants GRE encapsulation", HFILL } }, { &hf_a11_v, { "Van Jacobson", "a11.v", FT_BOOLEAN, 8, NULL, 4, NULL, HFILL } }, { &hf_a11_t, { "Reverse Tunneling", "a11.t", FT_BOOLEAN, 8, NULL, 2, "Reverse tunneling requested", HFILL } }, { &hf_a11_code, { "Reply Code", "a11.code", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &a11_reply_codes_ext, 0, "A11 Registration Reply code", HFILL } }, { &hf_a11_status, { "Reply Status", "a11.ackstat", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &a11_ack_status_ext, 0, "A11 Registration Ack Status", HFILL } }, { &hf_a11_life, { "Lifetime", "a11.life", FT_UINT16, BASE_DEC, NULL, 0, "A11 Registration Lifetime", HFILL } }, { &hf_a11_homeaddr, { "Home Address", "a11.homeaddr", FT_IPv4, BASE_NONE, NULL, 0, "Mobile Node's home address", HFILL } }, { &hf_a11_haaddr, { "Home Agent", "a11.haaddr", FT_IPv4, BASE_NONE, NULL, 0, "Home agent IP Address", HFILL } }, { &hf_a11_coa, { "Care of Address", "a11.coa", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_ident, { "Identification", "a11.ident", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, "MN Identification", HFILL } }, { &hf_a11_ext_type, { "Extension Type", "a11.ext.type", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &a11_ext_types_ext, 0, "Mobile IP Extension Type", HFILL } }, { &hf_a11_ext_stype, { "Gen Auth Ext SubType", "a11.ext.auth.subtype", FT_UINT8, BASE_DEC, VALS(a11_ext_stypes), 0, "Mobile IP Auth Extension Sub Type", HFILL } }, { &hf_a11_ext_len, { "Extension Length", "a11.ext.len", FT_UINT16, BASE_DEC, NULL, 0, "Mobile IP Extension Length", HFILL } }, { &hf_a11_ext, { "Extension", "a11.extension", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_aext_spi, { "SPI", "a11.auth.spi", FT_UINT32, BASE_HEX, NULL, 0, "Authentication Header Security Parameter Index", HFILL } }, { &hf_a11_aext_auth, { "Authenticator", "a11.auth.auth", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_next_nai, { "NAI", "a11.nai", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_ses_key, { "Key", "a11.ext.key", FT_UINT32, BASE_HEX, NULL, 0, "Session Key", HFILL } }, { &hf_a11_ses_sidver, { "Session ID Version", "a11.ext.sidver", FT_UINT8, BASE_DEC, NULL, 3, NULL, HFILL} }, { &hf_a11_ses_mnsrid, { "MNSR-ID", "a11.ext.mnsrid", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_a11_ses_msid_type, { "MSID Type", "a11.ext.msid_type", FT_UINT16, BASE_DEC, VALS(a11_ses_msid_type_vals), 0, NULL, HFILL } }, { &hf_a11_ses_msid_len, { "MSID Length", "a11.ext.msid_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_ses_msid, { "MSID(BCD)", "a11.ext.msid", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_ses_ptype, { "Protocol Type", "a11.ext.ptype", FT_UINT16, BASE_HEX, VALS(a11_ses_ptype_vals), 0, NULL, HFILL } }, { &hf_a11_vse_vid, { "Vendor ID", "a11.ext.vid", FT_UINT32, BASE_ENTERPRISES, STRINGS_ENTERPRISES, 0, NULL, HFILL } }, { &hf_a11_vse_apptype, { "Application Type", "a11.ext.apptype", FT_UINT16, BASE_HEX | BASE_EXT_STRING, &a11_ext_app_ext, 0, NULL, HFILL } }, { &hf_a11_vse_ppaddr, { "Anchor P-P Address", "a11.ext.ppaddr", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_vse_dormant, { "All Dormant Indicator", "a11.ext.dormant", FT_UINT16, BASE_HEX, VALS(a11_ext_dormant), 0, NULL, HFILL } }, { &hf_a11_vse_ehrpd_mode, { "eHRPD Mode", "a11.ext.ehrpd.mode", FT_BOOLEAN, BASE_NONE, TFS(&a11_tfs_ehrpd_mode), 0, NULL, HFILL } }, { &hf_a11_vse_ehrpd_pmk, { "PMK", "a11.ext.ehrpd.pmk", FT_BOOLEAN, 8, TFS(&a11_tfs_ehrpd_pmk), 0x04, NULL, HFILL } }, { &hf_a11_vse_ehrpd_handoff_info, { "E-UTRAN Handoff Info", "a11.ext.ehrpd.handoff_info", FT_BOOLEAN, 8, TFS(&a11_tfs_ehrpd_handoff_info), 0x02, NULL, HFILL } }, { &hf_a11_vse_ehrpd_tunnel_mode, { "Tunnel Mode", "a11.ext.ehrpd.tunnel_mode", FT_BOOLEAN, 8, TFS(&a11_tfs_ehrpd_tunnel_mode), 0x01, NULL, HFILL } }, { &hf_a11_vse_code, { "Reply Code", "a11.ext.code", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &a11_reply_codes_ext, 0, NULL, HFILL } }, /* XXX: Is this the correct filter name ?? */ { &hf_a11_vse_pdit, { "PDSN Code", "a11.ext.code", FT_UINT8, BASE_HEX, VALS(a11_ext_nvose_pdsn_code), 0, NULL, HFILL } }, { &hf_a11_vse_session_parameter, { "Session Parameter - Always On", "a11.ext.session_parameter", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_vse_srvopt, { "Service Option", "a11.ext.srvopt", FT_UINT16, BASE_HEX, VALS(a11_ext_nvose_srvopt), 0, NULL, HFILL } }, { &hf_a11_vse_panid, { "PANID", "a11.ext.panid", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_vse_canid, { "CANID", "a11.ext.canid", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_vse_qosmode, { "QoS Mode", "a11.ext.qosmode", FT_UINT8, BASE_HEX, VALS(a11_ext_nvose_qosmode), 0, NULL, HFILL } }, { &hf_a11_ase_len_type, { "Entry Length", "a11.ext.ase.len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_srid_type, { "Service Reference ID (SRID)", "a11.ext.ase.srid", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_servopt_type, { "Service Option", "a11.ext.ase.srvopt", FT_UINT16, BASE_HEX, VALS(a11_ext_nvose_srvopt), 0, NULL, HFILL } }, { &hf_a11_ase_gre_proto_type, { "GRE Protocol Type", "a11.ext.ase.ptype", FT_UINT16, BASE_HEX, VALS(a11_ses_ptype_vals), 0, NULL, HFILL } }, { &hf_a11_ase_gre_key, { "GRE Key", "a11.ext.ase.key", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_pcf_addr_key, { "PCF IP Address", "a11.ext.ase.pcfip", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_fqi_srid, { "SRID", "a11.ext.fqi.srid", FT_UINT8, BASE_DEC, NULL, 0, "Forward Flow Entry SRID", HFILL } }, { &hf_a11_fqi_flags, { "Flags", "a11.ext.fqi.flags", FT_UINT8, BASE_HEX, NULL, 0, "Forward Flow Entry Flags", HFILL } }, { &hf_a11_fqi_flags_ip_flow, { "IP Flow Discriminator", "a11.ext.fqi.flags.ip_flow", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), A11_FQI_IPFLOW_DISC_ENABLED, NULL, HFILL } }, { &hf_a11_fqi_flags_dscp, { "DSCP", "a11.ext.fqi.flags.dscp", FT_BOOLEAN, 8, TFS(&tfs_included_not_included), A11_FQI_DSCP_INCLUDED, NULL, HFILL } }, { &hf_a11_fqi_entry_flag, { "DSCP and Flow State", "a11.ext.fqi.entry_flag", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_a11_fqi_entry_flag_dscp, { "DSCP", "a11.ext.fqi.entry_flag.dscp", FT_UINT8, BASE_HEX, NULL, 0x7E, NULL, HFILL } }, { &hf_a11_fqi_entry_flag_flow_state, { "Flow State", "a11.ext.fqi.entry_flag.flow_state", FT_BOOLEAN, 8, TFS(&tfs_active_inactive), 0x01, NULL, HFILL } }, { &hf_a11_fqi_flowcount, { "Forward Flow Count", "a11.ext.fqi.flowcount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_fqi_flowid, { "Forward Flow Id", "a11.ext.fqi.flowid", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_fqi_entrylen, { "Entry Length", "a11.ext.fqi.entrylen", FT_UINT8, BASE_DEC, NULL, 0, "Forward Entry Length", HFILL } }, #if 0 { &hf_a11_fqi_flowstate, { "Forward Flow State", "a11.ext.fqi.flowstate", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } }, #endif { &hf_a11_fqi_requested_qoslen, { "Requested QoS Length", "a11.ext.fqi.reqqoslen", FT_UINT8, BASE_DEC, NULL, 0, "Forward Requested QoS Length", HFILL } }, { &hf_a11_fqi_flow_priority, { "Flow Priority", "a11.ext.fqi.flow_priority", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL } }, { &hf_a11_fqi_num_qos_attribute_set, { "Number of QoS Attribute Sets", "a11.ext.fqi.num_qos_attribute_set", FT_UINT8, BASE_DEC, NULL, 0x0E, NULL, HFILL } }, { &hf_a11_fqi_qos_attribute_setlen, { "QoS Attribute Set Length", "a11.ext.fqi.qos_attribute_setlen", FT_UINT16, BASE_DEC, NULL, 0x01E0, NULL, HFILL } }, { &hf_a11_fqi_qos_attribute_setid, { "QoS Attribute SetID", "a11.ext.fqi.qos_attribute_setid", FT_UINT16, BASE_DEC, NULL, 0x1FC0, NULL, HFILL } }, { &hf_a11_fqi_verbose, { "Verbose", "a11.ext.fqi.verbose", FT_UINT8, BASE_DEC, NULL, 0x20, NULL, HFILL } }, { &hf_a11_fqi_flow_profileid, { "Flow Profile Id", "a11.ext.fqi.flow_profileid", FT_UINT24, BASE_DEC, NULL, 0x1FFFE0, NULL, HFILL } }, { &hf_a11_fqi_qos_granted_attribute_setid, { "QoS Attribute SetID", "a11.ext.fqi.qos_granted_attribute_setid", FT_UINT8, BASE_DEC, NULL, 0xFE, NULL, HFILL } }, { &hf_a11_fqi_granted_qoslen, { "Granted QoS Length", "a11.ext.fqi.graqoslen", FT_UINT8, BASE_DEC, NULL, 0, "Forward Granted QoS Length", HFILL } }, { &hf_a11_rqi_flow_priority, { "Flow Priority", "a11.ext.rqi.flow_priority", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL } }, { &hf_a11_rqi_num_qos_attribute_set, { "Number of QoS Attribute Sets", "a11.ext.rqi.num_qos_attribute_set", FT_UINT8, BASE_DEC, NULL, 0x0E, NULL, HFILL } }, { &hf_a11_rqi_qos_attribute_setlen, { "QoS Attribute Set Length", "a11.ext.rqi.qos_attribute_setlen", FT_UINT16, BASE_DEC, NULL, 0x01E0, NULL, HFILL } }, { &hf_a11_rqi_qos_attribute_setid, { "QoS Attribute SetID", "a11.ext.rqi.qos_attribute_setid", FT_UINT16, BASE_DEC, NULL, 0x1FC0, NULL, HFILL } }, { &hf_a11_rqi_verbose, { "Verbose", "a11.ext.rqi.verbose", FT_UINT8, BASE_DEC, NULL, 0x20, NULL, HFILL } }, { &hf_a11_rqi_flow_profileid, { "Flow Profile Id", "a11.ext.rqi.flow_profileid", FT_UINT24, BASE_DEC, NULL, 0x1FFFE0, NULL, HFILL } }, { &hf_a11_rqi_qos_granted_attribute_setid, { "QoS Attribute SetID", "a11.ext.rqi.qos_granted_attribute_setid", FT_UINT8, BASE_DEC, NULL, 0xFE, NULL, HFILL } }, { &hf_a11_rqi_srid, { "SRID", "a11.ext.rqi.srid", FT_UINT8, BASE_DEC, NULL, 0, "Reverse Flow Entry SRID", HFILL } }, { &hf_a11_rqi_flowcount, { "Reverse Flow Count", "a11.ext.rqi.flowcount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_rqi_flowid, { "Reverse Flow Id", "a11.ext.rqi.flowid", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_rqi_entrylen, { "Entry Length", "a11.ext.rqi.entrylen", FT_UINT8, BASE_DEC, NULL, 0, "Reverse Flow Entry Length", HFILL } }, { &hf_a11_rqi_entry_flag, { "Flags", "a11.ext.rqi.entry_flag", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_a11_rqi_entry_flag_flow_state, { "Flow State", "a11.ext.rqi.entry_flag.flow_state", FT_BOOLEAN, 8, TFS(&tfs_active_inactive), 0x01, NULL, HFILL } }, #if 0 { &hf_a11_rqi_flowstate, { "Flow State", "a11.ext.rqi.flowstate", FT_UINT8, BASE_HEX, NULL, 0, "Reverse Flow State", HFILL } }, #endif { &hf_a11_rqi_requested_qoslen, { "Requested QoS Length", "a11.ext.rqi.reqqoslen", FT_UINT8, BASE_DEC, NULL, 0, "Reverse Requested QoS Length", HFILL } }, #if 0 { &hf_a11_rqi_requested_qos, { "Requested QoS", "a11.ext.rqi.reqqos", FT_BYTES, BASE_NONE, NULL, 0, "Reverse Requested QoS", HFILL } }, #endif { &hf_a11_rqi_granted_qoslen, { "Granted QoS Length", "a11.ext.rqi.graqoslen", FT_UINT8, BASE_DEC, NULL, 0, "Reverse Granted QoS Length", HFILL } }, #if 0 { &hf_a11_rqi_granted_qos, { "Granted QoS", "a11.ext.rqi.graqos", FT_BYTES, BASE_NONE, NULL, 0, "Reverse Granted QoS", HFILL } }, #endif { &hf_a11_fqui_flowcount, { "Forward QoS Update Flow Count", "a11.ext.fqui.flowcount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_rqui_flowcount, { "Reverse QoS Update Flow Count", "a11.ext.rqui.flowcount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_fqui_updated_qoslen, { "Forward Updated QoS Sub-Blob Length", "a11.ext.fqui.updatedqoslen", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_fqui_updated_qos, { "Forward Updated QoS Sub-Blob", "a11.ext.fqui.updatedqos", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_rqui_updated_qoslen, { "Reverse Updated QoS Sub-Blob Length", "a11.ext.rqui.updatedqoslen", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_rqui_updated_qos, { "Reverse Updated QoS Sub-Blob", "a11.ext.rqui.updatedqos", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, #if 0 { &hf_a11_subscriber_profile_len, { "Subscriber QoS Profile Length", "a11.ext.sqp.profilelen", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, #endif { &hf_a11_subscriber_profile, { "Subscriber QoS Profile", "a11.ext.sqp.profile", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_forward_rohc_info_len, { "Forward ROHC Info Length", "a11.ext.ase.forwardlen", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_forward_maxcid, { "Forward MAXCID", "a11.ext.ase.maxcid", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_forward_mrru, { "Forward MRRU", "a11.ext.ase.mrru", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_forward_large_cids, { "Forward Large CIDS", "a11.ext.ase.forwardlargecids", FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL } }, { &hf_a11_ase_forward_profile_count, { "Forward Profile Count", "a11.ext.ase.profilecount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_forward_profile, { "Forward Profile", "a11.ext.ase.forwardprofile", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &a11_rohc_profile_vals_ext, 0, NULL, HFILL } }, { &hf_a11_ase_reverse_rohc_info_len, { "Reverse ROHC Info Length", "a11.ext.ase.reverselen", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_reverse_maxcid, { "Reverse MAXCID", "a11.ext.ase.revmaxcid", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_reverse_mrru, { "Reverse MRRU", "a11.ext.ase.revmrru", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_reverse_large_cids, { "Reverse Large CIDS", "a11.ext.ase.reverselargecids", FT_UINT8, BASE_DEC, NULL, 128, NULL, HFILL } }, { &hf_a11_ase_reverse_profile_count, { "Reverse Profile Count", "a11.ext.ase.revprofilecount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_ase_reverse_profile, { "Reverse Profile", "a11.ext.ase.reverseprofile", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &a11_rohc_profile_vals_ext, 0, NULL, HFILL } }, { &hf_a11_aut_flow_prof_sub_type, { "Sub type", "a11.aut_flow_prof.sub_type", FT_UINT8, BASE_DEC, VALS(a11_aut_flow_prof_subtype_vals), 0, NULL, HFILL } }, { &hf_a11_aut_flow_prof_sub_type_len, { "Length", "a11.aut_flow_prof.length", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_aut_flow_prof_sub_type_value, { "Value", "a11.aut_flow_prof.value", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_serv_opt_prof_max_serv, { "Service-Connections-Per-Link-flow", "a11.serv_opt_prof.scplf", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_sub_type, { "Sub-Type", "a11.sub_type", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_sub_type_length, { "Sub-Type Length", "a11.sub_type_length", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_serv_opt, { "Service Option", "a11.serviceoption", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_max_num_serv_opt, { "Max number of service instances of Service Option", "a11.max_serviceoptions", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_a11_bcmcs_stype, { "Protocol Type", "a11.ext.bcmcs.ptype", FT_UINT8, BASE_HEX, VALS(a11_bcmcs_stype_vals), 0, NULL, HFILL } }, { &hf_a11_bcmcs_entry_len, { "Entry length", "a11.ext.bcmcs.entry_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, }; /* Setup protocol subtree array */ static int *ett[] = { &ett_a11, &ett_a11_flags, &ett_a11_ext, &ett_a11_exts, &ett_a11_radius, &ett_a11_radiuses, &ett_a11_ase, &ett_a11_fqi_flowentry, &ett_a11_fqi_requestedqos, &ett_a11_fqi_qos_attribute_set, &ett_a11_fqi_grantedqos, &ett_a11_rqi_flowentry, &ett_a11_rqi_requestedqos, &ett_a11_rqi_qos_attribute_set, &ett_a11_rqi_grantedqos, &ett_a11_fqi_flags, &ett_a11_fqi_entry_flags, &ett_a11_rqi_entry_flags, &ett_a11_fqui_flowentry, &ett_a11_rqui_flowentry, &ett_a11_subscriber_profile, &ett_a11_forward_rohc, &ett_a11_reverse_rohc, &ett_a11_forward_profile, &ett_a11_reverse_profile, &ett_a11_aut_flow_profile_ids, &ett_a11_bcmcs_entry, }; static ei_register_info ei[] = { { &ei_a11_sub_type_length_not2, { "a11.sub_type_length.bad", PI_PROTOCOL, PI_WARN, "Sub-Type Length should be at least 2", EXPFILL }}, { &ei_a11_sse_too_short, { "a11.sse_too_short", PI_MALFORMED, PI_ERROR, "SSE too short", EXPFILL }}, { &ei_a11_bcmcs_too_short, { "a11.bcmcs_too_short", PI_MALFORMED, PI_ERROR, "BCMCS too short", EXPFILL }}, { &ei_a11_entry_data_not_dissected, { "a11.entry_data_not_dissected", PI_UNDECODED, PI_WARN, "Entry Data, Not dissected yet", EXPFILL }}, { &ei_a11_session_data_not_dissected, { "a11.session_data_not_dissected", PI_UNDECODED, PI_WARN, "Session Data Type Not dissected yet", EXPFILL }}, }; expert_module_t* expert_a11; /* Register the protocol name and description */ proto_a11 = proto_register_protocol("3GPP2 A11", "3GPP2 A11", "a11"); /* Register the dissector by name */ a11_handle = register_dissector("a11", dissect_a11, proto_a11); /* Required function calls to register the header fields and subtrees used */ proto_register_field_array(proto_a11, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); expert_a11 = expert_register_protocol(proto_a11); expert_register_field_array(expert_a11, ei, array_length(ei)); } void proto_reg_handoff_a11(void) { dissector_add_uint_with_preference("udp.port", UDP_PORT_3GA11, a11_handle); /* 3GPP2-Service-Option-Profile(74) */ radius_register_avp_dissector(VENDOR_THE3GPP2, 74, dissect_3gpp2_service_option_profile); /* 3GPP2-Authorized-Flow-Profile-IDs(131) */ radius_register_avp_dissector(VENDOR_THE3GPP2, 131, dissect_3gpp2_radius_aut_flow_profile_ids); } /* * 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: */