/* packet-mux27010.c * Dissects a variant of 3GPP TS 27.010 multiplexing protocol * Copyright 2011, Hans-Christoph Schemmel * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ /* * This dissector analyses a multiplexed communication between a GSM modem and the host, * whereby the multiplexing is based upon a variant of the specification 3G TS 27.010. * * The assigned DLT value is: * LINKTYPE_MUX27010 236 DLT_MUX27010 * * A detailed description of the packet structure/LINKTYPE_MUX27010 can be found on: * http://www.tcpdump.org/linktypes/LINKTYPE_MUX27010.html */ #include "config.h" #include #include #include #include #include void proto_register_mux27010(void); void proto_reg_handoff_mux27010(void); #define PROTO_TAG_MUX27010 "MUX27010" /*Extended Header*/ #define MUX27010_EXTENDED_HEADER_NOT_ENDED 0x01 /*Address flags*/ #define MUX27010_DLCI_ADDRESS_FLAG 0xFC #define MUX27010_EA_ADDRESS_FLAG 0x01 #define MUX27010_CR_ADDRESS_FLAG 0x02 /*Control flags*/ #define MUX27010_FRAMETYPE_CONTROL_FLAG 0xEF #define MUX27010_FRAMETYPE_CONTROL_FLAG_SABM 0x2F #define MUX27010_FRAMETYPE_CONTROL_FLAG_UA 0x63 #define MUX27010_FRAMETYPE_CONTROL_FLAG_DM 0x0F #define MUX27010_FRAMETYPE_CONTROL_FLAG_DISC 0x43 #define MUX27010_FRAMETYPE_CONTROL_FLAG_UIH 0xEF #define MUX27010_PF_CONTROL_FLAG 0x10 #define MUX27010_FRAMETYPE_CONTROL_FLAG_UIH_E 0x00 #define MUX27010_FRAMETYPE_CONTROL_FLAG_RR 0x01 #define MUX27010_FRAMETYPE_CONTROL_FLAG_RNR 0x05 #define MUX27010_FRAMETYPE_CONTROL_FLAG_REJ 0x09 #define MUX27010_FRAMETYPE_CONTROL_FLAG_NS 0x0E #define MUX27010_FRAMETYPE_CONTROL_FLAG_NR 0xE0 #define MUX27010_FRAMETYPE_CONTROL_FLAG_NOT_GREATER_THEN_7 0x07 /*Length*/ #define MUX27010_EA_LENGTH_FLAG 0x01 #define MUX27010_FRAMESIZE_LENGTH_FLAG 0xFE #define MUX27010_FRAMESIZE_LENGTH_FLAG_EA 0xFFFE /*Control Channel*/ #define MUX27010_EA_CONTROLCHANNEL_FRAMETYPE_FLAG 0x01 #define MUX27010_CR_CONTROLCHANNEL_FRAMETYPE_FLAG 0x02 #define MUX27010_COMMAND_CONTROLCHANNEL_FRAMETYPE_FLAG 0xFC #define MUX27010_EA_CONTROLCHANNEL_LENGTH_FLAG 0x01 #define MUX27010_LENGTHFIELD_CONTROLCHANNEL_LENGTH_FLAG 0xFE #define MUX27010_VALUE_CONTROLCHANNEL_TEST_VERSION 0xFF #define MUX27010_VALUE_CONTROLCHANNEL_TEST_IEI_TE 0x04 #define MUX27010_VALUE_CONTROLCHANNEL_TEST_IEI_MS 0x08 #define MUX27010_VALUE_CONTROLCHANNEL_MSC_DCLI 0xFC #define MUX27010_VALUE_CONTROLCHANNEL_MSC_V24_FC 0x02 #define MUX27010_VALUE_CONTROLCHANNEL_MSC_V24_RTC 0x04 #define MUX27010_VALUE_CONTROLCHANNEL_MSC_V24_RTR 0x08 #define MUX27010_VALUE_CONTROLCHANNEL_MSC_V24_RING 0x40 #define MUX27010_VALUE_CONTROLCHANNEL_MSC_V24_DCD 0x80 #define MUX27010_VALUE_CONTROLCHANNEL_PN_DLCI 0x3F #define MUX27010_VALUE_CONTROLCHANNEL_PN_FRAMETYPE 0x0F #define MUX27010_VALUE_CONTROLCHANNEL_PN_CL 0xF0 #define MUX27010_VALUE_CONTROLCHANNEL_PN_PRIO 0x3F #define MUX27010_VALUE_CONTROLCHANNEL_PN_WINSIZE 0x07 /*Command pattern - set C/R bit to 1*/ #define MUX27010_COMMAND_MULTIPLEXER_CLOSEDOWN 0xC3 /*11000011*/ #define MUX27010_COMMAND_TEST_COMMAND 0x23 /*00100011*/ #define MUX27010_COMMAND_POWER_SAVING_CONTROL 0x43 /*01000011*/ #define MUX27010_COMMAND_NON_SUPPORTED_COMMAND_RESPONSE 0x13 /*00010011*/ #define MUX27010_COMMAND_MODEM_STATUS_COMMAND 0xE3 /*00010011*/ #define MUX27010_COMMAND_PARAMETER_NEGOTIATION 0x83 /*10000011*/ /* Wireshark ID of the MUX27010 protocol */ static int proto_mux27010; /* Handles of subdissectors */ static dissector_handle_t ppp_handle; #if 0 static const value_string packettypenames[] = { { 0, "TEXT" }, { 1, "SOMETHING_ELSE" }, { 0, NULL } }; #endif static const value_string direction_vals[] = { { 0, "Direction: Application => Module" }, { 1, "Module => Application" }, { 2, "Not valid" }, { 3, "Not valid" }, { 0, NULL } }; static const value_string detailedvalue_response_vals[] = { { 0, "Failure" }, { 1, "Success" }, { 0, NULL } }; static const value_string frame_type_vals[] = { { MUX27010_FRAMETYPE_CONTROL_FLAG_SABM, "SABM" }, { MUX27010_FRAMETYPE_CONTROL_FLAG_UA, "UA" }, { MUX27010_FRAMETYPE_CONTROL_FLAG_DM, "DM" }, { MUX27010_FRAMETYPE_CONTROL_FLAG_DISC, "DISC" }, { MUX27010_FRAMETYPE_CONTROL_FLAG_UIH, "UIH" }, { MUX27010_FRAMETYPE_CONTROL_FLAG_UIH_E, "UIH_E" }, { MUX27010_FRAMETYPE_CONTROL_FLAG_RR, "Receive Ready" }, { MUX27010_FRAMETYPE_CONTROL_FLAG_RNR, "Receive Not Ready" }, { MUX27010_FRAMETYPE_CONTROL_FLAG_REJ, "Reject" }, { 0, NULL } }; static const value_string command_vals[] = { { (MUX27010_COMMAND_MULTIPLEXER_CLOSEDOWN>>2), "Multiplexer Close Down" }, { (MUX27010_COMMAND_TEST_COMMAND>>2), "Test Command" }, { (MUX27010_COMMAND_POWER_SAVING_CONTROL>>2), "Power Saving Control" }, { (MUX27010_COMMAND_NON_SUPPORTED_COMMAND_RESPONSE>>2), "Non-supported Command Response" }, { (MUX27010_COMMAND_MODEM_STATUS_COMMAND>>2), "Modem Status Command" }, { (MUX27010_COMMAND_PARAMETER_NEGOTIATION>>2), "Parameter Negotiation" }, { 0, NULL } }; static const value_string iei_coding_vals[] = { { MUX27010_VALUE_CONTROLCHANNEL_TEST_IEI_TE, "TEMUX_VERSION" }, { MUX27010_VALUE_CONTROLCHANNEL_TEST_IEI_MS, "MSMUX_VERSION" }, { 0, NULL } }; /*Control channel*/ struct controlchannel_type { guint8 cr; guint8 command; gint number_of_type_frames; }; struct controlchannel { guint8 length_value; gint number_of_length_frames; }; /* The following hf_* variables are used to hold the Wireshark IDs of * the header fields; they are filled out when call * proto_register_field_array() in proto_register_mux27010() */ static gint hf_mux27010_extended_header; static gint hf_mux27010_direction; static gint hf_mux27010; static gint hf_mux27010_address; static gint hf_mux27010_control; static gint hf_mux27010_length; static gint hf_mux27010_controlchannel; /*Extended Header*/ static int hf_mux27010_extended_header_size; static int hf_mux27010_extended_header_msg_number_I; static int hf_mux27010_extended_header_freq_number_I; static int hf_mux27010_extended_header_start_pos_I; static int hf_mux27010_extended_header_start_byte_I; static int hf_mux27010_extended_header_end_pos_I; static int hf_mux27010_extended_header_end_byte_I; static int hf_mux27010_extended_header_flag_ended_I; static int hf_mux27010_extended_header_msg_number_II; static int hf_mux27010_extended_header_freq_number_II; static int hf_mux27010_extended_header_start_pos_II; static int hf_mux27010_extended_header_start_byte_II; static int hf_mux27010_extended_header_end_pos_II; static int hf_mux27010_extended_header_end_byte_II; static int hf_mux27010_extended_header_flag_ended_II; static int hf_mux27010_extended_header_msg_number_III; static int hf_mux27010_extended_header_freq_number_III; static int hf_mux27010_extended_header_start_pos_III; static int hf_mux27010_extended_header_start_byte_III; static int hf_mux27010_extended_header_end_pos_III; static int hf_mux27010_extended_header_end_byte_III; static int hf_mux27010_extended_header_flag_ended_III; /*Address*/ static int hf_mux27010_dlciaddressflag; static int hf_mux27010_eaaddressflag; static int hf_mux27010_craddressflag; /* static int hf_mux27010_addressdirection; */ /*Control*/ static int hf_mux27010_controlframetype; static int hf_mux27010_controlframetypens; static int hf_mux27010_controlframetypenr; static int hf_mux27010_pfcontrolflag; /*Length*/ static int hf_mux27010_ealengthflag; static int hf_mux27010_lengthframesize; static int hf_mux27010_lengthframesize_ea; /*Control channel dlci = 0*/ static int hf_mux27010_controlchannelframetype; static int hf_mux27010_controlchanneleaframetype; static int hf_mux27010_controlchannelcrframetype; static int hf_mux27010_controlchannelframetypecommand; static int hf_mux27010_controlchannellength; static int hf_mux27010_controlchannelealength; static int hf_mux27010_controlchannellengthfield; static int hf_mux27010_controlchannelvalue; static int hf_mux27010_controlchannel_iei_coding; static int hf_mux27010_controlchanneldetailedvalue; static int hf_mux27010_controlchannel_detailedvalue_response; static int hf_mux27010_controlchanneldetailedvaluetestcommandversion; static int hf_mux27010_controlchanneldetailedvaluemscdlci; /* static int hf_mux27010_controlchanneldetailedvaluemscv24; */ static int hf_mux27010_controlchanneldetailedvaluemscv24fc; static int hf_mux27010_controlchanneldetailedvaluemscv24rtc; static int hf_mux27010_controlchanneldetailedvaluemscv24rtr; static int hf_mux27010_controlchanneldetailedvaluemscv24ring; static int hf_mux27010_controlchanneldetailedvaluemscv24dcd; static int hf_mux27010_controlchanneldetailedvaluemscbreak; static int hf_mux27010_controlchanneldetailedvaluepndlci; static int hf_mux27010_controlchanneldetailedvaluepnframetype; static int hf_mux27010_controlchanneldetailedvaluepncl; static int hf_mux27010_controlchanneldetailedvaluepnprio; static int hf_mux27010_controlchanneldetailedvaluepntimer; static int hf_mux27010_controlchanneldetailedvaluepnframesize; static int hf_mux27010_controlchanneldetailedvaluepnna; static int hf_mux27010_controlchanneldetailedvaluepnwinsize; /*Information*/ static int hf_mux27010_information; static int hf_mux27010_information_str; /*Checksum*/ static int hf_mux27010_checksum; static int hf_mux27010_checksum_correct; /* These are the ids of the subtrees that we may be creating */ static gint ett_mux27010_extended_header; static gint ett_mux27010; static gint ett_mux27010_address; static gint ett_mux27010_control; static gint ett_mux27010_length; static gint ett_mux27010_controlchannel; static gint ett_mux27010_controlchannelframetype; static gint ett_mux27010_controlchannellength; static gint ett_mux27010_controlchannelvalue; static gint ett_mux27010_information; static gint ett_mux27010_checksum; static expert_field ei_mux27010_message_illogical; static expert_field ei_mux27010_checksum_incorrect; static int hf_msg_fragments; static int hf_msg_fragment; static int hf_msg_fragment_overlap; static int hf_msg_fragment_overlap_conflicts; static int hf_msg_fragment_multiple_tails; static int hf_msg_fragment_too_long_fragment; static int hf_msg_fragment_error; static int hf_msg_fragment_count; static int hf_msg_reassembled_in; static int hf_msg_reassembled_length; static gint ett_msg_fragment; static gint ett_msg_fragments; static dissector_handle_t mux27010_handle; static const fragment_items msg_frag_items = { /* Fragment subtrees */ &ett_msg_fragment, &ett_msg_fragments, /* Fragment fields */ &hf_msg_fragments, &hf_msg_fragment, &hf_msg_fragment_overlap, &hf_msg_fragment_overlap_conflicts, &hf_msg_fragment_multiple_tails, &hf_msg_fragment_too_long_fragment, &hf_msg_fragment_error, &hf_msg_fragment_count, /* Reassembled in field */ &hf_msg_reassembled_in, /* Reassembled length field */ &hf_msg_reassembled_length, /* Reassembled data field */ NULL, /* Tag */ "Message fragments" }; static reassembly_table msg_reassembly_table; static int getExtendedHeader(tvbuff_t *tvb, proto_tree *field_tree, int offset, guint8* sizeMuxPPPHeader){ int i; *sizeMuxPPPHeader = tvb_get_guint8(tvb, offset); proto_tree_add_item(field_tree, hf_mux27010_extended_header_size, tvb, offset, 1, ENC_BIG_ENDIAN); if (*sizeMuxPPPHeader > 0){ int tmpOffset = 1; guint16 tmpStartByte = 0; guint16 tmpLastByte = 0; for (i=0; i < *sizeMuxPPPHeader/7; i++){ switch(i){ case(0) : proto_tree_add_item(field_tree, hf_mux27010_extended_header_msg_number_I, tvb, offset+tmpOffset, 2, ENC_BIG_ENDIAN); tmpOffset+=2; proto_tree_add_item(field_tree, hf_mux27010_extended_header_freq_number_I, tvb, offset+tmpOffset, 2, ENC_BIG_ENDIAN); tmpOffset+=2; tmpStartByte = tvb_get_guint8(tvb, tmpOffset) + *sizeMuxPPPHeader + 1; proto_tree_add_item(field_tree, hf_mux27010_extended_header_start_pos_I, tvb, offset+tmpOffset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree, hf_mux27010_extended_header_start_byte_I, tvb, tmpStartByte, 1, ENC_BIG_ENDIAN); tmpOffset+=1; tmpLastByte = tvb_get_guint8(tvb, tmpOffset) + *sizeMuxPPPHeader + 1; proto_tree_add_item(field_tree, hf_mux27010_extended_header_end_pos_I, tvb, offset+tmpOffset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree, hf_mux27010_extended_header_end_byte_I, tvb, tmpLastByte, 1, ENC_BIG_ENDIAN); tmpOffset+=1; proto_tree_add_item(field_tree, hf_mux27010_extended_header_flag_ended_I, tvb, offset+tmpOffset, 1, ENC_BIG_ENDIAN); if ((tvb_get_guint8(tvb, tmpOffset) & MUX27010_EXTENDED_HEADER_NOT_ENDED) == MUX27010_EXTENDED_HEADER_NOT_ENDED) proto_tree_add_uint_format(field_tree, hf_mux27010_extended_header_flag_ended_I, tvb, offset+tmpOffset, 1, 1, "Not Last Packet in Frequence"); else proto_tree_add_uint_format(field_tree, hf_mux27010_extended_header_flag_ended_I, tvb, offset+tmpOffset, 1, 1, "Last Packet in Frequence"); break; case(1) : tmpOffset+=1; proto_tree_add_item(field_tree, hf_mux27010_extended_header_msg_number_II, tvb, offset+tmpOffset, 2, ENC_BIG_ENDIAN); tmpOffset+=2; proto_tree_add_item(field_tree, hf_mux27010_extended_header_freq_number_II, tvb, offset+tmpOffset, 2, ENC_BIG_ENDIAN); tmpOffset+=2; tmpStartByte = tvb_get_guint8(tvb, tmpOffset) + *sizeMuxPPPHeader + 1; proto_tree_add_item(field_tree, hf_mux27010_extended_header_start_pos_II, tvb, offset+tmpOffset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree, hf_mux27010_extended_header_start_byte_II, tvb, tmpStartByte, 1, ENC_BIG_ENDIAN); tmpOffset+=1; tmpLastByte = tvb_get_guint8(tvb, tmpOffset) + *sizeMuxPPPHeader + 1; proto_tree_add_item(field_tree, hf_mux27010_extended_header_end_pos_II, tvb, offset+tmpOffset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree, hf_mux27010_extended_header_end_byte_II, tvb, tmpLastByte, 1, ENC_BIG_ENDIAN); tmpOffset+=1; proto_tree_add_item(field_tree, hf_mux27010_extended_header_flag_ended_II, tvb, offset+tmpOffset, 1, ENC_BIG_ENDIAN); if ((tvb_get_guint8(tvb, tmpOffset) & MUX27010_EXTENDED_HEADER_NOT_ENDED) == MUX27010_EXTENDED_HEADER_NOT_ENDED) proto_tree_add_uint_format(field_tree, hf_mux27010_extended_header_flag_ended_II, tvb, offset+tmpOffset, 1, 1, "Not Last Packet in Frequence"); else proto_tree_add_uint_format(field_tree, hf_mux27010_extended_header_flag_ended_II, tvb, offset+tmpOffset, 1, 1, "Last Packet in Frequence"); break; case(2) : tmpOffset+=1; proto_tree_add_item(field_tree, hf_mux27010_extended_header_msg_number_III, tvb, offset+tmpOffset, 2, ENC_BIG_ENDIAN); tmpOffset+=2; proto_tree_add_item(field_tree, hf_mux27010_extended_header_freq_number_III, tvb, offset+tmpOffset, 2, ENC_BIG_ENDIAN); tmpOffset+=2; tmpStartByte = tvb_get_guint8(tvb, tmpOffset) + *sizeMuxPPPHeader + 1; proto_tree_add_item(field_tree, hf_mux27010_extended_header_start_pos_III, tvb, offset+tmpOffset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree, hf_mux27010_extended_header_start_byte_III, tvb, tmpStartByte, 1, ENC_BIG_ENDIAN); tmpOffset+=1; tmpLastByte = tvb_get_guint8(tvb, tmpOffset) + *sizeMuxPPPHeader + 1; proto_tree_add_item(field_tree, hf_mux27010_extended_header_end_pos_III, tvb, offset+tmpOffset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree, hf_mux27010_extended_header_end_byte_III, tvb, tmpLastByte, 1, ENC_BIG_ENDIAN); tmpOffset+=1; proto_tree_add_item(field_tree, hf_mux27010_extended_header_flag_ended_III, tvb, offset+tmpOffset, 1, ENC_BIG_ENDIAN); if ((tvb_get_guint8(tvb, tmpOffset) & MUX27010_EXTENDED_HEADER_NOT_ENDED) == MUX27010_EXTENDED_HEADER_NOT_ENDED) proto_tree_add_uint_format(field_tree, hf_mux27010_extended_header_flag_ended_III, tvb, offset+tmpOffset, 1, 1, "Not Last Packet in Frequence"); else proto_tree_add_uint_format(field_tree, hf_mux27010_extended_header_flag_ended_III, tvb, offset+tmpOffset, 1, 1, "Last Packet in Frequence"); break; } } } return *sizeMuxPPPHeader; } /*Get the direction of the actual packet*/ static int getFrameDirection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *field_tree, int offset){ guint8 direction_in_out; /*Direction is coded in the first byte of the frame*/ direction_in_out = tvb_get_guint8(tvb, offset); /*If first byte is 0 => Frame source is Application*/ /*If first byte is 1 => Frame source is Module*/ /*else Error*/ proto_tree_add_uint(field_tree, hf_mux27010_direction, tvb, offset, 1, direction_in_out & 3); switch (direction_in_out & 3) { case (0):/*Application >> Module*/ col_set_str(pinfo->cinfo, COL_DEF_SRC, "Application DLCI "); col_set_str(pinfo->cinfo, COL_DEF_DST, "Module"); break; case (1):/*Module >> Application*/ col_set_str(pinfo->cinfo, COL_DEF_SRC, "Module DLCI "); col_set_str(pinfo->cinfo, COL_DEF_DST, "Application"); break; default:/*?? >> ??*/ col_set_str(pinfo->cinfo, COL_DEF_SRC, "Direction not valid "); col_set_str(pinfo->cinfo, COL_DEF_DST, "Direction not valid "); break; } return 1; } /*Get the address of the actual frame*/ static int getFrameAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *field_tree_addr, int offset, guint8* dlci_number){ guint8 byte; byte = tvb_get_guint8(tvb, offset); /*Get the DCLI number of the frame >> overwrite other bits (E/A, CR) >> shift*/ *dlci_number = (byte & MUX27010_DLCI_ADDRESS_FLAG) >> 2; /*Add text to string for Source column*/ col_append_fstr(pinfo->cinfo, COL_DEF_SRC, "%d ", *dlci_number); /*Add items to subtree to display the details*/ proto_tree_add_item(field_tree_addr, hf_mux27010_eaaddressflag, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_addr, hf_mux27010_craddressflag, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_addr, hf_mux27010_dlciaddressflag, tvb, offset, 1, ENC_BIG_ENDIAN); return 1; } /*Get frame data from control field*/ static int getFrameControlData(tvbuff_t *tvb, packet_info *pinfo, proto_tree *field_tree, int offset, guint8* frame_type){ /*if the frame type is known -> 1 else 0*/ guint8 known_frame_type = 0; /*Get the type of frame*/ *frame_type = tvb_get_guint8(tvb, offset) & MUX27010_FRAMETYPE_CONTROL_FLAG; /*Find out the frame type and write info into column*/ switch (*frame_type) { case (MUX27010_FRAMETYPE_CONTROL_FLAG_SABM): /*SABM frame*/ case (MUX27010_FRAMETYPE_CONTROL_FLAG_UA): /*UA frame*/ case (MUX27010_FRAMETYPE_CONTROL_FLAG_DM): /*DM frame*/ case (MUX27010_FRAMETYPE_CONTROL_FLAG_DISC): /*DISC frame*/ case (MUX27010_FRAMETYPE_CONTROL_FLAG_UIH): /*UIH frame*/ proto_tree_add_uint(field_tree, hf_mux27010_controlframetype, tvb, offset, 1, *frame_type); break; default: /*Got another frame -> probably a UIH_E, RR, RNR or REJ frame from a DLCI channel != 0 ==> Data channel*/ /*Check if frame is a UIH_E frame*/ if ((MUX27010_FRAMETYPE_CONTROL_FLAG_UIH_E | MUX27010_FRAMETYPE_CONTROL_FLAG_NS | MUX27010_FRAMETYPE_CONTROL_FLAG_NR) == (*frame_type | MUX27010_FRAMETYPE_CONTROL_FLAG_NS | MUX27010_FRAMETYPE_CONTROL_FLAG_NR)) { *frame_type = MUX27010_FRAMETYPE_CONTROL_FLAG_UIH_E; /*Add frame type to column*/ proto_tree_add_uint(field_tree, hf_mux27010_controlframetype, tvb, offset, 1, MUX27010_FRAMETYPE_CONTROL_FLAG_UIH_E); /*Add info about sequence numbers to column*/ proto_tree_add_item(field_tree, hf_mux27010_controlframetypens, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree, hf_mux27010_controlframetypenr, tvb, offset, 1, ENC_BIG_ENDIAN); /*Frame type is known*/ known_frame_type = 1; } /*Check if frame is a RR frame*/ if ((MUX27010_FRAMETYPE_CONTROL_FLAG_RR | MUX27010_FRAMETYPE_CONTROL_FLAG_NR) == (*frame_type | MUX27010_FRAMETYPE_CONTROL_FLAG_NR)) { *frame_type = MUX27010_FRAMETYPE_CONTROL_FLAG_RR; /*Add frame type to column*/ proto_tree_add_uint(field_tree, hf_mux27010_controlframetype, tvb, offset, 1, MUX27010_FRAMETYPE_CONTROL_FLAG_RR); /*Add info about sequence number to column*/ proto_tree_add_item(field_tree, hf_mux27010_controlframetypenr, tvb, offset, 1, ENC_BIG_ENDIAN); /*Frame type is known*/ known_frame_type = 1; } if ((MUX27010_FRAMETYPE_CONTROL_FLAG_RNR | MUX27010_FRAMETYPE_CONTROL_FLAG_NR) == (*frame_type | MUX27010_FRAMETYPE_CONTROL_FLAG_NR)) { *frame_type = MUX27010_FRAMETYPE_CONTROL_FLAG_RNR; /*Add frame type to column*/ proto_tree_add_uint(field_tree, hf_mux27010_controlframetype, tvb, offset, 1, MUX27010_FRAMETYPE_CONTROL_FLAG_RNR); /*Add info about sequence number to column*/ proto_tree_add_item(field_tree, hf_mux27010_controlframetypenr, tvb, offset, 1, ENC_BIG_ENDIAN); /*Frame type is known*/ known_frame_type = 1; } if ((MUX27010_FRAMETYPE_CONTROL_FLAG_REJ | MUX27010_FRAMETYPE_CONTROL_FLAG_NR) == (*frame_type | MUX27010_FRAMETYPE_CONTROL_FLAG_NR)) { *frame_type = MUX27010_FRAMETYPE_CONTROL_FLAG_REJ; /*Add frame type to column*/ proto_tree_add_uint(field_tree, hf_mux27010_controlframetype, tvb, offset, 1, MUX27010_FRAMETYPE_CONTROL_FLAG_REJ); /*Add info about sequence number to column*/ proto_tree_add_item(field_tree, hf_mux27010_controlframetypenr, tvb, offset, 1, ENC_BIG_ENDIAN); /*Frame type is known*/ known_frame_type = 1; } /*Unknown frame*/ if (known_frame_type == 0) { /*Add frame type to column*/ proto_tree_add_uint(field_tree, hf_mux27010_controlframetype, tvb, offset, 1, *frame_type); } } /*Write information to string for column info*/ col_add_fstr(pinfo->cinfo, COL_INFO, "(%s)", val_to_str_const(*frame_type, frame_type_vals, "Unknown")); /*Add Frame type value and PF bit to column*/ proto_tree_add_item(field_tree, hf_mux27010_controlframetype, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree, hf_mux27010_pfcontrolflag, tvb, offset, 1, ENC_BIG_ENDIAN); return 1; } /*Get frame data from length field*/ static int getFrameLength(tvbuff_t *tvb, proto_tree *field_tree, int offset, guint32* length_info){ /*Get the E/A bit*/ guint8 length_ea = tvb_get_guint8(tvb, offset) & MUX27010_EA_LENGTH_FLAG; proto_tree_add_item(field_tree, hf_mux27010_ealengthflag, tvb, offset, 1, ENC_BIG_ENDIAN); /*Get the length of the info field*/ /*If E/A = 1 it is the last octet*/ if (length_ea == 1) { /*Add the E/A bit and the length value to the subtree*/ proto_tree_add_item(field_tree, hf_mux27010_lengthframesize, tvb, offset, 1, ENC_BIG_ENDIAN); *length_info = (tvb_get_guint8(tvb, offset) & MUX27010_FRAMESIZE_LENGTH_FLAG) >> 1; /*Shift because of EA bit*/ return 1; } /*If E/A = 0 the length of the info field is >127; first octet stores LSB bits, second octet MSB -> LITTLE ENDIAN stuffing*/ proto_tree_add_item_ret_uint(field_tree, hf_mux27010_lengthframesize_ea, tvb, offset, 2, ENC_LITTLE_ENDIAN, length_info); return 2; } /*Get frame type of control channel frame*/ static int getControlChannelFrameType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *field_tree_ctr, int offset, struct controlchannel_type* cctype){ guint8 controlchannel_type_ea; /*Get the E/A bit*/ controlchannel_type_ea = tvb_get_guint8(tvb, offset) & MUX27010_EA_CONTROLCHANNEL_FRAMETYPE_FLAG; /*Set variable for number of octets for frame type to 0*/ cctype->number_of_type_frames = 0; /*If E/A bit = 1, there will be no other frame type octet*/ if (controlchannel_type_ea == 1) cctype->number_of_type_frames++; /*If E/A = 0, read all frame type octets*/ while (controlchannel_type_ea == 0){ cctype->number_of_type_frames++; controlchannel_type_ea = tvb_get_guint8(tvb, offset+cctype->number_of_type_frames) & MUX27010_EA_CONTROLCHANNEL_FRAMETYPE_FLAG; } /*Get CR bit*/ cctype->cr = (tvb_get_guint8(tvb, offset) & MUX27010_CR_CONTROLCHANNEL_FRAMETYPE_FLAG) >> 1; /*Get command info*/ cctype->command = tvb_get_guint8(tvb, offset) & MUX27010_COMMAND_CONTROLCHANNEL_FRAMETYPE_FLAG; /*Add info to subtree*/ proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneleaframetype, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchannelcrframetype, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchannelframetypecommand, tvb, offset, 1, ENC_BIG_ENDIAN); /*Check the control channel frame types and add the name to the subtree and strcat the name to the info column*/ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", val_to_str_const(cctype->command>>2, command_vals, "Unknown")); if (cctype->cr == 1) /*Command C/R*/{ col_append_str(pinfo->cinfo, COL_INFO, " (Command)"); } else{ /*Response*/ col_append_str(pinfo->cinfo, COL_INFO, " (Response)"); } return cctype->number_of_type_frames; } /*Get length of control channel info field*/ static int getControlChannelLength(tvbuff_t *tvb, proto_tree *field_tree_ctr, int offset, struct controlchannel* cc) { guint8 controlchannel_length_ea; /*Get the E/A bit*/ controlchannel_length_ea = tvb_get_guint8(tvb, offset) & MUX27010_EA_CONTROLCHANNEL_LENGTH_FLAG; /*Set variable for number of octets for info field to 0*/ cc->number_of_length_frames = 0; /*If E/A bit = 1, there will be no other info field length octet*/ if (controlchannel_length_ea == 1) cc->number_of_length_frames++; /*If E/A = 0, read all length of info field octets*/ while (controlchannel_length_ea == 0){ cc->number_of_length_frames++; controlchannel_length_ea = tvb_get_guint8(tvb, offset+cc->number_of_length_frames) & MUX27010_EA_CONTROLCHANNEL_LENGTH_FLAG; } /*Get the data from info field*/ cc->length_value = (tvb_get_guint8(tvb, offset) & MUX27010_LENGTHFIELD_CONTROLCHANNEL_LENGTH_FLAG) >> 1; /*Add data to subtree*/ proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchannelealength, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchannellengthfield, tvb, offset, 1, ENC_BIG_ENDIAN); return cc->number_of_length_frames; } /*Get values of control channel*/ static int getControlChannelValues(tvbuff_t *tvb, proto_tree *field_tree_ctr, int offset, struct controlchannel* cc, struct controlchannel_type* cctype){ guint8 controlchannel_iei; guint8 controlchannel_psc; /*Command pattern for Test Command (C/R is set to 1)*/ switch (cctype->command | MUX27010_EA_CONTROLCHANNEL_FRAMETYPE_FLAG | MUX27010_CR_CONTROLCHANNEL_FRAMETYPE_FLAG) { case MUX27010_COMMAND_TEST_COMMAND: proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluetestcommandversion, tvb, offset, 1, ENC_BIG_ENDIAN); controlchannel_iei = tvb_get_guint8(tvb, offset); if ((controlchannel_iei == MUX27010_VALUE_CONTROLCHANNEL_TEST_IEI_TE) || (controlchannel_iei == MUX27010_VALUE_CONTROLCHANNEL_TEST_IEI_MS)) { proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchannel_iei_coding, tvb, offset, 1, ENC_BIG_ENDIAN); } proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchannelvalue, tvb, offset+1, cc->length_value-1, ENC_NA|ENC_ASCII); break; /*Command pattern for Power saving control (C/R is set to 1)*/ case MUX27010_COMMAND_POWER_SAVING_CONTROL: proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvalue, tvb, offset, 1, ENC_BIG_ENDIAN); controlchannel_psc = tvb_get_guint8(tvb, offset); if (cctype->cr == 0 && controlchannel_psc == 0) /*Response Failure*/ proto_tree_add_uint(field_tree_ctr, hf_mux27010_controlchannel_detailedvalue_response, tvb, offset, cc->length_value, 0); if (cctype->cr == 0 && controlchannel_psc == 1) /*Response Success*/ proto_tree_add_uint(field_tree_ctr, hf_mux27010_controlchannel_detailedvalue_response, tvb, offset, cc->length_value, 1); break; /*Command pattern for non-supported command response (C/R is set to 1)*/ case MUX27010_COMMAND_NON_SUPPORTED_COMMAND_RESPONSE: proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvalue, tvb, offset, 1, ENC_BIG_ENDIAN); break; /*Command pattern for Modem Status Command (C/R is set to 1)*/ case MUX27010_COMMAND_MODEM_STATUS_COMMAND: proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluemscdlci, tvb, offset, 1, ENC_BIG_ENDIAN); /*Add bits of Flow Control*/ proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluemscv24fc, tvb, offset+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluemscv24rtc, tvb, offset+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluemscv24rtr, tvb, offset+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluemscv24ring, tvb, offset+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluemscv24dcd, tvb, offset+1, 1, ENC_BIG_ENDIAN); /**/ if (cc->length_value == 3) { proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluemscbreak, tvb, offset+2, 1, ENC_BIG_ENDIAN); } break; /*Command pattern for Parameter Negotiation (EA + C/R is set to 1)*/ case MUX27010_COMMAND_PARAMETER_NEGOTIATION: proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluepndlci, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluepnframetype, tvb, offset+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluepncl, tvb, offset+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluepnprio, tvb, offset+2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluepntimer, tvb, offset+3, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluepnframesize, tvb, offset+4, 2, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluepnna, tvb, offset+6, 1, ENC_BIG_ENDIAN); proto_tree_add_item(field_tree_ctr, hf_mux27010_controlchanneldetailedvaluepnwinsize, tvb, offset+7, 1, ENC_BIG_ENDIAN); break; } return cc->length_value; } /*Get values information field*/ static int getFrameInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *field_tree, int offset, guint32 length_info){ /*Get the data from information field as string*/ char *information_field = tvb_get_string_enc(pinfo->pool, tvb,offset,length_info, ENC_ASCII); /*delete unneeded signs out of info field -> for info column: CR (0x0d) and LF (0x0a)*/ information_field = g_strdelimit(information_field, "\r\n", ' '); col_append_fstr(pinfo->cinfo, COL_INFO, " %s", information_field); /*Add info to subtree*/ proto_tree_add_string(field_tree, hf_mux27010_information_str, tvb, offset, length_info, information_field); /*Increment offset by the length of chars in info field*/ return length_info; } static int dissect_mux27010(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { proto_item *ti, *tf, *tf_extended_header, *tf_addr, *tf_ctr; proto_tree *mux27010_tree, *field_tree, *field_tree_extended_header, *field_tree_addr, *field_tree_ctr; int offset = 0; guint32 length_info; gboolean save_fragmented; /*Address DLCI*/ gint8 dlci_number = 0; guint8 frame_type; /*private MUX frame header (PPP)*/ guint8 sizeMuxPPPHeader; struct controlchannel_type cc_type; struct controlchannel cc; /* Setup columns */ col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_MUX27010); col_clear(pinfo->cinfo, COL_INFO); /* Set offset to 0 => start to read at the begin of the frame*/ offset = 0; ti = proto_tree_add_item(tree, proto_mux27010, tvb, 0, -1, ENC_NA); mux27010_tree = proto_item_add_subtree(ti, ett_mux27010); /*Add a subtree (=item) to the child node => in this subtree the details of extended header will be displayed*/ tf_extended_header = proto_tree_add_item(mux27010_tree, hf_mux27010_extended_header, tvb, offset, 1, ENC_BIG_ENDIAN); field_tree_extended_header = proto_item_add_subtree(tf_extended_header, ett_mux27010_extended_header); offset += getExtendedHeader(tvb, field_tree_extended_header, offset, &sizeMuxPPPHeader); offset++; /*Get direction of the frame*/ offset += getFrameDirection(tvb, pinfo, mux27010_tree, offset); /*~~~~~~~~Flag~~~~~~~~*/ /*(Insert data into the child node)*/ /*Create item to show/highlight flag sequence*/ proto_tree_add_item(mux27010_tree, hf_mux27010, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /*~~~~~~~~/Flag~~~~~~~~*/ /*~~~~~~~~Address~~~~~~~~*/ /*Add a subtree (=item) to the child node => in this subtree the details of address data will be displayed*/ tf_addr = proto_tree_add_item(mux27010_tree, hf_mux27010_address, tvb, offset, 1, ENC_BIG_ENDIAN); field_tree_addr = proto_item_add_subtree(tf_addr, ett_mux27010_address); /*Get address data (DLCI, E/A, CR)*/ offset += getFrameAddress(tvb, pinfo, field_tree_addr, offset, &dlci_number); /*~~~~~~~~/Address~~~~~~~~*/ /*~~~~~~~~Control Data~~~~~~~~*/ /*Add a subtree (=item) to the child node => in this subtree the details of control data will be displayed*/ tf = proto_tree_add_item(mux27010_tree, hf_mux27010_control, tvb, offset, 1, ENC_BIG_ENDIAN); field_tree = proto_item_add_subtree(tf, ett_mux27010_control); /*Get control data of frame (Frame type)*/ offset += getFrameControlData(tvb, pinfo, field_tree, offset, &frame_type); /*~~~~~~~~/Control Data~~~~~~~~*/ /*~~~~~~~~Length~~~~~~~~*/ /*Set the variable for length of the info field to 0*/ length_info = 0; /*Check the frame type because in RR, RNR and REJ are no info and no length fields*/ if ((frame_type != MUX27010_FRAMETYPE_CONTROL_FLAG_RR) && (frame_type != MUX27010_FRAMETYPE_CONTROL_FLAG_RNR) && (frame_type != MUX27010_FRAMETYPE_CONTROL_FLAG_REJ)){ /*Add a subtree (=item) to the child node => in this subtree will be the details of length field*/ tf = proto_tree_add_item(mux27010_tree, hf_mux27010_length, tvb, offset, 1, ENC_BIG_ENDIAN); field_tree = proto_item_add_subtree(tf, ett_mux27010_length); /*Get frame length data*/ offset += getFrameLength(tvb, field_tree, offset, &length_info); } /*~~~~~~~~/Length~~~~~~~~*/ /*~~~~~~~~Control Channel~~~~~~~~*/ /*Control Channel only exists if DLCI = 0*/ if (dlci_number == 0) { /*If length field > 0, otherwise the frame has no data*/ if (length_info > 0) { /*--------Frame Type--------*/ /*Get and display data of frame type*/ /*Add a subtree (=item) to the child node => in this subtree the details of control channel will be displayed*/ tf = proto_tree_add_item(mux27010_tree, hf_mux27010_controlchannel, tvb, offset, 1, ENC_BIG_ENDIAN); field_tree = proto_item_add_subtree(tf, ett_mux27010_controlchannel); /*Add another subtree to the control channel subtree => in this subtree the details of control channel frame type will be displayed*/ tf_ctr = proto_tree_add_item(field_tree, hf_mux27010_controlchannelframetype, tvb, offset, 1, ENC_BIG_ENDIAN); field_tree_ctr = proto_item_add_subtree(tf_ctr, ett_mux27010_controlchannelframetype); /*Get data about the type of the frame*/ offset += getControlChannelFrameType(tvb, pinfo, field_tree_ctr, offset, &cc_type); proto_item_set_len(tf_ctr, cc_type.number_of_type_frames); /*--------/Frame Type--------*/ /*--------Length Field--------*/ /*Add another subtree to the control channel subtree => in this subtree the details of control channel length field will be displayed*/ tf_ctr = proto_tree_add_item(field_tree, hf_mux27010_controlchannellength, tvb, offset, 1, ENC_BIG_ENDIAN); field_tree_ctr = proto_item_add_subtree(tf_ctr, ett_mux27010_controlchannellength); /*Get data of length field*/ offset += getControlChannelLength(tvb, field_tree_ctr, offset, &cc); proto_item_set_len(tf_ctr, cc.number_of_length_frames); /*--------/Length Field--------*/ /*--------Values--------*/ /*If frame has data inside the length_value is > 0*/ if (cc.length_value > 0) { /*Add another subtree to the control channel subtree => in this subtree the details of control channel values/data will be displayed*/ field_tree_ctr = proto_tree_add_subtree_format(field_tree, tvb, offset, cc.length_value, ett_mux27010_controlchannelvalue, NULL, "Data: %i Byte(s)", cc.length_value); /*Get data of frame*/ offset += getControlChannelValues(tvb, field_tree_ctr, offset, &cc, &cc_type); }/*(controlchannel_length_value > 0)*/ /*--------/Values--------*/ }/*length_info > 0*/ }/*dlci_number == 0*/ /*~~~~~~~~Information~~~~~~~~*/ /*Display "normal" data/values (not control channel) if exists ==> length_info > 0*/ if (dlci_number != 0 && length_info > 0) { /*Add a subtree (=item) to the child node => in this subtree will be the data*/ tf = proto_tree_add_item(mux27010_tree, hf_mux27010_information, tvb, offset, 1, ENC_BIG_ENDIAN); field_tree = proto_item_add_subtree(tf, ett_mux27010_information); /*We have at least one PPP packet*/ if (sizeMuxPPPHeader > 0){ guint16 tmpOffset = 1; guint16 tmpOffsetBegin = 1; guint16 tmpOffsetEnd = 1; guint16 msg_seqid; guint16 msg_num; guint8 msg_start; guint8 msg_end; guint8 msg_flag; fragment_head *frag_msg = NULL; tvbuff_t *new_tvb = NULL; tvbuff_t *next_tvb2 = NULL; int i; for (i = 0; i < sizeMuxPPPHeader/7; i++){ tmpOffset = 7; tmpOffset = (i * tmpOffset)+1; msg_seqid = tvb_get_ntohs(tvb, tmpOffset); tmpOffset += 2; msg_num = tvb_get_ntohs(tvb, tmpOffset); tmpOffset += 2; msg_start = tvb_get_guint8(tvb, tmpOffset); tmpOffset += 1; msg_end = tvb_get_guint8(tvb, tmpOffset); tmpOffset += 1; msg_flag = tvb_get_guint8(tvb, tmpOffset); tmpOffset += 1; if (msg_end <= msg_start) { proto_tree_add_expert(field_tree, pinfo, &ei_mux27010_message_illogical, tvb, tmpOffset-3, 2); continue; } tmpOffsetBegin = sizeMuxPPPHeader + 1 + msg_start; /*+ Header_Size, + Direction*/ tmpOffsetEnd = sizeMuxPPPHeader + 1 + msg_end; save_fragmented = pinfo->fragmented; pinfo->fragmented = TRUE; frag_msg = fragment_add_seq_check(&msg_reassembly_table, tvb, tmpOffsetBegin, pinfo, msg_seqid, /* ID for fragments belonging together */ NULL, msg_num, /* fragment sequence number */ (tmpOffsetEnd-tmpOffsetBegin)+1, /* fragment length */ msg_flag); /* More fragments? */ new_tvb = process_reassembled_data(tvb, tmpOffsetBegin, pinfo, "Reassembled Message", frag_msg, &msg_frag_items, NULL, mux27010_tree); if (!frag_msg) { /* Not last packet of reassembled Message */ col_append_str(pinfo->cinfo, COL_INFO, " [Split Msg]"); } if (new_tvb) { /* take it all */ next_tvb2 = tvb_new_subset_remaining(new_tvb, 1); call_dissector(ppp_handle, next_tvb2, pinfo, tree); } pinfo->fragmented = save_fragmented; } } /*Get and display information*/ offset += getFrameInformation(tvb, pinfo, field_tree, offset, length_info); } /*~~~~~~~~/Information~~~~~~~~*/ /*~~~~~~~~Checksum~~~~~~~~*/ /*Validate checksum of frame*/ /*Add a subtree (=item) to the child node => in this subtree will be the checksum*/ tf = proto_tree_add_item(mux27010_tree, hf_mux27010_checksum, tvb, offset, 1, ENC_BIG_ENDIAN); field_tree = proto_item_add_subtree(tf, ett_mux27010_checksum); /*Call method check_checksum and validate checksum*/ if (check_fcs(tvb,offset-sizeMuxPPPHeader-3-length_info, sizeMuxPPPHeader+3, tvb_get_guint8(tvb, offset))){ /*Checksum is correct*/ proto_tree_add_boolean(field_tree, hf_mux27010_checksum_correct, tvb, offset, 1, TRUE); } else{ /*Checksum is incorrect*/ expert_add_info(pinfo, tf, &ei_mux27010_checksum_incorrect); } /*~~~~~~~~/Checksum~~~~~~~~*/ return tvb_captured_length(tvb); } /*Register the protocol*/ void proto_register_mux27010 (void) { /* A header field is something you can search/filter on. * * Create a structure to register fields. It consists of an * array of hf_register_info structures, each of which are of the format * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}. */ static hf_register_info hf[] = { /*Extended MUX header (for PPP)*/ {&hf_mux27010_extended_header, { "Extended Header", "mux27010.ext_header", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_size, { "Header Size", "mux27010.ext_header.size", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_msg_number_I, { "Message Number I", "mux27010.ext_header.msg_number_I", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_freq_number_I, { "Frequenz Number I", "mux27010.ext_header.frequenz_number_I", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_start_pos_I, { "Start Position I", "mux27010.ext_header.start_pos_I", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_start_byte_I, { "Start Byte I", "mux27010.ext_header.start_byte_I", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_end_pos_I, { "End Position I", "mux27010.ext_header.end_pos_I", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_end_byte_I, { "End Byte I", "mux27010.ext_header.end_byte_I", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_flag_ended_I, { "Flag Ended I", "mux27010.ext_header.flag_ended_I", FT_UINT8, BASE_HEX, NULL, MUX27010_EXTENDED_HEADER_NOT_ENDED, NULL, HFILL }}, {&hf_mux27010_extended_header_msg_number_II, { "Message Number II", "mux27010.ext_header.msg_number_II", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_freq_number_II, { "Frequenz Number II", "mux27010.ext_header.frequenz_number_II", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_start_pos_II, { "Start Position II", "mux27010.ext_header.start_pos_II", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_start_byte_II, { "Start Byte II", "mux27010.ext_header.start_byte_II", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_end_pos_II, { "End Position II", "mux27010.ext_header.end_pos_II", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_end_byte_II, { "End Byte II", "mux27010.ext_header.end_byte_II", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_flag_ended_II, { "Flag Ended II", "mux27010.ext_header.flag_ended_II", FT_UINT8, BASE_HEX, NULL, MUX27010_EXTENDED_HEADER_NOT_ENDED, NULL, HFILL }}, {&hf_mux27010_extended_header_msg_number_III, { "Message Number III", "mux27010.ext_header.msg_number_III", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_freq_number_III, { "Frequenz Number III", "mux27010.ext_header.frequenz_number_III", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_start_pos_III, { "Start Position III", "mux27010.ext_header.start_pos_III", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_start_byte_III, { "Start Byte III", "mux27010.ext_header.start_byte_III", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_end_pos_III, { "End Position III", "mux27010.ext_header.end_pos_III", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_end_byte_III, { "End Byte III", "mux27010.ext_header.end_byte_III", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, {&hf_mux27010_extended_header_flag_ended_III, { "Flag Ended III", "mux27010.ext_header.flag_ended_III", FT_UINT8, BASE_HEX, NULL, MUX27010_EXTENDED_HEADER_NOT_ENDED, NULL, HFILL }}, /*Direction*/ {&hf_mux27010_direction, { "Direction", "mux27010.direction", FT_UINT8, BASE_HEX, VALS(direction_vals), 0x0, NULL, HFILL }}, /*Flag*/ {&hf_mux27010, { "Flag", "mux27010.flag", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, /*Address frame*/ { &hf_mux27010_address, { "Address field", "mux27010.address", FT_UINT8, BASE_HEX, NULL, 0x0,NULL, HFILL }}, { &hf_mux27010_dlciaddressflag, { "DLCI number (decimal)", "mux27010.address.dlciaddress", FT_UINT8, BASE_DEC, NULL, MUX27010_DLCI_ADDRESS_FLAG, NULL, HFILL }}, { &hf_mux27010_eaaddressflag, { "EA Address Flag", "mux27010.address.eaaddress", FT_BOOLEAN, 8, NULL, MUX27010_EA_ADDRESS_FLAG, NULL, HFILL }}, { &hf_mux27010_craddressflag, { "C/R Address Flag", "mux27010.address.craddress", FT_BOOLEAN, 8, NULL, MUX27010_CR_ADDRESS_FLAG, NULL, HFILL }}, #if 0 { &hf_mux27010_addressdirection, { "Direction", "mux27010.address.direction", FT_UINT8, BASE_HEX, NULL, MUX27010_CR_ADDRESS_FLAG, NULL, HFILL }}, #endif /*Control frame*/ { &hf_mux27010_control, { "Control field", "mux27010.control", FT_UINT8, BASE_HEX, NULL, 0x0,NULL, HFILL }}, { &hf_mux27010_controlframetype, { "Frame Type", "mux27010.control.frametype", FT_UINT8, BASE_HEX, VALS(frame_type_vals), MUX27010_FRAMETYPE_CONTROL_FLAG, NULL, HFILL }}, { &hf_mux27010_controlframetypens, { "N(S) Sequence Number", "mux27010.control.frametype.ns", FT_UINT8, BASE_DEC, NULL, MUX27010_FRAMETYPE_CONTROL_FLAG_NS, NULL, HFILL }}, { &hf_mux27010_controlframetypenr, { "N(R) Receive Number", "mux27010.control.frametype.nr", FT_UINT8, BASE_DEC, NULL, MUX27010_FRAMETYPE_CONTROL_FLAG_NR, NULL, HFILL }}, { &hf_mux27010_pfcontrolflag, { "Poll/Final bit", "mux27010.control.pfcontrol", FT_UINT8, BASE_DEC, NULL, MUX27010_PF_CONTROL_FLAG, NULL, HFILL }}, /*Length frame*/ { &hf_mux27010_length, { "Length field", "mux27010.length", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_mux27010_ealengthflag, { "E/A Flag", "mux27010.length.ealength", FT_BOOLEAN, 8, NULL, MUX27010_EA_LENGTH_FLAG, NULL, HFILL }}, { &hf_mux27010_lengthframesize_ea, { "Info length", "mux27010.length.framesize_ea", FT_UINT16, BASE_DEC, NULL, MUX27010_FRAMESIZE_LENGTH_FLAG_EA, NULL, HFILL }}, { &hf_mux27010_lengthframesize, { "Info length", "mux27010.length.framesize", FT_UINT8, BASE_DEC, NULL, MUX27010_FRAMESIZE_LENGTH_FLAG, NULL, HFILL }}, /*Control Channel DLCI = 0*/ { &hf_mux27010_controlchannel, { "Control Channel", "mux27010.controlchannel", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, /*Frame Type*/ { &hf_mux27010_controlchannelframetype, { "Frame Type", "mux27010.controlchannel.frametype", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_mux27010_controlchanneleaframetype, { "EA Flag", "mux27010.controlchannel.frametype.eatype", FT_BOOLEAN, 8, NULL, MUX27010_EA_CONTROLCHANNEL_FRAMETYPE_FLAG, NULL, HFILL }}, { &hf_mux27010_controlchannelcrframetype, { "C/R Flag", "mux27010.controlchannel.frametype.crtype", FT_BOOLEAN, 8, NULL, MUX27010_CR_CONTROLCHANNEL_FRAMETYPE_FLAG, NULL, HFILL }}, { &hf_mux27010_controlchannelframetypecommand, { "Command Type", "mux27010.controlchannel.frametype.command", FT_UINT8, BASE_HEX, VALS(command_vals), MUX27010_COMMAND_CONTROLCHANNEL_FRAMETYPE_FLAG, NULL, HFILL }}, /*Length*/ { &hf_mux27010_controlchannellength, { "Length", "mux27010.controlchannel.length", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_mux27010_controlchannelealength, { "EA Flag", "mux27010.controlchannel.length.ealength", FT_BOOLEAN, 8, NULL, MUX27010_EA_CONTROLCHANNEL_LENGTH_FLAG, NULL, HFILL }}, { &hf_mux27010_controlchannellengthfield, { "Length field", "mux27010.controlchannel.length.length", FT_UINT8, BASE_DEC, NULL, MUX27010_LENGTHFIELD_CONTROLCHANNEL_LENGTH_FLAG, NULL, HFILL }}, /*Value*/ { &hf_mux27010_controlchannelvalue, { "Value (ASCII)", "mux27010.controlchannel.value", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_mux27010_controlchannel_iei_coding, { "IEI coding", "mux27010.controlchannel.value.iei_coding", FT_UINT8, BASE_HEX, VALS(iei_coding_vals), 0x0, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvalue, { "Detailed Values", "mux27010.controlchannel.value.detailedvalues", FT_UINT8, BASE_HEX, NULL, 0xFF, NULL, HFILL }}, { &hf_mux27010_controlchannel_detailedvalue_response, { "Response", "mux27010.controlchannel.value.detailedvalue.response", FT_UINT8, BASE_DEC, VALS(detailedvalue_response_vals), 0, NULL, HFILL }}, /*Test Command*/ { &hf_mux27010_controlchanneldetailedvaluetestcommandversion, { "Version", "mux27010.controlchannel.value.detailedvaluetestcommandversion", FT_UINT8, BASE_HEX, NULL, MUX27010_VALUE_CONTROLCHANNEL_TEST_VERSION, NULL, HFILL }}, /*Modem Status Command*/ { &hf_mux27010_controlchanneldetailedvaluemscdlci, { "DLCI number (decimal)", "mux27010.controlchannel.value.detailedvaluemscdlci", FT_UINT8, BASE_DEC, NULL, MUX27010_VALUE_CONTROLCHANNEL_MSC_DCLI, NULL, HFILL }}, #if 0 { &hf_mux27010_controlchanneldetailedvaluemscv24, { "V.24 Signal", "mux27010.controlchannel.value.detailedvaluemscv24", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, #endif { &hf_mux27010_controlchanneldetailedvaluemscv24fc, { "FC", "mux27010.controlchannel.value.detailedvaluemscv24.fc", FT_BOOLEAN, 8, NULL, MUX27010_VALUE_CONTROLCHANNEL_MSC_V24_FC, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluemscv24rtc, { "RTC", "mux27010.controlchannel.value.detailedvaluemscv24.rtc", FT_BOOLEAN, 8, NULL, MUX27010_VALUE_CONTROLCHANNEL_MSC_V24_RTC, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluemscv24rtr, { "RTR", "mux27010.controlchannel.value.detailedvaluemscv24.rtr", FT_BOOLEAN, 8, NULL, MUX27010_VALUE_CONTROLCHANNEL_MSC_V24_RTR, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluemscv24ring, { "RING", "mux27010.controlchannel.value.detailedvaluemscv24.ring", FT_BOOLEAN, 8, NULL, MUX27010_VALUE_CONTROLCHANNEL_MSC_V24_RING, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluemscv24dcd, { "DCD", "mux27010.controlchannel.value.detailedvaluemscv24.dcd", FT_BOOLEAN, 8, NULL, MUX27010_VALUE_CONTROLCHANNEL_MSC_V24_DCD, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluemscbreak, { "Break Signal", "mux27010.controlchannel.value.detailedvaluemscbreak", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, /*Parameter Negotiation*/ { &hf_mux27010_controlchanneldetailedvaluepndlci, { "DLCI", "mux27010.controlchannel.value.detailedvaluepndlci", FT_UINT8, BASE_DEC, NULL, MUX27010_VALUE_CONTROLCHANNEL_PN_DLCI, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluepnframetype, { "Frame Type", "mux27010.controlchannel.value.detailedvaluepnframetype", FT_UINT8, BASE_HEX, NULL, MUX27010_VALUE_CONTROLCHANNEL_PN_FRAMETYPE, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluepncl, { "Convergence Layer", "mux27010.controlchannel.value.detailedvaluepncl", FT_UINT8, BASE_DEC, NULL, MUX27010_VALUE_CONTROLCHANNEL_PN_CL, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluepnprio, { "Priority", "mux27010.controlchannel.value.detailedvaluepnprio", FT_UINT8, BASE_DEC, NULL, MUX27010_VALUE_CONTROLCHANNEL_PN_PRIO, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluepntimer, { "Acknowledgment Timer (ms)", "mux27010.controlchannel.value.detailedvaluepntimer", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluepnframesize, { "Max. Frame Size", "mux27010.controlchannel.value.detailedvaluepnframesize", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluepnna, { "Max. Number of Retransmissions", "mux27010.controlchannel.value.detailedvaluepnna", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_mux27010_controlchanneldetailedvaluepnwinsize, { "Window Size for Error Recovery Mode", "mux27010.controlchannel.value.detailedvaluepnwinsize", FT_UINT8, BASE_DEC, NULL, MUX27010_VALUE_CONTROLCHANNEL_PN_WINSIZE, NULL, HFILL }}, /*Information frame*/ { &hf_mux27010_information, { "Information field", "mux27010.information", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_mux27010_information_str, { "Information", "mux27010.information_str", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, /*Checksum frame*/ { &hf_mux27010_checksum, { "Checksum", "mux27010.checksum", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_mux27010_checksum_correct, { "Correct", "mux27010.checksum_correct", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }}, {&hf_msg_fragments, {"Message fragments", "mux27010.fragments", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } }, {&hf_msg_fragment, {"Message fragment", "mux27010.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } }, {&hf_msg_fragment_overlap, {"Message fragment overlap", "mux27010.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, {&hf_msg_fragment_overlap_conflicts, {"Message fragment overlapping with conflicting data", "mux27010.fragment.overlap.conflicts", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, {&hf_msg_fragment_multiple_tails, {"Message has multiple tail fragments", "mux27010.fragment.multiple_tails", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, {&hf_msg_fragment_too_long_fragment, {"Message fragment too long", "mux27010.fragment.too_long_fragment", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } }, {&hf_msg_fragment_error, {"Message defragmentation error", "mux27010.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } }, {&hf_msg_fragment_count, {"Message fragment count", "mux27010.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }, {&hf_msg_reassembled_in, {"Reassembled in", "mux27010.reassembled.in", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } }, {&hf_msg_reassembled_length, {"Reassembled length", "mux27010.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }, }; /* Setup protocol subtree array */ static gint *ett[] = { &ett_mux27010_extended_header, &ett_mux27010, &ett_mux27010_address, &ett_mux27010_control, &ett_mux27010_length, &ett_mux27010_controlchannel, &ett_mux27010_controlchannelframetype, &ett_mux27010_controlchannellength, &ett_mux27010_controlchannelvalue, &ett_mux27010_information, &ett_mux27010_checksum, &ett_msg_fragment, &ett_msg_fragments }; static ei_register_info ei[] = { { &ei_mux27010_message_illogical, { "mux27010.message_illogical", PI_MALFORMED, PI_ERROR, "Message start and end are illogical, aborting dissection", EXPFILL }}, { &ei_mux27010_checksum_incorrect, { "mux27010.checksum_incorrect", PI_CHECKSUM, PI_WARN, "Checksum: incorrect", EXPFILL }}, }; expert_module_t* expert_mux27010; /*Register protocol*/ proto_mux27010 = proto_register_protocol ("MUX27010 Protocol", "MUX27010", "mux27010"); /*Register arrays*/ proto_register_field_array (proto_mux27010, hf, array_length (hf)); proto_register_subtree_array (ett, array_length (ett)); mux27010_handle = register_dissector("mux27010", dissect_mux27010, proto_mux27010); expert_mux27010 = expert_register_protocol(proto_mux27010); expert_register_field_array(expert_mux27010, ei, array_length(ei)); reassembly_table_register(&msg_reassembly_table, &addresses_reassembly_table_functions); } /*Initialize dissector*/ void proto_reg_handoff_mux27010(void) { /*Initialization of dissector*/ dissector_add_uint("wtap_encap", WTAP_ENCAP_MUX27010, mux27010_handle); ppp_handle = find_dissector_add_dependency("ppp", proto_mux27010); } /* * 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: */