static int dissect_turnchannel_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint len; guint16 channel_id; guint16 data_len; proto_item *ti; proto_tree *turnchannel_tree; len = tvb_length(tvb); /* First, make sure we have enough data to do the check. */ if (len < TURNCHANNEL_HDR_LEN) { return 0; } channel_id = tvb_get_ntohs(tvb, 0); data_len = tvb_get_ntohs(tvb, 2); if ((channel_id < 0x4000) || (channel_id > 0xFFFE)) { return 0; } if (len != TURNCHANNEL_HDR_LEN + data_len) { return 0; } /* Seems to be a decent TURN channel message */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TURN CHANNEL"); if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "Channel Id 0x%x", channel_id); ti = proto_tree_add_item(tree, proto_turnchannel, tvb, 0, -1, ENC_NA); turnchannel_tree = proto_item_add_subtree(ti, ett_turnchannel); proto_tree_add_uint(turnchannel_tree, hf_turnchannel_id, tvb, 0, 2, channel_id); proto_tree_add_uint(turnchannel_tree, hf_turnchannel_len, tvb, 2, 2, data_len); if (len > TURNCHANNEL_HDR_LEN) { tvbuff_t *next_tvb; guint reported_len, new_len; new_len = tvb_length_remaining(tvb, TURNCHANNEL_HDR_LEN); reported_len = tvb_reported_length_remaining(tvb, TURNCHANNEL_HDR_LEN); if (data_len < reported_len) { reported_len = data_len; } next_tvb = tvb_new_subset(tvb, TURNCHANNEL_HDR_LEN, new_len, reported_len); if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)) { call_dissector(data_handle,next_tvb, pinfo, tree); } } return tvb_length(tvb); }
/* XXX: Are all the tests against tvb_length() really the right way to handle invalid fields ? * It seems to me that invalid fields should just add an expert item * or cause a "Malformed" exception. */ static void dissect_elcom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean is_request, length_ok; proto_tree *elcom_tree; proto_item *ti, *hidden_item; gint offset = 0; guint elcom_len; guint8 elcom_msg_type; guint8 *suffix; /* Check that there's enough data */ if (tvb_length(tvb) < 3) return; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ELCOM"); col_clear(pinfo->cinfo, COL_INFO); is_request = (pinfo->match_port == pinfo->destport); elcom_len = tvb_get_ntohs(tvb, 0); length_ok = (tvb_reported_length(tvb) == (elcom_len+2)); col_add_fstr(pinfo->cinfo, COL_INFO, "%s Len=%d%s", is_request ? "Request" : "Response", elcom_len, length_ok ? "" : " (incorrect)"); elcom_msg_type = tvb_get_guint8(tvb, 2); switch (elcom_msg_type) { case P_CONRQ: case P_CONRS: /* starting after elcom_len and elcom_msg_type, initiator + responder + userdata fields must be there */ if (tvb_length_remaining(tvb, 3+TOTAL_LEN+TOTAL_LEN+3) < 0) return; /* check also that those field lengths are valid */ if (tvb_get_guint8(tvb, 3) != LOWADR_LEN) return; if (tvb_get_guint8(tvb, 3+1+LOWADR_LEN) != SUFFIX_LEN) return; if (tvb_get_guint8(tvb, 3+TOTAL_LEN) != LOWADR_LEN) return; if (tvb_get_guint8(tvb, 3+1+TOTAL_LEN+LOWADR_LEN) != SUFFIX_LEN) return; /* finally believe that there is valid suffix */ suffix = tvb_get_string(wmem_packet_scope(), tvb, 3+2+LOWADR_LEN, 2); col_append_fstr(pinfo->cinfo, COL_INFO, " %s Connect", suffix); break; case P_RELRQ: case P_RELRS: col_append_str(pinfo->cinfo, COL_INFO, " Release"); break; case P_DATRQ: col_append_str(pinfo->cinfo, COL_INFO, " Data"); break; } switch (elcom_msg_type) { case P_CONRQ: case P_RELRQ: col_append_str(pinfo->cinfo, COL_INFO, " Request"); break; case P_CONRS: case P_RELRS: col_append_str(pinfo->cinfo, COL_INFO, " Response"); break; } if (!tree) return; ti = proto_tree_add_item(tree, proto_elcom, tvb, offset, -1, ENC_NA); elcom_tree = proto_item_add_subtree(ti, ett_elcom); hidden_item = proto_tree_add_boolean(elcom_tree, is_request ? hf_elcom_request : hf_elcom_response, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); /* 2 first bytes are the frame length */ offset = 0; ti = proto_tree_add_item(elcom_tree, hf_elcom_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset = +2; if (! length_ok) { proto_item_append_text(ti, " (incorrect)"); } elcom_msg_type = tvb_get_guint8(tvb, offset); ti = proto_tree_add_item(elcom_tree, hf_elcom_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(elcom_tree, " ( %s)", val_to_str(elcom_msg_type, type_vals, "Unknown %d")); offset++; if (tvb_length_remaining(tvb, offset) <= 0) return; switch (elcom_msg_type) { case P_CONRQ: case P_CONRS: /* * Connection request/release assiciated PDU's, * /ELCOM-90 P Protocol spec/ p. 85... */ /* We need the length here, hardcode the LOWADR_LEN = 21 */ ti = proto_tree_add_item(elcom_tree, hf_elcom_initiator, tvb, offset, TOTAL_LEN, ENC_BIG_ENDIAN); offset = dissect_lower_address(ti, ett_elcom_initiator, tvb, offset, hf_elcom_initiator_endian, hf_elcom_initiator_ip, hf_elcom_initiator_port, hf_elcom_initiator_suff); if (tvb_length_remaining(tvb, offset) <= 0) return; ti = proto_tree_add_item(elcom_tree, hf_elcom_responder, tvb, offset, TOTAL_LEN, ENC_BIG_ENDIAN); offset = dissect_lower_address(ti, ett_elcom_responder, tvb, offset, hf_elcom_responder_endian, hf_elcom_responder_ip, hf_elcom_responder_port, hf_elcom_responder_suff); if (tvb_length_remaining(tvb, offset) <= 0) return; /* Rest of the payload is USER-DATA, 0..82 bytes */ ti = proto_tree_add_item(elcom_tree, hf_elcom_userdata, tvb, offset, -1, ENC_NA); offset = dissect_userdata(ti, ett_elcom_userdata, tvb, offset); break; case P_RELRQ: proto_tree_add_item(elcom_tree, hf_elcom_release_reason, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case P_RELRS: proto_tree_add_item(elcom_tree, hf_elcom_release_result, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case P_DATRQ: ti = proto_tree_add_item(elcom_tree, hf_elcom_datarequest, tvb, offset, -1, ENC_NA); offset = dissect_datarequest(ti, ett_elcom_datarequest, tvb, offset); break; default: proto_item_append_text(ti, " <<--- meaning WHAT??"); break; } if (tvb_length_remaining(tvb, offset) <= 0) return; /* We should not get here, but if we do, show what is left over: */ ti = proto_tree_add_item(elcom_tree, hf_elcom_strangeleftover, tvb, offset, -1, ENC_NA); while (tvb_length_remaining(tvb, offset) > 0) { proto_item_append_text(ti, elcom_show_hex ? " %02x" : " %03o", tvb_get_guint8(tvb, offset)); offset++; } }
static gboolean dissect_fcip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean check_port) { gint offset = 0, start = 0, frame_len = 0; gint bytes_remaining = tvb_length (tvb); guint8 pflags, sof = 0, eof = 0; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *fcip_tree = NULL; tvbuff_t *next_tvb; if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) { return FALSE; } if (check_port && ((pinfo->srcport != fcip_port) && (pinfo->destport != fcip_port))) { return FALSE; } while (bytes_remaining > FCIP_ENCAP_HEADER_LEN) { if ((offset = get_next_fcip_header_offset (tvb, pinfo, offset)) == -1) { return FALSE; } else if (offset == -2) { /* We need more data to desegment */ return (TRUE); } start = offset; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCIP"); frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4; if (bytes_remaining < frame_len) { if(fcip_desegment && pinfo->can_desegment) { /* * This frame doesn't have all of the data for * this message, but we can do reassembly on it. * * Tell the TCP dissector where the data for this * message starts in the data it handed us, and * how many more bytes we need, and return. */ pinfo->desegment_offset = offset; pinfo->desegment_len = frame_len - bytes_remaining; return (TRUE); } } pflags = tvb_get_guint8 (tvb, start+8); if (tree) { if (FCIP_IS_SF (pflags)) { ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0, FCIP_ENCAP_HEADER_LEN, "FCIP"); } else if (tvb_bytes_exist (tvb, offset, offset+frame_len-4)) { sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN); eof = tvb_get_guint8 (tvb, offset+frame_len - 4); ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0, FCIP_ENCAP_HEADER_LEN, "FCIP (%s/%s)", val_to_str (sof, fcip_sof_vals, "0x%x"), val_to_str (eof, fcip_eof_vals, "0x%x")); } else { sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN); ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0, FCIP_ENCAP_HEADER_LEN, "FCIP (%s/%s)", val_to_str (sof, fcip_sof_vals, "0x%x"), "NA"); } fcip_tree = proto_item_add_subtree (ti, ett_fcip); /* Dissect the Common FC Encap header */ dissect_fcencap_header (tvb, fcip_tree, offset); offset += FCIP_ENCAP_HEADER_LEN; if (!FCIP_IS_SF (pflags)) { /* print SOF */ proto_tree_add_item (fcip_tree, hf_fcip_sof, tvb, offset, 1, 0); proto_tree_add_item (fcip_tree, hf_fcip_sof_c, tvb, offset+2, 1, 0); /* print EOF */ offset += (frame_len-FCIP_ENCAP_HEADER_LEN-4); if (tvb_bytes_exist (tvb, offset, 4)) { proto_tree_add_item (fcip_tree, hf_fcip_eof, tvb, offset, 1, 0); proto_tree_add_item (fcip_tree, hf_fcip_eof_c, tvb, offset+2, 1, 0); } } } /* Call the FC Dissector if this is carrying an FC frame */ if (!FCIP_IS_SF(pflags)) { /* Set the SOF/EOF flags in the packet_info header */ pinfo->sof_eof = 0; if (sof) { if ((sof == FCIP_SOFi3) || (sof == FCIP_SOFi2) || (sof == FCIP_SOFi4)) { pinfo->sof_eof = PINFO_SOF_FIRST_FRAME; } else if (sof == FCIP_SOFf) { pinfo->sof_eof = PINFO_SOF_SOFF; } if (eof != FCIP_EOFn) { pinfo->sof_eof |= PINFO_EOF_LAST_FRAME; } else if (eof != FCIP_EOFt) { pinfo->sof_eof |= PINFO_EOF_INVALID; } } /* Special frame bit is not set */ next_tvb = tvb_new_subset_remaining (tvb, FCIP_ENCAP_HEADER_LEN+4); if (fc_handle) { call_dissector (fc_handle, next_tvb, pinfo, tree); } else if (data_handle) { call_dissector (data_handle, next_tvb, pinfo, tree); } } else { col_set_str(pinfo->cinfo, COL_INFO, "Special Frame"); if (FCIP_IS_CH (pflags)) { col_append_str(pinfo->cinfo, COL_INFO, "(Changed)"); } dissect_fcip_sf (tvb, fcip_tree, offset+4); } bytes_remaining -= frame_len; } return (TRUE); }
static void dissect_wtls_handshake(proto_tree *tree, tvbuff_t *tvb, guint offset, guint count) { char pdu_msg_type; nstime_t timeValue; int client_size = 0; guint value = 0; int size = 0; guint public_key = 0; char valStr[1024]; const char *valBulk = NULL; const char *valMac = NULL; proto_item *ti; proto_item *cli_key_item; proto_tree *wtls_msg_type_tree; proto_tree *wtls_msg_type_item_tree; proto_tree *wtls_msg_type_item_sub_tree; proto_tree *wtls_msg_type_item_sub_sub_tree; pdu_msg_type = tvb_get_guint8 (tvb, offset); ti = proto_tree_add_uint(tree, hf_wtls_hands, tvb, offset,count, pdu_msg_type); wtls_msg_type_tree = proto_item_add_subtree(ti, ett_wtls_msg_type); proto_tree_add_item (wtls_msg_type_tree, hf_wtls_hands_type, tvb,offset,1,ENC_BIG_ENDIAN); offset+=1; count = tvb_get_ntohs (tvb, offset); proto_tree_add_item (wtls_msg_type_tree, hf_wtls_hands_length, tvb,offset,2,ENC_BIG_ENDIAN); offset+=2; switch(pdu_msg_type) { case WTLS_HANDSHAKE_CLIENT_HELLO : ti = proto_tree_add_item(wtls_msg_type_tree, hf_wtls_hands_cli_hello, tvb, offset, count, ENC_NA); wtls_msg_type_item_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item); proto_tree_add_item (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_version, tvb,offset,1,ENC_BIG_ENDIAN); offset++; timeValue.secs = tvb_get_ntohl (tvb, offset); timeValue.nsecs = 0; proto_tree_add_time (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_gmt, tvb, offset, 4, &timeValue); offset+=4; proto_tree_add_item (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_random, tvb,offset,12,ENC_NA); offset+=12; offset = add_session_id (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_session, hf_wtls_hands_cli_hello_session_str, tvb, offset); /* process client_key_ids structure */ count = tvb_get_ntohs (tvb, offset); ti = proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_cli_key_id, tvb, offset, count+2, ENC_NA); wtls_msg_type_item_sub_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item_sub); /* display length of client_key_ids structure */ proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_cli_hello_cli_key_len, tvb,offset,2,ENC_BIG_ENDIAN); offset+=2; /* cycle through client_key_ids entries */ for (;count > 0;count-=client_size) { /* get encryption suite id (one byte) */ value = tvb_get_guint8 (tvb, offset); cli_key_item = proto_tree_add_uint(wtls_msg_type_item_sub_tree, hf_wtls_hands_cli_hello_key_exchange, tvb, offset,1, value); client_size=1; wtls_msg_type_item_sub_sub_tree = proto_item_add_subtree(cli_key_item, ett_wtls_msg_type_item_sub_sub); proto_tree_add_uint(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_exchange_suite, tvb,offset,1,value); offset++; #ifdef DEBUG fprintf(stderr, "encryption suite = %d, client_size = %d\n", value, client_size); #endif /* DEBUG */ /* get parameter index (one byte) */ value = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_parameter_index, tvb,offset,1,ENC_BIG_ENDIAN); offset++; client_size++; #ifdef DEBUG fprintf(stderr, "parameter index = %d, client_size = %d\n", value, client_size); #endif /* DEBUG */ /* explicit parameters present in next field */ if (value == 0xff) { size = tvb_get_ntohs (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_parameter_set, tvb,offset,size+2,ENC_ASCII|ENC_NA); offset+=size+2; client_size+=size+2; } /* get identifier type */ value = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier_type, tvb,offset,1,ENC_BIG_ENDIAN); offset++; client_size++; #ifdef DEBUG fprintf(stderr, "identifier type = %d, client_size = %d\n", value, client_size); #endif /* DEBUG */ /* identifier present in next field */ /* note: value 0x0 means no identifier */ switch(value) { case IDENTIFIER_TEXT : /* text identifier */ /* not tested */ size = add_text_identifier( tvb, offset, hf_wtls_hands_cli_hello_key_identifier_charset, hf_wtls_hands_cli_hello_key_identifier_size, hf_wtls_hands_cli_hello_key_identifier_str, wtls_msg_type_item_sub_sub_tree); offset += size; client_size += size; break; case IDENTIFIER_BIN : /* binary identifier */ size = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier_size, tvb,offset,1,ENC_BIG_ENDIAN); offset++; proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier, tvb,offset,size,ENC_NA); offset+=size; client_size+=size+1; #ifdef DEBUG fprintf(stderr, "binary id size = %d, client_size = %d\n", size, client_size); #endif /* DEBUG */ break; case IDENTIFIER_SHA_1 : /* SHA-1 hash of the public key */ proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier, tvb,offset,20,ENC_NA); offset+=20; client_size+=20; #ifdef DEBUG fprintf(stderr, "SHA-1 hash size = 20, client_size = %d\n", client_size); #endif /* DEBUG */ break; case IDENTIFIER_X509 : /* X.509 distinguished name */ /* not tested */ size = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier_size, tvb,offset,1,ENC_BIG_ENDIAN); offset++; proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier, tvb,offset,size,ENC_NA); offset+=size; client_size+=size+1; #ifdef DEBUG fprintf(stderr, "X.509 name size = %d, client_size = %d\n", size, client_size); #endif /* DEBUG */ break; } proto_item_set_len(cli_key_item, client_size); } /* process trusted_keys structure */ count = tvb_get_ntohs (tvb, offset); ti = proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_trust_key_id, tvb, offset, count+2, ENC_NA); wtls_msg_type_item_sub_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item_sub); /* display length of trusted_keys structure */ proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_cli_hello_cli_key_len, tvb,offset,2,ENC_BIG_ENDIAN); offset+=2; for (;count > 0;count-=client_size) { /* get encryption suite id (one byte) */ value = tvb_get_guint8 (tvb, offset); cli_key_item = proto_tree_add_uint(wtls_msg_type_item_sub_tree, hf_wtls_hands_cli_hello_key_exchange, tvb, offset,1, value); client_size=1; wtls_msg_type_item_sub_sub_tree = proto_item_add_subtree(cli_key_item, ett_wtls_msg_type_item_sub_sub); proto_tree_add_uint(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_exchange_suite, tvb,offset,1,value); offset++; #ifdef DEBUG fprintf(stderr, "encryption suite = %d, client_size = %d\n", value, client_size); #endif /* DEBUG */ /* get parameter index (one byte) */ value = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_parameter_index, tvb,offset,1,ENC_BIG_ENDIAN); offset++; client_size++; #ifdef DEBUG fprintf(stderr, "parameter index = %d, client_size = %d\n", value, client_size); #endif /* DEBUG */ /* explicit parameters present in next field */ if (value == 0xff) { size = tvb_get_ntohs (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_parameter_set, tvb,offset,size+2,ENC_ASCII|ENC_NA); offset+=size+2; client_size+=size+2; } /* get identifier type */ value = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier_type, tvb,offset,1,ENC_BIG_ENDIAN); offset++; client_size++; #ifdef DEBUG fprintf(stderr, "identifier type = %d, client_size = %d\n", value, client_size); #endif /* DEBUG */ /* identifier present in next field */ /* note: value 0x0 means no identifier */ switch (value) { case IDENTIFIER_TEXT : /* text identifier */ /* not tested */ size = add_text_identifier( tvb, offset, hf_wtls_hands_cli_hello_key_identifier_charset, hf_wtls_hands_cli_hello_key_identifier_size, hf_wtls_hands_cli_hello_key_identifier_str, wtls_msg_type_item_sub_sub_tree); offset += size; client_size += size; break; case IDENTIFIER_BIN : /* binary identifier */ size = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier_size, tvb,offset,1,ENC_BIG_ENDIAN); offset++; proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier, tvb,offset,size,ENC_NA); offset+=size; client_size+=size+1; #ifdef DEBUG fprintf(stderr, "binary id size = %d, client_size = %d\n", size, client_size); #endif /* DEBUG */ break; case IDENTIFIER_SHA_1 : /* SHA-1 hash of the public key */ proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier, tvb,offset,20,ENC_NA); offset+=20; client_size+=20; #ifdef DEBUG fprintf(stderr, "SHA-1 hash size = 20, client_size = %d\n", client_size); #endif /* DEBUG */ break; case IDENTIFIER_X509 : /* X.509 distinguished name */ /* not tested */ size = tvb_get_guint8 (tvb, offset); /* need to fetch identifier and display it */ proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier_size, tvb,offset,1,ENC_BIG_ENDIAN); offset++; proto_tree_add_item(wtls_msg_type_item_sub_sub_tree, hf_wtls_hands_cli_hello_key_identifier, tvb,offset,size,ENC_NA); offset+=size; client_size+=size+1; #ifdef DEBUG fprintf(stderr, "X.509 name size = %d, client_size = %d\n", size, client_size); #endif /* DEBUG */ break; } proto_item_set_len(cli_key_item, client_size); } /* process cipher_suites structure */ count = tvb_get_guint8 (tvb, offset); ti = proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_cipher_suite, tvb, offset, count+1, ENC_NA); wtls_msg_type_item_sub_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item_sub); offset+=1; for (;count > 0;count-=client_size) { value = tvb_get_guint8 (tvb, offset); valBulk = match_strval_ext(value, &wtls_vals_cipher_bulk_ext); offset++; client_size=1; valMac = match_strval_ext(tvb_get_guint8 (tvb, offset), &wtls_vals_cipher_mac_ext); if (valBulk != NULL) { if (valMac != NULL) { g_snprintf(valStr,1024,"%s, %s",valBulk,valMac); } else { g_snprintf(valStr,1024,"%s, Unknown MAC (0x%02x)",valBulk,tvb_get_guint8 (tvb, offset)); } } else { if (valMac != NULL) { g_snprintf(valStr,1024,"Unknown Bulk (0x%02x), %s",value,valMac); } else { g_snprintf(valStr,1024,"Unknown Bulk (0x%02x), Unknown MAC (0x%02x)",value, tvb_get_guint8 (tvb, offset)); } } offset++; client_size++; proto_tree_add_string(wtls_msg_type_item_sub_tree, hf_wtls_hands_cli_hello_cipher_suite_item, tvb, offset-2,2, valStr); } count = tvb_get_guint8 (tvb, offset); ti = proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_compression_methods, tvb, offset, count+1, ENC_NA); wtls_msg_type_item_sub_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item_sub); offset+=1; for (;count > 0;count-=client_size) { client_size=0; proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_cli_hello_compression, tvb, offset,1, ENC_LITTLE_ENDIAN); offset++; client_size++; } proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_sequence_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_key_refresh, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case WTLS_HANDSHAKE_SERVER_HELLO : ti = proto_tree_add_item(wtls_msg_type_tree, hf_wtls_hands_serv_hello, tvb, offset, count, ENC_NA); wtls_msg_type_item_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item); proto_tree_add_item (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_version, tvb,offset,1,ENC_BIG_ENDIAN); offset++; timeValue.secs = tvb_get_ntohl (tvb, offset); timeValue.nsecs = 0; proto_tree_add_time (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_gmt, tvb, offset, 4, &timeValue); offset+=4; proto_tree_add_item (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_random, tvb,offset,12,ENC_NA); offset+=12; offset = add_session_id (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_session, hf_wtls_hands_serv_hello_session_str, tvb, offset); proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_cli_key_id, tvb,offset,1,ENC_BIG_ENDIAN); offset++; cli_key_item = proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_cipher_suite_item, tvb, offset,2, ENC_NA); wtls_msg_type_item_sub_tree = proto_item_add_subtree(cli_key_item, ett_wtls_msg_type_item_sub); proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_serv_hello_cipher_bulk, tvb,offset,1,ENC_BIG_ENDIAN); offset++; value = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_serv_hello_cipher_mac, tvb,offset,1,ENC_BIG_ENDIAN); offset++; proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_compression, tvb, offset,1, ENC_LITTLE_ENDIAN); offset++; proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_sequence_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_key_refresh, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; break; case WTLS_HANDSHAKE_CERTIFICATE : ti = proto_tree_add_item(wtls_msg_type_tree, hf_wtls_hands_certificates, tvb, offset,count, ENC_NA); wtls_msg_type_item_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item); count = tvb_get_ntohs (tvb, offset); offset+=2; for (;count > 0;count-=client_size) { cli_key_item = proto_tree_add_item(wtls_msg_type_item_tree, hf_wtls_hands_certificate, tvb, offset,1, ENC_NA); client_size=0; wtls_msg_type_item_sub_tree = proto_item_add_subtree(cli_key_item, ett_wtls_msg_type_item_sub); proto_item_set_len(cli_key_item, client_size); value = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_type, tvb, offset,1, ENC_LITTLE_ENDIAN); offset++; client_size++; switch(value) { case CERTIFICATE_WTLS: proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_version, tvb, offset,1, ENC_LITTLE_ENDIAN); offset++; client_size++; proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_signature_type, tvb, offset,1, ENC_LITTLE_ENDIAN); offset++; client_size++; value = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_issuer_type, tvb, offset,1, ENC_LITTLE_ENDIAN); offset++; client_size++; switch (value) { case IDENTIFIER_NULL : break; case IDENTIFIER_TEXT : value = add_text_identifier(tvb, offset, hf_wtls_hands_certificate_wtls_issuer_charset, hf_wtls_hands_certificate_wtls_issuer_size, hf_wtls_hands_certificate_wtls_issuer_name, wtls_msg_type_item_sub_tree); offset += value; client_size += value; break; case IDENTIFIER_BIN : break; case IDENTIFIER_SHA_1 : break; case IDENTIFIER_X509 : break; } timeValue.secs = tvb_get_ntohl (tvb, offset); timeValue.nsecs = 0; proto_tree_add_time (wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_valid_not_before, tvb, offset, 4, &timeValue); offset+=4; client_size+=4; timeValue.secs = tvb_get_ntohl (tvb, offset); timeValue.nsecs = 0; proto_tree_add_time (wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_valid_not_after, tvb, offset, 4, &timeValue); offset+=4; client_size+=4; value = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_subject_type, tvb, offset,1, ENC_LITTLE_ENDIAN); offset++; client_size++; switch (value) { case IDENTIFIER_NULL : break; case IDENTIFIER_TEXT : value = add_text_identifier(tvb, offset, hf_wtls_hands_certificate_wtls_subject_charset, hf_wtls_hands_certificate_wtls_subject_size, hf_wtls_hands_certificate_wtls_subject_name, wtls_msg_type_item_sub_tree); offset += value; client_size += value; break; case IDENTIFIER_BIN : break; case IDENTIFIER_SHA_1 : break; case IDENTIFIER_X509 : break; } public_key = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_public_key_type, tvb, offset,1, ENC_LITTLE_ENDIAN); offset++; client_size++; value = tvb_get_guint8 (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_key_parameter_index, tvb,offset,1,ENC_BIG_ENDIAN); offset++; client_size++; if (value == 0xff) { size = tvb_get_ntohs (tvb, offset); proto_tree_add_item(wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_key_parameter_set, tvb,offset,size+2,ENC_ASCII|ENC_NA); offset+=size+2; client_size+=size+2; } switch (public_key) { case PUBLIC_KEY_RSA : value = tvb_get_ntohs (tvb, offset); proto_tree_add_uint(wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_rsa_exponent, tvb,offset,value+2,value*8); offset+=2+value; client_size+=2+value; value = tvb_get_ntohs (tvb, offset); proto_tree_add_uint(wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_rsa_modules, tvb,offset,value+2,value*8); offset+=2+value; client_size+=2+value; break; case PUBLIC_KEY_ECDH : break; case PUBLIC_KEY_ECDSA : break; } value = tvb_get_ntohs (tvb, offset); proto_tree_add_uint(wtls_msg_type_item_sub_tree, hf_wtls_hands_certificate_wtls_signature, tvb,offset,2+value,value*8); offset+=2+value; client_size+=2+value; break; case CERTIFICATE_X509: case CERTIFICATE_X968: value = tvb_get_ntohs (tvb, offset); offset+=2; client_size+=2; client_size += value; offset += value; break; case CERTIFICATE_URL: value = tvb_get_guint8 (tvb, offset); offset++; client_size++; client_size += value; offset += value; break; } proto_item_set_len(cli_key_item, client_size); } break; default: offset+=count; break; } }
static void dissect_eapol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; guint8 eapol_type; guint8 keydesc_type; guint16 eapol_len; guint len; guint16 eapol_key_len, eapol_data_len; guint8 key_index; guint16 keyinfo; proto_tree *ti = NULL; proto_tree *eapol_tree = NULL; proto_tree *keyinfo_item = NULL; proto_tree *keyinfo_tree = NULL; proto_tree *key_index_tree, *keydes_tree; tvbuff_t *next_tvb; col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAPOL"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { ti = proto_tree_add_item(tree, proto_eapol, tvb, 0, -1, ENC_NA); eapol_tree = proto_item_add_subtree(ti, ett_eapol); proto_tree_add_item(eapol_tree, hf_eapol_version, tvb, offset, 1, ENC_BIG_ENDIAN); } offset++; eapol_type = tvb_get_guint8(tvb, offset); if (tree) proto_tree_add_uint(eapol_tree, hf_eapol_type, tvb, offset, 1, eapol_type); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, val_to_str(eapol_type, eapol_type_vals, "Unknown type (0x%02X)")); offset++; eapol_len = tvb_get_ntohs(tvb, offset); len = EAPOL_HDR_LEN + eapol_len; set_actual_length(tvb, len); if (tree) { proto_item_set_len(ti, len); proto_tree_add_uint(eapol_tree, hf_eapol_len, tvb, offset, 2, eapol_len); } offset += 2; switch (eapol_type) { case EAP_PACKET: next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(eap_handle, next_tvb, pinfo, eapol_tree); break; case EAPOL_KEY: if (tree) { keydesc_type = tvb_get_guint8(tvb, offset); proto_tree_add_item(eapol_tree, hf_eapol_keydes_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (keydesc_type == EAPOL_WPA_KEY || keydesc_type == EAPOL_RSN_KEY) { keyinfo = tvb_get_ntohs(tvb, offset); if (check_col(pinfo->cinfo, COL_INFO)) { if (keyinfo & KEY_INFO_REQUEST_MASK) { col_set_str(pinfo->cinfo, COL_INFO, "Key (Request)"); if (keyinfo & KEY_INFO_ERROR_MASK) col_set_str(pinfo->cinfo, COL_INFO, "Key (Request, Error)"); } else if (keyinfo & KEY_INFO_KEY_TYPE_MASK) { guint16 masked; masked = keyinfo & (KEY_INFO_INSTALL_MASK | KEY_INFO_KEY_ACK_MASK | KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK); switch (masked) { case KEY_INFO_KEY_ACK_MASK: col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 1/4)"); break; case KEY_INFO_KEY_MIC_MASK: col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 2/4)"); break; case (KEY_INFO_INSTALL_MASK | KEY_INFO_KEY_ACK_MASK | KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK): col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 3/4)"); break; case (KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK): col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 4/4)"); break; } } else { if (keyinfo & KEY_INFO_KEY_ACK_MASK) col_set_str(pinfo->cinfo, COL_INFO, "Key (Group msg 1/2)"); else col_set_str(pinfo->cinfo, COL_INFO, "Key (Group msg 2/2)"); } } keyinfo_item = proto_tree_add_uint(eapol_tree, hf_eapol_wpa_keydes_keyinfo, tvb, offset, 2, keyinfo); keyinfo_tree = proto_item_add_subtree(keyinfo_item, ett_keyinfo); proto_tree_add_uint(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_keydes_ver, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_type, tvb, offset, 2, keyinfo); proto_tree_add_uint(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_index, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_install, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_ack, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_mic, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_secure, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_error, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_request, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_encr_key_data, tvb, offset, 2, keyinfo); offset += 2; proto_tree_add_uint(eapol_tree, hf_eapol_keydes_keylen, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset += 2; proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_nonce, tvb, offset, 32, ENC_NA); offset += 32; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb, offset, 16, ENC_NA); offset += 16; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_rsc, tvb, offset, 8, ENC_NA); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_id, tvb, offset, 8, ENC_NA); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_mic, tvb, offset, 16, ENC_NA); offset += 16; eapol_data_len = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(eapol_tree, hf_eapol_wpa_keydes_datalen, tvb, offset, 2, eapol_data_len); offset += 2; if (eapol_data_len != 0) { ti = proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_data, tvb, offset, eapol_data_len, ENC_NA); if ((keyinfo & KEY_INFO_ENCR_KEY_DATA_MASK) || !(keyinfo & KEY_INFO_KEY_TYPE_MASK)) { /* RSN: EAPOL-Key Key Data is encrypted. * WPA: Group Keys use encrypted Key Data. * Cannot parse this without knowing the key. * IEEE 802.11i-2004 8.5.2. */ } else { keydes_tree = proto_item_add_subtree(ti, ett_eapol_keydes_data); ieee_80211_add_tagged_parameters(tvb, offset, pinfo, keydes_tree, eapol_data_len, -1); } } } else { eapol_key_len = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(eapol_tree, hf_eapol_keydes_keylen, tvb, offset, 2, eapol_key_len); offset += 2; proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb, offset, 16, ENC_NA); offset += 16; key_index = tvb_get_guint8(tvb, offset); ti = proto_tree_add_text(eapol_tree, tvb, offset, 1, "Key Index: %s, index %u", (key_index & 0x80) ? "unicast" : "broadcast", key_index & 0x7F); key_index_tree = proto_item_add_subtree(ti, ett_eapol_key_index); proto_tree_add_boolean(key_index_tree, hf_eapol_keydes_key_index_keytype, tvb, offset, 1, key_index); proto_tree_add_uint(key_index_tree, hf_eapol_keydes_key_index_indexnum, tvb, offset, 1, key_index); offset += 1; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_signature, tvb, offset, 16, ENC_NA); offset += 16; if (eapol_key_len != 0) { if (eapol_len > 44) { /* Size of rc4 key with no key content */ proto_tree_add_item(eapol_tree, hf_eapol_keydes_key, tvb, offset, eapol_key_len, ENC_NA); } else { /* IEEE 802.1X-2004 7.6.3.6: If no bytes remain, then */ proto_tree_add_text(eapol_tree, tvb, offset, 0, "Key: Use key locally generated by peer"); } } } } break; case EAPOL_ENCAP_ASF_ALERT: /* XXX - is this an SNMP trap? */ default: next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, eapol_tree); break; } }
/* dissector of each payload */ static int dissect_xtp_aseg(tvbuff_t *tvb, proto_tree *tree, guint32 offset) { guint32 len = tvb_length_remaining(tvb, offset); guint32 start = offset; proto_item *ti, *ti2, *top_ti; proto_tree *xtp_subtree; struct xtp_ip_addr_seg aseg[1]; int error = 0; top_ti = proto_tree_add_text(tree, tvb, offset, len, "Address Segment"); xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_aseg); if (len < XTP_NULL_ADDR_SEG_LEN) { proto_item_append_text(top_ti, ", bogus length(%u, must be at least %u)", len, XTP_NULL_ADDR_SEG_LEN); return 0; } /** parse common fields **/ /* alen(2) */ aseg->alen = tvb_get_ntohs(tvb, offset); offset += 2; /* adomain(1) */ aseg->adomain = tvb_get_guint8(tvb, offset); offset++; /* aformat(1) */ aseg->aformat = tvb_get_guint8(tvb, offset); /** display common fields **/ offset = start; /* alen(2) */ ti = proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_alen, tvb, offset, 2, aseg->alen); offset += 2; if (aseg->alen > len) { proto_item_append_text(ti, ", bogus length(%u, must be at most %u)", aseg->alen, len); error = 1; } /* adomain(1) */ proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_adomain, tvb, offset, 1, aseg->adomain); offset++; /* aformat(1) */ ti2 = proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_aformat, tvb, offset, 1, aseg->aformat); offset++; switch (aseg->aformat) { case 0: if (aseg->alen != XTP_NULL_ADDR_SEG_LEN) { proto_item_append_text(ti, ", bogus length(%u, must be %u)", aseg->alen, XTP_NULL_ADDR_SEG_LEN); error = 1; } break; case 1: if (aseg->alen != XTP_IP_ADDR_SEG_LEN) { proto_item_append_text(ti, ", bogus length(%u, must be %u)", aseg->alen, XTP_IP_ADDR_SEG_LEN); error = 1; } break; default: if (aseg->aformat < 128) { proto_item_append_text(ti2, ", Unsupported aformat(%u)", aseg->aformat); error = 1; } break; } if (error) return (offset - start); /** parse and display each address fileds */ switch (aseg->aformat) { case 0: /* address(4) */ aseg->dsthost = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_address, tvb, offset, 4, aseg->dsthost); offset += 4; break; case 1: /* dsthost(4) */ aseg->dsthost = tvb_get_ipv4(tvb, offset); proto_tree_add_ipv4(xtp_subtree, hf_xtp_aseg_dsthost, tvb, offset, 4, aseg->dsthost); offset += 4; /* srchost(4) */ aseg->srchost = tvb_get_ipv4(tvb, offset); proto_tree_add_ipv4(xtp_subtree, hf_xtp_aseg_srchost, tvb, offset, 4, aseg->srchost); offset += 4; /* dstport(2) */ aseg->dstport = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_dstport, tvb, offset, 2, aseg->dstport); offset += 2; /* srcport(2) */ aseg->srcport = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_srcport, tvb, offset, 2, aseg->srcport); offset += 2; /** add summary **/ proto_item_append_text(top_ti, ", Dst Port: %u", aseg->dstport); proto_item_append_text(top_ti, ", Src Port: %u", aseg->srcport); break; default: break; } return (offset - start); }
static void dissect_drda(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gint offset = 0; guint16 iCommand; guint16 iLength; guint16 iCommandEnd = 0; guint8 iFormatFlags; guint8 iDSSType; guint8 iDSSFlags; guint16 iParameterCP; gint iLengthParam; col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRDA"); /* This is a trick to know whether this is the first PDU in this packet or not */ if (iPreviousFrameNumber != pinfo->fd->num) col_clear(pinfo->cinfo, COL_INFO); else col_append_str(pinfo->cinfo, COL_INFO, " | "); iPreviousFrameNumber = pinfo->fd->num; /* There may be multiple DRDA commands in one frame */ while ((guint) (offset + 10) <= tvb_length(tvb)) { iCommand = tvb_get_ntohs(tvb, offset + 8); iLength = tvb_get_ntohs(tvb, offset + 0); if (iLength < 10) { expert_add_info_format_text(pinfo, NULL, &ei_drda_opcode_invalid_length, "Invalid length detected (%u): should be at least 10 bytes long", iLength); break; } /* iCommandEnd is the length of the packet up to the end of the current command */ iCommandEnd += iLength; if (offset > 0) col_append_str(pinfo->cinfo, COL_INFO, " | "); col_append_str(pinfo->cinfo, COL_INFO, val_to_str_ext(iCommand, &drda_opcode_abbr_ext, "Unknown (0x%02x)")); if (tree) { proto_tree *drda_tree; proto_tree *drdaroot_tree; proto_tree *drda_tree_sub; proto_item *ti; ti = proto_tree_add_item(tree, proto_drda, tvb, offset, -1, ENC_NA); proto_item_append_text(ti, " (%s)", val_to_str_ext(iCommand, &drda_opcode_vals_ext, "Unknown (0x%02x)")); drdaroot_tree = proto_item_add_subtree(ti, ett_drda); ti = proto_tree_add_text(drdaroot_tree, tvb, offset, 10, DRDA_TEXT_DDM); proto_item_append_text(ti, " (%s)", val_to_str_ext(iCommand, &drda_opcode_abbr_ext, "Unknown (0x%02x)")); drda_tree = proto_item_add_subtree(ti, ett_drda_ddm); proto_tree_add_item(drda_tree, hf_drda_ddm_length, tvb, offset + 0, 2, ENC_BIG_ENDIAN); proto_tree_add_item(drda_tree, hf_drda_ddm_magic, tvb, offset + 2, 1, ENC_BIG_ENDIAN); iFormatFlags = tvb_get_guint8(tvb, offset + 3); iDSSType = iFormatFlags & 0x0F; iDSSFlags = iFormatFlags >> 4; ti = proto_tree_add_item(drda_tree, hf_drda_ddm_format, tvb, offset + 3, 1, ENC_BIG_ENDIAN); drda_tree_sub = proto_item_add_subtree(ti, ett_drda_ddm_format); proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_reserved, tvb, offset + 3, 1, iDSSFlags); proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_chained, tvb, offset + 3, 1, iDSSFlags); proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_errcont, tvb, offset + 3, 1, iDSSFlags); proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_samecorr, tvb, offset + 3, 1, iDSSFlags); proto_tree_add_uint(drda_tree_sub, hf_drda_ddm_fmt_dsstyp, tvb, offset + 3, 1, iDSSType); proto_tree_add_item(drda_tree, hf_drda_ddm_rc, tvb, offset + 4, 2, ENC_BIG_ENDIAN); proto_tree_add_item(drda_tree, hf_drda_ddm_length2, tvb, offset + 6, 2, ENC_BIG_ENDIAN); proto_tree_add_item(drda_tree, hf_drda_ddm_codepoint, tvb, offset + 8, 2, ENC_BIG_ENDIAN); /* The number of attributes is variable */ for (offset += 10; offset < iCommandEnd; ) { if (tvb_length_remaining(tvb, offset) >= 2) { iLengthParam = tvb_get_ntohs(tvb, offset + 0); if (iLengthParam == 0 || iLengthParam == 1) iLengthParam = iLength - 10; if (tvb_length_remaining(tvb, offset) >= iLengthParam) { iParameterCP = tvb_get_ntohs(tvb, offset + 2); ti = proto_tree_add_text(drdaroot_tree, tvb, offset, iLengthParam, DRDA_TEXT_PARAM); proto_item_append_text(ti, " (%s)", val_to_str_ext(iParameterCP, &drda_opcode_vals_ext, "Unknown (0x%02x)")); drda_tree_sub = proto_item_add_subtree(ti, ett_drda_param); proto_tree_add_item(drda_tree_sub, hf_drda_param_length, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(drda_tree_sub, hf_drda_param_codepoint, tvb, offset + 2, 2, ENC_BIG_ENDIAN); proto_tree_add_item(drda_tree_sub, hf_drda_param_data, tvb, offset + 4, iLengthParam - 4, ENC_UTF_8|ENC_NA); proto_tree_add_item(drda_tree_sub, hf_drda_param_data_ebcdic, tvb, offset + 4, iLengthParam - 4, ENC_EBCDIC|ENC_NA); if (iCommand == DRDA_CP_SQLSTT) { /* Extract SQL statement from packet */ tvbuff_t* next_tvb = NULL; next_tvb = tvb_new_subset(tvb, offset + 4, iLengthParam - 4, iLengthParam - 4); add_new_data_source(pinfo, next_tvb, "SQL statement"); proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement, next_tvb, 0, iLengthParam - 5, ENC_UTF_8|ENC_NA); proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement_ebcdic, next_tvb, 0, iLengthParam - 4, ENC_EBCDIC|ENC_NA); } } offset += iLengthParam; } else { break; } } } else { /* No tree, advance directly to next command */ offset += iLength; } }
/* Code to actually dissect the packets */ static void dissect_ipa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_udp) { gint remaining; gint header_length = 3; int offset = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPA"); col_clear(pinfo->cinfo, COL_INFO); while ((remaining = tvb_reported_length_remaining(tvb, offset)) > 0) { proto_item *ti; proto_tree *ipa_tree = NULL; guint16 len, msg_type; tvbuff_t *next_tvb; len = tvb_get_ntohs(tvb, offset); msg_type = tvb_get_guint8(tvb, offset+2); col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(msg_type, ipa_protocol_vals, "unknown 0x%02x")); /* * The IPA header is different depending on the transport protocol. * With UDP there seems to be a fourth byte for the IPA header. * We attempt to detect this by checking if the length from the * header + four bytes of the IPA header equals the remaining size. */ if (is_udp && (len + 4 == remaining)) { header_length++; } if (tree) { ti = proto_tree_add_protocol_format(tree, proto_ipa, tvb, offset, len+header_length, "IPA protocol ip.access, type: %s", val_to_str(msg_type, ipa_protocol_vals, "unknown 0x%02x")); ipa_tree = proto_item_add_subtree(ti, ett_ipa); proto_tree_add_item(ipa_tree, hf_ipa_data_len, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ipa_tree, hf_ipa_protocol, tvb, offset+2, 1, ENC_BIG_ENDIAN); } next_tvb = tvb_new_subset_length(tvb, offset+header_length, len); switch (msg_type) { case ABISIP_OML: /* hand this off to the standard A-bis OML dissector */ if (sub_handles[SUB_OML]) call_dissector(sub_handles[SUB_OML], next_tvb, pinfo, tree); break; case ABISIP_IPACCESS: dissect_ipaccess(next_tvb, pinfo, tree); break; case AIP_SCCP: /* hand this off to the standard SCCP dissector */ call_dissector(sub_handles[SUB_SCCP], next_tvb, pinfo, tree); break; case IPA_MGCP: /* hand this off to the standard MGCP dissector */ call_dissector(sub_handles[SUB_MGCP], next_tvb, pinfo, tree); break; case OSMO_EXT: dissect_osmo(next_tvb, pinfo, ipa_tree, tree); break; case HSL_DEBUG: if (tree) { proto_tree_add_item(ipa_tree, hf_ipa_hsl_debug, next_tvb, 0, len, ENC_ASCII|ENC_NA); if (global_ipa_in_root == TRUE) proto_tree_add_item(tree, hf_ipa_hsl_debug, next_tvb, 0, len, ENC_ASCII|ENC_NA); } if (global_ipa_in_info == TRUE) col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", tvb_get_stringz_enc(wmem_packet_scope(), next_tvb, 0, NULL, ENC_ASCII)); break; default: if (msg_type < ABISIP_RSL_MAX) { /* hand this off to the standard A-bis RSL dissector */ call_dissector(sub_handles[SUB_RSL], next_tvb, pinfo, tree); } break; } offset += len + header_length; } }
proto_item *ti_main; proto_item *hidden_item; proto_tree *mdshdr_tree_main, *mdshdr_tree_hdr, *mdshdr_tree_trlr; int offset = 0; guint pktlen; tvbuff_t *next_tvb; guint8 sof, eof; int trailer_start = 0; /*0 means "no trailer found"*/ fc_data_t fc_data; col_set_str(pinfo->cinfo, COL_PROTOCOL, "MDS Header"); col_clear(pinfo->cinfo, COL_INFO); sof = tvb_get_guint8(tvb, offset+MDSHDR_SOF_OFFSET) & 0x0F; pktlen = tvb_get_ntohs(tvb, offset+MDSHDR_PKTLEN_OFFSET) & 0x1FFF; /* The Mdshdr trailer is at the end of the frame */ if ((tvb_captured_length(tvb) >= (MDSHDR_HEADER_SIZE + pktlen)) /* Avoid header/trailer overlap if something wrong */ && (pktlen >= MDSHDR_TRAILER_SIZE)) { trailer_start = MDSHDR_HEADER_SIZE + pktlen - MDSHDR_TRAILER_SIZE; eof = tvb_get_guint8(tvb, trailer_start); tvb_set_reported_length(tvb, MDSHDR_HEADER_SIZE+pktlen); } else { eof = MDSHDR_EOF_UNKNOWN; } fc_data.sof_eof = 0;
/* main dissector function. wireshark calls it for segments in both * directions. */ static void dissect_ajp13_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 mag; /* guint16 len; */ conversation_t *conv = NULL; ajp13_conv_data *cd = NULL; proto_tree *ajp13_tree = NULL; ajp13_frame_data* fd = NULL; /* conversational state really only does us good during the first * in-order traversal */ conv = find_or_create_conversation(pinfo); cd = (ajp13_conv_data*)conversation_get_proto_data(conv, proto_ajp13); if (!cd) { cd = se_new(ajp13_conv_data); cd->content_length = 0; cd->was_get_body_chunk = FALSE; conversation_add_proto_data(conv, proto_ajp13, cd); } /* we use the per segment user data to record the conversational * state for use later on when we're called out of order (see * comments at top of this file) */ fd = (ajp13_frame_data*)p_get_proto_data(pinfo->fd, proto_ajp13); if (!fd) { /*printf("ajp13:dissect_ajp13_common():no frame data, adding");*/ /* since there's no per-packet user data, this must be the first * time we've see the packet, and it must be the first "in order" * pass through the data. */ fd = se_new(ajp13_frame_data); p_add_proto_data(pinfo->fd, proto_ajp13, fd); fd->is_request_body = FALSE; if (cd->content_length) { /* this is screwy, see AJPv13.html. the idea is that if the * request has a body (as determined by the content-length * header), then there's always an immediate follow-up PDU with * no GET_BODY_CHUNK from the container. */ fd->is_request_body = TRUE; } } col_clear(pinfo->cinfo, COL_INFO); mag = tvb_get_ntohs(tvb, 0); /* len = tvb_get_ntohs(tvb, 2); */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AJP13"); if (mag == 0x1234 && !fd->is_request_body) col_append_fstr(pinfo->cinfo, COL_INFO, "%d:REQ:", conv->index); else if (mag == 0x1234 && fd->is_request_body) col_append_fstr(pinfo->cinfo, COL_INFO, "%d:REQ:Body", conv->index); else if (mag == 0x4142) col_append_fstr(pinfo->cinfo, COL_INFO, "%d:RSP:", conv->index); else col_set_str(pinfo->cinfo, COL_INFO, "AJP13 Error?"); if (tree) { proto_item *ti; ti = proto_tree_add_item(tree, proto_ajp13, tvb, 0, -1, ENC_NA); ajp13_tree = proto_item_add_subtree(ti, ett_ajp13); } if (mag == 0x1234) { if (fd->is_request_body) display_req_body(tvb, ajp13_tree, cd); else display_req_forward(tvb, pinfo, ajp13_tree, cd); } else if (mag == 0x4142) { display_rsp(tvb, pinfo, ajp13_tree, cd); } }
static int dissect_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mndp_tree, guint32 offset, guint32 length _U_, const ext_value_string *value_array) { guint32 tlv_type; guint32 tlv_length; proto_item *tlv_tree; proto_item *type_item; int type_index; guint32 tlv_end; guint encoding_info; tlv_type = tvb_get_ntohs(tvb, offset); tlv_length = tvb_get_ntohs(tvb, offset + 2); /* DISSECTOR_ASSERT(tlv_length >= 4); */ tlv_tree = proto_tree_add_subtree_format(mndp_tree, tvb, offset, tlv_length+4, ett_mndp_tlv_header, NULL, "T %d, L %d: %s", tlv_type, tlv_length, extval_to_str_idx(tlv_type, value_array, NULL, "Unknown")); type_item = proto_tree_add_item(tlv_tree, hf_mndp_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN); proto_item_append_text(type_item, " = %s", extval_to_str_idx(tlv_type, value_array, &type_index, "Unknown")); offset += 2; proto_tree_add_item(tlv_tree, hf_mndp_tlv_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* tlv_length -= 4; */ if (tlv_length == 0) return offset; tlv_end = offset + tlv_length; /* Make hf_ handling independent of specialfuncion */ /* FIXME: Properly handle encoding info */ if ( type_index != -1 && !value_array[type_index].specialfunction && value_array[type_index].evs != NULL ) { encoding_info = value_array[type_index].evs ? TRUE : FALSE; } else { encoding_info = FALSE; } if ( type_index != -1 && value_array[type_index].hf_element) { proto_tree_add_item(tlv_tree, *(value_array[type_index].hf_element), tvb, offset, tlv_length, encoding_info); } else { proto_tree_add_item(tlv_tree, hf_mndp_tlv_data, tvb, offset, tlv_length, ENC_NA); } if ( type_index != -1 && value_array[type_index].specialfunction ) { guint32 newoffset; while (offset < tlv_end) { newoffset = value_array[type_index].specialfunction ( tvb, pinfo, tlv_tree, offset, tlv_length, value_array[type_index].evs); DISSECTOR_ASSERT(newoffset > offset); offset = newoffset; } } return tlv_end; }
/* note that even if ajp13_tree is null on the first pass, we still * need to dissect the packet in order to determine if there is a * content-length, and thus if there is a subsequent automatic * request-body transmitted in the next request packet. if there is a * content-length, we record the fact in the conversation context. * ref the top of this file for comments explaining the multi-pass * thing. */ static void display_req_forward(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ajp13_tree, ajp13_conv_data* cd) { int pos = 0; guint8 meth; guint8 cod; const gchar *ver; guint16 ver_len; const gchar *uri; guint16 uri_len; const gchar *raddr; guint16 raddr_len; const gchar *rhost; guint16 rhost_len; const gchar *srv; guint16 srv_len; guint nhdr; guint i; if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_magic, tvb, pos, 2, ENC_NA); pos+=2; if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_len, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* PACKET CODE */ cod = tvb_get_guint8(tvb, 4); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_code, tvb, pos, 1, ENC_BIG_ENDIAN); pos+=1; if ( cod == MTYPE_CPING ) { col_append_str(pinfo->cinfo, COL_INFO, "CPING" ); return; } /* HTTP METHOD (ENCODED AS INTEGER) */ meth = tvb_get_guint8(tvb, pos); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(meth, http_method_codes, "Unknown method %u")); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_method, tvb, pos, 1, ENC_BIG_ENDIAN); pos+=1; /* HTTP VERSION STRING */ ver = ajp13_get_nstring(tvb, pos, &ver_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_ver, tvb, pos, ver_len+2, ver); pos=pos+ver_len+2; /* skip over size + chars + trailing null */ /* URI */ uri = ajp13_get_nstring(tvb, pos, &uri_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_uri, tvb, pos, uri_len+2, uri); pos=pos+uri_len+2; /* skip over size + chars + trailing null */ col_append_fstr(pinfo->cinfo, COL_INFO, " %s %s", uri, ver); /* REMOTE ADDRESS */ raddr = ajp13_get_nstring(tvb, pos, &raddr_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_raddr, tvb, pos, raddr_len+2, raddr); pos=pos+raddr_len+2; /* skip over size + chars + trailing null */ /* REMOTE HOST */ rhost = ajp13_get_nstring(tvb, pos, &rhost_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_rhost, tvb, pos, rhost_len+2, rhost); pos=pos+rhost_len+2; /* skip over size + chars + trailing null */ /* SERVER NAME */ srv = ajp13_get_nstring(tvb, pos, &srv_len); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_srv, tvb, pos, srv_len+2, srv); pos=pos+srv_len+2; /* skip over size + chars + trailing null */ /* SERVER PORT */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_port, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* IS SSL? */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_sslp, tvb, pos, 1, ENC_NA); pos+=1; /* NUM HEADERS */ nhdr = tvb_get_ntohs(tvb, pos); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_nhdr, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; cd->content_length = 0; /* HEADERS */ for(i=0; i<nhdr; i++) { guint8 hcd; guint8 hid; const gchar* hname = NULL; header_field_info *hfinfo; int hpos = pos; int cl = 0; const gchar *hval; guint16 hval_len, hname_len; /* HEADER CODE/NAME */ hcd = tvb_get_guint8(tvb, pos); if (hcd == 0xA0) { pos+=1; hid = tvb_get_guint8(tvb, pos); pos+=1; if (hid >= array_length(req_headers)) hid = 0; hval = ajp13_get_nstring(tvb, pos, &hval_len); if (ajp13_tree) { hfinfo = proto_registrar_get_nth(*req_headers[hid]); proto_tree_add_string_format(ajp13_tree, *req_headers[hid], tvb, hpos, 2+hval_len+2, hval, "%s: %s", hfinfo->name, hval); } pos+=hval_len+2; if (hid == 0x08) cl = 1; } else { hname = ajp13_get_nstring(tvb, pos, &hname_len); pos+=hname_len+2; hval = ajp13_get_nstring(tvb, pos, &hval_len); if (ajp13_tree) { proto_tree_add_string_format(ajp13_tree, hf_ajp13_additional_header, tvb, hpos, hname_len+2+hval_len+2, ep_strdup_printf("%s: %s", hname, hval), "%s: %s", hname, hval); } pos+=hval_len+2; } if (cl) { cl = atoi(hval); cd->content_length = cl; } } /* ATTRIBUTES */ while(tvb_reported_length_remaining(tvb, pos) > 0) { guint8 aid; const gchar* aname = NULL; const gchar* aval; guint16 aval_len, aname_len; header_field_info *hfinfo; int apos = pos; /* ATTRIBUTE CODE/NAME */ aid = tvb_get_guint8(tvb, pos); pos+=1; if (aid == 0xFF) { /* request terminator */ break; } if (aid == 0x0A) { /* req_attribute - name and value follow */ aname = ajp13_get_nstring(tvb, pos, &aname_len); pos+=aname_len+2; aval = ajp13_get_nstring(tvb, pos, &aval_len); pos+=aval_len+2; if (ajp13_tree) { proto_tree_add_string_format(ajp13_tree, hf_ajp13_req_attribute, tvb, apos, 1+aname_len+2+aval_len+2, g_strdup_printf("%s: %s", aname, aval), "%s: %s", aname, aval); } } else if (aid == 0x0B ) { /* ssl_key_length */ if (ajp13_tree) { proto_tree_add_uint(ajp13_tree, hf_ajp13_ssl_key_size, tvb, apos, 1+2, tvb_get_ntohs(tvb, pos)); } pos+=2; } else { if (aid >= array_length(req_attributes)) aid = 0; hfinfo = proto_registrar_get_nth(*req_attributes[aid]); aval = ajp13_get_nstring(tvb, pos, &aval_len); pos+=aval_len+2; if (ajp13_tree) { proto_tree_add_string_format(ajp13_tree, *req_attributes[aid], tvb, apos, 1+aval_len+2, aval, "%s: %s", hfinfo->name, aval); } } } }
/* dissect a response. more work to do here. */ static void display_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ajp13_tree, ajp13_conv_data* cd) { int pos = 0; guint8 mcode = 0; int i; /* MAGIC */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_magic, tvb, pos, 2, ENC_NA); pos+=2; /* PDU LENGTH */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_len, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* MESSAGE TYPE CODE */ mcode = tvb_get_guint8(tvb, pos); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(mcode, mtype_codes, "Unknown message code %u")); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_code, tvb, pos, 1, ENC_BIG_ENDIAN); pos+=1; switch (mcode) { case MTYPE_END_RESPONSE: if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_reusep, tvb, pos, 1, ENC_BIG_ENDIAN); /*pos+=1;*/ break; case MTYPE_SEND_HEADERS: { const gchar *rsmsg; guint16 rsmsg_len; guint16 nhdr; guint16 rcode_num; /* HTTP RESPONSE STATUS CODE */ rcode_num = tvb_get_ntohs(tvb, pos); col_append_fstr(pinfo->cinfo, COL_INFO, ":%d", rcode_num); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_rstatus, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* HTTP RESPONSE STATUS MESSAGE */ rsmsg = ajp13_get_nstring(tvb, pos, &rsmsg_len); col_append_fstr(pinfo->cinfo, COL_INFO, " %s", rsmsg); if (ajp13_tree) proto_tree_add_string(ajp13_tree, hf_ajp13_rsmsg, tvb, pos, rsmsg_len+2, rsmsg); pos+=rsmsg_len+2; /* NUMBER OF HEADERS */ nhdr = tvb_get_ntohs(tvb, pos); if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_nhdr, tvb, pos, 2, ENC_BIG_ENDIAN); pos+=2; /* HEADERS */ for(i=0; i<nhdr; i++) { guint8 hcd; guint8 hid; const gchar *hval; guint16 hval_len, hname_len; const gchar* hname = NULL; header_field_info *hfinfo; int hpos = pos; /* int cl = 0; TODO: Content-Length header (encoded by 0x08) is special */ /* HEADER CODE/NAME */ hcd = tvb_get_guint8(tvb, pos); if (hcd == 0xA0) { pos+=1; hid = tvb_get_guint8(tvb, pos); pos+=1; if (hid >= array_length(rsp_headers)) hid = 0; hval = ajp13_get_nstring(tvb, pos, &hval_len); if (ajp13_tree) { hfinfo = proto_registrar_get_nth(*rsp_headers[hid]); proto_tree_add_string_format(ajp13_tree, *rsp_headers[hid], tvb, hpos, 2+hval_len+2, hval, "%s: %s", hfinfo->name, hval); } pos+=hval_len+2; #if 0 /* TODO: Content-Length header (encoded by 0x08) is special */ if (hid == 0x08) cl = 1; #endif } else { hname = ajp13_get_nstring(tvb, pos, &hname_len); pos+=hname_len+2; hval = ajp13_get_nstring(tvb, pos, &hval_len); if (ajp13_tree) { proto_tree_add_string_format(ajp13_tree, hf_ajp13_additional_header, tvb, hpos, hname_len+2+hval_len+2, ep_strdup_printf("%s: %s", hname, hval), "%s: %s", hname, hval); } pos+=hval_len+2; } } break; } case MTYPE_GET_BODY_CHUNK: { guint16 rlen; rlen = tvb_get_ntohs(tvb, pos); cd->content_length = rlen; if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_rlen, tvb, pos, 2, ENC_BIG_ENDIAN); /*pos+=2;*/ break; } case MTYPE_CPONG: break; default: /* MESSAGE DATA (COPOUT) */ if (ajp13_tree) proto_tree_add_item(ajp13_tree, hf_ajp13_data, tvb, pos+2, -1, ENC_UTF_8|ENC_NA); break; } }
} } /* given the first chunk of the AJP13 pdu, extract out and return the * packet length. see comments in packet-tcp.c:tcp_dissect_pdus(). */ static guint get_ajp13_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset) { /*guint16 magic;*/ guint16 plen; /*magic = tvb_get_ntohs(tvb, offset); */ plen = tvb_get_ntohs(tvb, offset+2); plen += 4; return plen; } /* Code to actually dissect the packets. */ static void dissect_ajp13(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ tcp_dissect_pdus(tvb, pinfo, tree, TRUE, /* desegment or not */
/* Actor Key */ proto_tree_add_item(lacpdu_tree, hf_lacp_actor_key, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Actor Port Priority */ proto_tree_add_item(lacpdu_tree, hf_lacp_actor_port_priority, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Actor Port */ raw_word = tvb_get_ntohs(tvb, offset); col_append_fstr(pinfo->cinfo, COL_INFO, "Actor Port = %d ", raw_word); proto_tree_add_uint(lacpdu_tree, hf_lacp_actor_port, tvb, offset, 2, raw_word); offset += 2; /* Actor State */ proto_tree_add_bitmask_with_flags(lacpdu_tree, tvb, offset, hf_lacp_actor_state, ett_lacp_a_flags, actor_flags, ENC_NA, BMT_NO_INT|BMT_NO_TFS|BMT_NO_FALSE); offset += 1; /* Actor Reserved */ proto_tree_add_item(lacpdu_tree, hf_lacp_actor_reserved, tvb, offset, 3, ENC_NA); offset += 3;
guint16 checksum, checksum_calculated; guint checksum_offset; #endif guint16 addr, cr, eah, eal, v5addr; gboolean is_response = 0; #if 0 guint length, reported_length; #endif tvbuff_t *next_tvb; const char *srcname = "?"; const char *dstname = "?"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "V5DL"); col_clear(pinfo->cinfo, COL_INFO); addr = tvb_get_ntohs(tvb, 0); cr = addr & V5DL_CR; eal = (addr & V5DL_EAL) >> V5DL_EAL_SHIFT; eah = (addr & V5DL_EAH) >> V5DL_EAH_SHIFT; v5addr = (eah << 7) + eal; v5dl_header_len = 2; /* addr */ direction = pinfo->p2p_dir; if (pinfo->p2p_dir == P2P_DIR_RECV) { is_response = cr ? FALSE : TRUE; srcname = "Network"; dstname = "User"; } else if (pinfo->p2p_dir == P2P_DIR_SENT) { is_response = cr ? TRUE : FALSE; srcname = "User";
static void dissect_http2_frame_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) { proto_item *ti; proto_tree *http2_tree; guint32 offset = 0; http2_frame_header frame; /* tvb_memeql makes certain there are enough bytes in the buffer. * returns -1 if there are not enough bytes or if there is not a * match. Returns 0 on a match */ if ( tvb_memeql( tvb, offset, kMagicHello, MAGIC_FRAME_LENGTH ) == 0 ) { col_append_sep_str( pinfo->cinfo, COL_INFO, ", ", "Magic" ); ti = proto_tree_add_item(tree, proto_http2, tvb, offset, MAGIC_FRAME_LENGTH, ENC_NA); proto_item_append_text( ti, ", Magic" ); http2_tree = proto_item_add_subtree(ti, ett_http2); proto_tree_add_item(http2_tree, hf_http2_magic, tvb, offset, MAGIC_FRAME_LENGTH, ENC_BIG_ENDIAN); return; } frame.length = tvb_get_ntohs( tvb, offset + 0 ); frame.type = tvb_get_guint8( tvb, offset + 2 ); frame.flags = tvb_get_guint8( tvb, offset + 3 ); frame.streamid = tvb_get_ntohl( tvb, offset + 4 ); col_append_sep_fstr( pinfo->cinfo, COL_INFO, ", ", "%s", val_to_str( frame.type, frametypenames, "Unknown (0x%02X)" ) ); /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_http2, tvb, offset, FRAME_HEADER_LENGTH + frame.length, ENC_NA); proto_item_append_text( ti, ", %s", val_to_str( frame.type, frametypenames, "Unknown (0x%02X)" ) ); proto_item_append_text( ti, ", Length: %d, Flags: %d, streamid: %d", frame.length, frame.flags, frame.streamid ); http2_tree = proto_item_add_subtree(ti, ett_http2); /* Add an item to the subtree, see section 1.6 of README.developer for more * information. */ proto_tree_add_item(http2_tree, hf_http2_length, tvb, offset + 0, 2, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_type, tvb, offset + 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_flags, tvb, offset + 3, 1, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_streamid, tvb, offset + 4, 4, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_payload, tvb, offset + 8, frame.length, ENC_BIG_ENDIAN); offset += frame.length + FRAME_HEADER_LENGTH; return; }
static void dissect_turbocell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti, *name_item; proto_tree *turbocell_tree = NULL, *network_tree; tvbuff_t *next_tvb; int i=0; guint8 packet_type; guint8 * str_name; guint str_len; gint remaining_length; packet_type = tvb_get_guint8(tvb, 0); if (!(packet_type & 0x0F)){ col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Beacon)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } else if ( packet_type == TURBOCELL_TYPE_MANAGEMENT ) { col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Management)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } else if ( packet_type == TURBOCELL_TYPE_DATA ) { col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Data)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } else { col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Unknown)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } if (tree) { ti = proto_tree_add_item(tree, proto_turbocell, tvb, 0, 20, ENC_NA); turbocell_tree = proto_item_add_subtree(ti, ett_turbocell); proto_tree_add_item(turbocell_tree, hf_turbocell_type, tvb, 0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_satmode, tvb, 1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_nwid, tvb, 1, 1, ENC_BIG_ENDIAN); /* it seem when we have this magic number,that means an alternate header version */ if (tvb_get_bits64(tvb, 64,48,ENC_BIG_ENDIAN) != G_GINT64_CONSTANT(0x000001fe23dc45ba)){ proto_tree_add_item(turbocell_tree, hf_turbocell_counter, tvb, 0x02, 2, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_dst, tvb, 0x04, 6, ENC_NA); proto_tree_add_item(turbocell_tree, hf_turbocell_timestamp, tvb, 0x0A, 3, ENC_BIG_ENDIAN); } else { proto_tree_add_item(turbocell_tree, hf_turbocell_timestamp, tvb, 0x02, 3, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_counter, tvb, 0x05, 3, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_dst, tvb, 0x08, 6, ENC_NA); } proto_tree_add_item(turbocell_tree, hf_turbocell_unknown, tvb, 0x0E, 2, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_ip, tvb, 0x10, 4, ENC_BIG_ENDIAN); } remaining_length=tvb_captured_length_remaining(tvb, 0x14); if (remaining_length > 6) { /* If the first character is a printable character that means we have a payload with network info */ /* I couldn't find anything in the header that would definitvely indicate if payload is either data or network info */ /* Since the frame size is limited this should work ok */ if (tvb_get_guint8(tvb, 0x14)>=0x20){ name_item = proto_tree_add_item(turbocell_tree, hf_turbocell_name, tvb, 0x14, 30, ENC_ASCII|ENC_NA); network_tree = proto_item_add_subtree(name_item, ett_network); str_name=tvb_get_stringz_enc(wmem_packet_scope(), tvb, 0x14, &str_len, ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, ", Network=\"%s\"",format_text(str_name, str_len-1)); while(tvb_get_guint8(tvb, 0x34 + 8*i)==0x00 && (tvb_captured_length_remaining(tvb,0x34 + 8*i) > 6) && (i<32)) { proto_tree_add_item(network_tree, hf_turbocell_station[i], tvb, 0x34+8*i, 6, ENC_NA); i++; } /*Couldn't make sense of the apparently random data in the end*/ next_tvb = tvb_new_subset_remaining(tvb, 0x34 + 8*i); call_dissector(data_handle, next_tvb, pinfo, tree); } else { tvbuff_t *volatile msdu_tvb = NULL; guint32 msdu_offset = 0x04; guint16 j = 1; guint16 msdu_length; proto_item *parent_item; proto_tree *mpdu_tree; proto_tree *subframe_tree; next_tvb = tvb_new_subset(tvb, 0x14, -1, tvb_get_ntohs(tvb, 0x14)); parent_item = proto_tree_add_protocol_format(tree, proto_aggregate, next_tvb, 0, tvb_reported_length_remaining(next_tvb, 0), "Turbocell Aggregate Frames"); mpdu_tree = proto_item_add_subtree(parent_item, ett_msdu_aggregation_parent_tree); proto_tree_add_item(mpdu_tree, hf_turbocell_aggregate_len, next_tvb, 0x00, 2, ENC_BIG_ENDIAN); proto_tree_add_item(mpdu_tree, hf_turbocell_aggregate_unknown1, next_tvb, 0x02, 2, ENC_BIG_ENDIAN); remaining_length=tvb_captured_length_remaining(next_tvb, msdu_offset); do { msdu_length = (tvb_get_letohs(next_tvb, msdu_offset) & 0x0FFF); if (msdu_length==0) break; parent_item = proto_tree_add_uint_format(mpdu_tree, hf_turbocell_aggregate_msdu_header_text, next_tvb,msdu_offset, msdu_length + 0x02,j, "A-MSDU Subframe #%u", j); subframe_tree = proto_item_add_subtree(parent_item, ett_msdu_aggregation_subframe_tree); j++; proto_tree_add_item(subframe_tree, hf_turbocell_aggregate_msdu_len, next_tvb, msdu_offset, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(subframe_tree, hf_turbocell_aggregate_unknown2, next_tvb, msdu_offset+1, 1, ENC_BIG_ENDIAN); msdu_offset += 0x02; remaining_length -= 0x02; msdu_tvb = tvb_new_subset(next_tvb, msdu_offset, (msdu_length>remaining_length)?remaining_length:msdu_length, msdu_length); call_dissector(eth_handle, msdu_tvb, pinfo, subframe_tree); msdu_offset += msdu_length; remaining_length -= msdu_length; } while (remaining_length > 6); if (remaining_length > 2) { next_tvb = tvb_new_subset_remaining(next_tvb, msdu_offset); call_dissector(data_handle, next_tvb, pinfo, tree); } } } }
static int dissect_xtp_tspec(tvbuff_t *tvb, proto_tree *tree, guint32 offset) { guint32 len = tvb_length_remaining(tvb, offset); guint32 start = offset; proto_item *ti, *ti2; proto_tree *xtp_subtree; struct xtp_traffic_spec1 tspec[1]; int error = 0; ti = proto_tree_add_text(tree, tvb, offset, len, "Traffic Specifier"); xtp_subtree = proto_item_add_subtree(ti, ett_xtp_tspec); if (len < XTP_TRAFFIC_SPEC0_LEN) { proto_item_append_text(ti, ", bogus length(%u, must be at least %u)", len, XTP_TRAFFIC_SPEC0_LEN); return 0; } /** parse common fields **/ /* tlen(2) */ tspec->tlen = tvb_get_ntohs(tvb, offset); offset += 2; /* service(1) */ tspec->service = tvb_get_guint8(tvb, offset); offset++; /* tformat(1) */ tspec->tformat = tvb_get_guint8(tvb, offset); /** display common fields */ offset = start; /* tlen(2) */ ti = proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_tlen, tvb, offset, 2, tspec->tlen); offset += 2; if (tspec->tlen > len) { proto_item_append_text(ti, ", bogus length(%u, must be at most %u)", tspec->tlen, len); error = 1; } /* service(1) */ proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_service, tvb, offset, 1, tspec->service); offset++; /* tformat(1) */ ti2 = proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_tformat, tvb, offset, 1, tspec->tformat); offset++; switch (tspec->tformat) { case 0: if (tspec->tlen != XTP_TRAFFIC_SPEC0_LEN) { proto_item_append_text(ti, ", bogus length(%u, must be %u)", tspec->tlen, XTP_TRAFFIC_SPEC0_LEN); error = 1; } break; case 1: if (tspec->tlen != XTP_TRAFFIC_SPEC1_LEN) { proto_item_append_text(ti, ", bogus length(%u, must be %u)", tspec->tlen, XTP_TRAFFIC_SPEC1_LEN); error = 1; } break; default: proto_item_append_text(ti2, ", Unsupported tformat(%u)", tspec->tformat); error = 1; break; } if (error) return (offset - start); /** parse and display each traffic fields **/ switch (tspec->tformat) { case 0: /* traffic(4) */ tspec->maxdata = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_traffic, tvb, offset, 4, tspec->maxdata); offset += 4; break; case 1: /* maxdata(4) */ tspec->maxdata = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_maxdata, tvb, offset, 4, tspec->maxdata); offset += 4; /* inrate(4) */ tspec->inrate = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_inrate, tvb, offset, 4, tspec->inrate); offset += 4; /* inburst(4) */ tspec->inburst = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_inburst, tvb, offset, 4, tspec->inburst); offset += 4; /* outrate(4) */ tspec->outrate = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_outrate, tvb, offset, 4, tspec->outrate); offset += 4; /* outburst(4) */ tspec->outburst = tvb_get_ntohl(tvb, offset); proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_outburst, tvb, offset, 4, tspec->outburst); offset += 4; break; default: break; } return (offset - start); }
proto_tree *add_protocol_subtree(tlv_info_t *self, gint idx, proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length _U_, const char *label) { /* Declare local variables */ proto_tree *tlv_tree; proto_item *tlv_item; gint tlv_value_length, tlv_val_offset; guint8 size_of_tlv_length_field; guint8 tlv_type; guint32 tlv_value; const gchar *hex_fmt; /* Make sure we're dealing with a valid TLV here */ if (get_tlv_type(self) < 0) return tree; /* Retrieve the necessary TLV information */ tlv_val_offset = get_tlv_value_offset(self); tlv_value_length = get_tlv_length(self); size_of_tlv_length_field = get_tlv_size_of_length(self); tlv_type = get_tlv_type(self); /* display the TLV name and display the value in hex. Highlight type, length, and value. */ tlv_item = proto_tree_add_protocol_format(tree, hfindex, tvb, start, tlv_value_length+tlv_val_offset, "%s (%u byte(s))", label, tlv_value_length); tlv_tree = proto_item_add_subtree(tlv_item, ett_tlv[tlv_type]); proto_tree_add_uint(tlv_tree, hf_tlv_type, tvb, start, 1, tlv_type); if (size_of_tlv_length_field > 0) /* It is */ { /* display the length of the length field TLV */ proto_tree_add_uint(tlv_tree, hf_tlv_length_size, tvb, start+1, 1, size_of_tlv_length_field); /* display the TLV length */ proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+2, size_of_tlv_length_field, tlv_value_length); } else { /* It is not */ /* display the TLV length */ proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+1, 1, tlv_value_length); } /* display the TLV value and make it a subtree */ switch (tlv_value_length) { case 1: tlv_value = tvb_get_guint8(tvb, start+tlv_val_offset); hex_fmt = tlv_val_1byte; break; case 2: tlv_value = tvb_get_ntohs(tvb, start+tlv_val_offset); hex_fmt = tlv_val_2byte; break; case 3: tlv_value = tvb_get_ntoh24(tvb, start+tlv_val_offset); hex_fmt = tlv_val_3byte; break; case 4: tlv_value = tvb_get_ntohl(tvb, start+tlv_val_offset); hex_fmt = tlv_val_4byte; break; default: tlv_value = tvb_get_ntohl(tvb, start+tlv_val_offset); hex_fmt = tlv_val_5byte; break; } /* Show "TLV value: " */ tlv_item = proto_tree_add_text(tlv_tree, tvb, start+tlv_val_offset, tlv_value_length, hex_fmt, label, tlv_value); tlv_tree = proto_item_add_subtree(tlv_item, idx); /* Return a pointer to the value level */ return tlv_tree; }
/* Code to actually dissect the packets */ static void dissect_wtls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; char pdut; guint count = 0; guint offset_wtls = 0; /* Set up structures we will need to add the protocol subtree and manage it */ proto_item *ti; proto_tree *wtls_tree; proto_tree *wtls_rec_tree; proto_tree *wtls_msg_type_tree; if (check_col(pinfo->cinfo, COL_PROTOCOL)) { switch ( pinfo->match_uint ) { case UDP_PORT_WTLS_WSP: col_set_str(pinfo->cinfo, COL_PROTOCOL, "WTLS+WSP" ); break; case UDP_PORT_WTLS_WTP_WSP: col_set_str(pinfo->cinfo, COL_PROTOCOL, "WTLS+WTP+WSP" ); break; } } /* Develop the string to put in the Info column */ col_set_str(pinfo->cinfo, COL_INFO, "WTLS"); /* In the interest of speed, if "tree" is NULL, don't do any work not necessary to generate protocol tree items. */ if (tree) { ti = proto_tree_add_item(tree, proto_wtls, tvb, offset_wtls, -1, ENC_NA); wtls_tree = proto_item_add_subtree(ti, ett_wtls); for (offset_wtls=0; offset_wtls < (tvb_reported_length(tvb)-1);) { pdut = tvb_get_guint8 (tvb, offset_wtls); offset = offset_wtls+1; if (pdut & WTLS_RECORD_TYPE_SEQUENCE) { offset+=2; } if (pdut & WTLS_RECORD_TYPE_LENGTH) { count = tvb_get_ntohs(tvb, offset); offset+=2; count += offset-offset_wtls; } else { count = tvb_length_remaining (tvb, offset_wtls); } ti = proto_tree_add_uint(wtls_tree, hf_wtls_record, tvb, offset_wtls, count, pdut); wtls_rec_tree = proto_item_add_subtree(ti, ett_wtls_rec); offset = offset_wtls; proto_tree_add_item (wtls_rec_tree, hf_wtls_record_type, tvb,offset,1,ENC_BIG_ENDIAN); offset++; offset_wtls += count; if (pdut & WTLS_RECORD_TYPE_SEQUENCE) { proto_tree_add_item (wtls_rec_tree, hf_wtls_record_sequence, tvb,offset,2,ENC_BIG_ENDIAN); offset+=2; } if (pdut & WTLS_RECORD_TYPE_LENGTH) { count = tvb_get_ntohs(tvb, offset); proto_tree_add_item (wtls_rec_tree, hf_wtls_record_length, tvb,offset,2,ENC_BIG_ENDIAN); offset+=2; } else { count = tvb_length_remaining (tvb, offset); } if (pdut & WTLS_RECORD_TYPE_CIPHER_CUR) { proto_tree_add_item (wtls_rec_tree, hf_wtls_record_ciphered, tvb,offset,count,ENC_NA); continue; } switch (pdut & WTLS_RECORD_CONTENT_TYPE) { case WTLS_PLAIN_HANDSHAKE : dissect_wtls_handshake(wtls_rec_tree,tvb,offset,count); break; case WTLS_ALERT : ti = proto_tree_add_item(wtls_rec_tree, hf_wtls_alert, tvb, offset, count, ENC_NA); wtls_msg_type_tree = proto_item_add_subtree(ti, ett_wtls_msg_type); proto_tree_add_item (wtls_msg_type_tree, hf_wtls_alert_level, tvb,offset,1,ENC_BIG_ENDIAN); offset+=1; count = tvb_get_ntohs (tvb, offset); proto_tree_add_item (wtls_msg_type_tree, hf_wtls_alert_description, tvb,offset,1,ENC_BIG_ENDIAN); offset+=1; default: offset+=count; break; } } } }
/* Code to actually dissect the packets */ static int dissect_mbtcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ mbtcp_hdr mh; proto_item *mi, *mf; proto_tree *mbtcp_tree, *modbus_tree, *group_tree; int offset, group_offset, packet_type; guint i; gint packet_len, payload_start, payload_len; const char *func_string = ""; const char *pkt_type_str = ""; const char *err_str = ""; guint32 byte_cnt, group_byte_cnt, group_word_cnt; guint32 packet_num; /* num to uniquely identify different mbtcp * packets in one packet */ guint8 exception_code; gboolean exception_returned; guint8 fc; mh.transaction_id = tvb_get_ntohs(tvb, 0); mh.protocol_id = tvb_get_ntohs(tvb, 2); mh.len = tvb_get_ntohs(tvb, 4); mh.mdbs_hdr.unit_id = tvb_get_guint8(tvb, 6); mh.mdbs_hdr.function_code = tvb_get_guint8(tvb, 7); /* check that it actually looks like Modbus/TCP */ /* protocol id == 0 */ if( mh.protocol_id != 0 ){ return 0; } /* length is at least 2 (unit_id + function_code) */ if( mh.len < 2 ){ return 0; } /* function code is in the set 1-24, 40, 125-127. * Note that function code is only 7 bits. */ fc=mh.mdbs_hdr.function_code&0x7f; if(!match_strval(fc, function_code_vals)) return 0; /* Make entries in Protocol column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Modbus/TCP"); col_clear(pinfo->cinfo, COL_INFO); /* Make entries in Info column on summary display */ offset = 0; if ( mh.mdbs_hdr.function_code & 0x80 ) { exception_code = tvb_get_guint8(tvb, offset + sizeof(mbtcp_hdr)); mh.mdbs_hdr.function_code ^= 0x80; exception_returned = TRUE; } else { exception_code = 0; exception_returned = FALSE; } func_string = val_to_str(mh.mdbs_hdr.function_code, function_code_vals, "Unknown function (%u)"); if (check_col(pinfo->cinfo, COL_INFO)) { packet_type = classify_packet(pinfo); switch ( packet_type ) { case QUERY_PACKET : pkt_type_str="query"; break; case RESPONSE_PACKET : pkt_type_str="response"; break; case CANNOT_CLASSIFY : err_str="Unable to classify as query or response."; pkt_type_str="unknown"; break; default : break; } if ( exception_returned ) err_str="Exception returned "; col_add_fstr(pinfo->cinfo, COL_INFO, "%8s [%2u pkt(s)]: trans: %5u; unit: %3u, func: %3u: %s. %s", pkt_type_str, 1, mh.transaction_id, (unsigned char) mh.mdbs_hdr.unit_id, (unsigned char) mh.mdbs_hdr.function_code, func_string, err_str); } /* build up protocol tree and iterate over multiple packets */ packet_num = 0; while (1) { packet_type = classify_packet(pinfo); packet_len = sizeof(mbtcp_hdr) - sizeof(modbus_hdr) + mh.len; /* if a tree exists, perform operations to add fields to it */ if (tree) { mi = proto_tree_add_protocol_format(tree, proto_mbtcp, tvb, offset, packet_len, "Modbus/TCP"); mbtcp_tree = proto_item_add_subtree(mi, ett_mbtcp); /* Add items to protocol tree specific to Modbus/TCP */ proto_tree_add_uint(mbtcp_tree, hf_mbtcp_transid, tvb, offset, 2, mh.transaction_id); proto_tree_add_uint(mbtcp_tree, hf_mbtcp_protid, tvb, offset + 2, 2, mh.protocol_id); proto_tree_add_uint(mbtcp_tree, hf_mbtcp_len, tvb, offset + 4, 2, mh.len); proto_tree_add_uint(mbtcp_tree, hf_mbtcp_unitid, tvb, offset + 6, 1, mh.mdbs_hdr.unit_id); /* Add items to protocol tree specific to Modbus generic */ mf = proto_tree_add_text(mbtcp_tree, tvb, offset + 7, mh.len - 1, "Modbus"); modbus_tree = proto_item_add_subtree(mf, ett_modbus_hdr); mi = proto_tree_add_uint(modbus_tree, hf_mbtcp_functioncode, tvb, offset + 7, 1, mh.mdbs_hdr.function_code); /** detail payload as a function of exception/function code */ func_string = val_to_str(mh.mdbs_hdr.function_code, function_code_vals, "Unknown function"); payload_start = offset + 8; payload_len = mh.len - sizeof(modbus_hdr); if (exception_returned) { proto_item_set_text(mi, "function %u: %s. Exception: %s", mh.mdbs_hdr.function_code, func_string, val_to_str(exception_code, exception_code_vals, "Unknown exception code (%u)")); proto_tree_add_uint(modbus_tree, hf_modbus_exceptioncode, tvb, payload_start, 1, exception_code); } else { proto_item_set_text(mi, "function %u: %s", mh.mdbs_hdr.function_code, func_string); switch (mh.mdbs_hdr.function_code) { case READ_COILS: case READ_INPUT_DISCRETES: if (packet_type == QUERY_PACKET) { proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE); } else if (packet_type == RESPONSE_PACKET) { byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start); proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt); proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data"); } break; case READ_MULT_REGS: case READ_INPUT_REGS: if (packet_type == QUERY_PACKET) { proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE); } else if (packet_type == RESPONSE_PACKET) { byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start); proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt); proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data"); } break; case WRITE_COIL: if (packet_type == QUERY_PACKET) { proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 1, "Data"); proto_tree_add_text(modbus_tree, tvb, payload_start + 3, 1, "Padding"); } else if (packet_type == RESPONSE_PACKET) { proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 1, "Data"); proto_tree_add_text(modbus_tree, tvb, payload_start + 3, 1, "Padding"); } break; case WRITE_SINGLE_REG: if (packet_type == QUERY_PACKET) { proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 2, "Data"); } else if (packet_type == RESPONSE_PACKET) { proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 2, "Data"); } break; case READ_EXCEPT_STAT: if (packet_type == RESPONSE_PACKET) proto_tree_add_text(modbus_tree, tvb, payload_start, 1, "Data"); break; case FORCE_MULT_COILS: if (packet_type == QUERY_PACKET) { proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE); byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 4); proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 4, 1, byte_cnt); proto_tree_add_text(modbus_tree, tvb, payload_start + 5, byte_cnt, "Data"); } else if (packet_type == RESPONSE_PACKET) { proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE); } break; case WRITE_MULT_REGS: if (packet_type == QUERY_PACKET) { proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE); byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 4); proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 4, 1, byte_cnt); proto_tree_add_text(modbus_tree, tvb, payload_start + 5, byte_cnt, "Data"); } else if (packet_type == RESPONSE_PACKET) { proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE); } break; case READ_GENL_REF: if (packet_type == QUERY_PACKET) { byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start); proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt); /* add subtrees to describe each group of packet */ group_offset = payload_start + 1; for (i = 0; i < byte_cnt / 7; i++) { mi = proto_tree_add_text( modbus_tree, tvb, group_offset, 7, "Group %u", i); group_tree = proto_item_add_subtree(mi, ett_group_hdr); proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset, 1, FALSE); proto_tree_add_item(group_tree, hf_modbus_lreference, tvb, group_offset + 1, 4, FALSE); proto_tree_add_item(group_tree, hf_modbus_wordcnt, tvb, group_offset + 5, 2, FALSE); group_offset += 7; } } else if (packet_type == RESPONSE_PACKET) { byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start); proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt); /* add subtrees to describe each group of packet */ group_offset = payload_start + 1; i = 0; while (byte_cnt > 0) { group_byte_cnt = (guint32)tvb_get_guint8(tvb, group_offset); mi = proto_tree_add_text( modbus_tree, tvb, group_offset, group_byte_cnt + 1, "Group %u", i); group_tree = proto_item_add_subtree(mi, ett_group_hdr); proto_tree_add_uint(group_tree, hf_modbus_bytecnt, tvb, group_offset, 1, group_byte_cnt); proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset + 1, 1, FALSE); proto_tree_add_text(group_tree, tvb, group_offset + 2, group_byte_cnt - 1, "Data"); group_offset += (group_byte_cnt + 1); byte_cnt -= (group_byte_cnt + 1); i++; } } break; case WRITE_GENL_REF: if ((packet_type == QUERY_PACKET) || (packet_type == RESPONSE_PACKET)) { byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start); proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt); /* add subtrees to describe each group of packet */ group_offset = payload_start + 1; i = 0; while (byte_cnt > 0) { group_word_cnt = tvb_get_ntohs(tvb, group_offset + 5); group_byte_cnt = (2 * group_word_cnt) + 7; mi = proto_tree_add_text( modbus_tree, tvb, group_offset, group_byte_cnt, "Group %u", i); group_tree = proto_item_add_subtree(mi, ett_group_hdr); proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset, 1, FALSE); proto_tree_add_item(group_tree, hf_modbus_lreference, tvb, group_offset + 1, 4, FALSE); proto_tree_add_uint(group_tree, hf_modbus_wordcnt, tvb, group_offset + 5, 2, group_word_cnt); proto_tree_add_text(group_tree, tvb, group_offset + 7, group_byte_cnt - 7, "Data"); group_offset += group_byte_cnt; byte_cnt -= group_byte_cnt; i++; } } break; case MASK_WRITE_REG: if ((packet_type == QUERY_PACKET) || (packet_type == RESPONSE_PACKET)) { proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); proto_tree_add_item(modbus_tree, hf_modbus_andmask, tvb, payload_start + 2, 2, FALSE); proto_tree_add_item(modbus_tree, hf_modbus_ormask, tvb, payload_start + 4, 2, FALSE); } break; case READ_WRITE_REG: if (packet_type == QUERY_PACKET) { proto_tree_add_item(modbus_tree, hf_modbus_readref, tvb, payload_start, 2, FALSE); proto_tree_add_item(modbus_tree, hf_modbus_readwordcnt, tvb, payload_start + 2, 2, FALSE); proto_tree_add_item(modbus_tree, hf_modbus_writeref, tvb, payload_start + 4, 2, FALSE); proto_tree_add_item(modbus_tree, hf_modbus_writewordcnt, tvb, payload_start + 6, 2, FALSE); byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 8); proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 8, 1, byte_cnt); proto_tree_add_text(modbus_tree, tvb, payload_start + 9, byte_cnt, "Data"); } else if (packet_type == RESPONSE_PACKET) { byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start); proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt); proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data"); } break; case READ_FIFO_QUEUE: if (packet_type == QUERY_PACKET) proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE); else if (packet_type == RESPONSE_PACKET) { byte_cnt = (guint32)tvb_get_ntohs(tvb, payload_start); proto_tree_add_uint(modbus_tree, hf_modbus_lbytecnt, tvb, payload_start, 2, byte_cnt); proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE); proto_tree_add_text(modbus_tree, tvb, payload_start + 4, byte_cnt - 2, "Data"); } break; case DIAGNOSTICS: case PROGRAM_484: case POLL_484: case GET_COMM_EVENT_CTRS: case GET_COMM_EVENT_LOG: case PROGRAM_584_984: case POLL_584_984: case REPORT_SLAVE_ID: case PROGRAM_884_U84: case RESET_COMM_LINK: case PROGRAM_CONCEPT: case FIRMWARE_REPLACE: case PROGRAM_584_984_2: case REPORT_LOCAL_ADDR_MB: /* these function codes are not part of the Modbus/TCP specification */ default: if (payload_len > 0) proto_tree_add_text(modbus_tree, tvb, payload_start, payload_len, "Data"); break; } } } /* move onto next packet (if there) */ offset += packet_len; packet_num++; if (tvb_reported_length_remaining(tvb, offset) > 0) { /* load header structure for next packet */ mh.transaction_id = tvb_get_ntohs(tvb, offset+0); mh.protocol_id = tvb_get_ntohs(tvb, offset+2); mh.len = tvb_get_ntohs(tvb, offset+4); mh.mdbs_hdr.unit_id = tvb_get_guint8(tvb, offset+6); mh.mdbs_hdr.function_code = tvb_get_guint8(tvb, offset+7); if ( mh.mdbs_hdr.function_code & 0x80 ) { exception_code = tvb_get_guint8(tvb, offset + sizeof(mbtcp_hdr)); mh.mdbs_hdr.function_code ^= 0x80; exception_returned = TRUE; } else exception_returned = FALSE; } else break; } return tvb_length(tvb); }
{ CONFIRM_STATUS_SERVER_ERROR, "Server couldn't start confirmation process" }, { 0, NULL } }; /* Initialize the protocol and registered fields */ static int proto_aim_admin = -1; static int hf_admin_acctinfo_code = -1; static int hf_admin_acctinfo_permissions = -1; static int hf_admin_confirm_status = -1; /* Initialize the subtree pointers */ static gint ett_aim_admin = -1; static int dissect_aim_admin_accnt_info_req(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *admin_tree) { proto_tree_add_item(admin_tree, hf_admin_acctinfo_code, tvb, 0, 2, tvb_get_ntohs(tvb, 0)); proto_tree_add_text(admin_tree, tvb, 2, 2, "Unknown"); return 4; } static int dissect_aim_admin_accnt_info_repl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *admin_tree) { int offset = 0; proto_tree_add_uint(admin_tree, hf_admin_acctinfo_permissions, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2; return dissect_aim_tlv_list(tvb, pinfo, offset, admin_tree, client_tlvs); } static int dissect_aim_admin_info_change_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *admin_tree) { return dissect_aim_tlv_sequence(tvb, pinfo, 0, admin_tree, client_tlvs); }
ti = proto_tree_add_item(tree, proto_hsr, tvb, 0, HSR_TOTAL_LENGTH, ENC_NA); hsr_tree = proto_item_add_subtree(ti, ett_hsr_frame); proto_tree_add_item(hsr_tree, hf_hsr_path, tvb, HSR_PATH_OFFSET, HSR_LSDU_PATH_LENGTH , ENC_BIG_ENDIAN); proto_tree_add_item(hsr_tree, hf_hsr_netid, tvb, HSR_PATH_OFFSET, HSR_LSDU_PATH_LENGTH , ENC_BIG_ENDIAN); proto_tree_add_item(hsr_tree, hf_hsr_laneid, tvb, HSR_PATH_OFFSET, HSR_LSDU_PATH_LENGTH , ENC_BIG_ENDIAN); lsdu_size = tvb_get_ntohs(tvb, HSR_PATH_OFFSET) & 0x0fff; lsdu_size_correct = tvb_reported_length_remaining(tvb, 0); if (lsdu_size == lsdu_size_correct) { proto_tree_add_uint_format_value(hsr_tree, hf_hsr_lsdu_size, tvb, HSR_PATH_OFFSET, HSR_LSDU_PATH_LENGTH, lsdu_size, "%d [correct]", lsdu_size); } else { proto_tree_add_uint_format_value(hsr_tree, hf_hsr_lsdu_size, tvb, HSR_PATH_OFFSET, HSR_LSDU_PATH_LENGTH, lsdu_size, "%d [WRONG, should be %d]", lsdu_size, lsdu_size_correct); } proto_tree_add_item(hsr_tree, hf_hsr_sequence_nr, tvb, HSR_SEQUENZNR_OFFSET,HSR_SEQUENZNR_LENGTH, ENC_BIG_ENDIAN); proto_tree_add_item(hsr_tree, hf_type,
static gint dissect_userdata(proto_item *ti_arg, gint ett_arg, tvbuff_t *tvb, gint arg_offset) { gint offset = arg_offset; guint8 flen, lenbytes; guint8 year, month, day, hour, min, sec; guint16 msec; proto_tree *tree; proto_item *ti; tree = proto_item_add_subtree(ti_arg, ett_arg); /* length of User Data, should be 1 byte field ... */ flen = tvb_get_guint8(tvb, offset); lenbytes = 1; /* ... but sometimes it seems to be 2 bytes; try to be clever */ if (flen == 0) { flen = tvb_get_guint8(tvb, offset+1); lenbytes = 2; } if (flen == 0 || flen > 79) /* invalid */ return offset; ti = proto_tree_add_item(tree, hf_elcom_userdata_length, tvb, offset, lenbytes, ENC_BIG_ENDIAN); offset += lenbytes; if (lenbytes == 2) { proto_item_append_text(ti, " (2 bytes, should be 1 byte)"); } if (tvb_length_remaining(tvb, offset) <= 0) return offset; proto_tree_add_item(tree, hf_elcom_userdata_pduid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; if (tvb_length_remaining(tvb, offset) <= 0) return offset; proto_tree_add_item(tree, hf_elcom_userdata_version, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; if (tvb_length_remaining(tvb, offset) <= 0) return offset; proto_tree_add_item(tree, hf_elcom_userdata_result, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* show the rest */ /* tree2 = proto_tree_add_text(tree, tvb, offset, -1, "User Data"); */ if (tvb_length_remaining(tvb, offset) <= 0) return offset; ti = proto_tree_add_item(tree, hf_elcom_userdata_restmark, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(ti, " <-- '0' = no restart etc."); offset +=1; if (tvb_length_remaining(tvb, offset+8) <= 0) return offset; year = tvb_get_guint8(tvb, offset); month = tvb_get_guint8(tvb, offset+1); day = tvb_get_guint8(tvb, offset+2); hour = tvb_get_guint8(tvb, offset+3); min = tvb_get_guint8(tvb, offset+4); sec = tvb_get_guint8(tvb, offset+5); msec = tvb_get_ntohs(tvb, offset+6); proto_tree_add_none_format(tree, hf_elcom_userdata_cf, tvb, offset, 8, "Control Field: %4d-%02d-%02d %02d:%02d:%02d.%d", year+1900, month, day, hour, min, sec, msec); offset += 12; if (tvb_length_remaining(tvb, offset+12) > 0) { proto_item_append_text(ti, " Security info: "); } /* security info field, if present */ while (tvb_length_remaining(tvb, offset) > 0) { proto_item_append_text(ti, elcom_show_hex ? " %02x" : " %03o", tvb_get_guint8(tvb, offset)); offset++; } return offset; }
static int dissect_headers(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo) { proto_tree *hdrs_tree = NULL; proto_tree *hdr_tree = NULL; proto_item *hdr = NULL; proto_item *handle_item; gint item_length = -1; guint8 hdr_id, i; if (tvb_length_remaining(tvb, offset) > 0) { proto_item *hdrs; hdrs = proto_tree_add_text(tree, tvb, offset, item_length, "Headers"); hdrs_tree = proto_item_add_subtree(hdrs, ett_btobex_hdrs); } else { return offset; } while (tvb_length_remaining(tvb, offset) > 0) { hdr_id = tvb_get_guint8(tvb, offset); switch(0xC0 & hdr_id) { case 0x00: /* null terminated unicode */ item_length = tvb_get_ntohs(tvb, offset+1); break; case 0x40: /* byte sequence */ item_length = tvb_get_ntohs(tvb, offset+1); break; case 0x80: /* 1 byte */ item_length = 2; break; case 0xc0: /* 4 bytes */ item_length = 5; break; } hdr = proto_tree_add_text(hdrs_tree, tvb, offset, item_length, "%s", val_to_str_ext_const(hdr_id, &header_id_vals_ext, "Unknown")); hdr_tree = proto_item_add_subtree(hdr, ett_btobex_hdr); proto_tree_add_item(hdr_tree, hf_hdr_id, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; switch(0xC0 & hdr_id) { case 0x00: /* null terminated unicode */ { proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if ((item_length - 3) > 0) { char *str; display_unicode_string(tvb, hdr_tree, offset, &str); proto_item_append_text(hdr_tree, " (\"%s\")", str); col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", str); } else { col_append_str(pinfo->cinfo, COL_INFO, " \"\""); } offset += item_length - 3; } break; case 0x40: /* byte sequence */ proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; handle_item = proto_tree_add_item(hdr_tree, hf_hdr_val_byte_seq, tvb, offset, item_length - 3, ENC_NA); if (((hdr_id == 0x46) || (hdr_id == 0x4a)) && (item_length == 19)) { /* target or who */ for(i=0; target_vals[i].strptr != NULL; i++) { if (tvb_memeql(tvb, offset, target_vals[i].value, 16) == 0) { proto_item_append_text(handle_item, ": %s", target_vals[i].strptr); proto_item_append_text(hdr_tree, " (%s)", target_vals[i].strptr); col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", target_vals[i].strptr); } } } if (!tvb_strneql(tvb, offset, "<?xml", 5)) { tvbuff_t* next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(xml_handle, next_tvb, pinfo, tree); } else if (is_ascii_str(tvb_get_ptr(tvb, offset,item_length - 3), item_length - 3)) { proto_item_append_text(hdr_tree, " (\"%s\")", tvb_get_ephemeral_string(tvb, offset,item_length - 3)); col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", tvb_get_ephemeral_string(tvb, offset,item_length - 3)); } offset += item_length - 3; break; case 0x80: /* 1 byte */ proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset)); proto_tree_add_item(hdr_tree, hf_hdr_val_byte, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; break; case 0xc0: /* 4 bytes */ proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset)); proto_tree_add_item(hdr_tree, hf_hdr_val_long, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; default: break; } } return offset; }
/* This routine attempts to locate the position of the next header in the * provided segment */ static guint get_next_fcip_header_offset (tvbuff_t *tvb, packet_info *pinfo, gint offset) { gint bytes_remaining = tvb_length_remaining (tvb, offset); gint frame_len; guint16 flen, flen1; fcip_eof_t eof, eofc; /* * As per the FCIP standard, the following tests must PASS: * 1) Frame Length field validation -- 15 < Frame Length < 545; * 2) Comparison of Frame Length field to its ones complement; and * 3) A valid EOF is found in the word preceding the start of the next * FCIP header as indicated by the Frame Length field, to be tested * as follows: * 1) Bits 24-31 and 16-23 contain identical legal EOF values (the * list of legal EOF values is in the FC Frame Encapsulation * [21]); and * 2) Bits 8-15 and 0-7 contain the ones complement of the EOF * value found in bits 24-31. * * As per the FCIP standard, in addition, at least 3 of the following set * of tests must be performed to identify that we've located the start of * an FCIP frame. * a) Protocol# ones complement field (1 test); * b) Version ones complement field (1 test); * c) Replication of encapsulation word 0 in word 1 (1 test); * d) Reserved field and its ones complement (2 tests); * e) Flags field and its ones complement (2 tests); * f) CRC field is equal to zero (1 test); (DONT DO THIS TEST!) * g) SOF fields and ones complement fields (4 tests); * h) Format and values of FC header (1 test); * i) CRC of FC Frame (2 tests); * j) FC Frame Encapsulation header information in the next FCIP Frame * (1 test). * * At least 3 of the 16 tests listed above SHALL be performed. Failure * of any of the above tests actually performed SHALL indicate an * encapsulation error and the FC Frame SHALL NOT be forwarded on to * the FC Entity. */ NXT_BYTE: while (bytes_remaining) { if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) { if(fcip_desegment && pinfo->can_desegment) { /* * This frame doesn't have all of the data for * the message header, but we can do reassembly on it. * * Tell the TCP dissector where the data for this * message starts in the data it handed us, and that we need * "some more data." Don't tell it exactly how many bytes * we need because if/when we ask for even more (after the * header) that will break reassembly. */ pinfo->desegment_offset = offset; pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; return -2; } } /* I check that we have a valid header before checking for the frame * length and the other initial tests. */ /* * Tests a, b and c */ if (tvb_memeql(tvb, offset, fcip_header_8_bytes, 8) != 0) { offset++; bytes_remaining--; goto NXT_BYTE; } flen = (tvb_get_ntohs (tvb, offset+12)) & 0x03FF; frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4; if ((flen < 15) || (flen > 545)) { /* Frame length check failed. Skip byte and try again */ offset++; bytes_remaining--; goto NXT_BYTE; } flen1 = (tvb_get_ntohs (tvb, offset+14)) & 0x03FF; if ((flen & 0x03FF) != ((~flen1)&0x03FF)) { /* frame_len and its one's complement are not the same */ offset++; bytes_remaining--; goto NXT_BYTE; } /* Valid EOF check */ if (tvb_bytes_exist (tvb, offset+(frame_len-1)*4, 4)) { eof = (fcip_eof_t)tvb_get_guint8 (tvb, offset+(frame_len-1)*4); eofc = (fcip_eof_t)tvb_get_guint8 (tvb, offset+(frame_len-1)*4+2); if ((eof != FCIP_EOFn) && (eof != FCIP_EOFt) && (eof != FCIP_EOFrt) && (eof != FCIP_EOFdt) && (eof != FCIP_EOFni) && (eof != FCIP_EOFdti) && (eof != FCIP_EOFrti) && (eof != FCIP_EOFa)) { offset++; bytes_remaining--; goto NXT_BYTE; } if ((eof != ~eofc) || (eof != tvb_get_guint8 (tvb, offset+(frame_len-1)*4+1)) || (eofc != tvb_get_guint8 (tvb, offset+(frame_len-1)*4+3))) { offset++; bytes_remaining--; goto NXT_BYTE; } } /* Test d */ if ((tvb_get_guint8 (tvb, offset+9) != 0) || (tvb_get_guint8 (tvb, offset+11) != 0xFF)) { /* Failed */ offset++; bytes_remaining--; goto NXT_BYTE; } /* Test e */ /* Test f * We dont test this since some implementations actually provide * a CRC here. */ if (bytes_remaining >= (frame_len)) { if (tvb_bytes_exist (tvb, offset+frame_len, 8)) { /* The start of the next header matches what we wish to see */ if (tvb_memeql (tvb, offset+frame_len, fcip_header_8_bytes, 8) == 0) { return (offset); } else { offset++; bytes_remaining--; goto NXT_BYTE; } } else { return (offset); } } else { if(fcip_desegment && pinfo->can_desegment) { /* * This frame doesn't have all of the data for * this message, but we can do reassembly on it. * * Tell the TCP dissector where the data for this * message starts in the data it handed us, and * how many more bytes we need, and return. */ pinfo->desegment_offset = offset; pinfo->desegment_len = frame_len - bytes_remaining; return -2; } else { return (offset); } } } return (-1); /* Unable to find FCIP header */ }
static void dissect_btobex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *st; fragment_data *frag_msg = NULL; gboolean save_fragmented, complete; tvbuff_t* new_tvb = NULL; tvbuff_t* next_tvb = NULL; guint32 no_of_segments = 0; int offset = 0; save_fragmented = pinfo->fragmented; frag_msg = NULL; complete = FALSE; if (fragment_get(pinfo, pinfo->p2p_dir, fragment_table)) { /* not the first fragment */ frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir, fragment_table, reassembled_table, tvb_length(tvb), TRUE); new_tvb = process_reassembled_data(tvb, 0, pinfo, "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree); pinfo->fragmented = TRUE; } else { if (tvb_length(tvb) < tvb_get_ntohs(tvb, offset+1)) { /* first fragment in a sequence */ no_of_segments = tvb_get_ntohs(tvb, offset+1)/tvb_length(tvb); if (tvb_get_ntohs(tvb, offset+1) > (no_of_segments * tvb_length(tvb))) no_of_segments++; frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir, fragment_table, reassembled_table, tvb_length(tvb), TRUE); fragment_set_tot_len(pinfo, pinfo->p2p_dir, fragment_table, no_of_segments-1); new_tvb = process_reassembled_data(tvb, 0, pinfo, "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree); pinfo->fragmented = TRUE; } else if (tvb_length(tvb) == tvb_get_ntohs(tvb, offset+1)) { /* non-fragmented */ complete = TRUE; pinfo->fragmented = FALSE; } } if (new_tvb) { /* take it all */ next_tvb = new_tvb; complete = TRUE; } else { /* make a new subset */ next_tvb = tvb_new_subset_remaining(tvb, offset); } if (complete) { guint8 code, final_flag; /* fully dissectable packet ready */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "OBEX"); ti = proto_tree_add_item(tree, proto_btobex, next_tvb, 0, -1, ENC_NA); st = proto_item_add_subtree(ti, ett_btobex); /* op/response code */ code = tvb_get_guint8(next_tvb, offset) & BTOBEX_CODE_VALS_MASK; final_flag = tvb_get_guint8(next_tvb, offset) & 0x80; switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_add_fstr(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_add_fstr(pinfo->cinfo, COL_INFO, "Rcvd "); break; case P2P_DIR_UNKNOWN: break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ", pinfo->p2p_dir); break; } col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext_const(code, &code_vals_ext, "Unknown")); if ((code < BTOBEX_CODE_VALS_CONTINUE) || (code == BTOBEX_CODE_VALS_ABORT)) { proto_tree_add_item(st, hf_opcode, next_tvb, offset, 1, ENC_BIG_ENDIAN); if (pinfo->p2p_dir == P2P_DIR_SENT || pinfo->p2p_dir == P2P_DIR_RECV) { last_opcode[pinfo->p2p_dir] = code; } } else { proto_tree_add_item(st, hf_response_code, next_tvb, offset, 1, ENC_BIG_ENDIAN); } proto_tree_add_item(st, hf_final_flag, next_tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* length */ proto_tree_add_item(st, hf_length, next_tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; switch(code) { case BTOBEX_CODE_VALS_CONNECT: proto_tree_add_item(st, hf_version, next_tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; case BTOBEX_CODE_VALS_PUT: case BTOBEX_CODE_VALS_GET: col_append_fstr(pinfo->cinfo, COL_INFO, " %s", (final_flag == 0x80) ? "final" : "continue"); break; case BTOBEX_CODE_VALS_SET_PATH: proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(st, hf_set_path_flags_0, next_tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(st, hf_set_path_flags_1, next_tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(st, hf_constants, next_tvb, offset, 1, ENC_BIG_ENDIAN); offset++; break; case BTOBEX_CODE_VALS_DISCONNECT: case BTOBEX_CODE_VALS_ABORT: break; default: { guint8 response_opcode = last_opcode[(pinfo->p2p_dir + 1) & 0x01]; if (response_opcode == BTOBEX_CODE_VALS_CONNECT) { proto_tree_add_item(st, hf_version, next_tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } } break; } dissect_headers(st, next_tvb, offset, pinfo); } else { /* packet fragment */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Obex fragment", (pinfo->p2p_dir==P2P_DIR_SENT) ? "Sent" : "Rcvd"); call_dissector(data_handle, next_tvb, pinfo, tree); } pinfo->fragmented = save_fragmented; }
{ 0x01, "CDCP" }, { 0x02, "VDP" }, { 0, NULL } }; /* Dissect Unknown TLV */ static gint32 dissect_ecp_unknown_tlv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset) { guint16 tempLen; guint16 tempShort; proto_tree *ecp_unknown_tlv_tree; /* Get tlv type and length */ tempShort = tvb_get_ntohs(tvb, offset); /* Get tlv length */ tempLen = TLV_INFO_LEN(tempShort); ecp_unknown_tlv_tree = proto_tree_add_subtree(tree, tvb, offset, (tempLen + 2), ett_ecp, NULL, "Unknown TLV"); proto_tree_add_item(ecp_unknown_tlv_tree, hf_ecp_subtype, tvb, offset, 2, ENC_BIG_ENDIAN); return -1; } /* Dissect mac/vid pairs in VDP TLVs */ static gint32 dissect_vdp_fi_macvid(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset) {
static gboolean dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree, proto_tree *param_tree, packet_info *pinfo, guint8 param_type, guint16 param_len, struct SESSION_DATA_STRUCTURE *session) { gboolean has_user_information = TRUE; guint16 flags; proto_item *tf; proto_tree *flags_tree; asn1_ctx_t asn1_ctx; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); switch (param_type) { case Called_SS_user_Reference: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_called_ss_user_reference, tvb, offset, param_len, FALSE); } break; case Calling_SS_user_Reference: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_calling_ss_user_reference, tvb, offset, param_len, FALSE); } break; case Common_Reference: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_common_reference, tvb, offset, param_len, FALSE); } break; case Additional_Reference_Information: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_additional_reference_information, tvb, offset, param_len, FALSE); } break; case Token_Item: if (param_len != 1) { proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); break; } if (tree) { flags = tvb_get_guint8(tvb, offset); tf = proto_tree_add_uint(param_tree, hf_token_item_options_flags, tvb, offset, 1, flags); flags_tree = proto_item_add_subtree(tf, ett_token_item_flags); proto_tree_add_boolean(flags_tree, hf_release_token, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_major_activity_token, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_synchronize_minor_token, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_data_token, tvb, offset, 1, flags); } break; case Transport_Disconnect: if (param_len != 1) { proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); break; } if (tree) { guint8 flags8; flags8 = tvb_get_guint8(tvb, offset); if(flags8 & transport_connection_is_released ) { proto_tree_add_text(param_tree, tvb, offset, 1, "transport connection is released"); } else { proto_tree_add_text(param_tree, tvb, offset, 1, "transport connection is kept"); } if(flags8 & user_abort ) { proto_tree_add_text(param_tree, tvb, offset, 1, "user abort"); session->abort_type = SESSION_USER_ABORT; } else { session->abort_type = SESSION_PROVIDER_ABORT; } if(flags8 & protocol_error ) { proto_tree_add_text(param_tree, tvb, offset, 1, "protocol error"); } if(flags8 & no_reason ) { proto_tree_add_text(param_tree, tvb, offset, 1, "no reason"); } if(flags8 & implementation_restriction ) { proto_tree_add_text(param_tree, tvb, offset, 1, "implementation restriction"); } } break; case Protocol_Options: if (param_len != 1) { proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); break; } if (tree) { flags = tvb_get_guint8(tvb, offset); tf = proto_tree_add_uint(param_tree, hf_connect_protocol_options_flags, tvb, offset, 1, flags); flags_tree = proto_item_add_subtree(tf, ett_connect_protocol_options_flags); proto_tree_add_boolean(flags_tree, hf_able_to_receive_extended_concatenated_SPDU, tvb, offset, 1, flags); } break; case Session_Requirement: if (param_len != 2) { proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 2", param_len); break; } if (tree) { flags = tvb_get_ntohs(tvb, offset); tf = proto_tree_add_uint(param_tree, hf_session_user_req_flags, tvb, offset, 2, flags); flags_tree = proto_item_add_subtree(tf, ett_ses_req_options_flags); proto_tree_add_boolean(flags_tree, hf_session_exception_report, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_data_separation_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_symmetric_synchronize_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_typed_data_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_exception_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_capability_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_negotiated_release_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_activity_management_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_resynchronize_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_major_resynchronize_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_minor_resynchronize_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_expedited_data_resynchronize_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_duplex_function_unit, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_half_duplex_function_unit, tvb, offset, 2, flags); } break; case TSDU_Maximum_Size: if (param_len != 4) { proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 4", param_len); break; } if (tree) { proto_tree_add_item(param_tree, hf_proposed_tsdu_maximum_size_i2r, tvb, offset, 2, FALSE); proto_tree_add_item(param_tree, hf_proposed_tsdu_maximum_size_r2i, tvb, offset+2, 2, FALSE); } break; case Version_Number: if (param_len != 1) { proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); break; } if (tree) { flags = tvb_get_guint8(tvb, offset); tf = proto_tree_add_uint(param_tree, hf_version_number_options_flags, tvb, offset, 1, flags); flags_tree = proto_item_add_subtree(tf, ett_protocol_version_flags); proto_tree_add_boolean(flags_tree, hf_protocol_version_2, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_protocol_version_1, tvb, offset, 1, flags); } break; case Initial_Serial_Number: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_initial_serial_number, tvb, offset, param_len, FALSE); } break; case EnclosureItem: if (param_len != 1) { proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); break; } flags = tvb_get_guint8(tvb, offset); if (tree) { tf = proto_tree_add_uint(param_tree, hf_enclosure_item_options_flags, tvb, offset, 1, flags); flags_tree = proto_item_add_subtree(tf, ett_enclosure_item_flags); proto_tree_add_boolean(flags_tree, hf_end_of_SSDU, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_beginning_of_SSDU, tvb, offset, 1, flags); } if (flags & END_SPDU) { /* * In Data Transfer and Typed Data SPDUs, (X.225: 8.3.{11,13}.4) * "The User Information Field shall be present * if the Enclosure Item is not present, or has * bit 2 = 0", which presumably means it shall * *not* be present if the Enclosure item *is* * present and has bit 2 = 1. */ if(!(flags & BEGINNING_SPDU)) { /* X.225 7.11.2 also states: * "All DATA TRANSFER SPDUs, except the last DATA TRANSFER SPDU in a sequence greater than one, must have user information" * So if BEGINNING_SPDU and END_SPDU are set in the enclosure item, then this is presumably a sequence of one and * consequently there must be user information. * * So, there is only no user information if *only* END_SPDU is set. */ has_user_information = FALSE; } } break; case Token_Setting_Item: if (param_len != 1) { proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be 1", param_len); break; } if (tree) { proto_tree_add_item(param_tree, hf_release_token_setting, tvb, offset, 1, FALSE); proto_tree_add_item(param_tree, hf_major_activity_token_setting, tvb, offset, 1, FALSE); proto_tree_add_item(param_tree, hf_synchronize_minor_token_setting, tvb, offset, 1, FALSE); proto_tree_add_item(param_tree, hf_data_token_setting, tvb, offset, 1, FALSE); } break; case Activity_Identifier: if (param_len == 0) break; if (tree) { dissect_ber_integer(FALSE, &asn1_ctx, param_tree, tvb, offset, hf_activity_identifier, NULL); } break; case Serial_Number: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_serial_number, tvb, offset, param_len, FALSE); } break; case Reason_Code: /* 0: Rejection by called SS-user; reason not specified. 1: Rejection by called SS-user due to temporary congestion. 2: Rejection by called SS-user. Subsequent octets may be used for user data up to a length of 512 octets if Protocol Version 1 has been selected, and up to a length such that the total length (including SI and LI) of the SPDU does not exceed 65 539 octets if Protocol Version 2 has been selected. 128 + 1: Session Selector unknown. 128 + 2: SS-user not attached to SSAP. 128 + 3: SPM congestion at connect time. 128 + 4: Proposed protocol versions not supported. 128 + 5: Rejection by the SPM; reason not specified. 128 + 6: Rejection by the SPM; implementation restriction stated in the PICS. */ if (param_len < 1) { proto_tree_add_text(param_tree, tvb, offset, param_len, "Length is %u, should be >= 1", param_len); break; } if (tree) { guint8 reason_code; reason_code = tvb_get_guint8(tvb, offset); proto_tree_add_text(param_tree, tvb, offset, 1, "Reason Code: %s", val_to_str(reason_code, reason_vals, "Unknown (%u)")); } offset++; param_len--; if (param_len != 0) { call_pres_dissector(tvb, offset, param_len, pinfo, tree, param_tree, session); } break; case Calling_Session_Selector: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_calling_session_selector, tvb, offset, param_len, FALSE); } break; case Called_Session_Selector: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_called_session_selector, tvb, offset, param_len, FALSE); } break; case Second_Serial_Number: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_second_serial_number, tvb, offset, param_len, FALSE); } break; case Second_Initial_Serial_Number: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_second_initial_serial_number, tvb, offset, param_len, FALSE); } break; case Large_Initial_Serial_Number: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_large_initial_serial_number, tvb, offset, param_len, FALSE); } break; case Large_Second_Initial_Serial_Number: if (param_len == 0) break; if (tree) { proto_tree_add_item(param_tree, hf_large_second_initial_serial_number, tvb, offset, param_len, FALSE); } break; default: break; } return has_user_information; }