diff options
author | Chris Maynard <Christopher.Maynard@GTECH.COM> | 2012-05-30 17:02:44 +0000 |
---|---|---|
committer | Chris Maynard <Christopher.Maynard@GTECH.COM> | 2012-05-30 17:02:44 +0000 |
commit | 39d4fbeb52c19ecfaa6fe361d2a4250d1c5aa101 (patch) | |
tree | f7cbd2ae007bf3f8d9f22f180959d346b86afd7b | |
parent | 77b9085de9d3864e09b49212d95e69d10424c1d2 (diff) |
PPP CCP improvements. And yay, checkAPIs no longer complains about the number of useless add_text()'s since the ratio is finally below 50%. This ratio should continue to drop as more and more fields become filterable.
svn path=/trunk/; revision=42920
-rw-r--r-- | epan/dissectors/packet-ppp.c | 681 |
1 files changed, 536 insertions, 145 deletions
diff --git a/epan/dissectors/packet-ppp.c b/epan/dissectors/packet-ppp.c index 8b1a5f7e81..4e8794061e 100644 --- a/epan/dissectors/packet-ppp.c +++ b/epan/dissectors/packet-ppp.c @@ -152,12 +152,23 @@ static int proto_ccp = -1; static gint ett_ccp = -1; static gint ett_ccp_options = -1; +static gint ett_ccp_oui_opt = -1; +static gint ett_ccp_predict1_opt = -1; +static gint ett_ccp_predict2_opt = -1; +static gint ett_ccp_puddle_opt = -1; +static gint ett_ccp_hpppc_opt = -1; static gint ett_ccp_stac_opt = -1; -static gint ett_ccp_mppc_opt = -1; +static gint ett_ccp_stac_opt_check_mode = -1; +static gint ett_ccp_mppe_opt = -1; +static gint ett_ccp_mppe_opt_supp_bits = -1; +static gint ett_ccp_gfza_opt = -1; +static gint ett_ccp_v42bis_opt = -1; static gint ett_ccp_bsdcomp_opt = -1; static gint ett_ccp_lzsdcp_opt = -1; static gint ett_ccp_mvrca_opt = -1; +static gint ett_ccp_dce_opt = -1; static gint ett_ccp_deflate_opt = -1; +static gint ett_ccp_v44lzjh_opt = -1; static int proto_cbcp = -1; @@ -728,18 +739,26 @@ static const value_string lzsdcp_checkmode_vals[] = { {LZSDCP_CM_NONE, "None"}, {LZSDCP_CM_LCB, "LCB"}, {LZSDCP_CM_SN, "Sequence Number"}, - {LZSDCP_CM_SN_LCB, "Sequence Number + LCB"}, + {LZSDCP_CM_SN_LCB, "Sequence Number + LCB (default)"}, {0, NULL} }; #define LZSDCP_PM_NONE 0 #define LZSDCP_PM_PROC_UNCOMP 1 static const value_string lzsdcp_processmode_vals[] = { - {LZSDCP_PM_NONE, "None"}, + {LZSDCP_PM_NONE, "None (default)"}, {LZSDCP_PM_PROC_UNCOMP, "Process-Uncompressed"}, {0, NULL} }; +#define DCE_MODE_1 1 +#define DCE_MODE_2 2 +static const value_string dce_mode_vals[] = { + {DCE_MODE_1, "No Additional Negotiation"}, + {DCE_MODE_2, "Full PPP Negotiation and State Machine"}, + {0, NULL} +}; + /* * Options. (LCP) */ @@ -1252,55 +1271,117 @@ static const ip_tcp_opt osinlcp_opts[] = { #define CI_CCP_PUDDLE 3 /* Puddle Jumper (RFC1962) */ #define CI_CCP_HPPPC 16 /* Hewlett-Packard PPC (RFC1962) */ #define CI_CCP_STAC 17 /* stac Electronics LZS (RFC1974) */ -#define CI_CCP_MPPC 18 /* Microsoft PPC (RFC2218/3078) */ +#define CI_CCP_MPPE 18 /* Microsoft PPE/C (RFC2218/3078) */ #define CI_CCP_GFZA 19 /* Gandalf FZA (RFC1962) */ #define CI_CCP_V42BIS 20 /* V.42bis compression */ #define CI_CCP_BSDLZW 21 /* BSD LZW Compress (RFC1977) */ #define CI_CCP_LZSDCP 23 /* LZS-DCP (RFC1967) */ #define CI_CCP_MVRCA 24 /* MVRCA (Magnalink) (RFC1975) */ +#define CI_CCP_DCE 25 /* DCE (RFC1976) */ #define CI_CCP_DEFLATE 26 /* Deflate (RFC1979) */ +#define CI_CCP_V44LZJH 27 /* V.44/LZJH (http://www.watersprings.org/pub/id/draft-heath-ppp-v44-01.txt) */ #define CI_CCP_RESERVED 255 /* Reserved (RFC1962) */ -/* - * Microsoft Point-To-Point Compression (MPPC) and Encryption (MPPE) - * supported bits. - */ -#define MPPC_SUPPORTED_BITS_C 0x00000001 /* MPPC negotiation */ -#define MPPE_SUPPORTED_BITS_D 0x00000010 /* Obsolete */ -#define MPPE_SUPPORTED_BITS_L 0x00000020 /* 40-bit encryption */ -#define MPPE_SUPPORTED_BITS_S 0x00000040 /* 128-bit encryption */ -#define MPPE_SUPPORTED_BITS_M 0x00000080 /* 56-bit encryption */ -#define MPPE_SUPPORTED_BITS_H 0x01000000 /* stateless mode */ - +static int hf_ccp_opt_type = -1; +static int hf_ccp_opt_length = -1; +static int hf_ccp_opt_oui = -1; +static int hf_ccp_opt_subtype = -1; +static int hf_ccp_opt_data = -1; +static int hf_ccp_opt_history_count = -1; +static int hf_ccp_opt_cm = -1; +static int hf_ccp_opt_cm_reserved = -1; +static int hf_ccp_opt_cm_check_mode = -1; +static int hf_ccp_opt_supported_bits = -1; +static int hf_ccp_opt_supported_bits_h = -1; +static int hf_ccp_opt_supported_bits_m = -1; +static int hf_ccp_opt_supported_bits_s = -1; +static int hf_ccp_opt_supported_bits_l = -1; +static int hf_ccp_opt_supported_bits_d = -1; +static int hf_ccp_opt_supported_bits_c = -1; +static int hf_ccp_opt_history = -1; +static int hf_ccp_opt_version = -1; +static int hf_ccp_opt_vd = -1; +static int hf_ccp_opt_vd_vers = -1; +static int hf_ccp_opt_vd_dict = -1; +static int hf_ccp_opt_check_mode = -1; +static int hf_ccp_opt_process_mode = -1; +static int hf_ccp_opt_fe = -1; +static int hf_ccp_opt_p = -1; +static int hf_ccp_opt_History = -1; /* Different than hf_ccp_opt_history */ +static int hf_ccp_opt_contexts = -1; +static int hf_ccp_opt_mode = -1; +static int hf_ccp_opt_window = -1; +static int hf_ccp_opt_method = -1; +static int hf_ccp_opt_mbz = -1; +static int hf_ccp_opt_chk = -1; +static int hf_ccp_opt_mode_dictcount = -1; +static int hf_ccp_opt_dict_size = -1; +static int hf_ccp_opt_history_length = -1; + +static void dissect_ccp_oui_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, proto_tree *tree); +static void dissect_ccp_other_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, proto_tree *tree); +#define dissect_ccp_predict1_opt dissect_ccp_other_opt +#define dissect_ccp_predict2_opt dissect_ccp_other_opt +#define dissect_ccp_puddle_opt dissect_ccp_other_opt +#define dissect_ccp_hpppc_opt dissect_ccp_other_opt static void dissect_ccp_stac_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, guint length, packet_info *pinfo, proto_tree *tree); -static void dissect_ccp_mppc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, +static void dissect_ccp_mppe_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, guint length, packet_info *pinfo, proto_tree *tree); +static void dissect_ccp_gfza_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, proto_tree *tree); +#define dissect_ccp_v42bis_opt dissect_ccp_other_opt static void dissect_ccp_bsdcomp_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, guint length, packet_info *pinfo, proto_tree *tree); static void dissect_ccp_lzsdcp_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, guint length, packet_info *pinfo, proto_tree *tree); static void dissect_ccp_mvrca_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, guint length, packet_info *pinfo, proto_tree *tree); +static void dissect_ccp_dce_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo _U_, proto_tree *tree); static void dissect_ccp_deflate_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, guint length, packet_info *pinfo, proto_tree *tree); +static void dissect_ccp_v44lzjh_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, proto_tree *tree); static const ip_tcp_opt ccp_opts[] = { + + {CI_CCP_OUI, "OUI", &ett_ccp_oui_opt, + VARIABLE_LENGTH, 6, dissect_ccp_oui_opt}, + {CI_CCP_PREDICT1, "Predictor type 1", &ett_ccp_predict1_opt, + VARIABLE_LENGTH, 2, dissect_ccp_predict1_opt}, + {CI_CCP_PREDICT2, "Predictor type 2", &ett_ccp_predict2_opt, + VARIABLE_LENGTH, 2, dissect_ccp_predict2_opt}, + {CI_CCP_PUDDLE, "Puddle Jumper", &ett_ccp_puddle_opt, + VARIABLE_LENGTH, 2, dissect_ccp_puddle_opt}, + {CI_CCP_HPPPC, "Hewlett-Packard PPC", &ett_ccp_hpppc_opt, + VARIABLE_LENGTH, 2, dissect_ccp_hpppc_opt}, {CI_CCP_STAC, "Stac Electronics LZS", &ett_ccp_stac_opt, /* In RFC 1974, this is a fixed-length field of size 5, but in * Ascend Proprietary STAC compression this field is 6 octets. */ VARIABLE_LENGTH, 5, dissect_ccp_stac_opt}, - {CI_CCP_MPPC, "Microsoft PPC", &ett_ccp_mppc_opt, - FIXED_LENGTH, 6, dissect_ccp_mppc_opt}, - {CI_CCP_BSDLZW, "BSD Compress", &ett_ccp_bsdcomp_opt, + {CI_CCP_MPPE, "Microsoft PPE/PPC", &ett_ccp_mppe_opt, + FIXED_LENGTH, 6, dissect_ccp_mppe_opt}, + {CI_CCP_GFZA, "Gandalf FZA", &ett_ccp_gfza_opt, + VARIABLE_LENGTH, 3, dissect_ccp_gfza_opt}, + {CI_CCP_V42BIS, "V.42bis compression", &ett_ccp_v42bis_opt, + VARIABLE_LENGTH, 2, dissect_ccp_v42bis_opt}, + {CI_CCP_BSDLZW, "BSD LZW Compress", &ett_ccp_bsdcomp_opt, FIXED_LENGTH, 3, dissect_ccp_bsdcomp_opt}, {CI_CCP_LZSDCP, "LZS-DCP", &ett_ccp_lzsdcp_opt, FIXED_LENGTH, 6, dissect_ccp_lzsdcp_opt}, {CI_CCP_MVRCA, "MVRCA (Magnalink)", &ett_ccp_mvrca_opt, FIXED_LENGTH, 4, dissect_ccp_mvrca_opt}, + {CI_CCP_DCE, + "PPP for Data Compression in Data Circuit-Terminating Equipment (DCE)", + &ett_ccp_dce_opt, FIXED_LENGTH, 3, dissect_ccp_dce_opt}, {CI_CCP_DEFLATE, "Deflate", &ett_ccp_deflate_opt, /* RFC1979 says the length is 3 but it's actually 4. */ - FIXED_LENGTH, 4, dissect_ccp_deflate_opt} + FIXED_LENGTH, 4, dissect_ccp_deflate_opt}, + {CI_CCP_V44LZJH, "V.44/LZJH compression", &ett_ccp_v44lzjh_opt, + VARIABLE_LENGTH, 4, dissect_ccp_v44lzjh_opt} }; #define N_CCP_OPTS (sizeof ccp_opts / sizeof ccp_opts[0]) @@ -2865,106 +2946,231 @@ dissect_pppmuxcp_def_pid_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, static void +dissect_ccp_opt_type_len(tvbuff_t *tvb, int offset, proto_tree *tree, + const char *name) +{ + guint8 type; + + type = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(tree, hf_ccp_opt_type, tvb, offset, 1, + type, "%s (%u)", name, type); + proto_tree_add_item(tree, hf_ccp_opt_length, tvb, offset + 1, 1, ENC_NA); +} + +/* http://tools.ietf.org/html/rfc1962 */ +static void dissect_ccp_oui_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *field_tree; + proto_item *tf, *ti; + guint32 oui; + const gchar *manuf; + + oui = tvb_get_ntoh24(tvb, offset + 2); + tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name); + field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + dissect_ccp_opt_type_len(tvb, offset, field_tree, optp->name); + ti = proto_tree_add_uint_format_value(field_tree, hf_ccp_opt_oui, tvb, + offset + 2, 3, oui, "%02x:%02x:%02x", + (oui >> 16) & 0xff, (oui >> 8) & 0xff, oui & 0xff); + manuf = uint_get_manuf_name_if_known(oui); + if (manuf) + proto_item_append_text(ti, "(%s)", manuf); + + proto_tree_add_item(field_tree, hf_ccp_opt_subtype, tvb, offset + 5, 1, + ENC_NA); + if (length > 6) { + proto_tree_add_item(field_tree, hf_ccp_opt_data, tvb, offset + 6, + length - 6, ENC_NA); + } +} + +/* The following configuration option types are mentioned at + * http://www.iana.org/assignments/ppp-numbers as referencing RFC1962; however, + * RFC1962 only mentions Proprietary Compression OUI in section 4.1. These + * others are therefore being treated as section 4.2 "Other Compression Types", + * in terms of how they are dissected: + * 1) Predictor type 1 + * 2) Predictor type 2 + * 3) Puddle Jumper + * 16) Hewlett-Packard PPC + * 20) V.42bis compression + */ +static void dissect_ccp_other_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *field_tree; + proto_item *tf; + + tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name); + field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + dissect_ccp_opt_type_len(tvb, offset, field_tree, optp->name); + + if (length > 2) { + proto_tree_add_item(field_tree, hf_ccp_opt_data, tvb, offset + 2, + length - 2, ENC_NA); + } +} + +/* http://tools.ietf.org/html/rfc1974 */ +static void dissect_ccp_stac_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; - guint8 check_mode; + const char *stac_ascend = "Stac Electronics LZS (Ascend Proprietary version)"; + static const int *check_mode_fields[] = { + &hf_ccp_opt_cm_reserved, + &hf_ccp_opt_cm_check_mode, + NULL + }; if (length == 6) { - proto_tree_add_text(tree, tvb, offset, length, - "%s (Ascend Proprietary version)", optp->name); + tf = proto_tree_add_text(tree, tvb, offset, length, stac_ascend); + field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + dissect_ccp_opt_type_len(tvb, offset, field_tree, stac_ascend); + /* We don't know how to decode the following 4 octets, since - there's no public document that describe their usage. */ + there are no public documents that describe their usage. */ + proto_tree_add_item(field_tree, hf_ccp_opt_data, tvb, offset + 2, + length - 2, ENC_NA); } else { tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name); field_tree = proto_item_add_subtree(tf, *optp->subtree_index); - proto_tree_add_text(field_tree, tvb, offset + 2, 2, - "History Count: %u", tvb_get_ntohs(tvb, offset + 2)); - check_mode = tvb_get_guint8(tvb, offset + 4); - proto_tree_add_text(field_tree, tvb, offset + 4, 1, - "Check Mode: %s (0x%02X)", - val_to_str_const(check_mode, stac_checkmode_vals, "Unknown"), - check_mode); + dissect_ccp_opt_type_len(tvb, offset, field_tree, optp->name); + + proto_tree_add_item(field_tree, hf_ccp_opt_history_count, tvb, + offset + 2, 2, ENC_BIG_ENDIAN); + proto_tree_add_bitmask(field_tree, tvb, offset + 4, hf_ccp_opt_cm, + ett_ccp_stac_opt_check_mode, check_mode_fields, ENC_NA); } } +/* + * Microsoft Point-To-Point Compression (MPPC) and Encryption (MPPE) + * supported bits. + */ +#define MPPC_SUPPORTED_BITS_C 0x00000001 /* MPPC negotiation */ +#define MPPE_SUPPORTED_BITS_D 0x00000010 /* Obsolete */ +#define MPPE_SUPPORTED_BITS_L 0x00000020 /* 40-bit encryption */ +#define MPPE_SUPPORTED_BITS_S 0x00000040 /* 128-bit encryption */ +#define MPPE_SUPPORTED_BITS_M 0x00000080 /* 56-bit encryption */ +#define MPPE_SUPPORTED_BITS_H 0x01000000 /* stateless mode */ + +static const true_false_string ccp_mppe_h_tfs = { + "Stateless mode ON", + "Stateless mode OFF" +}; +static const true_false_string ccp_mppe_m_tfs = { + "56-bit encryption ON", + "56-bit encryption OFF" +}; +static const true_false_string ccp_mppe_s_tfs = { + "128-bit encryption ON", + "128-bit encryption OFF" +}; +static const true_false_string ccp_mppe_l_tfs = { + "40-bit encryption ON", + "40-bit encryption OFF" +}; +static const true_false_string ccp_mppe_d_tfs = { + "Obsolete (should NOT be 1)", + "Obsolete (should ALWAYS be 0)" +}; +static const true_false_string ccp_mppe_c_tfs = { + "Desire to negotiate MPPC", + "No desire to negotiate MPPC" +}; + +/* http://tools.ietf.org/html/rfc2118, + * http://tools.ietf.org/html/rfc3078 */ static void -dissect_ccp_mppc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, +dissect_ccp_mppe_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 *flags_tree; - guint32 supported_bits; + proto_tree *field_tree; + static const int *supported_bits_fields[] = { + &hf_ccp_opt_supported_bits_h, + &hf_ccp_opt_supported_bits_m, + &hf_ccp_opt_supported_bits_s, + &hf_ccp_opt_supported_bits_l, + &hf_ccp_opt_supported_bits_d, + &hf_ccp_opt_supported_bits_c, + NULL + }; + + tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name); + field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + dissect_ccp_opt_type_len(tvb, offset, field_tree, optp->name); + + proto_tree_add_bitmask(field_tree, tvb, offset + 2, + hf_ccp_opt_supported_bits, ett_ccp_mppe_opt_supp_bits, + supported_bits_fields, ENC_BIG_ENDIAN); +} + +/* http://tools.ietf.org/html/rfc1993 */ +static void dissect_ccp_gfza_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *field_tree; + proto_item *tf; - supported_bits = tvb_get_ntohl(tvb, offset + 2); - tf = proto_tree_add_text(tree, tvb, offset, length, - "%s: Supported Bits: 0x%08X", optp->name, supported_bits); - flags_tree = proto_item_add_subtree(tf, *optp->subtree_index); - - proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s", - decode_boolean_bitfield(supported_bits, MPPC_SUPPORTED_BITS_C, 8 * 4, - "Desire to negotiate MPPC", "NO Desire to negotiate MPPC")); - proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s", - decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_D, 8 * 4, - "Obsolete (should NOT be 1)", "Obsolete (should ALWAYS be 0)")); - proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s", - decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_L, 8 * 4, - "40-bit encryption ON", "40-bit encryption OFF")); - proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s", - decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_S, 8 * 4, - "128-bit encryption ON", "128-bit encryption OFF")); - proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s", - decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_M, 8 * 4, - "56-bit encryption ON", "56-bit encryption OFF")); - proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s", - decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_H, 8 * 4, - "Stateless mode ON", "Stateless mode OFF")); + tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name); + field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + dissect_ccp_opt_type_len(tvb, offset, field_tree, optp->name); + + proto_tree_add_item(field_tree, hf_ccp_opt_history, tvb, offset + 2, 1, + ENC_NA); + + if (length > 3) { + proto_tree_add_item(field_tree, hf_ccp_opt_version, tvb, offset + 3, + length - 3, ENC_NA); + } } +/* http://tools.ietf.org/html/rfc1977 */ static void dissect_ccp_bsdcomp_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; + static const int *vd_fields[] = { + &hf_ccp_opt_vd_vers, + &hf_ccp_opt_vd_dict + }; tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name); field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + dissect_ccp_opt_type_len(tvb, offset, field_tree, optp->name); - proto_tree_add_text(field_tree, tvb, offset + 2, 1, "Version: %u", - tvb_get_guint8(tvb, offset + 2) >> 5); - proto_tree_add_text(field_tree, tvb, offset + 2, 1, "Dict: %u bits", - tvb_get_guint8(tvb, offset + 2) & 0x1f); + proto_tree_add_bitmask(field_tree, tvb, offset + 2, hf_ccp_opt_vd, + *optp->subtree_index, vd_fields, ENC_BIG_ENDIAN); } +/* http://tools.ietf.org/html/rfc1967 */ static void dissect_ccp_lzsdcp_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; - guint8 check_mode; - guint8 process_mode; tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name); field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + dissect_ccp_opt_type_len(tvb, offset, field_tree, optp->name); - proto_tree_add_text(field_tree, tvb, offset + 2, 2, "History Count: %u", - tvb_get_ntohs(tvb, offset + 2)); - check_mode = tvb_get_guint8(tvb, offset + 4); - proto_tree_add_text(field_tree, tvb, offset + 4, 1, - "Check Mode: %s (0x%02X)", - val_to_str_const(check_mode, lzsdcp_checkmode_vals, "Unknown"), - check_mode); - process_mode = tvb_get_guint8(tvb, offset + 5); - proto_tree_add_text(field_tree, tvb, offset + 5, 1, - "Process Mode: %s (0x%02X)", - val_to_str_const(process_mode, lzsdcp_processmode_vals, "Unknown"), - process_mode); + proto_tree_add_item(field_tree, hf_ccp_opt_history_count, tvb, + offset + 2, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(field_tree, hf_ccp_opt_check_mode, tvb, offset + 4, 1, + ENC_NA); + proto_tree_add_item(field_tree, hf_ccp_opt_process_mode, tvb, offset + 5, + 1, ENC_NA); } +/* http://tools.ietf.org/html/rfc1975 */ static void dissect_ccp_mvrca_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, guint length, packet_info *pinfo _U_, proto_tree *tree) @@ -2974,39 +3180,100 @@ dissect_ccp_mvrca_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name); field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + dissect_ccp_opt_type_len(tvb, offset, field_tree, optp->name); - proto_tree_add_text(field_tree, tvb, offset + 2, 1, "Features: %u", - tvb_get_guint8(tvb, offset + 2) >> 5); - proto_tree_add_text(field_tree, tvb, offset + 2, 1, - "Packet by Packet flag: %s", - tvb_get_guint8(tvb, offset + 2) & 0x20 ? "true" : "false"); - proto_tree_add_text(field_tree, tvb, offset + 2, 1, "History: %u", - tvb_get_guint8(tvb, offset + 2) & 0x20); - proto_tree_add_text(field_tree, tvb, offset + 3, 1, - "Number of contexts: %u", tvb_get_guint8(tvb, offset + 3)); + proto_tree_add_item(field_tree, hf_ccp_opt_fe, tvb, offset + 2, 1, ENC_NA); + proto_tree_add_item(field_tree, hf_ccp_opt_p, tvb, offset + 2, 1, ENC_NA); + proto_tree_add_item(field_tree, hf_ccp_opt_History, tvb, offset + 2, 1, + ENC_NA); + proto_tree_add_item(field_tree, hf_ccp_opt_contexts, tvb, offset + 3, 1, + ENC_NA); +} + +/* http://tools.ietf.org/html/rfc1976 */ +static void +dissect_ccp_dce_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", optp->name); + field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + dissect_ccp_opt_type_len(tvb, offset, field_tree, optp->name); + + proto_tree_add_item(field_tree, hf_ccp_opt_mode, tvb, offset + 2, 1, + ENC_NA); } +static const value_string deflate_method_vals[] = { + {8, "zlib compression"}, + {0, NULL} +}; + +static const value_string deflate_chk_vals[] = { + {0, "sequence number check method"}, + {0, NULL} +}; + +/* http://tools.ietf.org/html/rfc1979 */ static void dissect_ccp_deflate_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; - guint8 method; + guint8 window; + + tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name); + field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + dissect_ccp_opt_type_len(tvb, offset, field_tree, optp->name); + + window = tvb_get_guint8(tvb, offset + 2); + proto_tree_add_uint_format_value(field_tree, hf_ccp_opt_window, tvb, + offset + 2, 1, window, "%u", 1 << (hi_nibble(window) + 8)); + proto_tree_add_item(field_tree, hf_ccp_opt_method, tvb, offset + 2, 1, + ENC_NA); + proto_tree_add_item(field_tree, hf_ccp_opt_mbz, tvb, offset + 3, 1, + ENC_NA); + proto_tree_add_item(field_tree, hf_ccp_opt_chk, tvb, offset + 3, 1, + ENC_NA); +} + +static const range_string v44lzjh_mode_dict_rvals[] = { + {0, 0, "Datagram Mode (one dictionary and no history)"}, + {1, 1, "Multi-Datagram Mode (one dictionary with history)"}, + {2, G_MAXUINT16, "Individual Link Mode" /* "(and proposed number of + dictionaries each with a + corresponding history" */}, + {0, 0, NULL} +}; + +/* http://www.watersprings.org/pub/id/draft-heath-ppp-v44-01.txt */ +static void dissect_ccp_v44lzjh_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, + int offset, guint length, packet_info *pinfo, proto_tree *tree) +{ + proto_item *tf; + proto_tree *field_tree; tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name); field_tree = proto_item_add_subtree(tf, *optp->subtree_index); + dissect_ccp_opt_type_len(tvb, offset, field_tree, optp->name); + + proto_tree_add_item(field_tree, hf_ccp_opt_mode_dictcount, tvb, offset + 2, + 2, ENC_BIG_ENDIAN); - proto_tree_add_text(field_tree, tvb, offset + 2, 1, "Window: %u", - hi_nibble(tvb_get_guint8(tvb, offset + 2))); - method = lo_nibble(tvb_get_guint8(tvb, offset + 2)); - proto_tree_add_text(field_tree, tvb, offset + 2, 1, "Method: %s (0x%02x)", - method == 0x08 ? "zlib compression" : "other", method); - proto_tree_add_text(field_tree, tvb, offset + 3, 1, - "Sequence number check method: %u", - tvb_get_guint8(tvb, offset + 2) & 0x03); + if (length > 4) { + proto_tree_add_item(field_tree, hf_ccp_opt_dict_size, tvb, offset + 4, + 2, ENC_BIG_ENDIAN); + if (length > 6) { + proto_tree_add_item(field_tree, hf_ccp_opt_history_length, tvb, + offset + 6, 2, ENC_BIG_ENDIAN); + } + } } + static void dissect_cbcp_no_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset, guint length, packet_info *pinfo _U_, proto_tree *tree) @@ -3528,44 +3795,18 @@ dissect_cp(tvbuff_t *tvb, int proto_id, int proto_subtree_index, } break; - case ECHOREQ: /* All 3 are LCP only: RFC 1661 */ - case ECHOREP: - case DISCREQ: - if (tree) { - proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4, - ENC_BIG_ENDIAN); - if (length > 4) { - proto_tree_add_item(fh_tree, hf_lcp_data, tvb, offset + 4, - length - 4, ENC_NA); - } - } - break; - - case IDENT: /* LCP only: RFC 1570 */ - if (tree) { - proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4, - ENC_BIG_ENDIAN); - if (length > 4) { - proto_tree_add_item(fh_tree, hf_lcp_message, tvb, offset + 4, - length - 4, ENC_NA); - } - } - break; - - case TIMEREMAIN: /* LCP only: RFC 1570 */ - if (tree) { - guint32 secs_remaining; - - proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4, - ENC_BIG_ENDIAN); - secs_remaining = tvb_get_ntohl(tvb, offset + 4); - proto_tree_add_uint_format_value(fh_tree, hf_lcp_secs_remaining, - tvb, offset + 4, 4, secs_remaining, "%u %s", secs_remaining, - (secs_remaining == 0xffffffff) ? "(forever)" : "seconds"); - if (length > 8) { - proto_tree_add_item(fh_tree, hf_lcp_message, tvb, offset + 8, - length - 8, ENC_NA); - } + case CODEREJ: + if (tree && (length > 0)) { + /* TODO: Decode the rejected packet here ... but wait until we have + * a valid capture file with a CODEREJ, since the only capture file + * with CODEREJ packets in it that I know of is pppoe.dump.gz from + * the menagerie, and that file appears to have malformed CODEREJ + * packets as they don't include the Code, Identifier or Length + * fields so it's impossible to do the decode. */ + proto_tree_add_bytes_format(fh_tree, hf_ppp_data, tvb, offset, + length, NULL, "Rejected Packet (%d byte%s): %s", length, + plurality(length, "", "s"), + tvb_bytes_to_str(tvb, offset, length)); } break; @@ -3604,23 +3845,51 @@ dissect_cp(tvbuff_t *tvb, int proto_id, int proto_subtree_index, } break; - case CODEREJ: - if (tree && (length > 0)) { - /* TODO: Decode the rejected packet here ... but wait until we have - * a valid capture file with a CODEREJ, since the only capture file - * with CODEREJ packets in it that I know of is pppoe.dump.gz from - * the menagerie, and that file appears to have malformed CODEREJ - * packets as they don't include the Code, Identifier or Length - * fields so it's impossible to do the decode. */ - proto_tree_add_bytes_format(fh_tree, hf_ppp_data, tvb, offset, - length, NULL, "Rejected Packet (%d byte%s): %s", length, - plurality(length, "", "s"), - tvb_bytes_to_str(tvb, offset, length)); + case ECHOREQ: /* All 3 are LCP only: RFC 1661 */ + case ECHOREP: + case DISCREQ: + if (tree) { + proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4, + ENC_BIG_ENDIAN); + if (length > 4) { + proto_tree_add_item(fh_tree, hf_lcp_data, tvb, offset + 4, + length - 4, ENC_NA); + } + } + break; + + case IDENT: /* LCP only: RFC 1570 */ + if (tree) { + proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4, + ENC_BIG_ENDIAN); + if (length > 4) { + proto_tree_add_item(fh_tree, hf_lcp_message, tvb, offset + 4, + length - 4, ENC_NA); + } + } + break; + + case TIMEREMAIN: /* LCP only: RFC 1570 */ + if (tree) { + guint32 secs_remaining; + + proto_tree_add_item(fh_tree, hf_lcp_magic_number, tvb, offset, 4, + ENC_BIG_ENDIAN); + secs_remaining = tvb_get_ntohl(tvb, offset + 4); + proto_tree_add_uint_format_value(fh_tree, hf_lcp_secs_remaining, + tvb, offset + 4, 4, secs_remaining, "%u %s", secs_remaining, + (secs_remaining == 0xffffffff) ? "(forever)" : "seconds"); + if (length > 8) { + proto_tree_add_item(fh_tree, hf_lcp_message, tvb, offset + 8, + length - 8, ENC_NA); + } } break; case TERMREQ: case TERMACK: + case RESETREQ: /* RESETREQ and RESETACK are CCP only: RFC 1962 */ + case RESETACK: default: if (tree && (length > 0)) { proto_tree_add_item(fh_tree, hf_ppp_data, tvb, offset, length, @@ -5861,19 +6130,141 @@ proto_reg_handoff_osinlcp(void) void proto_register_ccp(void) { + static hf_register_info hf[] = { + { &hf_ccp_opt_type, + { "Type", "ccp.opt.type", FT_UINT8, BASE_DEC, + NULL, 0x0, NULL, HFILL }}, + { &hf_ccp_opt_length, + { "Length", "ccp.opt.length", FT_UINT8, BASE_DEC, + NULL, 0x0, NULL, HFILL }}, + { &hf_ccp_opt_oui, + { "OUI", "ccp.opt.oui", FT_BYTES, BASE_NONE, + NULL, 0x0, NULL, HFILL }}, + { &hf_ccp_opt_subtype, + { "Subtype", "ccp.opt.subtype", FT_UINT8, BASE_DEC_HEX, + NULL, 0x0, NULL, HFILL }}, + { &hf_ccp_opt_history_count, + { "History Count", "ccp.opt.history_count", FT_UINT16, BASE_DEC, + NULL, 0x0, "The maximum number of compression histories", + HFILL }}, + { &hf_ccp_opt_cm, + { "Check Mode Field", "ccp.opt.cm", FT_UINT8, BASE_DEC, + NULL, 0x0, NULL, HFILL }}, + { &hf_ccp_opt_cm_reserved, + { "Reserved", "ccp.opt.cm.reserved", FT_UINT8, BASE_DEC, + NULL, 0xF8, NULL, HFILL }}, + { &hf_ccp_opt_cm_check_mode, + { "Check Mode", "ccp.opt.cm.check_mode", FT_UINT8, BASE_DEC, + VALS(stac_checkmode_vals), 0x07, NULL, HFILL }}, + { &hf_ccp_opt_supported_bits, + { "Supported Bits", "ccp.opt.supported_bits", FT_UINT32, BASE_HEX, + NULL, 0x0, NULL, HFILL }}, + { &hf_ccp_opt_supported_bits_h, + { "H", "ccp.opt.supported_bits.h", FT_BOOLEAN, 32, + TFS(&ccp_mppe_h_tfs), MPPE_SUPPORTED_BITS_H, NULL, HFILL }}, + { &hf_ccp_opt_supported_bits_m, + { "M", "ccp.opt.supported_bits.m", FT_BOOLEAN, 32, + TFS(&ccp_mppe_m_tfs), MPPE_SUPPORTED_BITS_M, NULL, HFILL }}, + { &hf_ccp_opt_supported_bits_s, + { "S", "ccp.opt.supported_bits.s", FT_BOOLEAN, 32, + TFS(&ccp_mppe_s_tfs), MPPE_SUPPORTED_BITS_S, NULL, HFILL }}, + { &hf_ccp_opt_supported_bits_l, + { "L", "ccp.opt.supported_bits.l", FT_BOOLEAN, 32, + TFS(&ccp_mppe_l_tfs), MPPE_SUPPORTED_BITS_L, NULL, HFILL }}, + { &hf_ccp_opt_supported_bits_d, + { "D", "ccp.opt.supported_bits.d", FT_BOOLEAN, 32, + TFS(&ccp_mppe_d_tfs), MPPE_SUPPORTED_BITS_D, NULL, HFILL }}, + { &hf_ccp_opt_supported_bits_c, + { "C", "ccp.opt.supported_bits.c", FT_BOOLEAN, 32, + TFS(&ccp_mppe_c_tfs), MPPC_SUPPORTED_BITS_C, NULL, HFILL }}, + { &hf_ccp_opt_history, + { "History", "ccp.opt.history", FT_UINT8, BASE_DEC, NULL, 0x0, + "Maximum size of the compression history in powers of 2", + HFILL }}, + { &hf_ccp_opt_version, + { "Version", "ccp.opt.version", FT_BYTES, BASE_NONE, + NULL, 0x0, NULL, HFILL }}, + { &hf_ccp_opt_vd, + { "Vers/Dict", "ccp.opt.vd", FT_UINT8, BASE_HEX, + NULL, 0x0, NULL, HFILL }}, + { &hf_ccp_opt_vd_vers, + { "Vers", "ccp.opt.vd.vers", FT_UINT8, BASE_DEC, + NULL, 0xE0, NULL, HFILL }}, + { &hf_ccp_opt_vd_dict, + { "Dict", "ccp.opt.vd.dict", FT_UINT8, BASE_DEC, NULL, + 0x1F, "The size in bits of the largest code used", HFILL }}, + { &hf_ccp_opt_check_mode, + { "Check Mode", "ccp.opt.check_mode", FT_UINT8, BASE_DEC, + VALS(&lzsdcp_checkmode_vals), 0x0, NULL, HFILL }}, + { &hf_ccp_opt_process_mode, + { "Process Mode", "ccp.opt.process_mode", FT_UINT8, BASE_DEC, + VALS(&lzsdcp_processmode_vals), 0x0, NULL, HFILL }}, + { &hf_ccp_opt_fe, + { "Features", "ccp.opt.fe", FT_UINT8, BASE_DEC, + NULL, 0xC0, NULL, HFILL }}, + { &hf_ccp_opt_p, + { "Packet by Packet flag", "ccp.opt.p", FT_BOOLEAN, 8, + TFS(&tfs_enabled_disabled), 0x20, NULL, HFILL }}, + { &hf_ccp_opt_History, + { "History", "ccp.opt.History", FT_UINT8, BASE_DEC, + NULL, 0x1F, NULL, HFILL }}, + { &hf_ccp_opt_contexts, + { "# Contexts", "ccp.opt.contexts", FT_UINT8, BASE_DEC, + NULL, 0x0, NULL, HFILL }}, + { &hf_ccp_opt_mode, + { "Mode", "ccp.opt.mode", FT_UINT8, BASE_DEC, + VALS(&dce_mode_vals), 0x0, NULL, HFILL }}, + { &hf_ccp_opt_window, + { "Window", "ccp.opt.window", FT_UINT8, BASE_DEC, + NULL, 0xF0, NULL, HFILL }}, + { &hf_ccp_opt_method, + { "Method", "ccp.opt.method", FT_UINT8, BASE_DEC, + VALS(&deflate_method_vals), 0x0F, NULL, HFILL }}, + { &hf_ccp_opt_mbz, + { "MBZ", "ccp.opt.mbz", FT_UINT8, BASE_DEC, + NULL, 0xFC, NULL, HFILL }}, + { &hf_ccp_opt_chk, + { "Chk", "ccp.opt.chk", FT_UINT8, BASE_DEC, + VALS(&deflate_chk_vals), 0x03, NULL, HFILL }}, + { &hf_ccp_opt_mode_dictcount, + { "Mode/Dictionary Count", "ccp.opt.mode_dictcount", FT_UINT16, + BASE_DEC | BASE_RANGE_STRING, RVALS(v44lzjh_mode_dict_rvals), + 0x0, NULL, HFILL }}, + { &hf_ccp_opt_dict_size, + { "Dictionary Size", "ccp.opt.dict_size", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL }}, + { &hf_ccp_opt_history_length, + { "History Length", "ccp.opt.history_length", FT_UINT16, BASE_DEC, + NULL, 0x0, NULL, HFILL }}, + { &hf_ccp_opt_data, + { "Data", "ccp.opt.data", FT_BYTES, BASE_NONE, + NULL, 0x0, NULL, HFILL }}, + }; static gint *ett[] = { &ett_ccp, &ett_ccp_options, + &ett_ccp_oui_opt, + &ett_ccp_predict1_opt, + &ett_ccp_predict2_opt, + &ett_ccp_puddle_opt, + &ett_ccp_hpppc_opt, &ett_ccp_stac_opt, - &ett_ccp_mppc_opt, + &ett_ccp_stac_opt_check_mode, + &ett_ccp_mppe_opt, + &ett_ccp_mppe_opt_supp_bits, + &ett_ccp_gfza_opt, + &ett_ccp_v42bis_opt, &ett_ccp_bsdcomp_opt, &ett_ccp_lzsdcp_opt, &ett_ccp_mvrca_opt, - &ett_ccp_deflate_opt + &ett_ccp_dce_opt, + &ett_ccp_deflate_opt, + &ett_ccp_v44lzjh_opt }; proto_ccp = proto_register_protocol("PPP Compression Control Protocol", "PPP CCP", "ccp"); + proto_register_field_array(proto_ccp, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } |