diff options
author | jake <jake@f5534014-38df-0310-8fa8-9805f1628bb7> | 2010-01-30 13:08:11 +0000 |
---|---|---|
committer | jake <jake@f5534014-38df-0310-8fa8-9805f1628bb7> | 2010-01-30 13:08:11 +0000 |
commit | d1a812ba9a7e4952d18e40f3303e7e538e334cfc (patch) | |
tree | 11e0f098dd9e241b80e1a43c3a3868b6974c507b /epan/dissectors/packet-ppp.c | |
parent | 9fb5752d7761f3fc44e3a701b0f5cf4c9c7cef87 (diff) |
From Shivesh Makharia:
I had written the VSNCP/VSNP which are specific to the CDMA community and
wanted to contribute this to Wireshark development.
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@31739 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/dissectors/packet-ppp.c')
-rw-r--r-- | epan/dissectors/packet-ppp.c | 561 |
1 files changed, 561 insertions, 0 deletions
diff --git a/epan/dissectors/packet-ppp.c b/epan/dissectors/packet-ppp.c index bb48b0d2e8..3743eef5d4 100644 --- a/epan/dissectors/packet-ppp.c +++ b/epan/dissectors/packet-ppp.c @@ -82,6 +82,20 @@ static gint ett_ipcp_ipaddrs_opt = -1; static gint ett_ipcp_compress_opt = -1; static gint ett_ipcp_iphc_disableprot_opt = -1; +static int proto_vsncp = -1; + +static gint ett_vsncp = -1; +static gint ett_vsncp_options = -1; + +static int proto_vsnp = -1; +static gint hf_vsnp = -1; +static gint hf_vsnp_header = -1; +static gint hf_vsnp_type = -1; +static gint hf_vsnp_data = -1; + +static gint ett_vsnp =-1; +static gint ett_vsnp_pdnid = -1; + static int proto_osicp = -1; static gint ett_osicp = -1; @@ -942,6 +956,134 @@ static const ip_tcp_opt lcp_opts[] = { #define N_LCP_OPTS (sizeof lcp_opts / sizeof lcp_opts[0]) /* + * Options. (VSNCP) + */ + +#define CI_PDN_IDENTIFIER 1 +#define CI_ACCESS_POINT_NM 2 +#define CI_PDN_TYPE 3 +#define CI_PDN_ADDRESS 4 +#define CI_PROTOCOL_CONFIG 5 +#define CI_ERROR_CODE 6 +#define CI_ATTACH_TYPE 7 +#define CI_IPv4DEFAULT_ROUTER 8 +#define CI_ADDRESS_ALLOC 9 +#define CI_APN_AMBR 10 + +static void dissect_vsncp_pdnid_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, + proto_tree *tree); +static void dissect_vsncp_apname_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, + proto_tree *tree); +static void dissect_vsncp_pdntype_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, + proto_tree *tree); +static void dissect_vsncp_pdnaddress_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, + proto_tree *tree); +static void dissect_vsncp_pco_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, + proto_tree *tree); +static void dissect_vsncp_errorcode_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, + proto_tree *tree); +static void dissect_vsncp_attachtype_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, + proto_tree *tree); +static void dissect_vsncp_ipv4adress_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, + proto_tree *tree); +static void dissect_vsncp_addressalloc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, + proto_tree *tree); + +static const ip_tcp_opt vsncp_opts[] = { + { + CI_PDN_IDENTIFIER, + "PDN Identifier", + NULL, + FIXED_LENGTH, + 3, + dissect_vsncp_pdnid_opt + }, + { + CI_ACCESS_POINT_NM, + "Access Point Name", + NULL, + VARIABLE_LENGTH, + 2, + dissect_vsncp_apname_opt + }, + { + CI_PDN_TYPE, + "PDN Type", + NULL, + FIXED_LENGTH, + 3, + dissect_vsncp_pdntype_opt + }, + { + CI_PDN_ADDRESS, + "PDN Address", + NULL, + VARIABLE_LENGTH, + 3, + dissect_vsncp_pdnaddress_opt + }, + { + CI_PROTOCOL_CONFIG, + "Protocol Configuration Options", + NULL, + VARIABLE_LENGTH, + 3, + dissect_vsncp_pco_opt + }, + { + CI_ERROR_CODE, + "Error Code", + NULL, + FIXED_LENGTH, + 3, + dissect_vsncp_errorcode_opt + }, + { + CI_ATTACH_TYPE, + "Attach Type", + NULL, + FIXED_LENGTH, + 3, + dissect_vsncp_attachtype_opt + }, + { + CI_IPv4DEFAULT_ROUTER, + "IPv4 Default Router Address", + NULL, + FIXED_LENGTH, + 6, + dissect_vsncp_ipv4adress_opt + }, + { + CI_ADDRESS_ALLOC, + "Address Allocation Cause", + NULL, + FIXED_LENGTH, + 3, + dissect_vsncp_addressalloc_opt + }, + { + CI_APN_AMBR, + "APN-AMBR", + NULL, + VARIABLE_LENGTH, + 4, + NULL + } +}; + +#define N_VSNCP_OPTS (sizeof vsncp_opts / sizeof vsncp_opts[0]) + +/* * CHAP Algorithms */ #define CHAP_ALG_MD5 0x05 /* CHAP with MD5 */ @@ -2632,6 +2774,268 @@ dissect_bap_call_status_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, val_to_str(action, bap_call_status_opt_action_vals, "Unknown"), action); } +static void dissect_vsncp_pdnid_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo _U_, + proto_tree *tree) +{ + proto_item *tf; + guint8 PDNID; + + PDNID = tvb_get_guint8(tvb, offset + 2); + tf = proto_tree_add_text(tree, tvb, offset, length, "%s: 0x%02x", + optp->name, PDNID); + offset += 2; +} + +static void dissect_vsncp_attachtype_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo _U_, + proto_tree *tree) +{ + static const value_string attach_vals[] = + { + {1, "Initial Attach" }, + {3, "Handover Attach"}, + {0, NULL } + }; + + guint8 attach; + attach = tvb_get_guint8(tvb, offset + 2); + + if(tree) + { + proto_tree_add_text(tree, tvb, offset, length, "%s: %s (0x%02x)", + optp->name, val_to_str(attach , attach_vals, "Unknown"), attach); + } + offset += 2; + +} + +static void dissect_vsncp_pdntype_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo _U_, + proto_tree *tree) +{ + static const value_string pdntype_vals[] = + { + {1, "IPv4" }, + {2, "IPv6" }, + {3, "IPv6/IPv4" }, + {0, NULL } + }; + + guint8 pdntype; + pdntype = tvb_get_guint8(tvb, offset + 2); + + if(tree) + { + proto_tree_add_text(tree, tvb, offset, length, "%s: %s (0x%02x)", + optp->name, val_to_str(pdntype, pdntype_vals, "Unknown"), pdntype); + } + offset += 2; +} + +static void dissect_vsncp_errorcode_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo _U_, + proto_tree *tree) +{ + static const value_string errorcode_vals[] = + { + {0, "General Eror" }, + {1, "Unauthorized APN" }, + {2, "PDN Limit Exceeded" }, + {3, "NO PG-W Available" }, + {4, "P-GW Unreachable" }, + {5, "P-GW Reject" }, + {6, "Insufficient Parameters" }, + {7, "Resource Unavailable" }, + {8, "Admin Prohibited" }, + {9, "PDN-ID Already in Use" }, + {10, "Subscription Limitation" }, + {11, "PDN connection already exists for APN"}, + {0, NULL } + }; + + guint8 pdntype; + pdntype = tvb_get_guint8(tvb, offset + 2); + + if(tree) + { + proto_tree_add_text(tree, tvb, offset, length, "%s: %s (0x%02x)", + optp->name, val_to_str(pdntype, errorcode_vals, "Unknown"), pdntype); + } + offset += 2; + +} +static void dissect_vsncp_pdnaddress_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo _U_, + proto_tree *tree) +{ + guint8 pdnaddtype; + + static const value_string pdntype_vals[] = + { + {0, "Initial Request by UE" }, + {1, "IPv4 Address" }, + {2, "IPv6 Address" }, + {3, "IPv6/IPv4 Address" }, + {0, NULL } + }; + proto_item *tf; + proto_tree *field_tree; + + tf = proto_tree_add_text(tree, tvb, offset, length, + "%s: (%d byte%s)", optp->name, length, plurality(length, "", "s")); + + field_tree = proto_item_add_subtree(tf, ett_lcp_options); + + + pdnaddtype = tvb_get_guint8(tvb, offset + 2); + + proto_tree_add_text(field_tree, tvb, offset+2, 1, "PDN Type (%s): 0x%02x", + val_to_str(pdnaddtype, pdntype_vals, "Unknown"), pdnaddtype); + + + switch (pdnaddtype) + { + case 1: + proto_tree_add_text(field_tree, tvb, offset+3, length-3, "%s: %s", + val_to_str(pdnaddtype, pdntype_vals, "Unknown"), + ip_to_str(tvb_get_ptr(tvb, offset + 3, 4))); + break; + + case 2: + { + struct e_in6_addr *ad = ep_alloc0(sizeof (struct e_in6_addr)); + tvb_memcpy(tvb, &ad->bytes[8], offset+3, 8); + + proto_tree_add_text(field_tree, tvb, offset+3, length-3, "%s: %s", + val_to_str(pdnaddtype, pdntype_vals, "Unknown"), ip6_to_str(ad)); + break; + } + case 3: + { + struct e_in6_addr *ad = ep_alloc0(sizeof (struct e_in6_addr)); + tvb_memcpy(tvb, &ad->bytes[8], offset+3, 8); + + proto_tree_add_text(field_tree, tvb, offset+3, length-3, "%s: %s", + val_to_str(pdnaddtype, pdntype_vals, "Unknown"), ip6_to_str(ad)); + + proto_tree_add_text(field_tree, tvb, offset+11, length-11, "%s: %s", + val_to_str(pdnaddtype, pdntype_vals, "Unknown"), + ip_to_str(tvb_get_ptr(tvb, offset + 11, 4))); + break; + } + default: + break; + } + offset += 2; + +} + +static void dissect_vsncp_ipv4adress_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo _U_, + proto_tree *tree) +{ + proto_tree_add_text(tree, tvb, offset, length, "%s: %s", optp->name, + ip_to_str(tvb_get_ptr(tvb, offset + 2, 4))); + offset += 2; +} + +static void dissect_vsncp_apname_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo _U_, + proto_tree *tree) +{ + proto_item *tf; + proto_tree *field_tree; + + tf = proto_tree_add_text(tree, tvb, offset, length, + "%s: (%d byte%s)", optp->name, length, plurality(length, "", "s")); + + field_tree = proto_item_add_subtree(tf, ett_lcp_options); + + if(length>2) + { + guint8 i = 0; + guint8 j = 1; + guint8 lengthofapn; + int off = offset+2; + + while(i<(length-2)) + { + lengthofapn = tvb_get_guint8(tvb, off); + off = off+1; + proto_tree_add_text(field_tree, tvb, off, lengthofapn, + "Label%d (%d byte%s): %s", j, lengthofapn, plurality(lengthofapn, "", "s"), + tvb_format_text(tvb, off, lengthofapn)); + off = off+lengthofapn; + i = i+lengthofapn+1; + j++; + } + } +} + +static void dissect_vsncp_addressalloc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo _U_, + proto_tree *tree) +{ + static const value_string alloc_vals[] = + { + {0, "Null Value (Attach or Handover)" }, + {18, "New PDN type due to network preference" }, + {255, "Success" }, + {0, NULL } + }; + + guint8 alloc; + alloc = tvb_get_guint8(tvb, offset + 2); + + if(tree) + { + proto_tree_add_text(tree, tvb, offset, length, "%s: %s (0x%02x)", + optp->name, val_to_str(alloc, alloc_vals, "Unknown"), alloc); + } + offset += 2; +} + +static void dissect_vsncp_pco_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo _U_, + proto_tree *tree) +{ + static const value_string pco_vals[] = + { + {0x8021, "IPCP (DNS Address Request)" }, + {0x0001, "P-CSCF Address Request (IPv6)" }, + {0x0003, "DNS Server Address (IPv6)" }, + {0x000A, "IP address allocation via NAS signalling" }, + {0, NULL } + }; + int off = offset+3; + guint8 i = 0; + guint16 pcotype; + guint8 len; + + proto_item *tf; + proto_tree *field_tree; + + tf = proto_tree_add_text(tree, tvb, offset, length, + "%s: (%d byte%s)", optp->name, length, plurality(length, "", "s")); + + field_tree = proto_item_add_subtree(tf, ett_lcp_options); + + while(i<length-3) + { + pcotype = tvb_get_ntohs(tvb, off); + len = tvb_get_guint8(tvb, (off+2)); + proto_tree_add_text(field_tree, tvb, off,2, "Protocol: %s (0x%02x)", + val_to_str(pcotype, pco_vals, "Unknown"), pcotype); + proto_tree_add_text(field_tree, tvb, off+2,1, "Length:(0x%02x)", len); + if(len >0) + proto_tree_add_text(field_tree, tvb, off+3,len, "Data (%d byte%s)", len, plurality(len, "", "s")); + + off = off+3+len; + i = i+3+len; + } +} + static void dissect_cp( tvbuff_t *tvb, int proto_id, int proto_subtree_index, const value_string *proto_vals, int options_subtree_index, @@ -2861,6 +3265,103 @@ dissect_lcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) lcp_opts, N_LCP_OPTS, pinfo, tree); } +static void +dissect_vsncp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + proto_tree *fh_tree = NULL; + proto_item *tf; + proto_tree *field_tree; + + guint8 code; + guint8 id; + int length, offset; + int OUI; + + static const value_string OUI_vals[] = + { + {0xcf0002, "3GPP2 Unique Organization Number" }, + {0, NULL } + }; + + code = tvb_get_guint8(tvb, 0); + id = tvb_get_guint8(tvb, 1); + length = tvb_get_ntohs(tvb, 2); + OUI = tvb_get_ntoh24(tvb, 4); + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSNCP"); + col_add_str(pinfo->cinfo, COL_INFO, val_to_str(code, cp_vals, "Unknown")); + + if(tree) + { + ti = proto_tree_add_item(tree, proto_vsncp, tvb, 0, length, FALSE); + fh_tree = proto_item_add_subtree(ti, ett_vsncp); + proto_tree_add_text(fh_tree, tvb, 0, 1, "Code: %s (0x%02x)", val_to_str(code, cp_vals, "Unknown"), code); + proto_tree_add_text(fh_tree, tvb, 1, 1, "Identifier: 0x%02x", id); + proto_tree_add_text(fh_tree, tvb, 2, 2, "Length: %u", length); + proto_tree_add_text(fh_tree, tvb, 4, 3, "OUI: %s (0x%02x)", val_to_str(OUI, OUI_vals, "Unknown"), OUI); + } + offset = 7; + length -= 7; + + switch (code) + { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + case TERMREQ: + case TERMACK: + if(tree) + { + if (length > 0) + { + tf = proto_tree_add_text(fh_tree, tvb, offset, length, + "Options: (%d byte%s)", length, plurality(length, "", "s")); + field_tree = proto_item_add_subtree(tf, ett_vsncp_options); + dissect_ip_tcp_options(tvb, offset, length, vsncp_opts, N_VSNCP_OPTS, -1, + pinfo, field_tree); + } + } + break; + } +} + +static void +dissect_vsnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint8 PDNID; + proto_item *vsnp_item = NULL; + proto_tree *vsnp_tree = NULL; + guint32 offset = 0; + + /* To pass it on to IP */ + tvbuff_t *next_tvb; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSNP"); + + PDNID = tvb_get_guint8(tvb, 0); /* Get the PDNID byte */ + offset = 0; + + if (tree) /* we are being asked for details */ + { + vsnp_item = proto_tree_add_item(tree, proto_vsnp, tvb, 0, -1, FALSE); + vsnp_tree = proto_item_add_subtree(vsnp_item, ett_vsnp); + proto_tree_add_text(vsnp_tree, tvb, offset, 1, "PDN ID: 0x%02x", PDNID); + } + next_tvb = tvb_new_subset(tvb, 1, -1, -1); + + /* do lookup with the subdissector table */ + if (!dissector_try_port(ppp_subdissector_table, PPP_IP, next_tvb, pinfo, tree)) + { + col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", PPP_IP); + + col_add_fstr(pinfo->cinfo, COL_INFO, "PPP %s (0x%04x)", + val_to_str(PPP_IP, ppp_vals, "Unknown"), PPP_IP); + call_dissector(data_handle, next_tvb, pinfo, tree); + } +} + /* * RFC 1332. */ @@ -4305,6 +4806,66 @@ proto_reg_handoff_lcp(void) } void +proto_register_vsncp(void) +{ + static gint *ett[] = { + &ett_vsncp, + &ett_vsncp_options, + }; + + proto_vsncp = proto_register_protocol("Vendor Specific Control Protocol", "VSNCP", + "vsncp"); + proto_register_subtree_array(ett, array_length(ett)); +} + +void +proto_reg_handoff_vsncp(void) +{ + dissector_handle_t vsncp_handle; + + vsncp_handle = create_dissector_handle(dissect_vsncp, proto_vsncp); + dissector_add("ppp.protocol", PPP_VSNCP, vsncp_handle); +} + +void +proto_register_vsnp(void) +{ + static gint *ett[] = { + &ett_vsnp, + &ett_vsnp_pdnid, + }; + + static hf_register_info hf[] = { + { &hf_vsnp, + { "Data", "vsnp.data", FT_NONE, BASE_NONE, NULL, 0x0, + "VSNP PDU", HFILL }}, + { &hf_vsnp_header, + { "Header", "vsnp.header", FT_NONE, BASE_NONE, NULL, 0x0, + "VSNP Header", HFILL }}, + { &hf_vsnp_type, + { "PDN ID", "vsnp.pdnid", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_vsnp_data, + { "Data", "vsnp.data", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }} + }; + + proto_vsnp = proto_register_protocol("Vendor Specific Network Protocol", "PPP VSNP", + "vsnp"); + proto_register_subtree_array(ett, array_length(ett)); + proto_register_field_array(proto_vsnp, hf, array_length(hf)); +} + +void +proto_reg_handoff_vsnp(void) +{ + dissector_handle_t vsnp_handle; + + vsnp_handle = create_dissector_handle(dissect_vsnp, proto_vsnp); + dissector_add("ppp.protocol", PPP_VSNP, vsnp_handle); +} + +void proto_register_ipcp(void) { static gint *ett[] = { |