/* Code to actually dissect the packets */ static void dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { char *szInfo; int offCur = 0; /* current offset from start of WTP data */ gint returned_length, str_index = 0; unsigned char b0; /* continuation flag */ unsigned char fCon; /* Continue flag */ unsigned char fRID; /* Re-transmission indicator*/ unsigned char fTTR = '\0'; /* Transmission trailer */ guint cbHeader = 0; /* Fixed header length */ guint vHeader = 0; /* Variable header length*/ int abortType = 0; /* Set up structures we'll need to add the protocol subtree and manage it */ proto_item *ti = NULL; proto_tree *wtp_tree = NULL; char pdut; char clsTransaction = 3; int numMissing = 0; /* Number of missing packets in a negative ack */ int i; tvbuff_t *wsp_tvb = NULL; guint8 psn = 0; /* Packet sequence number*/ guint16 TID = 0; /* Transaction-Id */ int dataOffset; gint dataLen; #define SZINFO_SIZE 256 szInfo=(char *)wmem_alloc(wmem_packet_scope(), SZINFO_SIZE); b0 = tvb_get_guint8 (tvb, offCur + 0); /* Discover Concatenated PDUs */ if (b0 == 0) { guint c_fieldlen = 0; /* Length of length-field */ guint c_pdulen = 0; /* Length of conc. PDU */ if (tree) { ti = proto_tree_add_item(tree, proto_wtp, tvb, offCur, 1, ENC_NA); wtp_tree = proto_item_add_subtree(ti, ett_wtp_sub_pdu_tree); proto_item_append_text(ti, ", PDU concatenation"); } offCur = 1; i = 1; while (offCur < (int) tvb_reported_length(tvb)) { tvbuff_t *wtp_tvb; /* The length of an embedded WTP PDU is coded as either: * - a 7-bit value contained in one octet with highest bit == 0. * - a 15-bit value contained in two octets (little endian) * if the 1st octet has its highest bit == 1. * This means that this is NOT encoded as an uintvar-integer!!! */ b0 = tvb_get_guint8(tvb, offCur + 0); if (b0 & 0x80) { c_fieldlen = 2; c_pdulen = ((b0 & 0x7f) << 8) | tvb_get_guint8(tvb, offCur + 1); } else { c_fieldlen = 1; c_pdulen = b0; } if (tree) { proto_tree_add_uint(wtp_tree, hf_wtp_header_sub_pdu_size, tvb, offCur, c_fieldlen, c_pdulen); } if (i > 1) { col_append_str(pinfo->cinfo, COL_INFO, ", "); } /* Skip the length field for the WTP sub-tvb */ wtp_tvb = tvb_new_subset_length(tvb, offCur + c_fieldlen, c_pdulen); dissect_wtp_common(wtp_tvb, pinfo, wtp_tree); offCur += c_fieldlen + c_pdulen; i++; } if (tree) { proto_item_append_text(ti, ", PDU count: %u", i); } return; } /* No concatenation */ fCon = b0 & 0x80; fRID = retransmission_indicator(b0); pdut = pdu_type(b0); #ifdef DEBUG printf("WTP packet %u: tree = %p, pdu = %s (%u) length: %u\n", pinfo->fd->num, tree, val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x"), pdut, tvb_length(tvb)); #endif /* Develop the string to put in the Info column */ returned_length = g_snprintf(szInfo, SZINFO_SIZE, "WTP %s", val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x")); str_index += MIN(returned_length, SZINFO_SIZE-str_index); switch (pdut) { case INVOKE: fTTR = transmission_trailer(b0); TID = tvb_get_ntohs(tvb, offCur + 1); psn = 0; clsTransaction = transaction_class(tvb_get_guint8(tvb, offCur + 3)); returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index, " Class %d", clsTransaction); str_index += MIN(returned_length, SZINFO_SIZE-str_index); cbHeader = 4; break; case SEGMENTED_INVOKE: case SEGMENTED_RESULT: fTTR = transmission_trailer(b0); TID = tvb_get_ntohs(tvb, offCur + 1); psn = tvb_get_guint8(tvb, offCur + 3); if (psn != 0) { returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index, " (%u)", psn); str_index += MIN(returned_length, SZINFO_SIZE-str_index); } cbHeader = 4; break; case ABORT: cbHeader = 4; break; case RESULT: fTTR = transmission_trailer(b0); TID = tvb_get_ntohs(tvb, offCur + 1); psn = 0; cbHeader = 3; break; case ACK: cbHeader = 3; break; case NEGATIVE_ACK: /* Variable number of missing packets */ numMissing = tvb_get_guint8(tvb, offCur + 3); cbHeader = numMissing + 4; break; default: break; }; if (fRID) { /*returned_length =*/ g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index, " R" ); /*str_index += MIN(returned_length, SZINFO_SIZE-str_index);*/ }; /* In the interest of speed, if "tree" is NULL, don't do any work not necessary to generate protocol tree items. */ if (tree) { #ifdef DEBUG fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader); #endif /* NOTE - Length will be set when we process the TPI */ ti = proto_tree_add_item(tree, proto_wtp, tvb, offCur, 0, ENC_NA); #ifdef DEBUG fprintf(stderr, "dissect_wtp: (7) Returned from proto_tree_add_item\n"); #endif wtp_tree = proto_item_add_subtree(ti, ett_wtp); /* Code to process the packet goes here */ #ifdef DEBUG fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader); fprintf(stderr, "dissect_wtp: offCur = %d\n", offCur); #endif /* Add common items: only CON and PDU Type */ proto_tree_add_item( wtp_tree, /* tree */ hf_wtp_header_flag_continue, /* id */ tvb, offCur, /* start of highlight */ 1, /* length of highlight*/ b0 /* value */ ); proto_tree_add_item(wtp_tree, hf_wtp_header_pdu_type, tvb, offCur, 1, ENC_LITTLE_ENDIAN); switch(pdut) { case INVOKE: proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_version , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_TIDNew, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_UP, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_Reserved, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_TransactionClass, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(ti, ", PDU: Invoke (%u)" ", Transaction Class: %s (%u)", INVOKE, val_to_str_const(clsTransaction, vals_transaction_classes, "Undefined"), clsTransaction); break; case RESULT: proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_item_append_text(ti, ", PDU: Result (%u)", RESULT); break; case ACK: proto_tree_add_item(wtp_tree, hf_wtp_header_Ack_flag_TVETOK, tvb, offCur, 1, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_item_append_text(ti, ", PDU: ACK (%u)", ACK); break; case ABORT: abortType = tvb_get_guint8 (tvb, offCur) & 0x07; proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_type , tvb, offCur , 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); if (abortType == PROVIDER) { guint8 reason = tvb_get_guint8(tvb, offCur + 3); proto_tree_add_item( wtp_tree, hf_wtp_header_Abort_reason_provider , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN); proto_item_append_text(ti, ", PDU: Abort (%u)" ", Type: Provider (%u)" ", Reason: %s (%u)", ABORT, PROVIDER, val_to_str_const(reason, vals_abort_reason_provider, "Undefined"), reason); } else if (abortType == USER) { guint8 reason = tvb_get_guint8(tvb, offCur + 3); proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_reason_user , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN); proto_item_append_text(ti, ", PDU: Abort (%u)" ", Type: User (%u)" ", Reason: %s (%u)", ABORT, PROVIDER, val_to_str_ext_const(reason, &vals_wsp_reason_codes_ext, "Undefined"), reason); } break; case SEGMENTED_INVOKE: proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(ti, ", PDU: Segmented Invoke (%u)" ", Packet Sequence Number: %u", SEGMENTED_INVOKE, psn); break; case SEGMENTED_RESULT: proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(ti, ", PDU: Segmented Result (%u)" ", Packet Sequence Number: %u", SEGMENTED_RESULT, psn); break; case NEGATIVE_ACK: proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wtp_tree, hf_wtp_header_missing_packets , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN); /* Iterate through missing packets */ for (i = 0; i < numMissing; i++) { proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number, tvb, offCur + 4 + i, 1, ENC_LITTLE_ENDIAN); } proto_item_append_text(ti, ", PDU: Negative Ack (%u)" ", Missing Packets: %u", NEGATIVE_ACK, numMissing); break; default: break; }; if (fRID) { proto_item_append_text(ti, ", Retransmission"); } } else { /* tree is NULL */ #ifdef DEBUG fprintf(stderr, "dissect_wtp: (4) tree was %p\n", tree); #endif } /* Process the variable part */ if (fCon) { /* Now, analyze variable part */ guint8 tCon; guint8 tByte; guint tpiLen; tvbuff_t *tmp_tvb; vHeader = 0; /* Start scan all over */ do { tByte = tvb_get_guint8(tvb, offCur + cbHeader + vHeader); tCon = tByte & 0x80; if (tByte & 0x04) /* Long TPI */ tpiLen = 2 + tvb_get_guint8(tvb, offCur + cbHeader + vHeader + 1); else tpiLen = 1 + (tByte & 0x03); if (tree) { tmp_tvb = tvb_new_subset_length(tvb, offCur + cbHeader + vHeader, tpiLen); wtp_handle_tpi(wtp_tree, tmp_tvb); } vHeader += tpiLen; } while (tCon); } else { /* There is no variable part */ } /* End of variable part of header */ /* Set the length of the WTP protocol part now we know the length of the * fixed and variable WTP headers */ if (tree) proto_item_set_len(ti, cbHeader + vHeader); #ifdef DEBUG fprintf( stderr, "dissect_wtp: cbHeader = %d\n", cbHeader ); #endif /* * Any remaining data ought to be WSP data (if not WTP ACK, NACK * or ABORT pdu), so, if we have any remaining data, and it's * not an ACK, NACK, or ABORT PDU, hand it off (defragmented) to the * WSP dissector. * Note that the last packet of a fragmented WTP message needn't * contain any data, so we allow payloadless packets to be * reassembled. (XXX - does the reassembly code handle this * for packets other than the last packet?) * * Try calling a subdissector only if: * - The WTP payload is ressembled in this very packet, * - The WTP payload is not fragmented across packets. */ dataOffset = offCur + cbHeader + vHeader; dataLen = tvb_reported_length_remaining(tvb, dataOffset); if ((dataLen >= 0) && ! ((pdut==ACK) || (pdut==NEGATIVE_ACK) || (pdut==ABORT))) { /* Try to reassemble if needed, and hand over to WSP * A fragmented WTP packet is either: * - An INVOKE with fTTR (transmission trailer) not set, * - a SEGMENTED_INVOKE, * - A RESULT with fTTR (transmission trailer) not set, * - a SEGMENTED_RESULT. */ if ( ( (pdut == SEGMENTED_INVOKE) || (pdut == SEGMENTED_RESULT) || ( ((pdut == INVOKE) || (pdut == RESULT)) && (!fTTR) ) ) && tvb_bytes_exist(tvb, dataOffset, dataLen) ) { /* Try reassembling fragments */ fragment_head *fd_wtp = NULL; guint32 reassembled_in = 0; gboolean save_fragmented = pinfo->fragmented; pinfo->fragmented = TRUE; fd_wtp = fragment_add_seq(&wtp_reassembly_table, tvb, dataOffset, pinfo, TID, NULL, psn, dataLen, !fTTR, 0); /* XXX - fragment_add_seq() yields NULL unless Wireshark knows * that the packet is part of a reassembled whole. This means * that fd_wtp will be NULL as long as Wireshark did not encounter * (and process) the packet containing the last fragment. * This implies that Wireshark needs two passes over the data for * correct reassembly. At the first pass, a capture containing * three fragments plus a retransmssion of the last fragment * will progressively show: * * Packet 1: (Unreassembled fragment 1) * Packet 2: (Unreassembled fragment 2) * Packet 3: (Reassembled WTP) * Packet 4: (WTP payload reassembled in packet 3) * * However at subsequent evaluation (e.g., by applying a display * filter) the packet summary will show: * * Packet 1: (WTP payload reassembled in packet 3) * Packet 2: (WTP payload reassembled in packet 3) * Packet 3: (Reassembled WTP) * Packet 4: (WTP payload reassembled in packet 3) * * This is important to know, and also affects read filters! */ wsp_tvb = process_reassembled_data(tvb, dataOffset, pinfo, "Reassembled WTP", fd_wtp, &wtp_frag_items, NULL, wtp_tree); #ifdef DEBUG printf("WTP: Packet %u %s -> %d: wsp_tvb = %p, fd_wtp = %p, frame = %u\n", pinfo->fd->num, fd_wtp ? "Reassembled" : "Not reassembled", fd_wtp ? fd_wtp->reassembled_in : -1, wsp_tvb, fd_wtp ); #endif if (fd_wtp) { /* Reassembled */ reassembled_in = fd_wtp->reassembled_in; if (pinfo->fd->num == reassembled_in) { /* Reassembled in this very packet: * We can safely hand the tvb to the WSP dissector */ call_dissector(wsp_handle, wsp_tvb, pinfo, tree); } else { /* Not reassembled in this packet */ col_append_fstr(pinfo->cinfo, COL_INFO, "%s (WTP payload reassembled in packet %u)", szInfo, fd_wtp->reassembled_in); proto_tree_add_text(wtp_tree, tvb, dataOffset, -1, "Payload"); } } else { /* Not reassembled yet, or not reassembled at all */ col_append_fstr(pinfo->cinfo, COL_INFO, "%s (Unreassembled fragment %u)", szInfo, psn); proto_tree_add_text(wtp_tree, tvb, dataOffset, -1, "Payload"); } /* Now reset fragmentation information in pinfo */ pinfo->fragmented = save_fragmented; } else if ( ((pdut == INVOKE) || (pdut == RESULT)) && (fTTR) ) { /* Non-fragmented payload */ wsp_tvb = tvb_new_subset_remaining(tvb, dataOffset); /* We can safely hand the tvb to the WSP dissector */ call_dissector(wsp_handle, wsp_tvb, pinfo, tree); } else { /* Nothing to hand to subdissector */ col_append_str(pinfo->cinfo, COL_INFO, szInfo); } } else { /* Nothing to hand to subdissector */ col_append_str(pinfo->cinfo, COL_INFO, szInfo); } }
static int dissect_dtpt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *dtpt_tree = NULL; proto_item *dtpt_item = NULL; guint8 version; guint8 message_type; guint32 flags; guint32 payload_size; version = tvb_get_guint8(tvb, 0); if (version != 1) return 0; message_type = tvb_get_guint8(tvb, 1); switch (message_type) { case LookupBeginRequest: case LookupBeginResponse: case LookupNextRequest: case LookupNextResponse: case LookupEndRequest: if (tvb_reported_length(tvb) != 20) return 0; break; case ConnectRequest: case ConnectResponseOK: case ConnectResponseERR: if (tvb_reported_length(tvb) != 36) return 0; break; default: return 0; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "DTPT"); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, val_to_str(message_type, names_message_type, "Unknown (%d)")); if (message_type == LookupBeginRequest) { conversation_t *c; c = find_or_create_conversation(pinfo); conversation_set_dissector(c, dtpt_conversation_handle); } if (tree) { dtpt_item = proto_tree_add_item(tree, proto_dtpt, tvb, 0, -1, ENC_NA); if (dtpt_item) dtpt_tree = proto_item_add_subtree(dtpt_item, ett_dtpt); } if (dtpt_tree) { proto_tree_add_uint(dtpt_tree, hf_dtpt_version, tvb, 0, 1, version); proto_tree_add_uint(dtpt_tree, hf_dtpt_message_type, tvb, 1, 1, message_type); switch (message_type) { case LookupBeginRequest: { proto_item* flags_item = NULL; proto_tree* flags_tree = NULL; flags = tvb_get_letohl(tvb, 12); flags_item = proto_tree_add_uint(dtpt_tree, hf_dtpt_flags, tvb, 12, 4, flags); if (flags_item) { flags_tree = proto_item_add_subtree(flags_item, ett_dtpt_flags); } if (flags_tree) { proto_tree_add_boolean(flags_tree, hf_dtpt_flags_res_service, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_flushprevious, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_flushcache, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_query_string, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_aliases, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_blob, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_addr, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_comment, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_version, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_type, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_name, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_nearest, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_nocontainers, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_containers, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_deep, tvb, 12, 4, flags); } payload_size = tvb_get_letohl(tvb, 16); proto_tree_add_uint(dtpt_tree, hf_dtpt_payload_size, tvb, 16, 4, payload_size); } break; case LookupBeginResponse: { proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle, tvb, 4, 8, tvb_get_letoh64(tvb, 4)); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 12, 4, tvb_get_letohl(tvb, 12)); } break; case LookupNextRequest: { proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle, tvb, 4, 8, tvb_get_letoh64(tvb, 4)); proto_tree_add_uint(dtpt_tree, hf_dtpt_buffer_size, tvb, 16, 4, tvb_get_letohl(tvb, 16)); } break; case LookupNextResponse: { proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 12, 4, tvb_get_letohl(tvb, 12)); proto_tree_add_uint(dtpt_tree, hf_dtpt_data_size, tvb, 16, 4, tvb_get_letohl(tvb, 16)); } break; case LookupEndRequest: { proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle, tvb, 4, 8, tvb_get_letoh64(tvb, 4)); } break; case ConnectRequest: { dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 32, 4, tvb_get_letohl(tvb, 32)); } break; case ConnectResponseOK: { dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 32, 4, tvb_get_letohl(tvb, 32)); } break; case ConnectResponseERR: { dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 32, 4, tvb_get_letohl(tvb, 32)); } break; } } return tvb_length(tvb); }
/* WiMax MAC Management DCD message (table 15) dissector */ void dissect_mac_mgmt_msg_dcd_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint offset = 0; guint tvb_len, payload_type, length; gint tlv_type, tlv_len, tlv_offset, tlv_value_offset; guint dl_burst_diuc, dl_num_regions; proto_item *dcd_item = NULL; proto_tree *dcd_tree = NULL; proto_tree *tlv_tree = NULL; proto_tree *sub_tree = NULL; tlv_info_t tlv_info; /* Ensure the right payload type */ payload_type = tvb_get_guint8(tvb, offset); if(payload_type != MAC_MGMT_MSG_DCD) { return; } if(tree) { /* we are being asked for details */ /* Get the tvb reported length */ tvb_len = tvb_reported_length(tvb); /* display MAC payload type DCD */ dcd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tvb_len, "Downlink Channel Descriptor (DCD) (%u bytes)", tvb_len); /* add MAC DCD subtree */ dcd_tree = proto_item_add_subtree(dcd_item, ett_mac_mgmt_msg_dcd_decoder); /* Decode and display the Downlink Channel Descriptor (DCD) */ /* display the Message Type */ proto_tree_add_item(dcd_tree, hf_dcd_message_type, tvb, offset, 1, ENC_BIG_ENDIAN); /* set the offset for the Downlink Channel ID */ offset++; /* display the Downlink Channel ID */ proto_tree_add_item(dcd_tree, hf_dcd_downlink_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN); /* set the offset for the Configuration Change Count */ offset++; /* display the Configuration Change Count */ proto_tree_add_item(dcd_tree, hf_dcd_config_change_count, tvb, offset, 1, ENC_BIG_ENDIAN); /* set the offset for the TLV Encoded info */ offset++; /* process the DCD TLV Encoded information (table 358) */ while(offset < tvb_len) { /* get the TLV information */ init_tlv_info(&tlv_info, tvb, offset); /* get the TLV type */ tlv_type = get_tlv_type(&tlv_info); /* get the TLV length */ tlv_len = get_tlv_length(&tlv_info); if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) { /* invalid tlv info */ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DCD TLV error"); proto_tree_add_item(dcd_tree, hf_dcd_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); break; } /* get the TLV value offset */ tlv_value_offset = get_tlv_value_offset(&tlv_info); #ifdef DEBUG /* for debug only */ proto_tree_add_protocol_format(dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, (tlv_len + tlv_value_offset), "DCD Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len, offset, tvb_len); #endif /* update the offset */ offset += tlv_value_offset; /* process DCD TLVs */ switch (tlv_type) { case DCD_DOWNLINK_BURST_PROFILE: { /* Downlink Burst Profile TLV (table 363)*/ /* get the DIUC */ dl_burst_diuc = (tvb_get_guint8(tvb, offset) & 0x0F); /* display TLV info */ /* add TLV subtree */ tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "Downlink_Burst_Profile (DIUC=%u) (%u bytes)", (dl_burst_diuc+1), tlv_len); /* detail display */ proto_tree_add_item(tlv_tree, hf_dcd_dl_burst_profile_rsv, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_dcd_dl_burst_profile_diuc, tvb, offset, 1, ENC_BIG_ENDIAN); /* process subTLVs */ for (tlv_offset = 1; tlv_offset < tlv_len; ) { /* get the TLV information */ init_tlv_info(&tlv_info, tvb, (offset+tlv_offset)); /* get the TLV type */ tlv_type = get_tlv_type(&tlv_info); /* get the TLV length */ length = get_tlv_length(&tlv_info); if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) { /* invalid tlv info */ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DL Burst Profile TLV error"); proto_tree_add_item(tlv_tree, hf_dcd_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); break; } /* update the offset */ tlv_offset += get_tlv_value_offset(&tlv_info); switch (tlv_type) { case DCD_BURST_FREQUENCY: { proto_item *tlv_item = NULL; sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_burst_freq, tvb, (offset+tlv_offset), 1, FALSE); tlv_item = proto_tree_add_item(sub_tree, hf_dcd_burst_freq, tvb, (offset+tlv_offset), 1, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " kHz"); break; } case DCD_BURST_FEC_CODE_TYPE: { sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_burst_fec, tvb, (offset+tlv_offset), 1, FALSE); proto_tree_add_item(sub_tree, hf_dcd_burst_fec, tvb, (offset+tlv_offset), 1, ENC_BIG_ENDIAN); break; } case DCD_BURST_DIUC_EXIT_THRESHOLD: { sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_burst_diuc_exit_threshold, tvb, (offset+tlv_offset), length, FALSE); proto_tree_add_item(sub_tree, hf_dcd_burst_diuc_exit_threshold, tvb, (offset+tlv_offset), length, ENC_BIG_ENDIAN); break; } case DCD_BURST_DIUC_ENTRY_THRESHOLD: { sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_burst_diuc_entry_threshold, tvb, (offset+tlv_offset), length, FALSE); proto_tree_add_item(sub_tree, hf_dcd_burst_diuc_entry_threshold, tvb, (offset+tlv_offset), length, ENC_BIG_ENDIAN); break; } case DCD_BURST_TCS_ENABLE: { sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_burst_tcs, tvb, (offset+tlv_offset), length, FALSE); proto_tree_add_item(sub_tree, hf_dcd_burst_tcs, tvb, (offset+tlv_offset), 1, ENC_BIG_ENDIAN); break; } default: /* ??? */ break; } tlv_offset += length; } break; } case DCD_BS_EIRP: { proto_item *tlv_item = NULL; tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_bs_eirp, tvb, offset, tlv_len, FALSE); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_bs_eirp, tvb, offset, tlv_len, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " dBm"); break; } case DCD_FRAME_DURATION: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_frame_duration, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_frame_duration, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_PHY_TYPE: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_phy_type, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_phy_type, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_POWER_ADJUSTMENT: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_power_adjustment, tvb, offset, 1, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_power_adjustment, tvb, offset, 1, ENC_BIG_ENDIAN); break; } case DCD_CHANNEL_NR: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_channel_nr, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_channel_nr, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_TTG: { proto_item *tlv_item = NULL; tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_ttg, tvb, offset, tlv_len, FALSE); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_ttg, tvb, offset, tlv_len, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " PS"); break; } case DCD_RTG: { proto_item *tlv_item = NULL; tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_rtg, tvb, offset, tlv_len, FALSE); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_rtg, tvb, offset, tlv_len, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " PS"); break; } #ifdef WIMAX_16D_2004 case DCD_RSS: { proto_item *tlv_item = NULL; tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_rss, tvb, offset, tlv_len, FALSE); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_rss, tvb, offset, tlv_len, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " dBm"); break; } #else case DCD_EIRXP: { proto_item *tlv_item = NULL; tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_eirxp, tvb, offset, tlv_len, FALSE); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_eirxp, tvb, offset, tlv_len, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " dBm"); break; } #endif case DCD_CHANNEL_SWITCH_FRAME_NR: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_channel_switch_frame_nr, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_channel_switch_frame_nr, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_FREQUENCY: { proto_item *tlv_item = NULL; tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_frequency, tvb, offset, tlv_len, FALSE); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_frequency, tvb, offset, tlv_len, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " kHz"); break; } case DCD_BS_ID: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_bs_id, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_bs_id, tvb, offset, tlv_len, ENC_NA); break; } case DCD_FRAME_DURATION_CODE: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_frame_duration_code, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_frame_duration_code, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_FRAME_NR: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_frame_nr, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_frame_nr, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } #ifdef WIMAX_16D_2004 case DCD_SIZE_CQICH_ID: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_size_cqich_id, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_size_cqich_id, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } #endif case DCD_H_ARQ_ACK_DELAY: { proto_item *tlv_item = NULL; tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_h_arq_ack_delay, tvb, offset, tlv_len, FALSE); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_h_arq_ack_delay, tvb, offset, tlv_len, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " frame offset"); break; } case DCD_MAC_VERSION: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_mac_version, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_mac_version, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_TLV_T_19_PERMUTATION_TYPE_FOR_BROADCAST_REGION_IN_HARQ_ZONE: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_19_permutation_type_for_broadcast_regions_in_harq_zone, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_19_permutation_type_for_broadcast_regions_in_harq_zone, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_TLV_T_20_MAXIMUM_RETRANSMISSION: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_20_maximum_retransmission, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_20_maximum_retransmission, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_TLV_T_21_DEFAULT_RSSI_AND_CINR_AVERAGING_PARAMETER: { tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, 1, "Default RSSI and CINR averaging parameter (%u byte(s))", tlv_len); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter_physical_cinr_measurements, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter_rssi_measurements, tvb, offset, 1, ENC_BIG_ENDIAN); break; } case DCD_TLV_T_22_DL_AMC_ALLOCATED_PHYSICAL_BANDS_BITMAP: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_22_dl_amc_allocated_physical_bands_bitmap, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_22_dl_amc_allocated_physical_bands_bitmap, tvb, offset, tlv_len, ENC_NA); break; } case DCD_TLV_T_34_DL_REGION_DEFINITION: { tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "DL region definition (%u byte(s))", tlv_len); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition, tvb, offset, tlv_len, ENC_NA); dl_num_regions = tvb_get_guint8(tvb, offset); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_num_region, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); tlv_offset = offset; for(length = 0; length < dl_num_regions; length++) { proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_symbol_offset, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_subchannel_offset, tvb, (tlv_offset+1), 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_num_symbols, tvb, (tlv_offset+2), 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_num_subchannels, tvb, (tlv_offset+3), 1, ENC_BIG_ENDIAN); tlv_offset += 4; } break; } case DCD_TLV_T_50_HO_TYPE_SUPPORT: { tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "HO type support (%u byte(s))", tlv_len); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_ho, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_mdho, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_fbss_ho, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); break; } case DCD_TLV_T_31_H_ADD_THRESHOLD: { proto_item *tlv_item = NULL; tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_31_h_add_threshold, tvb, offset, 1, FALSE); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_31_h_add_threshold, tvb, offset, tlv_len, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " dB"); break; } case DCD_TLV_T_32_H_DELETE_THRESHOLD: { proto_item *tlv_item = NULL; tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_32_h_delete_threshold, tvb, offset, tlv_len, FALSE); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_32_h_delete_threshold, tvb, offset, tlv_len, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " dB"); break; } case DCD_TLV_T_33_ASR: { proto_item *tlv_item = NULL; tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "ASR Slot Length (M) and Switching Period (L) (%u byte(s))", tlv_len); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_33_asr, tvb, offset, 1, ENC_BIG_ENDIAN); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_33_asr_m, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " frames"); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_33_asr_l, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " frames"); break; } case DCD_TLV_T_35_PAGING_GROUP_ID: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_35_paging_group_id, tvb, offset, 1, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_35_paging_group_id, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_TLV_T_36_TUSC1_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_36_tusc1_permutation_active_subchannels_bitmap, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_36_tusc1_permutation_active_subchannels_bitmap, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_TLV_T_37_TUSC2_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_37_tusc2_permutation_active_subchannels_bitmap, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_37_tusc2_permutation_active_subchannels_bitmap, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_TLV_T_51_HYSTERSIS_MARGIN: { proto_item *tlv_item = NULL; tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_51_hysteresis_margin, tvb, offset, tlv_len, FALSE); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_51_hysteresis_margin, tvb, offset, tlv_len, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " dB"); break; } case DCD_TLV_T_52_TIME_TO_TRIGGER_DURATION: { proto_item *tlv_item = NULL; tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_52_time_to_trigger_duration, tvb, offset, tlv_len, FALSE); tlv_item = proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_52_time_to_trigger_duration, tvb, offset, tlv_len, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item, " ms"); break; } case DCD_TLV_T_54_TRIGGER: { /* Trigger TLV (table 358a & 358b) */ /* add TLV subtree */ tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "DCD Trigger (%u bytes)", tlv_len); for (tlv_offset = 0; tlv_offset < tlv_len; ) { /* get the TLV information */ init_tlv_info(&tlv_info, tvb, (offset + tlv_offset)); /* get the TLV type */ tlv_type = get_tlv_type(&tlv_info); /* get the TLV length */ length = get_tlv_length(&tlv_info); if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) { /* invalid tlv info */ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Trigger TLV error"); proto_tree_add_item(tlv_tree, hf_dcd_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); break; } /* update the offset */ tlv_offset += get_tlv_value_offset(&tlv_info); /* table 358a */ switch (tlv_type) { case DCD_TLV_T_541_TYPE_FUNCTION_ACTION: { /* table 358b */ sub_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, (offset + tlv_offset), length, "Trigger; Type/function/action description (%u byte(s))", tlv_len); proto_tree_add_item(sub_tree, hf_dcd_tlv_t_541_type, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dcd_tlv_t_541_function, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dcd_tlv_t_541_action, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); } break; case DCD_TLV_T542_TRIGGER_VALUE: sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_tlv_t_542_trigger_value, tvb, (offset + tlv_offset), length, FALSE); proto_tree_add_item(sub_tree, hf_dcd_tlv_t_542_trigger_value, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); break; case DCD_TLV_T_543_TRIGGER_AVERAGING_DURATION: sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, tlv_tree, hf_dcd_tlv_t_543_trigger_averaging_duration, tvb, (offset + tlv_offset), length, FALSE); proto_tree_add_item(sub_tree, hf_dcd_tlv_t_543_trigger_averaging_duration, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); break; } tlv_offset += length; } break; } case DCD_TLV_T_60_NOISE_AND_INTERFERENCE: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_60_noise_interference, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_60_noise_interference, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_TLV_T_153_DOWNLINK_BURST_PROFILE_FOR_MULTIPLE_FEC_TYPES: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_153_downlink_burst_profile_for_mutiple_fec_types, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_153_downlink_burst_profile_for_mutiple_fec_types, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_RESTART_COUNT: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_restart_count, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_restart_count, tvb, offset, tlv_len, ENC_BIG_ENDIAN); break; } case DCD_TLV_T_45_PAGING_INTERVAL_LENGTH: { if (include_cor2_changes) { tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tlv_len, "Reserved (%u byte(s))", tlv_len); proto_tree_add_text(tlv_tree, tvb, offset, tlv_len, "Reserved"); } else { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_tlv_t_45_paging_interval_length, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_45_paging_interval_length, tvb, offset, tlv_len, ENC_BIG_ENDIAN); } break; } default: { tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, hf_dcd_unknown_type, tvb, offset, tlv_len, FALSE); proto_tree_add_item(tlv_tree, hf_dcd_unknown_type, tvb, offset, tlv_len, ENC_NA); break; } } offset += tlv_len; } /* end of TLV process while loop */ } }
/* XXX - "packet comment" is passed into dissector as data, but currently doesn't have a use */ static int dissect_file_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data) { proto_item *volatile ti = NULL; guint cap_len = 0, frame_len = 0; proto_tree *volatile fh_tree = NULL; proto_tree *volatile tree; proto_item *item; const gchar *cap_plurality, *frame_plurality; const color_filter_t *color_filter; file_data_t *file_data = (file_data_t*)data; tree=parent_tree; pinfo->current_proto = "File"; /* if FILE is not referenced from any filters we don't need to worry about generating any tree items. */ if(!proto_field_is_referenced(tree, proto_file)) { tree=NULL; } else { gboolean old_visible; /* Put in frame header information. */ cap_len = tvb_captured_length(tvb); frame_len = tvb_reported_length(tvb); cap_plurality = plurality(cap_len, "", "s"); frame_plurality = plurality(frame_len, "", "s"); ti = proto_tree_add_protocol_format(tree, proto_file, tvb, 0, -1, "File record %u: %u byte%s", pinfo->fd->num, frame_len, frame_plurality); proto_item_append_text(ti, ", %u byte%s", cap_len, cap_plurality); fh_tree = proto_item_add_subtree(ti, ett_file); proto_tree_add_int(fh_tree, hf_file_ftap_encap, tvb, 0, 0, pinfo->fd->lnk_t); proto_tree_add_uint(fh_tree, hf_file_record_number, tvb, 0, 0, pinfo->fd->num); proto_tree_add_uint_format(fh_tree, hf_file_record_len, tvb, 0, 0, frame_len, "Record Length: %u byte%s (%u bits)", frame_len, frame_plurality, frame_len * 8); ti = proto_tree_add_boolean(fh_tree, hf_file_marked, tvb, 0, 0,pinfo->fd->flags.marked); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_boolean(fh_tree, hf_file_ignored, tvb, 0, 0,pinfo->fd->flags.ignored); PROTO_ITEM_SET_GENERATED(ti); if(proto_field_is_referenced(tree, hf_file_protocols)) { /* we are going to be using proto_item_append_string() on * hf_frame_protocols, and we must therefore disable the * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by * setting it as visible. * * See proto.h for details. */ old_visible = proto_tree_set_visible(fh_tree, TRUE); ti = proto_tree_add_string(fh_tree, hf_file_protocols, tvb, 0, 0, ""); PROTO_ITEM_SET_GENERATED(ti); proto_tree_set_visible(fh_tree, old_visible); } if(pinfo->fd->pfd != 0){ proto_item *ppd_item; guint num_entries = g_slist_length(pinfo->fd->pfd); guint i; ppd_item = proto_tree_add_uint(fh_tree, hf_file_num_p_prot_data, tvb, 0, 0, num_entries); PROTO_ITEM_SET_GENERATED(ppd_item); for(i=0; i<num_entries; i++){ gchar* str = p_get_proto_name_and_key(wmem_file_scope(), pinfo, i); proto_tree_add_string_format(fh_tree, hf_file_proto_name_and_key, tvb, 0, 0, str, "%s", str); } } #if 0 if (show_file_off) { proto_tree_add_int64_format_value(fh_tree, hf_frame_file_off, tvb, 0, 0, pinfo->fd->file_off, "%" G_GINT64_MODIFIER "d (0x%" G_GINT64_MODIFIER "x)", pinfo->fd->file_off, pinfo->fd->file_off); } #endif } if (pinfo->fd->flags.ignored) { /* Ignored package, stop handling here */ col_set_str(pinfo->cinfo, COL_INFO, "<Ignored>"); proto_tree_add_boolean_format(tree, hf_file_ignored, tvb, 0, -1, TRUE, "This record is marked as ignored"); return tvb_captured_length(tvb); } /* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */ TRY { #ifdef _MSC_VER /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations. (a running debugger will be called before the except part below) */ /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling) stack in an inconsistent state thus causing a crash at some point in the handling of the exception. See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html */ __try { #endif if (!dissector_try_uint(file_encap_dissector_table, pinfo->fd->lnk_t, tvb, pinfo, parent_tree)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN"); col_add_fstr(pinfo->cinfo, COL_INFO, "FTAP_ENCAP = %d", pinfo->fd->lnk_t); call_dissector(data_handle,tvb, pinfo, parent_tree); } #ifdef _MSC_VER } __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) { switch(GetExceptionCode()) { case(STATUS_ACCESS_VIOLATION): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address"); break; case(STATUS_INTEGER_DIVIDE_BY_ZERO): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero"); break; case(STATUS_STACK_OVERFLOW): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)"); /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */ break; /* XXX - add other hardware exception codes as required */ default: show_exception(tvb, pinfo, parent_tree, DissectorError, g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode())); } } #endif } CATCH_BOUNDS_AND_DISSECTOR_ERRORS { show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; if(proto_field_is_referenced(tree, hf_file_protocols)) { wmem_strbuf_t *val = wmem_strbuf_new(wmem_packet_scope(), ""); wmem_list_frame_t *frame; /* skip the first entry, it's always the "frame" protocol */ frame = wmem_list_frame_next(wmem_list_head(pinfo->layers)); if (frame) { wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)))); frame = wmem_list_frame_next(frame); } while (frame) { wmem_strbuf_append_c(val, ':'); wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)))); frame = wmem_list_frame_next(frame); } proto_item_append_string(ti, wmem_strbuf_get_str(val)); } /* Call postdissectors if we have any (while trying to avoid another * TRY/CATCH) */ if (have_postdissector()) { TRY { #ifdef _MSC_VER /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations */ /* (a running debugger will be called before the except part below) */ /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling) stack in an inconsistent state thus causing a crash at some point in the handling of the exception. See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html */ __try { #endif call_all_postdissectors(tvb, pinfo, parent_tree); #ifdef _MSC_VER } __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) { switch(GetExceptionCode()) { case(STATUS_ACCESS_VIOLATION): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address"); break; case(STATUS_INTEGER_DIVIDE_BY_ZERO): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero"); break; case(STATUS_STACK_OVERFLOW): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)"); /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */ break; /* XXX - add other hardware exception codes as required */ default: show_exception(tvb, pinfo, parent_tree, DissectorError, g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode())); } } #endif } CATCH_BOUNDS_AND_DISSECTOR_ERRORS { show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; } /* XXX optimize this so it doesn't need to scan the second time */ color_filter = color_filters_colorize_packet(file_data->color_edt); if (color_filter) { pinfo->fd->color_filter = color_filter; item = proto_tree_add_string(fh_tree, hf_file_color_filter_name, tvb, 0, 0, color_filter->filter_name); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_string(fh_tree, hf_file_color_filter_text, tvb, 0, 0, color_filter->filter_text); PROTO_ITEM_SET_GENERATED(item); } tap_queue_packet(file_tap, pinfo, NULL); if (pinfo->frame_end_routines) { g_slist_foreach(pinfo->frame_end_routines, &call_file_record_end_routine, NULL); g_slist_free(pinfo->frame_end_routines); pinfo->frame_end_routines = NULL; } return tvb_captured_length(tvb); }
static void dissect_wai(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Format of WAPI protocol packet in WAI authentication system 0 2 3 4 6 8 10 11 12 ------------------------------------------------------------------------------- | Ver. | Type | Subtype | Reserved | Length | packet | fragm. | flag | data | | | seq. no | seq. no | | |-----------------------------------------------------------------------------| Figure 18 from [ref:1] */ #define WAI_MESSAGE_LENGTH 12 /*Length of all fields without 'Data' field*/ #define WAI_DATA_OFFSET WAI_MESSAGE_LENGTH guint16 version; guint8 subtype; guint16 length; guint16 packet_num; guint8 fragment_num; guint8 flags; fragment_head *frag_msg; proto_tree *wai_tree = NULL; tvbuff_t *next_tvb; tvbuff_t *new_tvb; const gchar *subtype_name = "Unknown type"; length = tvb_get_ntohs(tvb, 6)-WAI_MESSAGE_LENGTH; subtype = tvb_get_guint8(tvb, 3); /* quick sanity check */ if ((length != tvb_reported_length (tvb)-WAI_MESSAGE_LENGTH) || (subtype > WAI_SUB_MULTICAST_ANNOUNCE_RESP)) { return; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "WAI"); col_clear(pinfo->cinfo, COL_INFO); version = tvb_get_ntohs(tvb, 0); if (version == 1) { subtype_name = val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type"); } col_append_fstr(pinfo->cinfo, COL_INFO, "%s", subtype_name); /* Field lengths and offsets in WAI protocol described above */ packet_num = tvb_get_ntohs(tvb, 8); fragment_num = tvb_get_guint8(tvb, 10); flags = tvb_get_guint8(tvb, 11); if (tree) { proto_item *wai_item; wai_item = proto_tree_add_item(tree, proto_wai, tvb, 0, -1, ENC_NA); proto_item_set_text (wai_item, "WAI Protocol (%s)", val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type")); wai_tree = proto_item_add_subtree(wai_item, ett_wai); /* Field lengths and offsets in WAI protocol described above */ proto_tree_add_item(wai_tree, hf_wai_version, tvb, 0, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_type, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_subtype, tvb, 3, 1, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_reserved, tvb, 4, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_length, tvb, 6, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_seq, tvb, 8, 2, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_fragm_seq, tvb, 10, 1, ENC_BIG_ENDIAN); proto_tree_add_item(wai_tree, hf_wai_flag, tvb, 11, 1, ENC_BIG_ENDIAN); } frag_msg = fragment_add_seq_check (&wai_reassembly_table, tvb, WAI_DATA_OFFSET, pinfo, packet_num, NULL, fragment_num, length, flags); next_tvb = tvb_new_subset_remaining(tvb, WAI_DATA_OFFSET); /* Replace INFO column if message is fragmented and call data_handle */ if (flags) { col_add_fstr(pinfo->cinfo, COL_INFO, "Fragment (%d) of message, data not dissected", fragment_num); process_reassembled_data(tvb, WAI_DATA_OFFSET, pinfo, "Reassembled WAI", frag_msg, &wai_frag_items, NULL, wai_tree); call_dissector(data_handle, next_tvb, pinfo, tree); } else { /* If this is the last fragment of fragmented message, then reassamble and dissect otherwise only dissect */ if (fragment_num > 0) { new_tvb = process_reassembled_data(tvb, WAI_DATA_OFFSET, pinfo, "Reassembled WAI", frag_msg, &wai_frag_items, NULL, wai_tree); if (new_tvb) { col_set_str(pinfo->cinfo, COL_INFO, "Last fragment of message, data dissected"); col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", subtype_name); next_tvb=new_tvb; length = tvb_reported_length (next_tvb); } } /* dissect Data field of WAI packet */ if (tree) { dissect_wai_data(next_tvb, wai_tree, subtype, length); } } }
/* Code to actually dissect the packets */ static void dissect_brdwlk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti, *hidden_item; proto_tree *brdwlk_tree = NULL; tvbuff_t *next_tvb; guint8 error, eof, sof; int hdrlen = 2, offset = 0; gint len, reported_len, plen; guint16 pkt_cnt; gboolean dropped_packets; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Boardwalk"); col_clear(pinfo->cinfo, COL_INFO); pinfo->vsan = (tvb_get_ntohs(tvb, offset) & 0xFFF); sof = (tvb_get_guint8(tvb, offset) & 0xF0) >> 4; if ((sof == FCM_DELIM_SOFI3) || (sof == FCM_DELIM_SOFI2) || (sof == FCM_DELIM_SOFI1) || (sof == FCM_DELIM_SOFI4)) { pinfo->sof_eof = PINFO_SOF_FIRST_FRAME; } else if (sof == FCM_DELIM_SOFF) { pinfo->sof_eof = PINFO_SOF_SOFF; } if (tree) { ti = proto_tree_add_protocol_format(tree, proto_brdwlk, tvb, 0, hdrlen, "Boardwalk"); brdwlk_tree = proto_item_add_subtree(ti, ett_brdwlk); proto_tree_add_item(brdwlk_tree, hf_brdwlk_sof, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(brdwlk_tree, hf_brdwlk_vsan, tvb, offset, 2, ENC_BIG_ENDIAN); } /* Locate EOF which is the last 4 bytes of the frame */ len = tvb_length_remaining(tvb, hdrlen); reported_len = tvb_reported_length_remaining(tvb, hdrlen); if (reported_len < 4) { /* * This packet is claimed not to even have enough data for * a 4-byte EOF. * Don't try to process the EOF. */ ; } else if (len < reported_len) { /* * This packet is claimed to have enough data for a 4-byte EOF, * but we didn't capture all of the packet. * Slice off the 4-byte EOF from the reported length, and trim * the captured length so it's no more than the reported length; * that will slice off what of the EOF, if any, is in the * captured length. */ reported_len -= 4; if (len > reported_len) len = reported_len; } else { /* * We have the entire packet, and it includes a 4-byte EOF. * Slice it off, and put it into the tree if we're building * a tree. */ len -= 4; reported_len -= 4; offset = tvb_reported_length(tvb) - 4; pkt_cnt = tvb_get_ntohs(tvb, offset); if (tree) { proto_tree_add_uint(brdwlk_tree, hf_brdwlk_pktcnt, tvb, offset, 2, pkt_cnt); } dropped_packets = FALSE; if (pinfo->fd->flags.visited) { /* * This isn't the first pass, so we can't use the global * "packet_count" variable to determine whether there were * any dropped frames or not. * We therefore attach a non-null pointer as frame data to * any frame preceded by dropped packets. */ if (p_get_proto_data(pinfo->fd, proto_brdwlk, 0) != NULL) dropped_packets = TRUE; } else { /* * This is the first pass, so we have to use the global * "packet_count" variable to determine whether there were * any dropped frames or not. * * XXX - can there be more than one stream of packets, so that * we can't just use a global variable? */ if (pkt_cnt != packet_count + 1) { if (!first_pkt && (pkt_cnt != 0 || (packet_count != BRDWLK_MAX_PACKET_CNT))) { dropped_packets = TRUE; /* * Mark this frame as having been preceded by dropped * packets. (The data we use as the frame data doesn't * matter - it just matters that it's non-null.) */ p_add_proto_data(pinfo->fd, proto_brdwlk, 0, &packet_count); } } } if (tree) { hidden_item = proto_tree_add_boolean(brdwlk_tree, hf_brdwlk_drop, tvb, offset, 0, dropped_packets); PROTO_ITEM_SET_HIDDEN(hidden_item); } packet_count = pkt_cnt; error=tvb_get_guint8(tvb, offset+2); dissect_brdwlk_err(brdwlk_tree, tvb, offset+2); eof = tvb_get_guint8(tvb, offset+3); if (eof != FCM_DELIM_EOFN) { pinfo->sof_eof |= PINFO_EOF_LAST_FRAME; } else if (eof != FCM_DELIM_EOFT) { pinfo->sof_eof |= PINFO_EOF_INVALID; } if (tree) { proto_tree_add_item(brdwlk_tree, hf_brdwlk_eof, tvb, offset+3, 1, ENC_BIG_ENDIAN); } if ((error & BRDWLK_HAS_PLEN) && tree) { /* In newer Boardwalks, if this bit is set, the actual frame length * is also provided. This length is the size between SOF & EOF * including FC CRC. */ plen = tvb_get_ntohl(tvb, offset-4); plen *= 4; proto_tree_add_uint(brdwlk_tree, hf_brdwlk_plen, tvb, offset-4, 4, plen); #if 0 /* XXX - this would throw an exception if it would increase * the reported length. */ if (error & BRDWLK_TRUNCATED_BIT) { tvb_set_reported_length(tvb, plen); } #endif } } next_tvb = tvb_new_subset(tvb, 2, len, reported_len); if (fc_dissector_handle) { call_dissector(fc_dissector_handle, next_tvb, pinfo, tree); } }
dissect_prp_redundancy_control_trailer(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) { proto_item *ti; proto_tree *prp_tree; guint i; guint length; guint offset; guint16 lan_id; guint16 lsdu_size; guint16 prp1_suffix; guint trailer_start; guint trailer_length; trailer_start = 0; trailer_length = 0; length = tvb_reported_length(tvb); if(length < 14) return 0; /* * This is horribly broken. It assumes the frame is an Ethernet * frame, with a type field at an offset of 12 bytes from the header. * That is not guaranteed to be true. * * Ideally, this should be a heuristic dissector registered in * the "eth.trailer" heuristic dissector table (and it can * be registered as "disabled by default" there); unfortunately, * it needs to know the length of the entire frame for the * PRP-0 heuristic, so it'd have to be passed that length * out of band.
/* Code to actually dissect the packets */ static void dissect_manolito(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { unsigned int offset; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *manolito_tree; const char* packet_type = 0; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MANOLITO"); ti = proto_tree_add_item(tree, proto_manolito, tvb, 0, -1, ENC_NA); manolito_tree = proto_item_add_subtree(ti, ett_manolito); /* MANOLITO packet header (network byte order) */ proto_tree_add_item(manolito_tree, hf_manolito_checksum, tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(manolito_tree, hf_manolito_seqno, tvb, 4, 4, ENC_BIG_ENDIAN); proto_tree_add_item(manolito_tree, hf_manolito_src, tvb, 8, 4, ENC_BIG_ENDIAN); proto_tree_add_item(manolito_tree, hf_manolito_dest, tvb, 12, 4, ENC_BIG_ENDIAN); if (tvb_reported_length(tvb) == 19) { packet_type = "Ping (truncated)"; proto_tree_add_item(manolito_tree, hf_manolito_options_short, tvb, 16, 3, ENC_BIG_ENDIAN); } else { proto_tree_add_item(manolito_tree, hf_manolito_options, tvb, 16, 4, ENC_BIG_ENDIAN); } if (tvb_reported_length(tvb) <= 20) /* no payload, just headers */ { col_set_str(pinfo->cinfo, COL_INFO, "Ping"); } else { offset = 20; /* fields start here */ /* fields format: 2-byte name, optional NULL, 1-byte lenlen, */ /* that many bytes(len or data), for NI,CN,VL is len, more */ /* (that many bytes) data follows; else is raw data. */ do { guint16 field_name; /* 16-bit field name */ guint8 dtype; /* data-type */ guint8 length; /* length */ guint8* data; /* payload */ int start; /* field starting location */ char field_name_str[3]; /* printable name */ const char* longname; /* human-friendly field name */ start = offset; /* 2-byte field name */ field_name = tvb_get_ntohs(tvb, offset); offset += 2; /* Identify the packet based on existing fields */ /* Maybe using the options fields is a better idea...*/ if (field_name == 0x434b) /* CK */ packet_type = "Search Hit"; if (field_name == 0x4e43) /* NC */ packet_type = "User Information"; if (field_name == 0x464e) /* FN - if only field */ packet_type = "Search Query"; if (field_name == 0x4944) /* ID ?? search by CK? */ packet_type = "Search Query (by hash)"; if (field_name == 0x5054) /* PT */ packet_type = "Download Request"; if (field_name == 0x4d45) /* ME */ packet_type = "Chat"; if (tvb_reported_length(tvb) == 20) /* no fields */ packet_type = "Ping"; /* Find the long name of the field */ switch(field_name) { case 0x5346: longname = "Shared Files"; break; /* SF */ case 0x534b: longname = "Shared Kilobytes";break; /* SK */ case 0x4e49: longname = "Network ID"; break; /* NI */ case 0x4e43: longname = "Num. Connections";break; /* NC */ case 0x4356: longname = "Client Version"; break; /* CV */ case 0x564c: longname = "Velocity"; break; /* VL */ case 0x464e: longname = "Filename"; break; /* FN */ case 0x464c: longname = "File Length"; break; /* FL */ case 0x4252: longname = "Bit Rate"; break; /* BR */ case 0x4643: longname = "Frequency"; break; /* FC */ case 0x5354: longname = "???"; break; /* ST */ case 0x534c: longname = "Song Length (s)"; break; /* SL */ case 0x434b: longname = "Checksum"; break; /* CK */ case 0x4e4e: longname = "Nickname"; break; /* NN */ case 0x434e: longname = "Client Name"; break; /* CN */ case 0x5054: longname = "Port"; break; /* PT */ case 0x484e: longname = "???"; break; /* HN */ case 0x4d45: longname = "Message"; break; /* ME */ case 0x4944: longname = "Identification"; break; /* ID */ case 0x4144: longname = "???"; break; /* AD */ default: longname = "unknown"; break; } /* 1-byte data type */ #define MANOLITO_STRING 1 #define MANOLITO_INTEGER 0 dtype = tvb_get_guint8(tvb, offset); length = tvb_get_guint8(tvb, ++offset); /* * Get the payload. * * XXX - is the cast necessary? I think the * "usual arithmetic conversions" should * widen it past 8 bits, so there shouldn't * be an overflow. */ data = ep_alloc((guint)length + 1); tvb_memcpy(tvb, data, ++offset, length); offset += length; /* convert the 16-bit integer field name to a string */ /* XXX: changed this to use g_htons */ field_name_str[0] = g_htons(field_name) & 0x00ff; field_name_str[1] = (g_htons(field_name) & 0xff00) >> 8; field_name_str[2] = 0; if (dtype == MANOLITO_STRING) { data[length] = 0; proto_tree_add_text(manolito_tree, tvb, start, offset - start, "%s (%s): %s", (char*)field_name_str, longname, data); } else if (dtype == MANOLITO_INTEGER) { int n = 0; /* integers can be up to 5 bytes */ switch(length) { case 5: n += data[4] << ((length - 5) * 8); case 4: n += data[3] << ((length - 4) * 8); case 3: n += data[2] << ((length - 3) * 8); case 2: n += data[1] << ((length - 2) * 8); case 1: n += data[0] << ((length - 1) * 8); } proto_tree_add_text(manolito_tree, tvb, start, offset - start, "%s (%s): %d", (char*)field_name_str, longname, n); } else { proto_tree_add_text(manolito_tree, tvb, start, offset - start, "unknown type %d", dtype); } } while(offset < tvb_reported_length(tvb)); } if (packet_type) { col_set_str(pinfo->cinfo, COL_INFO, packet_type); } }
static void dissect_kdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint body_len; guint8 version = 0; guint8 header_len = 0; guint8 packet_flags = 0; guint8 packet_errors = 0; guint32 sequence_number = G_MAXUINT32; guint32 ack_number = G_MAXUINT32; guint32 src_flowid = G_MAXUINT32; int offset; col_set_str(pinfo->cinfo, COL_PROTOCOL, "KDP"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { proto_item *ti; proto_tree *kdp_tree, *flags_tree; ti = NULL; kdp_tree = NULL; flags_tree = NULL; ti = proto_tree_add_item(tree, proto_kdp, tvb, 0, -1, ENC_NA); kdp_tree = proto_item_add_subtree(ti, ett_kdp); version = tvb_get_guint8(tvb, 0); if (version != 2) { /* Version other than 2 is really SDDP in UDP */ proto_tree_add_item(kdp_tree, hf_kdp_version, tvb, 0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(kdp_tree, hf_kdp_xml_body, tvb, 0, -1, ENC_ASCII|ENC_NA); } else { header_len = tvb_get_guint8(tvb, 1) * 4; body_len = tvb_reported_length(tvb); if (header_len > body_len) { body_len = 0; /* malformed packet */ } else { body_len = body_len - header_len; } packet_flags = tvb_get_guint8(tvb, 2); packet_errors = tvb_get_guint8(tvb, 3); proto_tree_add_item(kdp_tree, hf_kdp_version, tvb, 0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(kdp_tree, hf_kdp_headerlen, tvb, 1, 1, ENC_BIG_ENDIAN); ti = proto_tree_add_item(kdp_tree, hf_kdp_flags, tvb, 2, 1, ENC_BIG_ENDIAN); flags_tree = proto_item_add_subtree(ti, ett_kdp_flags); proto_tree_add_item(flags_tree, hf_kdp_drop_flag, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_kdp_syn_flag, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_kdp_ack_flag, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_kdp_rst_flag, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_kdp_bcst_flag, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_kdp_dup_flag, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(kdp_tree, hf_kdp_errors, tvb, 3, 1, ENC_BIG_ENDIAN); if (header_len > 4) { offset = 4; if (packet_flags & KDP_ACK_FLAG) { proto_tree_add_item(kdp_tree, hf_kdp_destflowid, tvb, offset, 4, ENC_BIG_ENDIAN); offset = offset + 4; } if (packet_flags & (KDP_SYN_FLAG | KDP_BCST_FLAG)) { proto_tree_add_item(kdp_tree, hf_kdp_srcflowid, tvb, offset, 4, ENC_BIG_ENDIAN); src_flowid = tvb_get_ntohl(tvb, offset); offset = offset + 4; } proto_tree_add_item(kdp_tree, hf_kdp_sequence, tvb, offset, 4, ENC_BIG_ENDIAN); sequence_number = tvb_get_ntohl(tvb, offset); offset = offset + 4; if (packet_flags & KDP_ACK_FLAG) { proto_tree_add_item(kdp_tree, hf_kdp_ack, tvb, offset, 4, ENC_BIG_ENDIAN); ack_number = tvb_get_ntohl(tvb, offset); offset = offset + 4; } if (packet_flags & KDP_SYN_FLAG) { proto_tree_add_item(kdp_tree, hf_kdp_maxsegmentsize, tvb, offset, 4, ENC_BIG_ENDIAN); offset = offset + 4; } while (offset < ((body_len > 0) ? header_len - 4 : header_len)) { guint8 option_number; guint8 option_len = 0; option_number = tvb_get_guint8(tvb, offset); proto_tree_add_item(kdp_tree, hf_kdp_optionnumber, tvb, offset, 1, ENC_BIG_ENDIAN); offset = offset + 1; if (option_number > 0) { option_len = tvb_get_guint8(tvb, offset); proto_tree_add_item(kdp_tree, hf_kdp_optionlen, tvb, offset, 1, ENC_BIG_ENDIAN); offset = offset + 1; } switch (option_number) { case 0: break; case 1: proto_tree_add_item(kdp_tree, hf_kdp_option1, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; break; case 2: proto_tree_add_item(kdp_tree, hf_kdp_option2, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; break; case 3: proto_tree_add_item(kdp_tree, hf_kdp_option3, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; break; case 4: proto_tree_add_item(kdp_tree, hf_kdp_option4, tvb, offset, 0, ENC_NA); break; case 5: proto_tree_add_item(kdp_tree, hf_kdp_option5, tvb, offset, 0, ENC_NA); break; case 6: proto_tree_add_item(kdp_tree, hf_kdp_option6, tvb, offset, option_len - 2, ENC_NA); offset = offset + option_len - 2; break; case 7: proto_tree_add_item(kdp_tree, hf_kdp_option7, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; break; case 8: proto_tree_add_item(kdp_tree, hf_kdp_option8, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; break; case 9: proto_tree_add_item(kdp_tree, hf_kdp_option9, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; break; default: proto_tree_add_item(kdp_tree, hf_kdp_option_unknown, tvb, offset, option_len - 2, ENC_NA); offset = offset + option_len - 2; break; } } if (body_len > 0) { proto_tree_add_item(kdp_tree, hf_kdp_fragment, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; proto_tree_add_item(kdp_tree, hf_kdp_fragtotal, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; proto_tree_add_item(kdp_tree, hf_kdp_body, tvb, offset, -1, ENC_NA); } } } } /* Now that we know sequence number and optional ack number, we can print more detailed summary info */ if (version != 2) { col_set_str(pinfo->cinfo, COL_INFO, "SDDP message"); } else { char ack_string[BUFFER_SIZE]; char seq_num_string[BUFFER_SIZE]; char src_flowid_string[BUFFER_SIZE]; if (packet_flags & KDP_ACK_FLAG) { g_snprintf(ack_string, sizeof(ack_string), "ACK=%x ", ack_number); } else { ack_string[0] = '\0'; } if (header_len > 4) { g_snprintf(seq_num_string, sizeof(seq_num_string), "SEQ=%x ", sequence_number); } else { seq_num_string[0] = '\0'; } if (packet_flags & (KDP_SYN_FLAG | KDP_BCST_FLAG)) { g_snprintf(src_flowid_string, sizeof(src_flowid_string), "SRC_FLOWID=%x ", src_flowid); } else { src_flowid_string[0] = '\0'; } col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s%s%s%s%s%serrors=%d", ((packet_flags & KDP_DROP_FLAG) ? "DROP " : ""), ((packet_flags & KDP_SYN_FLAG) ? "SYN " : ""), ((packet_flags & KDP_RST_FLAG) ? "RST " : ""), ((packet_flags & KDP_BCST_FLAG) ? "BCST " : ""), ((packet_flags & KDP_DUP_FLAG) ? "DUP " : ""), ack_string, seq_num_string, src_flowid_string, packet_errors); } }
/* Tests a tvbuff against the expected pattern/length. * Returns TRUE if all tests succeeed, FALSE if any test fails */ gboolean test(tvbuff_t *tvb, gchar* name, guint8* expected_data, guint expected_length, guint expected_reported_length) { guint length; guint reported_length; guint8 *ptr; volatile gboolean ex_thrown; volatile guint32 val32; guint32 expected32; guint incr, i; length = tvb_length(tvb); if (length != expected_length) { printf("01: Failed TVB=%s Length of tvb=%u while expected length=%u\n", name, length, expected_length); failed = TRUE; return FALSE; } reported_length = tvb_reported_length(tvb); if (reported_length != expected_reported_length) { printf("01: Failed TVB=%s Reported length of tvb=%u while expected reported length=%u\n", name, reported_length, expected_reported_length); failed = TRUE; return FALSE; } /* Test boundary case. A BoundsError exception should be thrown. */ ex_thrown = FALSE; TRY { tvb_get_ptr(tvb, 0, length + 1); } CATCH(BoundsError) { ex_thrown = TRUE; } CATCH(FragmentBoundsError) { printf("02: Caught wrong exception: FragmentBoundsError\n"); } CATCH(ReportedBoundsError) { printf("02: Caught wrong exception: ReportedBoundsError\n"); } CATCH_ALL { printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n"); } ENDTRY; if (!ex_thrown) { printf("02: Failed TVB=%s No BoundsError when retrieving %u bytes\n", name, length + 1); failed = TRUE; return FALSE; } /* Test boundary case with reported_length+1. A ReportedBoundsError exception should be thrown. */ ex_thrown = FALSE; TRY { tvb_get_ptr(tvb, 0, reported_length + 1); } CATCH(BoundsError) { printf("03: Caught wrong exception: BoundsError\n"); } CATCH(FragmentBoundsError) { printf("03: Caught wrong exception: FragmentBoundsError\n"); } CATCH(ReportedBoundsError) { ex_thrown = TRUE; } CATCH_ALL { printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n"); } ENDTRY; if (!ex_thrown) { printf("03: Failed TVB=%s No ReportedBoundsError when retrieving %u bytes\n", name, reported_length + 1); failed = TRUE; return FALSE; } /* Test boundary case. A BoundsError exception should be thrown. */ ex_thrown = FALSE; TRY { tvb_get_ptr(tvb, -1, 2); } CATCH(BoundsError) { ex_thrown = TRUE; } CATCH(FragmentBoundsError) { printf("04: Caught wrong exception: FragmentBoundsError\n"); } CATCH(ReportedBoundsError) { printf("04: Caught wrong exception: ReportedBoundsError\n"); } CATCH_ALL { printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n"); } ENDTRY; if (!ex_thrown) { printf("04: Failed TVB=%s No BoundsError when retrieving 2 bytes from" " offset -1\n", name); failed = TRUE; return FALSE; } /* Test boundary case. A BoundsError exception should not be thrown. */ ex_thrown = FALSE; TRY { tvb_get_ptr(tvb, 0, 1); } CATCH(BoundsError) { ex_thrown = TRUE; } CATCH(FragmentBoundsError) { printf("05: Caught wrong exception: FragmentBoundsError\n"); } CATCH(ReportedBoundsError) { printf("05: Caught wrong exception: ReportedBoundsError\n"); } CATCH_ALL { printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n"); } ENDTRY; if (ex_thrown) { printf("05: Failed TVB=%s BoundsError when retrieving 1 bytes from" " offset 0\n", name); failed = TRUE; return FALSE; } /* Test boundary case. A BoundsError exception should not be thrown. */ ex_thrown = FALSE; TRY { tvb_get_ptr(tvb, -1, 1); } CATCH(BoundsError) { ex_thrown = TRUE; } CATCH(FragmentBoundsError) { printf("06: Caught wrong exception: FragmentBoundsError\n"); } CATCH(ReportedBoundsError) { printf("06: Caught wrong exception: ReportedBoundsError\n"); } CATCH_ALL { printf("02: Caught wrong exception: %lu, exc->except_id.except_code\n"); } ENDTRY; if (ex_thrown) { printf("06: Failed TVB=%s BoundsError when retrieving 1 bytes from" " offset -1\n", name); failed = TRUE; return FALSE; } /* Check data at boundary. An exception should not be thrown. */ if (length >= 4) { ex_thrown = FALSE; TRY { val32 = tvb_get_ntohl(tvb, 0); } CATCH_ALL { ex_thrown = TRUE; } ENDTRY; if (ex_thrown) { printf("07: Failed TVB=%s Exception when retrieving " "guint32 from offset 0\n", name); failed = TRUE; return FALSE; } expected32 = pntohl(expected_data); if (val32 != expected32) { printf("08: Failed TVB=%s guint32 @ 0 %u != expected %u\n", name, val32, expected32); failed = TRUE; return FALSE; } }
return 10; else if ( (flagsValue & esl_port11_bitmask) != 0 ) return 11; return -1; } /*esl*/ static void dissect_esl_header(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree) { proto_item *ti = NULL; proto_tree *esl_header_tree; gint offset = 0; guint esl_length = tvb_reported_length(tvb); if ( esl_length >= SIZEOF_ESLHEADER ) { if (tree) { guint16 flags; ti = proto_tree_add_item(tree, proto_esl, tvb, 0, SIZEOF_ESLHEADER, TRUE); esl_header_tree = proto_item_add_subtree(ti, ett_esl); offset+=6; flags = tvb_get_letohs(tvb, offset); proto_tree_add_uint(esl_header_tree, hf_esl_port, tvb, offset, 2, flags_to_port(flags)); proto_tree_add_item(esl_header_tree, hf_esl_crcerror, tvb, offset, 2, TRUE); proto_tree_add_item(esl_header_tree, hf_esl_alignerror, tvb, offset, 2, TRUE);
static void dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { proto_item *volatile ti = NULL, *comment_item; guint cap_len = 0, frame_len = 0; proto_tree *volatile tree; proto_tree *comments_tree; proto_item *item; const gchar *cap_plurality, *frame_plurality; tree=parent_tree; switch (pinfo->phdr->rec_type) { case REC_TYPE_PACKET: pinfo->current_proto = "Frame"; if (pinfo->pseudo_header != NULL) { switch (pinfo->fd->lnk_t) { case WTAP_ENCAP_WFLEET_HDLC: case WTAP_ENCAP_CHDLC_WITH_PHDR: case WTAP_ENCAP_PPP_WITH_PHDR: case WTAP_ENCAP_SDLC: case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR: pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ? P2P_DIR_SENT : P2P_DIR_RECV; break; case WTAP_ENCAP_BLUETOOTH_HCI: pinfo->p2p_dir = pinfo->pseudo_header->bthci.sent; break; case WTAP_ENCAP_LAPB: case WTAP_ENCAP_FRELAY_WITH_PHDR: pinfo->p2p_dir = (pinfo->pseudo_header->x25.flags & FROM_DCE) ? P2P_DIR_RECV : P2P_DIR_SENT; break; case WTAP_ENCAP_ISDN: case WTAP_ENCAP_V5_EF: case WTAP_ENCAP_DPNSS: case WTAP_ENCAP_BACNET_MS_TP_WITH_PHDR: pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton ? P2P_DIR_SENT : P2P_DIR_RECV; break; case WTAP_ENCAP_LINUX_LAPD: pinfo->p2p_dir = (pinfo->pseudo_header->lapd.pkttype == 3 || pinfo->pseudo_header->lapd.pkttype == 4) ? P2P_DIR_SENT : P2P_DIR_RECV; break; case WTAP_ENCAP_MTP2_WITH_PHDR: pinfo->p2p_dir = pinfo->pseudo_header->mtp2.sent ? P2P_DIR_SENT : P2P_DIR_RECV; pinfo->link_number = pinfo->pseudo_header->mtp2.link_number; pinfo->annex_a_used = pinfo->pseudo_header->mtp2.annex_a_used; break; case WTAP_ENCAP_GSM_UM: pinfo->p2p_dir = pinfo->pseudo_header->gsm_um.uplink ? P2P_DIR_SENT : P2P_DIR_RECV; break; } } break; case REC_TYPE_FT_SPECIFIC_EVENT: pinfo->current_proto = "Event"; break; case REC_TYPE_FT_SPECIFIC_REPORT: pinfo->current_proto = "Report"; break; default: g_assert_not_reached(); break; } if(pinfo->pkt_comment){ item = proto_tree_add_item(tree, proto_pkt_comment, tvb, 0, 0, ENC_NA); comments_tree = proto_item_add_subtree(item, ett_comments); comment_item = proto_tree_add_string_format(comments_tree, hf_comments_text, tvb, 0, 0, pinfo->pkt_comment, "%s", pinfo->pkt_comment); expert_add_info_format(pinfo, comment_item, &ei_comments_text, "%s", pinfo->pkt_comment); } /* if FRAME is not referenced from any filters we don't need to worry about generating any tree items. */ if(!proto_field_is_referenced(tree, proto_frame)) { tree=NULL; if(pinfo->fd->flags.has_ts) { if(pinfo->fd->abs_ts.nsecs < 0 || pinfo->fd->abs_ts.nsecs >= 1000000000) expert_add_info(pinfo, NULL, &ei_arrive_time_out_of_range); } } else { proto_tree *fh_tree; gboolean old_visible; /* Put in frame header information. */ cap_len = tvb_length(tvb); frame_len = tvb_reported_length(tvb); cap_plurality = plurality(cap_len, "", "s"); frame_plurality = plurality(frame_len, "", "s"); ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_captured_length(tvb), "Frame %u: %u byte%s on wire", pinfo->fd->num, frame_len, frame_plurality); if (generate_bits_field) proto_item_append_text(ti, " (%u bits)", frame_len * 8); proto_item_append_text(ti, ", %u byte%s captured", cap_len, cap_plurality); if (generate_bits_field) { proto_item_append_text(ti, " (%u bits)", cap_len * 8); } if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) { proto_item_append_text(ti, " on interface %u", pinfo->phdr->interface_id); } if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) { if (pinfo->phdr->pack_flags & 0x00000001) { proto_item_append_text(ti, " (inbound)"); pinfo->p2p_dir = P2P_DIR_RECV; } if (pinfo->phdr->pack_flags & 0x00000002) { proto_item_append_text(ti, " (outbound)"); pinfo->p2p_dir = P2P_DIR_SENT; } } fh_tree = proto_item_add_subtree(ti, ett_frame); if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID && proto_field_is_referenced(tree, hf_frame_interface_id)) { const char *interface_name = epan_get_interface_name(pinfo->epan, pinfo->phdr->interface_id); if (interface_name) proto_tree_add_uint_format_value(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id, "%u (%s)", pinfo->phdr->interface_id, interface_name); else proto_tree_add_uint(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id); } if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) { proto_tree *flags_tree; proto_item *flags_item; flags_item = proto_tree_add_uint(fh_tree, hf_frame_pack_flags, tvb, 0, 0, pinfo->phdr->pack_flags); flags_tree = proto_item_add_subtree(flags_item, ett_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_direction, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_reception_type, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_fcs_length, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_uint(flags_tree, hf_frame_pack_reserved, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_crc_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_long_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_short_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_inter_frame_gap_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_unaligned_frame_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_start_frame_delimiter_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_preamble_error, tvb, 0, 0, pinfo->phdr->pack_flags); proto_tree_add_boolean(flags_tree, hf_frame_pack_symbol_error, tvb, 0, 0, pinfo->phdr->pack_flags); } if (pinfo->phdr->rec_type == REC_TYPE_PACKET) proto_tree_add_int(fh_tree, hf_frame_wtap_encap, tvb, 0, 0, pinfo->fd->lnk_t); if (pinfo->fd->flags.has_ts) { proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb, 0, 0, &(pinfo->fd->abs_ts)); if(pinfo->fd->abs_ts.nsecs < 0 || pinfo->fd->abs_ts.nsecs >= 1000000000) { expert_add_info_format(pinfo, ti, &ei_arrive_time_out_of_range, "Arrival Time: Fractional second %09ld is invalid," " the valid range is 0-1000000000", (long) pinfo->fd->abs_ts.nsecs); } item = proto_tree_add_time(fh_tree, hf_frame_shift_offset, tvb, 0, 0, &(pinfo->fd->shift_offset)); PROTO_ITEM_SET_GENERATED(item); if(generate_epoch_time) { proto_tree_add_time(fh_tree, hf_frame_arrival_time_epoch, tvb, 0, 0, &(pinfo->fd->abs_ts)); } if (proto_field_is_referenced(tree, hf_frame_time_delta)) { nstime_t del_cap_ts; frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->fd->num - 1, &del_cap_ts); item = proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb, 0, 0, &(del_cap_ts)); PROTO_ITEM_SET_GENERATED(item); } if (proto_field_is_referenced(tree, hf_frame_time_delta_displayed)) { nstime_t del_dis_ts; frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->fd->prev_dis_num, &del_dis_ts); item = proto_tree_add_time(fh_tree, hf_frame_time_delta_displayed, tvb, 0, 0, &(del_dis_ts)); PROTO_ITEM_SET_GENERATED(item); } item = proto_tree_add_time(fh_tree, hf_frame_time_relative, tvb, 0, 0, &(pinfo->rel_ts)); PROTO_ITEM_SET_GENERATED(item); if(pinfo->fd->flags.ref_time){ ti = proto_tree_add_item(fh_tree, hf_frame_time_reference, tvb, 0, 0, ENC_NA); PROTO_ITEM_SET_GENERATED(ti); } } proto_tree_add_uint(fh_tree, hf_frame_number, tvb, 0, 0, pinfo->fd->num); proto_tree_add_uint_format(fh_tree, hf_frame_len, tvb, 0, 0, frame_len, "Frame Length: %u byte%s (%u bits)", frame_len, frame_plurality, frame_len * 8); proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, tvb, 0, 0, cap_len, "Capture Length: %u byte%s (%u bits)", cap_len, cap_plurality, cap_len * 8); if (generate_md5_hash) { const guint8 *cp; md5_state_t md_ctx; md5_byte_t digest[16]; const gchar *digest_string; cp = tvb_get_ptr(tvb, 0, cap_len); md5_init(&md_ctx); md5_append(&md_ctx, cp, cap_len); md5_finish(&md_ctx, digest); digest_string = bytestring_to_str(wmem_packet_scope(), digest, 16, '\0'); ti = proto_tree_add_string(fh_tree, hf_frame_md5_hash, tvb, 0, 0, digest_string); PROTO_ITEM_SET_GENERATED(ti); } ti = proto_tree_add_boolean(fh_tree, hf_frame_marked, tvb, 0, 0,pinfo->fd->flags.marked); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_boolean(fh_tree, hf_frame_ignored, tvb, 0, 0,pinfo->fd->flags.ignored); PROTO_ITEM_SET_GENERATED(ti); if(proto_field_is_referenced(tree, hf_frame_protocols)) { /* we are going to be using proto_item_append_string() on * hf_frame_protocols, and we must therefore disable the * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by * setting it as visible. * * See proto.h for details. */ old_visible = proto_tree_set_visible(fh_tree, TRUE); ti = proto_tree_add_string(fh_tree, hf_frame_protocols, tvb, 0, 0, ""); PROTO_ITEM_SET_GENERATED(ti); proto_tree_set_visible(fh_tree, old_visible); } /* Check for existences of P2P pseudo header */ if (pinfo->p2p_dir != P2P_DIR_UNKNOWN) { proto_tree_add_int(fh_tree, hf_frame_p2p_dir, tvb, 0, 0, pinfo->p2p_dir); } /* Check for existences of MTP2 link number */ if ((pinfo->pseudo_header != NULL ) && (pinfo->fd->lnk_t == WTAP_ENCAP_MTP2_WITH_PHDR)) { proto_tree_add_uint(fh_tree, hf_link_number, tvb, 0, 0, pinfo->link_number); } if (show_file_off) { proto_tree_add_int64_format_value(fh_tree, hf_frame_file_off, tvb, 0, 0, pinfo->fd->file_off, "%" G_GINT64_MODIFIER "d (0x%" G_GINT64_MODIFIER "x)", pinfo->fd->file_off, pinfo->fd->file_off); } if(pinfo->fd->color_filter != NULL) { const color_filter_t *color_filter = (const color_filter_t *)pinfo->fd->color_filter; item = proto_tree_add_string(fh_tree, hf_frame_color_filter_name, tvb, 0, 0, color_filter->filter_name); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_string(fh_tree, hf_frame_color_filter_text, tvb, 0, 0, color_filter->filter_text); PROTO_ITEM_SET_GENERATED(item); } } if (pinfo->fd->flags.ignored) { /* Ignored package, stop handling here */ col_set_str(pinfo->cinfo, COL_INFO, "<Ignored>"); proto_tree_add_text (tree, tvb, 0, 0, "This frame is marked as ignored"); return; } /* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */ TRY { #ifdef _MSC_VER /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations. (a running debugger will be called before the except part below) */ /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling) stack in an inconsistent state thus causing a crash at some point in the handling of the exception. See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html */ __try { #endif switch (pinfo->phdr->rec_type) { case REC_TYPE_PACKET: if ((force_docsis_encap) && (docsis_handle)) { call_dissector(docsis_handle, tvb, pinfo, parent_tree); } else { if (!dissector_try_uint(wtap_encap_dissector_table, pinfo->fd->lnk_t, tvb, pinfo, parent_tree)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN"); col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %d", pinfo->fd->lnk_t); call_dissector(data_handle,tvb, pinfo, parent_tree); } } break; case REC_TYPE_FT_SPECIFIC_EVENT: case REC_TYPE_FT_SPECIFIC_REPORT: if (!dissector_try_uint(wtap_fts_rec_dissector_table, pinfo->file_type_subtype, tvb, pinfo, parent_tree)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN"); col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %d", pinfo->file_type_subtype); call_dissector(data_handle,tvb, pinfo, parent_tree); } break; } #ifdef _MSC_VER } __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) { switch(GetExceptionCode()) { case(STATUS_ACCESS_VIOLATION): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address"); break; case(STATUS_INTEGER_DIVIDE_BY_ZERO): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero"); break; case(STATUS_STACK_OVERFLOW): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)"); /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */ break; /* XXX - add other hardware exception codes as required */ default: show_exception(tvb, pinfo, parent_tree, DissectorError, g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode())); } } #endif } CATCH_BOUNDS_AND_DISSECTOR_ERRORS { show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; if(proto_field_is_referenced(tree, hf_frame_protocols)) { wmem_strbuf_t *val = wmem_strbuf_sized_new(wmem_packet_scope(), 128, 0); wmem_list_frame_t *frame; /* skip the first entry, it's always the "frame" protocol */ frame = wmem_list_frame_next(wmem_list_head(pinfo->layers)); if (frame) { wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)))); frame = wmem_list_frame_next(frame); } while (frame) { wmem_strbuf_append_c(val, ':'); wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)))); frame = wmem_list_frame_next(frame); } proto_item_append_string(ti, wmem_strbuf_get_str(val)); } /* Call postdissectors if we have any (while trying to avoid another * TRY/CATCH) */ if (have_postdissector()) { TRY { #ifdef _MSC_VER /* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions like memory access violations */ /* (a running debugger will be called before the except part below) */ /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling) stack in an inconsistent state thus causing a crash at some point in the handling of the exception. See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html */ __try { #endif call_all_postdissectors(tvb, pinfo, parent_tree); #ifdef _MSC_VER } __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) { switch(GetExceptionCode()) { case(STATUS_ACCESS_VIOLATION): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address"); break; case(STATUS_INTEGER_DIVIDE_BY_ZERO): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero"); break; case(STATUS_STACK_OVERFLOW): show_exception(tvb, pinfo, parent_tree, DissectorError, "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)"); /* XXX - this will have probably corrupted the stack, which makes problems later in the exception code */ break; /* XXX - add other hardware exception codes as required */ default: show_exception(tvb, pinfo, parent_tree, DissectorError, g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode())); } } #endif } CATCH_BOUNDS_AND_DISSECTOR_ERRORS { show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; } tap_queue_packet(frame_tap, pinfo, NULL); if (pinfo->frame_end_routines) { g_slist_foreach(pinfo->frame_end_routines, &call_frame_end_routine, NULL); g_slist_free(pinfo->frame_end_routines); pinfo->frame_end_routines = NULL; } }
static int dissect_mpls_y1711(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { struct mplsinfo *mplsinfo; int offset = 0; proto_item *ti; proto_tree *mpls_y1711_tree; int functype; tvbuff_t *data_tvb; static const guint8 allone[] = { 0xff, 0xff }; static const guint8 allzero[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* Reject the packet if data is NULL */ if (data == NULL) return 0; mplsinfo = (struct mplsinfo *)data; functype = tvb_get_guint8(tvb, offset); col_append_fstr(pinfo->cinfo, COL_INFO, " (Y.1711: %s)", (functype == 0x01) ? "CV" : (functype == 0x02) ? "FDI" : (functype == 0x03) ? "BDI" : (functype == 0x07) ? "FDD" : "reserved/unknown"); /* sanity checks */ if (tvb_reported_length(tvb) < 44) { /* * ITU-T Y.1711, 5.3: PDUs must have a minimum payload length of * 44 bytes */ proto_tree_add_expert(tree, pinfo, &ei_mpls_y1711_minimum_payload, tvb, offset, -1); data_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, data_tvb, pinfo, tree); return tvb_reported_length(tvb); } ti = proto_tree_add_text(tree, tvb, offset, 44, "Y.1711 OAM"); mpls_y1711_tree = proto_item_add_subtree(ti, ett_mpls_y1711); /* checks for exp, bos and ttl encoding */ if (mplsinfo->label != MPLS_LABEL_OAM_ALERT) proto_tree_add_expert_format(mpls_y1711_tree, pinfo, &ei_mpls_y1711_no_OAM_alert_label, tvb, offset - 4, 3, "Warning: Y.1711 but no OAM alert label (%d) ?!", MPLS_LABEL_OAM_ALERT); if (mplsinfo->exp != 0) proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_exp_bits_not_zero, tvb, offset - 2, 1); if (mplsinfo->bos != 1) proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_s_bit_not_one, tvb, offset - 2, 1); if (mplsinfo->ttl != 1) proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_ttl_not_one, tvb, offset - 1, 1); /* starting dissection */ functype = tvb_get_guint8(tvb, offset); proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_function_type, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; switch (functype) { case 0x01: /* CV */ { /* 3 octets reserved (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 3) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_reserved_not_zero, tvb, offset, 3); } offset += 3; /* ttsi (ipv4 flavor as in RFC 2373) */ if (tvb_memeql(tvb, offset, allzero, 10) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 10); } offset += 10; if (tvb_memeql(tvb, offset, allone, 2) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_ff, tvb, offset, 2); } offset += 2; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsr_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsp_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* 18 octets of padding (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 18) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 18); } offset += 18; } break; case 0x02: /* FDI */ case 0x03: /* BDI */ { /* 1 octets reserved (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 1) == -1) { proto_tree_add_expert_format(mpls_y1711_tree, pinfo, &ei_mpls_y1711_reserved_not_zero, tvb, offset, 3, "Error: this byte is reserved and must be 0x00"); } offset++; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_defect_type, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* * ttsi (ipv4 flavor as in RFC 2373) is optional if not used must * be set to all 0x00 */ if (tvb_memeql(tvb, offset, allzero, 20) == 0) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_ttsi_not_preset, tvb, offset, 20); offset += 20; } else { if (tvb_memeql(tvb, offset, allzero, 10) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 10); } offset += 10; if (tvb_memeql(tvb, offset, allone, 2) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_ff, tvb, offset, 2); } offset += 2; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsr_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsp_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } /* defect location */ proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_defect_location, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* 14 octets of padding (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 14) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 14); } offset += 14; } break; case 0x07: /* FDD */ { /* 3 octets reserved (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 3) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_reserved_not_zero, tvb, offset, 3); } offset += 3; /* ttsi (ipv4 flavor as in RFC 2373) */ if (tvb_memeql(tvb, offset, allzero, 10) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 10); } offset += 10; if (tvb_memeql(tvb, offset, allone, 2) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_ff, tvb, offset, 2); } offset += 2; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsr_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_lsp_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_frequency, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; /* 17 octets of padding (all 0x00) */ if (tvb_memeql(tvb, offset, allzero, 17) == -1) { proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_padding_not_zero, tvb, offset, 17); } offset += 17; } break; default: proto_tree_add_expert(mpls_y1711_tree, pinfo, &ei_mpls_y1711_unknown_pdu, tvb, offset - 1, -1); return offset; } /* BIP16 */ proto_tree_add_item(mpls_y1711_tree, hf_mpls_y1711_bip16, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; }
static int dissect_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_item *ti_bdt; proto_item *ti_fdt; proto_tree *bvlc_tree; proto_tree *bdt_tree; /* Broadcast Distribution Table */ proto_tree *fdt_tree; /* Foreign Device Table */ gint offset; guint8 bvlc_type; guint8 bvlc_function; guint16 bvlc_length; guint16 packet_length; guint npdu_length; guint length_remaining; guint16 bvlc_result; tvbuff_t *next_tvb; offset = 0; bvlc_type = tvb_get_guint8(tvb, offset); /* * Simple sanity check - make sure the type is one we know about. */ if (match_strval(bvlc_type, bvlc_types) == NULL) return 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "BVLC"); col_set_str(pinfo->cinfo, COL_INFO, "BACnet Virtual Link Control"); bvlc_function = tvb_get_guint8(tvb, offset+1); packet_length = tvb_get_ntohs(tvb, offset+2); length_remaining = tvb_reported_length_remaining(tvb, offset); if (bvlc_function > 0x08) { /* We have a constant header length of BVLC of 4 in every * BVLC-packet forewarding an NPDU. Beware: Changes in the * BACnet-IP-standard may break this. * At the moment, no functions above 0x0b * exist (Addendum 135a to ANSI/ASHRAE 135-1995 - BACnet) */ bvlc_length = 4; } else if(bvlc_function == 0x04) { /* 4 Bytes + 6 Bytes for B/IP Address of Originating Device */ bvlc_length = 10; } else { /* BVLC-packets with function below 0x09 contain * routing-level data (e.g. Broadcast Distribution) * but no NPDU for BACnet, so bvlc_length goes up to the end * of the captured frame. */ bvlc_length = packet_length; } if (tree) { if (bvlc_length < 4) { proto_tree_add_text(tree, tvb, 2, 2, "Bogus length: %d", bvlc_length); return tvb_reported_length(tvb); /* XXX - reject? */ } ti = proto_tree_add_item(tree, proto_bvlc, tvb, 0, bvlc_length, ENC_NA); bvlc_tree = proto_item_add_subtree(ti, ett_bvlc); proto_tree_add_uint(bvlc_tree, hf_bvlc_type, tvb, offset, 1, bvlc_type); offset ++; proto_tree_add_uint(bvlc_tree, hf_bvlc_function, tvb, offset, 1, bvlc_function); offset ++; if (length_remaining != packet_length) proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset, 2, bvlc_length, "%d of %d bytes (invalid length - expected %d bytes)", bvlc_length, packet_length, length_remaining); else proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset, 2, bvlc_length, "%d of %d bytes BACnet packet length", bvlc_length, packet_length); offset += 2; switch (bvlc_function) { case 0x00: /* BVLC-Result */ bvlc_result = tvb_get_ntohs(tvb, offset); /* I dont know why the result code is encoded in 4 nibbles, * but only using one: 0x00r0. Shifting left 4 bits. */ /* We should bitmask the result correctly when we have a * packet to dissect, see README.developer, 1.6.2, FID */ proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_result, tvb, offset, 2, bvlc_result,"0x%04x (%s)", bvlc_result, val_to_str(bvlc_result, bvlc_result_names, "Unknown")); offset += 2; break; case 0x01: /* Write-Broadcast-Distribution-Table */ case 0x03: /* Read-Broadcast-Distribution-Table-Ack */ /* List of BDT Entries: N*10-octet */ ti_bdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb, offset, bvlc_length-4, ENC_NA); bdt_tree = proto_item_add_subtree(ti_bdt, ett_bdt); /* List of BDT Entries: N*10-octet */ while ((bvlc_length - offset) > 9) { proto_tree_add_item(bdt_tree, hf_bvlc_bdt_ip, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(bdt_tree, hf_bvlc_bdt_port, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(bdt_tree, hf_bvlc_bdt_mask, tvb, offset, 4, ENC_NA); offset += 4; } /* We check this if we get a BDT-packet somewhere */ break; case 0x02: /* Read-Broadcast-Distribution-Table */ /* nothing to do here */ break; case 0x05: /* Register-Foreign-Device */ /* Time-to-Live 2-octets T, Time-to-Live T, in seconds */ proto_tree_add_item(bvlc_tree, hf_bvlc_reg_ttl, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; case 0x06: /* Read-Foreign-Device-Table */ /* nothing to do here */ break; case 0x07: /* Read-Foreign-Device-Table-Ack */ /* List of FDT Entries: N*10-octet */ /* N indicates the number of entries in the FDT whose * contents are being returned. Each returned entry * consists of the 6-octet B/IP address of the registrant; * the 2-octet Time-to-Live value supplied at the time of * registration; and a 2-octet value representing the * number of seconds remaining before the BBMD will purge * the registrant's FDT entry if no re-registration occurs. */ ti_fdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb, offset, bvlc_length -4, ENC_NA); fdt_tree = proto_item_add_subtree(ti_fdt, ett_fdt); /* List of FDT Entries: N*10-octet */ while ((bvlc_length - offset) > 9) { proto_tree_add_item(fdt_tree, hf_bvlc_fdt_ip, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(fdt_tree, hf_bvlc_fdt_port, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(fdt_tree, hf_bvlc_fdt_ttl, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(fdt_tree, hf_bvlc_fdt_timeout, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } /* We check this if we get a FDT-packet somewhere */ break; case 0x08: /* Delete-Foreign-Device-Table-Entry */ /* FDT Entry: 6-octets */ proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_ip, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_port, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; /* We check this if we get a FDT-packet somewhere */ case 0x04: /* Forwarded-NPDU * Why is this 0x04? It would have been a better * idea to append all forewarded NPDUs at the * end of the function table in the B/IP-standard! */ /* proto_tree_add_bytes_format(); */ proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_ip, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_port, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; default:/* Distribute-Broadcast-To-Network * Original-Unicast-NPDU * Original-Broadcast-NPDU * Going to the next dissector... */ break; } } /* Ok, no routing information BVLC packet. Dissect as * BACnet NPDU */ npdu_length = packet_length - bvlc_length; next_tvb = tvb_new_subset(tvb,bvlc_length,-1,npdu_length); /* Code from Guy Harris */ if (!dissector_try_uint(bvlc_dissector_table, bvlc_function, next_tvb, pinfo, tree)) { /* Unknown function - dissect the paylod as data */ call_dissector(data_handle,next_tvb, pinfo, tree); } return tvb_reported_length(tvb); }
static void dissect_smb_direct(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, enum SMB_DIRECT_HDR_TYPE hdr_type) { proto_tree *tree = NULL; proto_item *item = NULL; proto_tree *neg_req_tree = NULL; proto_tree *neg_rep_tree = NULL; proto_tree *data_tree = NULL; int offset = 0; guint32 status = 0; guint32 remaining_length = 0; guint32 data_offset = 0; guint32 data_length = 0; guint rlen = tvb_reported_length(tvb); gint len = 0; tvbuff_t *next_tvb = NULL; static const int * flags[] = { &hf_smb_direct_flags_response_requested, NULL }; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMBDirect"); col_clear(pinfo->cinfo, COL_INFO); if (parent_tree != NULL) { item = proto_tree_add_item(parent_tree, proto_smb_direct, tvb, 0, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb_direct); } switch (hdr_type) { case SMB_DIRECT_HDR_UNKNOWN: break; case SMB_DIRECT_HDR_NEG_REQ: col_append_str(pinfo->cinfo, COL_INFO, "NegotiateRequest"); if (tree == NULL) { break; } item = proto_tree_add_item(tree, hf_smb_direct_negotiate_request, tvb, 0, -1, ENC_NA); neg_req_tree = proto_item_add_subtree(item, ett_smb_direct_hdr); proto_tree_add_item(neg_req_tree, hf_smb_direct_min_version, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_req_tree, hf_smb_direct_max_version, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* 2 bytes reserved */ offset += 2; proto_tree_add_item(neg_req_tree, hf_smb_direct_credits_requested, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_req_tree, hf_smb_direct_preferred_send_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_req_tree, hf_smb_direct_max_receive_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_req_tree, hf_smb_direct_max_fragmented_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); /* offset += 4; */ break; case SMB_DIRECT_HDR_NEG_REP: col_append_str(pinfo->cinfo, COL_INFO, "NegotiateResponse"); status = tvb_get_letohl(tvb, 12); if (status != 0) { col_append_fstr( pinfo->cinfo, COL_INFO, ", Error: %s", val_to_str(status, NT_errors, "Unknown (0x%08X)")); } if (tree == NULL) { break; } item = proto_tree_add_item(tree, hf_smb_direct_negotiate_response, tvb, 0, -1, ENC_NA); neg_rep_tree = proto_item_add_subtree(item, ett_smb_direct_hdr); proto_tree_add_item(neg_rep_tree, hf_smb_direct_min_version, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_version, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_rep_tree, hf_smb_direct_negotiated_version, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* 2 bytes reserved */ offset += 2; proto_tree_add_item(neg_rep_tree, hf_smb_direct_credits_requested, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_rep_tree, hf_smb_direct_credits_granted, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_rep_tree, hf_smb_direct_status, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_read_write_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_rep_tree, hf_smb_direct_preferred_send_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_receive_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_fragmented_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); /* offset += 4; */ break; case SMB_DIRECT_HDR_DATA: col_append_str(pinfo->cinfo, COL_INFO, "DataMessage"); if (tree == NULL) { break; } rlen = MIN(rlen, 24); item = proto_tree_add_item(tree, hf_smb_direct_data_message, tvb, 0, rlen, ENC_NA); data_tree = proto_item_add_subtree(item, ett_smb_direct_hdr); proto_tree_add_item(data_tree, hf_smb_direct_credits_requested, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(data_tree, hf_smb_direct_credits_granted, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_bitmask(tree, tvb, offset, hf_smb_direct_flags, ett_smb_direct_flags, flags, ENC_LITTLE_ENDIAN); offset += 2; /* 2 bytes reserved */ offset += 2; remaining_length = tvb_get_letohl(tvb, offset); proto_tree_add_item(data_tree, hf_smb_direct_remaining_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; data_offset = tvb_get_letohl(tvb, offset); proto_tree_add_item(data_tree, hf_smb_direct_data_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; data_length = tvb_get_letohl(tvb, offset); proto_tree_add_item(data_tree, hf_smb_direct_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; if (data_length > 0 && data_offset > (guint32)offset) { len = tvb_reported_length_remaining(tvb, data_offset); } if (data_length <= (guint32)len) { next_tvb = tvb_new_subset_length(tvb, data_offset, data_length); } if (next_tvb != NULL) { dissect_smb_direct_payload(next_tvb, pinfo, parent_tree, remaining_length); } /* offset = data_offset + data_length; */ break; } return; }
/* ---------------------------------------------- */ static void dissect_fix_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *fix_tree; int pdu_len; int offset = 0; int field_offset, ctrla_offset; int tag_value; char *value; char *tag_str; fix_parameter *tag; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FIX"); col_clear(pinfo->cinfo, COL_INFO); /* get at least the fix version: 8=FIX.x.x */ if (fix_marker(tvb, 0) != 0) { /* not a fix packet start but it's a fix packet */ col_set_str(pinfo->cinfo, COL_INFO, "[FIX continuation]"); ti = proto_tree_add_item(tree, proto_fix, tvb, 0, -1, ENC_NA); fix_tree = proto_item_add_subtree(ti, ett_fix); proto_tree_add_item(fix_tree, hf_fix_data, tvb, 0, -1, ENC_NA); return; } pdu_len = tvb_reported_length(tvb); ti = proto_tree_add_item(tree, proto_fix, tvb, 0, -1, ENC_NA); fix_tree = proto_item_add_subtree(ti, ett_fix); /* begin string */ ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01); if (ctrla_offset == -1) { return; } offset = ctrla_offset + 1; /* msg length */ ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01); if (ctrla_offset == -1) { return; } offset = ctrla_offset + 1; /* msg type */ if (!(tag = fix_param(tvb, offset)) || tag->value_len < 1) { return; } if (check_col(pinfo->cinfo, COL_INFO)) { const char *msg_type; value = tvb_get_ephemeral_string(tvb, tag->value_offset, tag->value_len); msg_type = str_to_str(value, messages_val, "FIX Message (%s)"); col_add_str(pinfo->cinfo, COL_INFO, msg_type); } /* In the interest of speed, if "tree" is NULL, don't do any work not * necessary to generate protocol tree items. */ field_offset = 0; while(field_offset < pdu_len && (tag = fix_param(tvb, field_offset)) ) { int i, found; if (tag->tag_len < 1) { field_offset = tag->ctrla_offset + 1; continue; } tag_str = tvb_get_ephemeral_string(tvb, field_offset, tag->tag_len); tag_value = atoi(tag_str); if (tag->value_len < 1) { proto_tree *field_tree; /* XXX - put an error indication here. It's too late to return FALSE; we've already started dissecting, and if a heuristic dissector starts dissecting (either updating the columns or creating a protocol tree) and then gives up, it leaves crud behind that messes up other dissectors that might process the packet. */ ti = proto_tree_add_text(fix_tree, tvb, field_offset, tag->field_len, "%i: <missing value>", tag_value); field_tree = proto_item_add_subtree(ti, ett_badfield); proto_tree_add_uint(field_tree, hf_fix_field_tag, tvb, field_offset, tag->tag_len, tag_value); field_offset = tag->ctrla_offset + 1; continue; } /* fix_fields array is sorted by tag_value */ found = 0; if ((i = tag_search(tag_value)) >= 0) { found = 1; } value = tvb_get_ephemeral_string(tvb, tag->value_offset, tag->value_len); if (found) { if (fix_fields[i].table) { if (tree) { switch (fix_fields[i].type) { case 1: /* strings */ proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s (%s)", value, str_to_str(value, fix_fields[i].table, "unknown %s")); break; case 2: /* char */ proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s (%s)", value, val_to_str(*value, fix_fields[i].table, "unknown %d")); break; default: proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s (%s)", value, val_to_str(atoi(value), fix_fields[i].table, "unknown %d")); break; } } } else { proto_item *item; /* checksum */ switch(tag_value) { case 10: { proto_tree *checksum_tree; guint8 sum = 0; const guint8 *data = tvb_get_ptr(tvb, 0, field_offset); gboolean sum_ok; int j; for (j = 0; j < field_offset; j++, data++) { sum += *data; } sum_ok = (atoi(value) == sum); if (sum_ok) { item = proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s [correct]", value); } else { item = proto_tree_add_string_format_value(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value, "%s [incorrect should be %d]", value, sum); } checksum_tree = proto_item_add_subtree(item, ett_checksum); item = proto_tree_add_boolean(checksum_tree, hf_fix_checksum_good, tvb, field_offset, tag->field_len, sum_ok); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_fix_checksum_bad, tvb, field_offset, tag->field_len, !sum_ok); PROTO_ITEM_SET_GENERATED(item); if (!sum_ok) expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum"); } break; default: proto_tree_add_string(fix_tree, fix_fields[i].hf_id, tvb, field_offset, tag->field_len, value); break; } } } else if (tree) { proto_tree *field_tree; /* XXX - it could be -1 if the tag isn't a number */ ti = proto_tree_add_text(fix_tree, tvb, field_offset, tag->field_len, "%i: %s", tag_value, value); field_tree = proto_item_add_subtree(ti, ett_unknow); proto_tree_add_uint(field_tree, hf_fix_field_tag, tvb, field_offset, tag->tag_len, tag_value); proto_tree_add_item(field_tree, hf_fix_field_value, tvb, tag->value_offset, tag->value_len, ENC_ASCII|ENC_NA); } field_offset = tag->ctrla_offset + 1; tag_str = NULL; } return; }
case 8: return tvb_get_guint64(tvb, offset, encoding); } return 0; } static int dissect_uds(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void* data _U_) { proto_tree *uds_tree, *subtree; proto_item *ti; guint8 sid, service; guint32 enum_val; const char *service_name; guint32 data_length = tvb_reported_length(tvb); col_set_str(pinfo->cinfo, COL_PROTOCOL, "UDS"); col_clear(pinfo->cinfo,COL_INFO); sid = tvb_get_guint8(tvb, UDS_SID_OFFSET); service = sid & UDS_SID_MASK; service_name = val_to_str(service, uds_services, "Unknown (0x%02x)"); col_add_fstr(pinfo->cinfo, COL_INFO, "%-7s %-36s", (sid & UDS_REPLY_MASK)? "Reply": "Request", service_name); ti = proto_tree_add_item(tree, proto_uds, tvb, 0, -1, ENC_NA); uds_tree = proto_item_add_subtree(ti, ett_uds); proto_tree_add_item(uds_tree, hf_uds_service, tvb, UDS_SID_OFFSET, UDS_SID_LEN, ENC_BIG_ENDIAN); proto_tree_add_item(uds_tree, hf_uds_reply, tvb, UDS_SID_OFFSET, UDS_SID_LEN, ENC_BIG_ENDIAN);
/*ams*/ static gint dissect_ams(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti, *anItem; proto_tree *ams_tree = NULL, *ams_adstree, *ams_statetree; gint offset = 0; guint ams_length = tvb_reported_length(tvb); guint16 stateflags = 0; guint16 cmdId = 0; char szText[200]; int nMax = sizeof(szText)-1; col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMS"); col_clear(pinfo->cinfo, COL_INFO); if( pinfo->ethertype != 0x88a4 ) { if( TcpAdsParserHDR_Len > ams_length ) return offset; ams_length -= TcpAdsParserHDR_Len; offset = TcpAdsParserHDR_Len; } if( ams_length < AmsHead_Len ) return offset; if (tree) { ti = proto_tree_add_item(tree, proto_ams, tvb, 0, -1, ENC_NA); ams_tree = proto_item_add_subtree(ti, ett_ams); NetIdFormater(tvb, offset, szText, nMax); proto_tree_add_string(ams_tree, hf_ams_targetnetid, tvb, offset, AmsNetId_Len, szText); offset += AmsNetId_Len; proto_tree_add_item(ams_tree, hf_ams_targetport, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); offset += sizeof(guint16); NetIdFormater(tvb, offset, szText, nMax); proto_tree_add_string(ams_tree, hf_ams_sendernetid, tvb, offset, AmsNetId_Len, szText); offset += AmsNetId_Len; proto_tree_add_item(ams_tree, hf_ams_senderport, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); offset += sizeof(guint16); proto_tree_add_item(ams_tree, hf_ams_cmdid, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); cmdId = tvb_get_letohs(tvb, offset); offset+=sizeof(guint16); anItem = proto_tree_add_item(ams_tree, hf_ams_stateflags, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); ams_statetree = proto_item_add_subtree(anItem, ett_ams_stateflags); proto_tree_add_item(ams_statetree, hf_ams_stateresponse,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); proto_tree_add_item(ams_statetree, hf_ams_statenoreturn,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); proto_tree_add_item(ams_statetree, hf_ams_stateadscmd,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); proto_tree_add_item(ams_statetree, hf_ams_statesyscmd,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); proto_tree_add_item(ams_statetree, hf_ams_statehighprio,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); proto_tree_add_item(ams_statetree, hf_ams_statetimestampadded,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); proto_tree_add_item(ams_statetree, hf_ams_stateudp,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); proto_tree_add_item(ams_statetree, hf_ams_stateinitcmd,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); proto_tree_add_item(ams_statetree, hf_ams_statebroadcast,tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); stateflags = tvb_get_letohs(tvb, offset); offset+=sizeof(guint16); proto_tree_add_item(ams_tree, hf_ams_cbdata, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_tree, hf_ams_errorcode, tvb, offset, sizeof(guint32),ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_tree, hf_ams_invokeid, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); } else { offset+=AmsHead_Len; } if ( (stateflags & AMSCMDSF_ADSCMD) != 0 ) { /* ADS */ if ( (stateflags & AMSCMDSF_RESPONSE) == 0 ) { /* Request */ switch ( cmdId ) { case ADSSRVID_READ: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Request"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadrequest, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsReadReq_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadrequest); proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); } } } break; case ADSSRVID_WRITE: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Request"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adswriterequest, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsWriteReq_Len - sizeof(guint16) ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswriterequest); proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA); } } } break; case ADSSRVID_READWRITE: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Write Request"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadwriterequest, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsReadWriteReq_Len - sizeof(guint16)) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadwriterequest); proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adscbreadlength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adscbwritelength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset+16, ams_length-offset, ENC_NA); } } } break; case ADSSRVID_READSTATE: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Read State Request"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadstaterequest, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsReadStateReq_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadstaterequest); proto_tree_add_item(ams_adstree, hf_ams_adsinvokeid, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); } } } break; case ADSSRVID_WRITECTRL: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Control Request"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adswritectrlrequest, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsWriteControlReq_Len - sizeof(guint16) ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswritectrlrequest); proto_tree_add_item(ams_adstree, hf_ams_adsstate, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset+=sizeof(guint16); proto_tree_add_item(ams_adstree, hf_ams_adsdevicestate, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset+=sizeof(guint16); proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA); } } } break; case ADSSRVID_READDEVICEINFO: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Device Info Request"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsreaddinforequest, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsReadDeviceInfoReq_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreaddinforequest); proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); } } } break; case ADSSRVID_ADDDEVICENOTE: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Add Device Notification Request"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsadddnrequest, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsAddDeviceNotificationReq_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsadddnrequest); proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adstransmode, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsmaxdelay, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adscycletime, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); } } } break; case ADSSRVID_DELDEVICENOTE: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Delete Device Notification Request"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsdeldnrequest, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsDelDeviceNotificationReq_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsdeldnrequest); proto_tree_add_item(ams_adstree, hf_ams_adsnotificationhandle, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); } } } break; case ADSSRVID_DEVICENOTE: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Device Notification Request"); if( tree ) { /*guint32 cbLength; guint32 nStamps;*/ anItem = proto_tree_add_item(ams_tree, hf_ams_adsdnrequest, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsDeviceNotificationReq_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsdnrequest); proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); /*cbLength = tvb_get_letohs(tvb, offset);*/ offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsnoteblocksstamps, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); /*nStamps = tvb_get_letohs(tvb, offset);*/ offset+=sizeof(guint32); /*ToDo: dissect noteblocks*/ } } } break; } } else { /* Response */ switch ( cmdId ) { case ADSSRVID_READ: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Response"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadresponse, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsReadRes_Len - sizeof(guint16) ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadresponse); proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA); } } } break; case ADSSRVID_WRITE: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Response"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adswriteresponse, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsWriteRes_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswriteresponse); proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); } } } break; case ADSSRVID_READWRITE: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Write Response"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadwriteresponse, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsReadWriteRes_Len - sizeof(guint16) ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadwriteresponse); proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA); } } } break; case ADSSRVID_READSTATE: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Read State Response"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadstateresponse, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsReadStateRes_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadstateresponse); proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsstate, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsdevicestate, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); } } } break; case ADSSRVID_WRITECTRL: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Control Response"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adswritectrlresponse, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsWriteControlRes_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswritectrlresponse); proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); } } } break; case ADSSRVID_READDEVICEINFO: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Device Info Response"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsreaddinforesponse, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsReadDeviceInfoRes_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreaddinforesponse); proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsversionversion, tvb, offset++, sizeof(guint8), ENC_LITTLE_ENDIAN); proto_tree_add_item(ams_adstree, hf_ams_adsversionrevision, tvb, offset++, sizeof(guint8), ENC_LITTLE_ENDIAN); proto_tree_add_item(ams_adstree, hf_ams_adsversionbuild, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN); offset+=sizeof(guint16); proto_tree_add_item(ams_adstree, hf_ams_adsdevicename, tvb, offset, ams_length-offset, ENC_ASCII|ENC_NA); } } } break; case ADSSRVID_ADDDEVICENOTE: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Device Notification Response"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsadddnresponse, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsAddDeviceNotificationRes_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsadddnresponse); proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); offset+=sizeof(guint32); proto_tree_add_item(ams_adstree, hf_ams_adsnotificationhandle, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); } } } break; case ADSSRVID_DELDEVICENOTE: { col_append_str(pinfo->cinfo, COL_INFO, "ADS Delete Device Notification Response"); if( tree ) { anItem = proto_tree_add_item(ams_tree, hf_ams_adsdeldnresponse, tvb, offset, ams_length-offset, ENC_NA); if( ams_length-offset >= TAdsDelDeviceNotificationRes_Len ) { ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsdeldnresponse); proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, sizeof(guint32), ENC_LITTLE_ENDIAN); } } } break; } } } else { if ( (stateflags & AMSCMDSF_RESPONSE) == 0 ) col_append_str(pinfo->cinfo, COL_INFO, "AMS Request"); else col_append_str(pinfo->cinfo, COL_INFO, "AMS Response"); if( tree && ams_length-offset > 0 ) proto_tree_add_item(ams_tree, hf_ams_data, tvb, offset, ams_length-offset, ENC_NA); } return offset; }
/* Code to actually dissect the packets */ static void dissect_gvrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *gvrp_tree; guint16 protocol_id; guint8 octet; int msg_index, attr_index, offset = 0, length = tvb_reported_length(tvb); col_set_str(pinfo->cinfo, COL_PROTOCOL, "GVRP"); col_set_str(pinfo->cinfo, COL_INFO, "GVRP"); if (tree) { ti = proto_tree_add_item(tree, proto_gvrp, tvb, 0, length, FALSE); gvrp_tree = proto_item_add_subtree(ti, ett_gvrp); /* Read in GARP protocol ID */ protocol_id = tvb_get_ntohs(tvb, GARP_PROTOCOL_ID); proto_tree_add_uint_format(gvrp_tree, hf_gvrp_proto_id, tvb, GARP_PROTOCOL_ID, sizeof(guint16), protocol_id, "Protocol Identifier: 0x%04x (%s)", protocol_id, protocol_id == GARP_DEFAULT_PROTOCOL_ID ? "GARP VLAN Registration Protocol" : "Unknown Protocol"); /* Currently only one protocol ID is supported */ if (protocol_id != GARP_DEFAULT_PROTOCOL_ID) { proto_tree_add_text(gvrp_tree, tvb, GARP_PROTOCOL_ID, sizeof(guint16), " (Warning: this version of Wireshark only knows about protocol id = 1)"); call_dissector(data_handle, tvb_new_subset(tvb, GARP_PROTOCOL_ID + sizeof(guint16), -1, -1), pinfo, tree); return; } offset += sizeof(guint16); length -= sizeof(guint16); msg_index = 0; /* Begin to parse GARP messages */ while (length) { proto_item *msg_item; int msg_start = offset; /* Read in attribute type. */ octet = tvb_get_guint8(tvb, offset); /* Check for end of mark */ if (octet == GARP_END_OF_MARK) { /* End of GARP PDU */ if (msg_index) { proto_tree_add_text(gvrp_tree, tvb, offset, sizeof(guint8), "End of mark"); break; } else { call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); return; } } offset += sizeof(guint8); length -= sizeof(guint8); msg_item = proto_tree_add_text(gvrp_tree, tvb, msg_start, -1, "Message %d", msg_index + 1); proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_type, tvb, msg_start, sizeof(guint8), octet); /* GVRP only supports one attribute type. */ if (octet != GVRP_ATTRIBUTE_TYPE) { call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); return; } attr_index = 0; while (length) { int attr_start = offset; proto_item *attr_item; /* Read in attribute length. */ octet = tvb_get_guint8(tvb, offset); /* Check for end of mark */ if (octet == GARP_END_OF_MARK) { /* If at least one message has been already read, * check for another end of mark. */ if (attr_index) { proto_tree_add_text(gvrp_tree, tvb, offset, sizeof(guint8), " End of mark"); offset += sizeof(guint8); length -= sizeof(guint8); proto_item_set_len(msg_item, offset - msg_start); break; } else { call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); return; } } else { guint8 event; offset += sizeof(guint8); length -= sizeof(guint8); attr_item = proto_tree_add_text(gvrp_tree, tvb, attr_start, -1, " Attribute %d", attr_index + 1); proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_length, tvb, attr_start, sizeof(guint8), octet); /* Read in attribute event */ event = tvb_get_guint8(tvb, offset); proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_event, tvb, offset, sizeof(guint8), event); offset += sizeof(guint8); length -= sizeof(guint8); switch (event) { case GVRP_EVENT_LEAVEALL: if (octet != GVRP_LENGTH_LEAVEALL) { call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); return; } break; case GVRP_EVENT_JOINEMPTY: case GVRP_EVENT_JOININ: case GVRP_EVENT_LEAVEEMPTY: case GVRP_EVENT_LEAVEIN: case GVRP_EVENT_EMPTY: if (octet != GVRP_LENGTH_NON_LEAVEALL) { call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset),pinfo, tree); return; } /* Show attribute value */ proto_tree_add_item(gvrp_tree, hf_gvrp_attribute_value, tvb, offset, sizeof(guint16), FALSE); offset += sizeof(guint16); length -= sizeof(guint16); break; default: call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); return; } } proto_item_set_len(attr_item, offset - attr_start); attr_index++; } msg_index++; } } }
/* UCD dissector */ static void dissect_mac_mgmt_msg_ucd_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint offset = 0; guint tvb_len, length; gint tlv_type, tlv_len, tlv_offset, tlv_value_offset; tlv_info_t tlv_info; gchar* proto_str; { /* we are being asked for details */ proto_item *ucd_item; proto_tree *ucd_tree; guint ucd_ranging_backoff_start; guint ucd_ranging_backoff_end; guint ucd_request_backoff_start; guint ucd_request_backoff_end; tvb_len = tvb_reported_length(tvb); /* display MAC payload type UCD */ ucd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, -1, "Uplink Channel Descriptor (UCD)"); ucd_tree = proto_item_add_subtree(ucd_item, ett_mac_mgmt_msg_ucd_decoder); /* Decode and display the Uplink Channel Descriptor (UCD) */ /* display the Configuration Change Count */ proto_tree_add_item(ucd_tree, hf_ucd_config_change_count, tvb, offset, 1, ENC_NA); offset++; /* get the ranging backoff start */ ucd_ranging_backoff_start = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(ucd_tree, hf_ucd_ranging_backoff_start, tvb, offset, 1, (1 << ucd_ranging_backoff_start), "2^%u = %u", ucd_ranging_backoff_start, (1 << ucd_ranging_backoff_start)); offset++; /* get the ranging backoff end */ ucd_ranging_backoff_end = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(ucd_tree, hf_ucd_ranging_backoff_end, tvb, offset, 1, (1 << ucd_ranging_backoff_end), "2^%u = %u", ucd_ranging_backoff_end, (1 << ucd_ranging_backoff_end)); offset++; /* get the request backoff start */ ucd_request_backoff_start = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(ucd_tree, hf_ucd_request_backoff_start, tvb, offset, 1, (1 << ucd_request_backoff_start), "2^%u = %u", ucd_request_backoff_start, (1 << ucd_request_backoff_start)); offset++; /* get the request backoff end */ ucd_request_backoff_end = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(ucd_tree, hf_ucd_request_backoff_end, tvb, offset, 1, (1 << ucd_request_backoff_end), "2^%u = %u", ucd_request_backoff_end, (1 << ucd_request_backoff_end)); offset++; while(offset < tvb_len) { /* get the TLV information */ init_tlv_info(&tlv_info, tvb, offset); /* get the TLV type */ tlv_type = get_tlv_type(&tlv_info); /* get the TLV length */ tlv_len = get_tlv_length(&tlv_info); if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) { /* invalid tlv info */ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "UCD TLV error"); proto_tree_add_item(ucd_tree,hf_ucd_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); break; } /* get the TLV value offset */ tlv_value_offset = get_tlv_value_offset(&tlv_info); #ifdef DEBUG /* for debug only */ proto_tree_add_protocol_format(ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, (tlv_len + tlv_value_offset), "UCD Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len, offset, tvb_len); #endif /* update the offset */ offset += tlv_value_offset; /* process UCD TLV Encoded information */ if (include_cor2_changes) { switch (tlv_type) { case UCD_TLV_T_203_UL_PUSC_SUBCHANNEL_ROTATION: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_203_ul_pusc_subchannel_rotation, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_205_RELATIVE_POWER_OFFSET_UL_HARQ_BURST: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_205_relative_power_offset_ul_harq_burst, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_206_RELATIVE_POWER_OFFSET_UL_BURST_CONTAINING_MAC_MGMT_MSG: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_206_relative_power_offset_ul_burst_containing_mac_mgmt_msg, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_207_UL_INITIAL_TRANSMIT_TIMING: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_207_ul_initial_transmit_timing, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_210_FAST_FEEDBACK_REGION: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_210_fast_feedback_region, tvb, offset-tlv_value_offset, ENC_NA); break; } case UCD_TLV_T_211_HARQ_ACK_REGION: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_211_harq_ack_region, tvb, offset-tlv_value_offset, ENC_NA); break; } case UCD_TLV_T_212_RANGING_REGION: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_212_ranging_region, tvb, offset-tlv_value_offset, ENC_NA); break; } case UCD_TLV_T_213_SOUNDING_REGION: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_213_sounding_region, tvb, offset-tlv_value_offset, ENC_NA); break; } } } switch (tlv_type) { proto_tree *tlv_tree; proto_item *tlv_item1; guint ul_burst_uiuc; guint utemp; case UCD_UPLINK_BURST_PROFILE: { /* get the UIUC */ ul_burst_uiuc = tvb_get_guint8(tvb, offset) & 0x0F; /* add TLV subtree */ proto_str = wmem_strdup_printf(wmem_packet_scope(), "Uplink Burst Profile (UIUC = %u)", ul_burst_uiuc); tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset-tlv_value_offset, tlv_len, proto_str); proto_tree_add_item(tlv_tree, hf_ucd_ul_burst_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_ucd_ul_burst_uiuc, tvb, offset, 1, ENC_BIG_ENDIAN); for (tlv_offset = 1; tlv_offset < tlv_len;) { /* get the TLV information */ init_tlv_info(&tlv_info, tvb, (offset+tlv_offset)); /* get the TLV type */ tlv_type = get_tlv_type(&tlv_info); if(tlv_type == -1) { /* invalid tlv info */ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "UL Burst Profile error"); proto_tree_add_item(tlv_tree, hf_ucd_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); break; } /* get the TLV length */ length = get_tlv_length(&tlv_info); switch (tlv_type) { proto_item *tlv_item2; case UCD_BURST_FEC: { add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_fec, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN); break; } case UCD_BURST_RANGING_DATA_RATIO: { tlv_item2 = add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_ranging_data_ratio, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN); proto_item_append_text(tlv_item2, " dB"); break; } #if 0 /* for OFDM */ case UCD_BURST_POWER_BOOST: { tlv_item2 = add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_power_boost, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN); proto_item_append_text(tlv_item2, " dB"); break; } case UCD_BURST_TCS_ENABLE: { add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_tcs_enable, tvb, (offset+tlv_offset), 1, ENC_BIG_ENDIAN); break; } #endif default: /* ??? */ break; } tlv_offset += (length+get_tlv_value_offset(&tlv_info)); } break; } case UCD_RESERVATION_TIMEOUT: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_res_timeout, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_BW_REQ_SIZE: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_bw_req_size, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " PS"); break; } case UCD_RANGING_REQ_SIZE: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_ranging_req_size, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " PS"); break; } case UCD_FREQUENCY: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_freq, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " kHz"); break; } case UCD_TLV_T_7_HO_RANGING_START: { tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_ho_ranging_start, tvb, offset-tlv_value_offset); utemp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(tlv_tree, hf_ucd_ho_ranging_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); break; } case UCD_TLV_T_8_RANGING_HO_END: { tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_ho_ranging_end, tvb, offset-tlv_value_offset); utemp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(tlv_tree, hf_ucd_ho_ranging_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); break; } case UCD_TLV_T_158_OPTIONAL_PERMUTATION_UL_ALLOCATED_SUBCHANNELS_BITMAP: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_158_optional_permutation_ul_allocated_subchannels_bitmap, tvb, offset-tlv_value_offset, ENC_NA); break; } case UCD_TLV_T_159_BAND_AMC_ALLOCATION_THRESHHOLD: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_159_band_amc_allocation_threshold, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " dB"); break; } case UCD_TLV_T_160_BAND_AMC_RELEASE_THRESHOLD: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_160_band_amc_release_threshold, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " dB"); break; } case UCD_TLV_T_161_BAND_AMC_ALLOCATION_TIMER: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_161_band_amc_allocation_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " frames"); break; } case UCD_TLV_T_162_BAND_AMC_RELEASE_TIMER: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_161_band_amc_allocation_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " frames"); break; } case UCD_TLV_T_163_BAND_STATUS_REPORT_MAX_PERIOD: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_163_band_status_report_max_period, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " frames"); break; } case UCD_TLV_T_164_BAND_AMC_RETRY_TIMER: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_164_band_amc_retry_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " frames"); break; } case UCD_TLV_T_170_SAFETY_CHANNEL_RETRY_TIMER: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_170_safety_channel_retry_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " frames"); break; } case UCD_TLV_T_171_HARQ_ACK_DELAY_FOR_DL_BURST: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_171_harq_ack_delay_dl_burst, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " frames offset"); break; } case UCD_TLV_T_172_CQICH_BAND_AMC_TRANSITION_DELAY: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_172_cqich_band_amc_transition_delay, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); proto_item_append_text(tlv_item1, " frames"); break; } case UCD_TLV_T_174_MAXIMUM_RETRANSMISSION: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_174_maximum_retransmission, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_176_SIZE_OF_CQICH_ID_FIELD: { utemp = tvb_get_guint8(tvb, offset); cqich_id_size = 0; /* Default is 0 */ if (utemp && utemp < 8) { /* Set for CQICH_Alloc_IE */ cqich_id_size = utemp + 2; } add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_176_size_of_cqich_id_field, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_177_NORMALIZED_CN_OVERRIDE_2: { /* add TLV subtree */ tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_177_normalized_cn_override2, tvb, offset-tlv_value_offset, ENC_NA|ENC_ASCII); tlv_tree = proto_item_add_subtree(tlv_item1, ett_mac_mgmt_msg_ucd_decoder); proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_177_normalized_cn_override2_first_line, tvb, offset + 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_177_normalized_cn_override2_list, tvb, offset + 3, 7, ENC_ASCII|ENC_NA); break; } case UCD_TLV_T_186_UPPER_BOUND__AAS_PREAMBLE: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_186_upper_bound_aas_preamble, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_187_LOWER_BOUND_AAS_PREAMBLE: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_187_lower_bound_aas_preamble, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_188_ALLOW_AAS_BEAM_SELECT_MESSAGE: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_188_allow_aas_beam_select_message, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_189_USE_CQICH_INDICATION_FLAG: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_189_use_cqich_indication_flag, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_190_MS_SPECIFIC_UP_POWER_OFFSET_ADJUSTMENT_STEP: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_190_ms_specific_up_power_addjustment_step, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_191_MS_SPECIFIC_DOWN_POWER_OFSET_ADJUSTMENT_STEP: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_191_ms_specific_down_power_addjustment_step, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_192_MIN_LEVEL_POWER_OFFSET_ADJUSTMENT: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_192_min_level_power_offset_adjustment, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_193_MAX_LEVEL_POWER_OFFSETR_ADJUSTMENT: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_193_max_level_power_offset_adjustment, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_194_HANDOVER_RANGING_CODES: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_194_handover_ranging_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_195_INITIAL_RANGING_INTERVAL: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_195_initial_ranging_interval, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_196_TX_POWER_REPORT: { tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_196_tx_power_report, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); tlv_tree = proto_item_add_subtree(tlv_item1, ett_mac_mgmt_msg_ucd_decoder); proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_threshold, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_interval, tvb , offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_a_p_avg, tvb, (offset + 1), 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_threshold_icqch, tvb, (offset + 1), 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_interval_icqch, tvb, (offset + 2), 1, ENC_BIG_ENDIAN); proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_a_p_avg_icqch, tvb, (offset + 2), 1, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_197_NORMALIZED_CN_FOR_CHANNEL_SOUNDING: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_195_initial_ranging_interval, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_TLV_T_198_INTIAL_RANGING_BACKOFF_START: { tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_initial_range_backoff_start, tvb, offset-tlv_value_offset); utemp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(tlv_tree, hf_ucd_initial_range_backoff_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); break; } case UCD_TLV_T_199_INITIAL_RANGING_BACKOFF_END: { tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_initial_range_backoff_end, tvb, offset-tlv_value_offset); utemp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(tlv_tree, hf_ucd_initial_range_backoff_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); break; } case UCD_TLV_T_200_BANDWIDTH_REQUESET_BACKOFF_START: { tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_bandwidth_backoff_start, tvb, offset-tlv_value_offset); utemp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(tlv_tree, hf_ucd_bandwidth_backoff_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); break; } case UCD_TLV_T_201_BANDWIDTH_REQUEST_BACKOFF_END: { tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_bandwidth_backoff_end, tvb, offset-tlv_value_offset); utemp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(tlv_tree, hf_ucd_bandwidth_backoff_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); break; } case UCD_TLV_T_202_UPLINK_BURST_PROFILE_FOR_MULTIPLE_FEC_TYPES: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_202_uplink_burst_profile_for_multiple_fec_types, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_INITIAL_RANGING_CODES: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_150_initial_ranging_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_PERIODIC_RANGING_CODES: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_151_periodic_ranging_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_BANDWIDTH_REQUEST_CODES: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_152_bandwidth_request_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_PERIODIC_RANGING_BACKOFF_START: { tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_periodic_ranging_backoff_start, tvb, offset-tlv_value_offset); utemp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(tlv_tree, hf_ucd_periodic_ranging_backoff_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); break; } case UCD_PERIODIC_RANGING_BACKOFF_END: { tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_periodic_ranging_backoff_end, tvb, offset-tlv_value_offset); utemp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(tlv_tree, hf_ucd_periodic_ranging_backoff_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); break; } case UCD_START_OF_RANGING_CODES_GROUP: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_155_start_of_ranging_codes_group, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_PERMUTATION_BASE: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_156_permutation_base, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); break; } case UCD_UL_ALLOCATED_SUBCHANNELS_BITMAP: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_ul_allocated_subchannles_bitmap, tvb, offset-tlv_value_offset, ENC_NA); break; } case UCD_TLV_T_203_UL_PUSC_SUBCHANNEL_ROTATION: case UCD_TLV_T_205_RELATIVE_POWER_OFFSET_UL_HARQ_BURST: case UCD_TLV_T_206_RELATIVE_POWER_OFFSET_UL_BURST_CONTAINING_MAC_MGMT_MSG: case UCD_TLV_T_207_UL_INITIAL_TRANSMIT_TIMING: case UCD_TLV_T_210_FAST_FEEDBACK_REGION: case UCD_TLV_T_211_HARQ_ACK_REGION: case UCD_TLV_T_212_RANGING_REGION: case UCD_TLV_T_213_SOUNDING_REGION: { /* Unknown TLV type if cor2 not enabled. */ if (!include_cor2_changes) { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_invalid_tlv, tvb, offset-tlv_value_offset, ENC_NA); } break; } default: { add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_invalid_tlv, tvb, offset-tlv_value_offset, ENC_NA); } } /* end of switch(tlv_type) */ offset += tlv_len; } /* end of TLV process while loop */ } }
/* * dissect_pgm - The dissector for Pragmatic General Multicast */ static void dissect_pgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 pgmhdr_sport; guint16 pgmhdr_dport; guint8 pgmhdr_type; guint8 pgmhdr_opts; guint16 pgmhdr_cksum; guint16 pgmhdr_tsdulen; guint32 sqn; guint16 afi; guint plen = 0; proto_item *ti; const char *pktname; const char *pollstname; char *gsi; gboolean isdata = FALSE; guint pgmlen, reportedlen; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PGM"); col_clear(pinfo->cinfo, COL_INFO); if (tvb_reported_length_remaining(tvb, 0) < 18) { col_set_str(pinfo->cinfo, COL_INFO, "Packet too small"); return; } pinfo->srcport = pgmhdr_sport = tvb_get_ntohs(tvb, 0); pinfo->destport = pgmhdr_dport = tvb_get_ntohs(tvb, 2); pgmhdr_type = tvb_get_guint8(tvb, 4); pktname = val_to_str(pgmhdr_type, type_vals, "Unknown (0x%02x)"); pgmhdr_opts = tvb_get_guint8(tvb, 5); pgmhdr_cksum = tvb_get_ntohs(tvb, 6); gsi = tvb_bytes_to_str(wmem_packet_scope(), tvb, 8, 6); pgmhdr_tsdulen = tvb_get_ntohs(tvb, 14); sqn = tvb_get_ntohl(tvb, 16); switch(pgmhdr_type) { case PGM_SPM_PCKT: case PGM_NAK_PCKT: case PGM_NNAK_PCKT: case PGM_NCF_PCKT: case PGM_POLR_PCKT: case PGM_ACK_PCKT: col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s", pktname, sqn, gsi); break; case PGM_RDATA_PCKT: case PGM_ODATA_PCKT: col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s tsdulen %d", pktname, sqn, gsi, pgmhdr_tsdulen); isdata = TRUE; break; case PGM_POLL_PCKT: { guint16 poll_stype = tvb_get_ntohs(tvb, 22); pollstname = val_to_str(poll_stype, poll_subtype_vals, "Unknown (0x%02x)"); col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s subtype %s", pktname, sqn, gsi, pollstname); } break; default: return; } { proto_tree *pgm_tree = NULL; proto_tree *opt_tree = NULL; proto_tree *type_tree = NULL; proto_item *tf, *hidden_item; ptvcursor_t* cursor; ti = proto_tree_add_protocol_format(tree, proto_pgm, tvb, 0, -1, "Pragmatic General Multicast: Type %s" " Src Port %u, Dst Port %u, GSI %s", pktname, pgmhdr_sport, pgmhdr_dport, gsi); pgm_tree = proto_item_add_subtree(ti, ett_pgm); cursor = ptvcursor_new(pgm_tree, tvb, 0); hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 0, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 2, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); ptvcursor_add(cursor, hf_pgm_main_sport, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_dport, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_type, 1, ENC_BIG_ENDIAN); tf = proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_opts, tvb, ptvcursor_current_offset(cursor), 1, pgmhdr_opts, "%s (0x%x)", optsstr(pgmhdr_opts), pgmhdr_opts); opt_tree = proto_item_add_subtree(tf, ett_pgm_optbits); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_opt, 1, ENC_BIG_ENDIAN); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_netsig, 1, ENC_BIG_ENDIAN); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_varlen, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_opts_parity, 1, ENC_BIG_ENDIAN); ptvcursor_set_tree(cursor, pgm_tree); /* Checksum may be 0 (not available), but not for DATA packets */ if ((pgmhdr_type != PGM_RDATA_PCKT) && (pgmhdr_type != PGM_ODATA_PCKT) && (pgmhdr_cksum == 0)) { proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "not available"); } else { reportedlen = tvb_reported_length(tvb); pgmlen = tvb_captured_length(tvb); if (pgm_check_checksum && pgmlen >= reportedlen) { vec_t cksum_vec[1]; guint16 computed_cksum; SET_CKSUM_VEC_TVB(cksum_vec[0], tvb, 0, pgmlen); computed_cksum = in_cksum(&cksum_vec[0], 1); if (computed_cksum == 0) { proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "0x%04x [correct]", pgmhdr_cksum); } else { hidden_item = proto_tree_add_boolean(pgm_tree, hf_pgm_main_cksum_bad, tvb, ptvcursor_current_offset(cursor), 2, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "0x%04x [incorrect, should be 0x%04x]", pgmhdr_cksum, in_cksum_shouldbe(pgmhdr_cksum, computed_cksum)); } } else { ptvcursor_add_no_advance(cursor, hf_pgm_main_cksum, 2, ENC_BIG_ENDIAN); } } ptvcursor_advance(cursor, 2); ptvcursor_add(cursor, hf_pgm_main_gsi, 6, ENC_NA); ptvcursor_add(cursor, hf_pgm_main_tsdulen, 2, ENC_BIG_ENDIAN); switch(pgmhdr_type) { case PGM_SPM_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_spm, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_lead, 4, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_spm_pathafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_res, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_spm_path, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_spm_path6, 16, ENC_NA); break; default: expert_add_info(pinfo, ti, &ei_address_format_invalid); ptvcursor_free(cursor); return; } break; case PGM_RDATA_PCKT: case PGM_ODATA_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_data, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN); break; case PGM_NAK_PCKT: case PGM_NNAK_PCKT: case PGM_NCF_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_nak, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_nak_sqn, 4, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_nak_srcafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_nak_srcres, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_nak_src, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_nak_src6, 16, ENC_NA); break; default: expert_add_info(pinfo, ti, &ei_address_format_invalid); break; } afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_nak_grpafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_nak_grpres, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_nak_grp, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_nak_grp6, 16, ENC_NA); break; default: expert_add_info(pinfo, ti, &ei_address_format_invalid); ptvcursor_free(cursor); return; } break; case PGM_POLL_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_poll, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_poll_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_round, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_subtype, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_poll_pathafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_res, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_poll_path, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_poll_path6, 16, ENC_NA); break; default: expert_add_info(pinfo, ti, &ei_address_format_invalid); break; } ptvcursor_add(cursor, hf_pgm_poll_backoff_ivl, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_rand_str, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_matching_bmask, 4, ENC_BIG_ENDIAN); break; case PGM_POLR_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_polr, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_polr_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_polr_round, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_polr_res, 2, ENC_BIG_ENDIAN); break; case PGM_ACK_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_ack, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_ack_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_ack_bitmap, 4, ENC_BIG_ENDIAN); break; } if (pgmhdr_opts & PGM_OPT) dissect_pgmopts(cursor, pinfo, pktname); if (isdata) decode_pgm_ports(tvb, ptvcursor_current_offset(cursor), pinfo, tree, pgmhdr_sport, pgmhdr_dport); ptvcursor_free(cursor); } }
static void dissect_v5dl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *v5dl_tree, *addr_tree; proto_item *v5dl_ti, *addr_ti; int direction; guint v5dl_header_len; guint16 control; #if 0 proto_tree *checksum_tree; proto_item *checksum_ti; 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"; dstname = "Network"; } col_set_str(pinfo->cinfo, COL_RES_DL_SRC, srcname); col_set_str(pinfo->cinfo, COL_RES_DL_DST, dstname); if (tree) { proto_item *direction_ti; v5dl_ti = proto_tree_add_item(tree, proto_v5dl, tvb, 0, -1, ENC_NA); v5dl_tree = proto_item_add_subtree(v5dl_ti, ett_v5dl); /* * Don't show the direction if we don't know it. */ if (direction != P2P_DIR_UNKNOWN) { direction_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_direction, tvb, 0, 0, pinfo->p2p_dir); PROTO_ITEM_SET_GENERATED(direction_ti); } addr_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_ef, tvb, 0, 2, v5addr); addr_tree = proto_item_add_subtree(addr_ti, ett_v5dl_address); proto_tree_add_uint(addr_tree, hf_v5dl_eah, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_cr, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_ea1, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_eal, tvb, 1, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_ea2, tvb, 1, 1, addr); } else { v5dl_ti = NULL; v5dl_tree = NULL; } control = dissect_xdlc_control(tvb, 2, pinfo, v5dl_tree, hf_v5dl_control, ett_v5dl_control, &v5dl_cf_items, &v5dl_cf_items_ext, NULL, NULL, is_response, TRUE, FALSE); v5dl_header_len += XDLC_CONTROL_LEN(control, TRUE); if (tree) proto_item_set_len(v5dl_ti, v5dl_header_len); /* * XXX - the sample capture supplied with bug 7027 does not * appear to include checksums in the packets. */ #if 0 /* * Check the checksum, if available. * The checksum is a CCITT CRC-16 at the end of the packet, so * if we don't have the entire packet in the capture - i.e., if * tvb_length(tvb) != tvb_reported_length(tvb) we can't check it. */ length = tvb_length(tvb); reported_length = tvb_reported_length(tvb); /* * If the reported length isn't big enough for the V5DL header * and 2 bytes of checksum, the packet is malformed, as the * checksum overlaps the header. */ if (reported_length < v5dl_header_len + 2) THROW(ReportedBoundsError); if (length == reported_length) { /* * There's no snapshot length cutting off any of the * packet. */ checksum_offset = reported_length - 2; checksum = tvb_get_ntohs(tvb, checksum_offset); checksum_calculated = crc16_ccitt_tvb(tvb, checksum_offset); checksum_calculated = g_htons(checksum_calculated); /* Note: g_htons() macro may eval arg multiple times */ if (checksum == checksum_calculated) { checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset, 2, 0, "0x%04x [correct]", checksum); checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, TRUE); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, FALSE); } else { checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset, 2, 0, "0x%04x [incorrect, should be 0x%04x]", checksum, checksum_calculated); checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, FALSE); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, TRUE); } /* * Remove the V5DL header *and* the checksum. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_length_remaining(tvb, v5dl_header_len) - 2, tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } else { /* * Some or all of the packet is cut off by a snapshot * length. */ if (length == reported_length - 1) { /* * One byte is cut off, so there's only one * byte of checksum in the captured data. * Remove that byte from the captured length * and both bytes from the reported length. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_length_remaining(tvb, v5dl_header_len) - 1, tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } else { /* * Two or more bytes are cut off, so there are * no bytes of checksum in the captured data. * Just remove the checksum from the reported * length. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_length_remaining(tvb, v5dl_header_len), tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } } #else next_tvb = tvb_new_subset_remaining(tvb, v5dl_header_len); #endif if (XDLC_IS_INFORMATION(control)) { /* call V5.2 dissector */ call_dissector(v52_handle, next_tvb, pinfo, tree); } }
static void dissect_wai_data(tvbuff_t *tvb, proto_tree *tree, guint8 subtype, guint16 lenx) { proto_item *data_item; proto_tree *data_tree; const gchar *type_name; data_item = proto_tree_add_item(tree, hf_wai_data, tvb, 0, lenx, ENC_NA); data_tree = proto_item_add_subtree (data_item, ett_wai_data); type_name = val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type"); proto_item_set_text(data_item, "%s data (%d bytes)", type_name, lenx); switch (subtype) { case WAI_SUB_PRE_AUTHENTICATION: { /* Chapter 8.1.4.6 Preauthentication [ref: 1] */ dissect_flag(tvb, 0, data_tree); dissect_uskid(tvb, 1, data_tree); dissect_addid(tvb, 2, data_tree); dissect_counter(tvb, 14, data_tree); dissect_message_auth_code(tvb, 30, data_tree); break; } case WAI_SUB_STAKEY_REQ: { /* Chapter 8.1.4.5 STAKey Establishment procedure [ref: 1] */ dissect_flag(tvb, 0, data_tree); proto_tree_add_item(data_tree, hf_wai_sta_key_id, tvb, 1, 1, ENC_BIG_ENDIAN); dissect_uskid(tvb, 2, data_tree); dissect_addid(tvb, 3, data_tree); dissect_counter(tvb, 15, data_tree); dissect_message_auth_code(tvb, 31, data_tree); break; } case WAI_SUB_AUTH_ACTIVATION: { /* Chapter 8.1.4.2.1 WAI Authentication Activation [ref: 1] */ guint16 offset = 0; dissect_flag(tvb, offset, data_tree); offset += 1; dissect_authentication_id(tvb, offset, data_tree); offset += 32; offset += dissect_identity(tvb, offset, data_tree, "Local ASU "); offset += dissect_certificate(tvb, offset, data_tree, "STE AE "); dissect_ecdh_parameter(tvb, offset, data_tree); break; } case WAI_SUB_ACCESS_AUTH_REQ: { /* Chapter 8.1.4.2.2 Access WAI Authentication Request [ref: 1] */ guint16 offset = 0; guint8 optional_field; optional_field = tvb_get_guint8(tvb, 0) & FLAG_BIT3; dissect_flag(tvb, offset, data_tree); offset += 1; dissect_authentication_id(tvb, offset, data_tree); offset += 32; offset += dissect_challenge(tvb, offset, data_tree, "ASUE "); offset += dissect_key_data(tvb, offset, data_tree, "ASUE "); offset += dissect_identity(tvb, offset, data_tree, "STA AE "); offset += dissect_certificate(tvb, offset, data_tree, "STA ASUE "); offset += dissect_ecdh_parameter(tvb, offset, data_tree); if (optional_field) { offset += dissect_identity_list(tvb, offset, data_tree); } dissect_signature(tvb, offset, data_tree, "ASUE Signature"); break; } case WAI_SUB_ACCESS_AUTH_RESP: { /* Chapter 8.1.4.2.5 Access WAI Authentication Response [ref: 1] */ guint16 offset = 0; guint8 optional_field; optional_field = tvb_get_guint8(tvb, 0) & FLAG_BIT3; dissect_flag(tvb, offset, data_tree); offset += 1; offset += dissect_challenge(tvb, offset, data_tree, "ASUE "); offset += dissect_challenge(tvb, offset, data_tree, "AE "); proto_tree_add_item(data_tree, hf_wai_access_res, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; offset += dissect_key_data(tvb, offset, data_tree, "ASUE "); offset += dissect_key_data(tvb, offset, data_tree, "AE "); offset += dissect_identity(tvb, offset, data_tree, "STA AE "); offset += dissect_identity(tvb, offset, data_tree, "STA ASUE "); if (optional_field) { guint length = 0; offset += dissect_multiple_certificate(tvb, offset, data_tree); offset += dissect_signature(tvb, offset, data_tree, "Server Signature trusted by ASUE"); length = tvb_get_ntohs(tvb, offset+1); if (length + 3 + offset + 1 < lenx) offset += dissect_signature(tvb, offset, data_tree, "Server Signature trusted by AE"); } dissect_signature(tvb, offset, data_tree, "AE Signature"); break; } case WAI_SUB_CERT_AUTH_REQ: { /* Chapter 8.1.4.2.3 Certificate Authentication Request [ref: 1] */ guint16 offset = 0; guint8 optional_field; optional_field = tvb_get_guint8(tvb, 0) & FLAG_BIT3; dissect_addid(tvb, offset, data_tree); offset += 12; offset += dissect_challenge(tvb, offset, data_tree, "AE "); offset += dissect_challenge(tvb, offset, data_tree, "ASUE "); offset += dissect_certificate(tvb, offset, data_tree, "STE ASUE "); offset += dissect_certificate(tvb, offset, data_tree, "STE AE "); if (optional_field) { dissect_identity_list(tvb, offset, data_tree); } break; } case WAI_SUB_CERT_AUTH_RESP: { /* Chapter 8.1.4.2.4 Certificate Authentication Response [ref: 1] */ guint16 offset = 0; dissect_addid(tvb, offset, data_tree); offset += 12; offset += dissect_multiple_certificate(tvb, offset, data_tree); offset += dissect_signature(tvb, offset, data_tree, "Server Signature trusted by ASUE"); if (offset < lenx) dissect_signature(tvb, offset, data_tree, "Server Signature trusted by AE"); break; } case WAI_SUB_UNICAST_KEY_REQ: { /* Chapter 8.1.4.3.1 Unicast Key Negotiation Request [ref: 1] */ dissect_flag(tvb, 0, data_tree); dissect_bkid(tvb, 1, data_tree); dissect_uskid(tvb, 17, data_tree); dissect_addid(tvb, 18, data_tree); dissect_challenge(tvb, 30, data_tree , "AE "); break; } case WAI_SUB_UNICAST_KEY_RESP: { /* Chapter 8.1.4.3.2 Unicast Key Negotiation Response [ref: 1] */ tvbuff_t *next_tvb; guint length = 0; dissect_flag(tvb, 0, data_tree); dissect_bkid(tvb, 1, data_tree); dissect_uskid(tvb, 17, data_tree); dissect_addid(tvb, 18, data_tree); dissect_challenge(tvb, 30, data_tree, "ASUE "); dissect_challenge(tvb, 62, data_tree, "AE "); next_tvb = tvb_new_subset_remaining(tvb, 96); length = tvb_reported_length(next_tvb); dissect_wie(next_tvb, 0, length-20, data_tree); dissect_message_auth_code(next_tvb, length-20, data_tree); break; } case WAI_SUB_UNICAST_KEY_CONFIRM: { /* Chapter 8.1.4.3.3 Unicast Key Negotiation Confirmation [ref: 1] */ tvbuff_t *next_tvb; guint length = 0; dissect_flag(tvb, 0, data_tree); dissect_bkid(tvb, 1, data_tree); dissect_uskid(tvb, 17, data_tree); dissect_addid(tvb, 18, data_tree); dissect_challenge(tvb, 30, data_tree, "ASUE "); next_tvb = tvb_new_subset_remaining(tvb, 62); length = tvb_reported_length(next_tvb); dissect_wie(next_tvb, 0, length-20, data_tree); dissect_message_auth_code(next_tvb, length-20, data_tree); break; } case WAI_SUB_MULTICAST_ANNOUNCE: { /* Chapter 8.1.4.4.1 Multicast Key/STAKey Announcement [ref: 1] */ guint16 offset = 0; dissect_flag(tvb, offset, data_tree); offset += 1; dissect_mskid(tvb, offset, data_tree); offset += 1; dissect_uskid(tvb, offset, data_tree); offset += 1; dissect_addid(tvb, offset, data_tree); offset += 12; proto_tree_add_item(data_tree, hf_wai_data_pack_num, tvb, offset, 16, ENC_NA); offset += 16; dissect_key_announcement_identifier(tvb, offset, data_tree); offset += 16; offset += dissect_key_data(tvb, offset, data_tree, NULL); dissect_message_auth_code(tvb, offset, data_tree); break; } case WAI_SUB_MULTICAST_ANNOUNCE_RESP: { /* Chapter 8.1.4.4.2 Multicast Key/STAKey Announcement Response [ref: 1] */ dissect_flag(tvb, 0, data_tree); dissect_mskid(tvb, 1, data_tree); dissect_uskid(tvb, 2, data_tree); dissect_addid(tvb, 3, data_tree); dissect_key_announcement_identifier(tvb, 15, data_tree); dissect_message_auth_code(tvb, 31, data_tree); break; } default: break; } }
static void dissect_evrc_aux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, evrc_variant_t evrc_variant) { guint8 oct; guint8 frame_count; guint8 i; guint32 offset, saved_offset; gboolean further_entries; guint32 len; proto_item *item = NULL; proto_tree *evrc_tree = NULL; proto_tree *toc_tree = NULL; int hf_mode_request; int hf_toc_frame_type_high; int hf_toc_frame_type_low; /* * assumed max number of speech frames based on * frame count being 5 bits + 1 */ guint8 speech_data_len[0x20]; col_set_str(pinfo->cinfo, COL_PROTOCOL, "EVRC"); if (!tree) return; offset = 0; memset(speech_data_len, 0, sizeof(speech_data_len)); len = tvb_reported_length(tvb); item = proto_tree_add_item(tree, proto_evrc, tvb, 0, len, ENC_NA); evrc_tree = proto_item_add_subtree(item, ett_evrc); if (evrc_variant == EVRC_VARIANT_EVRC_LEGACY) { /* legacy 'payload type 60' draft-ietf-avt-evrc-07.txt header format */ proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(evrc_tree, hf_evrc_interleave_length, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(evrc_tree, hf_evrc_interleave_index, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; frame_count = 0; further_entries = TRUE; while (further_entries && (frame_count < sizeof(speech_data_len)) && ((len - offset) > 0)) { item = proto_tree_add_text(evrc_tree, tvb, offset, 1, "ToC [%u]", frame_count+1); toc_tree = proto_item_add_subtree(item, ett_toc); proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_fe_ind, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_reduc_rate, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(toc_tree, hf_evrc_legacy_toc_frame_type, tvb, offset, 1, ENC_BIG_ENDIAN); oct = tvb_get_guint8(tvb, offset); further_entries = (oct & 0x80) ? TRUE : FALSE; speech_data_len[frame_count] = evrc_frame_type_to_octs((guint8)(oct & 0x7f)); frame_count++; offset++; } } else { /* RFC 3558 header format */ switch (evrc_variant) { default: proto_tree_add_expert(evrc_tree, pinfo, &ei_evrc_unknown_variant, tvb, offset, len); return; case EVRC_VARIANT_EVRC: hf_mode_request = hf_evrc_mode_request; hf_toc_frame_type_high = hf_evrc_toc_frame_type_high; hf_toc_frame_type_low = hf_evrc_toc_frame_type_low; proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); break; case EVRC_VARIANT_EVRC_B: hf_mode_request = hf_evrc_b_mode_request; hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high; hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low; proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); break; case EVRC_VARIANT_EVRC_WB: hf_mode_request = hf_evrc_wb_mode_request; hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high; hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low; proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); break; case EVRC_VARIANT_EVRC_NW: hf_mode_request = hf_evrc_nw_mode_request; hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high; hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low; proto_tree_add_item(evrc_tree, hf_evrc_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); break; case EVRC_VARIANT_EVRC_NW2k: hf_mode_request = hf_evrc_nw2k_mode_request; hf_toc_frame_type_high = hf_evrc_b_toc_frame_type_high; hf_toc_frame_type_low = hf_evrc_b_toc_frame_type_low; proto_tree_add_item(evrc_tree, hf_evrc_reserved_2k, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(evrc_tree, hf_evrc_enc_capability_2k, tvb, offset, 1, ENC_BIG_ENDIAN); break; } proto_tree_add_item(evrc_tree, hf_evrc_interleave_length, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(evrc_tree, hf_evrc_interleave_index, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(evrc_tree, hf_mode_request, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(evrc_tree, hf_evrc_frame_count, tvb, offset, 1, ENC_BIG_ENDIAN); /* * number of frames in PACKET is frame_count + 1 */ frame_count = (tvb_get_guint8(tvb, offset) & 0x1f) + 1; offset++; saved_offset = offset; item = proto_tree_add_text(evrc_tree, tvb, offset, -1, "ToC - %u frame%s", frame_count, plurality(frame_count, "", "s")); toc_tree = proto_item_add_subtree(item, ett_toc); i = 0; while ((i < frame_count) && ((len - offset) > 0)) { oct = tvb_get_guint8(tvb, offset); proto_tree_add_item(toc_tree, hf_toc_frame_type_high, tvb, offset, 1, ENC_BIG_ENDIAN); speech_data_len[i] = evrc_frame_type_to_octs((guint8)((oct & 0xf0) >> 4)); i++; if (i < frame_count) { /* even number of frames */ proto_tree_add_item(toc_tree, hf_toc_frame_type_low, tvb, offset, 1, ENC_BIG_ENDIAN); speech_data_len[i] = evrc_frame_type_to_octs((guint8)(oct & 0x0f)); i++; } offset++; } if (frame_count & 0x01) { /* odd number of frames */ proto_tree_add_item(toc_tree, hf_evrc_padding, tvb, offset-1, 1, ENC_BIG_ENDIAN); } proto_item_set_len(item, offset - saved_offset); } i = 0; while ((i < frame_count) && ((len - offset) >= speech_data_len[i])) { proto_tree_add_text(evrc_tree, tvb, offset, speech_data_len[i], "Speech Data [%u]", i+1); offset += speech_data_len[i]; i++; } }
/* Decode REG-RSP messages. */ static void dissect_mac_mgmt_msg_reg_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint offset = 0; guint tlv_offset; guint tvb_len; proto_item *reg_rsp_item; proto_tree *reg_rsp_tree; proto_item *tlv_item = NULL; proto_tree *tlv_tree = NULL; proto_tree *sub_tree = NULL; gboolean hmac_found = FALSE; tlv_info_t tlv_info; gint tlv_type; guint tlv_len; guint this_offset = 0; tlv_info_t sub_tlv_info; gint sub_tlv_type; gint sub_tlv_len; guint sub_tlv_offset; { /* we are being asked for details */ /* Get the tvb reported length */ tvb_len = tvb_reported_length(tvb); /* display MAC payload type REG-RSP */ reg_rsp_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tvb_len, "MAC Management Message, REG-RSP"); /* add MAC REG-RSP subtree */ reg_rsp_tree = proto_item_add_subtree(reg_rsp_item, ett_mac_mgmt_msg_reg_rsp_decoder); proto_tree_add_item(reg_rsp_tree, hf_reg_rsp_status, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; while (offset < tvb_len) { /* Get the TLV data. */ init_tlv_info(&tlv_info, tvb, offset); /* get the TLV type */ tlv_type = get_tlv_type(&tlv_info); /* get the TLV length */ tlv_len = get_tlv_length(&tlv_info); if (tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) { /* invalid tlv info */ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REG-RSP TLV error"); proto_tree_add_item(reg_rsp_tree, hf_reg_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); break; } /* get the offset to the TLV data */ tlv_offset = offset + get_tlv_value_offset(&tlv_info); switch (tlv_type) { case REG_ARQ_PARAMETERS: case REG_SS_MGMT_SUPPORT: case REG_IP_MGMT_MODE: case REG_IP_VERSION: case REG_UL_TRANSPORT_CIDS_SUPPORTED: case REG_IP_PHS_SDU_ENCAP: case REG_MAX_CLASSIFIERS_SUPPORTED: case REG_PHS_SUPPORT: case REG_ARQ_SUPPORT: case REG_DSX_FLOW_CONTROL: case REG_MCA_FLOW_CONTROL: case REG_MCAST_POLLING_CIDS: case REG_NUM_DL_TRANS_CID: case REG_MAC_ADDRESS: #ifdef WIMAX_16E_2005 case REG_TLV_T_20_MAX_MAC_DATA_PER_FRAME_SUPPORT: case REG_TLV_T_21_PACKING_SUPPORT: case REG_TLV_T_22_MAC_EXTENDED_RTPS_SUPPORT: case REG_TLV_T_23_MAX_NUM_BURSTS_TRANSMITTED_CONCURRENTLY_TO_THE_MS: case REG_TLV_T_26_METHOD_FOR_ALLOCATING_IP_ADDR_SECONDARY_MGMNT_CONNECTION: case REG_TLV_T_27_HANDOVER_SUPPORTED: case REG_TLV_T_29_HO_PROCESS_OPTIMIZATION_MS_TIMER: case REG_TLV_T_31_MOBILITY_FEATURES_SUPPORTED: case REG_TLV_T_40_ARQ_ACK_TYPE: case REG_TLV_T_41_MS_HO_CONNECTIONS_PARAM_PROCESSING_TIME: case REG_TLV_T_42_MS_HO_TEK_PROCESSING_TIME: case REG_TLV_T_43_MAC_HEADER_AND_EXTENDED_SUBHEADER_SUPPORT: case REG_POWER_SAVING_CLASS_CAPABILITY: #endif dissect_extended_tlv(reg_rsp_tree, tlv_type, tvb, tlv_offset, tlv_len, pinfo, offset, proto_mac_mgmt_msg_reg_rsp_decoder); break; case REG_RSP_SECONDARY_MGMT_CID: add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_reg_rsp_secondary_mgmt_cid, tvb, offset, ENC_BIG_ENDIAN); break; case REG_RSP_TLV_T_36_TOTAL_PROVISIONED_SERVICE_FLOW_DSAs: add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_reg_total_provisioned_sf, tvb, offset, ENC_BIG_ENDIAN); break; case REG_RSP_TLV_T_24_CID_UPDATE_ENCODINGS: /* Display CID update encodings */ /* add subtree */ sub_tree = add_protocol_subtree(&tlv_info, ett_reg_rsp_message_tree, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "CID update encodings"); /* Use a local copy of tlv_offset */ this_offset = tlv_offset; while(this_offset < tlv_len) { /* Get the sub TLV data. */ init_tlv_info(&sub_tlv_info, tvb, this_offset); /* get the sub TLV type */ sub_tlv_type = get_tlv_type(&sub_tlv_info); /* get the TLV length */ sub_tlv_len = get_tlv_length(&sub_tlv_info); if (tlv_type == -1 || sub_tlv_len > MAX_TLV_LEN || sub_tlv_len < 1) { /* invalid tlv info */ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REG-RSP TLV error"); proto_tree_add_item(reg_rsp_tree, hf_reg_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); break; } /* get the offset to the sub TLV data */ sub_tlv_offset = this_offset + get_tlv_value_offset(&sub_tlv_info); switch (sub_tlv_type) { case REG_RSP_TLV_T_24_1_CID_UPDATE_ENCODINGS_NEW_CID: add_tlv_subtree(&sub_tlv_info, sub_tree, hf_reg_rsp_new_cid_after_ho, tvb, this_offset, ENC_BIG_ENDIAN); break; case REG_RSP_TLV_T_24_2_CID_UPDATE_ENCODINGS_SFID: add_tlv_subtree(&sub_tlv_info, sub_tree, hf_reg_rsp_service_flow_id, tvb, this_offset, ENC_BIG_ENDIAN); break; case REG_RSP_TLV_T_24_3_CID_UPDATE_ENCODINGS_CONNECTION_INFO: tlv_tree = add_protocol_subtree(&sub_tlv_info, ett_reg_rsp_message_tree, sub_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, this_offset, sub_tlv_len, "CID Update Encodings Connection Info"); /* Decode the DSC_RSP subTLV's */ call_dissector(dsc_rsp_handle, tvb_new_subset_length(tvb, sub_tlv_offset, sub_tlv_len), pinfo, tlv_tree); break; default: add_tlv_subtree(&sub_tlv_info, sub_tree, hf_tlv_type, tvb, this_offset, ENC_NA); break; } this_offset = sub_tlv_len + sub_tlv_offset; } break; case REG_RSP_TLV_T_28_HO_SYSTEM_RESOURCE_RETAIN_TIME: tlv_item = add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_reg_rsp_system_resource_retain_time, tvb, offset, ENC_BIG_ENDIAN); if (include_cor2_changes) { proto_item_append_text(tlv_item, " (in units of 100 milliseconds)"); } else { proto_item_append_text(tlv_item, " (multiple of 100 milliseconds)"); } break; case DSx_UPLINK_FLOW: /* display Uplink Service Flow Encodings info */ /* add subtree */ tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "Uplink Service Flow Encodings"); /* decode and display the DL Service Flow Encodings */ wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, tlv_tree); break; case DSx_DOWNLINK_FLOW: /* display Downlink Service Flow Encodings info */ /* add subtree */ tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "Downlink Service Flow Encodings"); /* decode and display the DL Service Flow Encodings */ wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, tlv_tree); break; case HMAC_TUPLE: /* Table 348d */ /* decode and display the HMAC Tuple */ tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "HMAC Tuple"); wimax_hmac_tuple_decoder(tlv_tree, tvb, offset+2, tlv_len); hmac_found = TRUE; break; case CMAC_TUPLE: /* Table 348b */ /* decode and display the CMAC Tuple */ tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "CMAC Tuple"); wimax_cmac_tuple_decoder(tlv_tree, tvb, offset+2, tlv_len); break; case SHORT_HMAC_TUPLE: case SHORT_HMAC_TUPLE_COR2: if ((!include_cor2_changes && (tlv_type == SHORT_HMAC_TUPLE)) || (include_cor2_changes && (tlv_type == SHORT_HMAC_TUPLE_COR2))) { /* decode and display the Short HMAC Tuple */ tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "Short HMAC Tuple"); wimax_short_hmac_tuple_decoder(tlv_tree, tvb, tlv_offset, tlv_len); } else { /* Unknown TLV Type */ add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_tlv_type, tvb, offset, ENC_NA); } break; case VENDOR_SPECIFIC_INFO: case VENDOR_ID_ENCODING: case MAC_VERSION_ENCODING: wimax_common_tlv_encoding_decoder(tvb_new_subset_length(tvb, offset, (tvb_len - offset)), pinfo, reg_rsp_tree); break; default: add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_tlv_type, tvb, offset, ENC_NA); break; } offset = tlv_len + tlv_offset; } /* end of TLV process while loop */ if (!hmac_found) proto_item_append_text(reg_rsp_tree, " (HMAC Tuple is missing !)"); } }
/* * Add an Ethernet trailer - which, for some captures, might be the FCS * rather than a pad-to-60-bytes trailer. * * If fcs_len is 0, we assume the frame has no FCS; if it's 4, we assume * it has an FCS; if it's anything else (such as -1, which means "maybe * it does, maybe it doesn't"), we try to infer whether it has an FCS. */ void add_ethernet_trailer(packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb, tvbuff_t *trailer_tvb, int fcs_len) { /* If there're some bytes left over, it could be a combination of: - padding to meet the minimum 64 byte frame length - an FCS, if present (if fcs_len is 0, we know it's not present; if fcs_len is 4, we know it's present; if fcs_len is -1, we need some heuristics to determine whether it's present) - information inserted by TAPs or other network monitoring equipment. If we don't know whether the FCS is present, then, if we don't have a network monitoring trailer, and if the Ethernet frame was claimed to have had 64 or more bytes - i.e., it was at least an FCS worth of data longer than the minimum payload size - we could assume the last 4 bytes of the trailer are an FCS. */ proto_item *item; proto_tree *checksum_tree; heur_dtbl_entry_t *hdtbl_entry; if (trailer_tvb) { guint trailer_length, trailer_reported_length; guint padding_length = 0; gboolean has_fcs = FALSE; tvbuff_t *real_trailer_tvb; trailer_length = tvb_captured_length(trailer_tvb); trailer_reported_length = tvb_reported_length(trailer_tvb); /* There can not have been padding when the length of the frame (including the trailer) is less than 60 bytes. */ if (eth_assume_padding && pinfo->fd->pkt_len>=60) { /* Calculate the amount of padding needed for a minimum sized frame */ if ( (pinfo->fd->pkt_len - trailer_reported_length) < 60 ) padding_length = 60 - (pinfo->fd->pkt_len - trailer_reported_length); /* Add the padding to the tree, unless it should be treated as part of the trailer and therefor be handed over to (one of) the ethernet-trailer dissectors */ if (padding_length > 0) { tvb_ensure_bytes_exist(tvb, 0, padding_length); proto_tree_add_item(fh_tree, hf_eth_padding, trailer_tvb, 0, padding_length, ENC_NA); trailer_length -= padding_length; trailer_reported_length -= padding_length; } } if (fcs_len != 0) { /* If fcs_len is 4, we assume we definitely have an FCS. Otherwise, then, if the frame is big enough that, if we have a trailer, it probably inclues an FCS, and we have enough space in the trailer for the FCS, we assume we have an FCS. "Big enough" means 64 bytes or more; any frame that big needs no trailer, as there's no need to pad an Ethernet packet past 60 bytes. The trailer must be at least 4 bytes long to have enough space for an FCS. */ if (fcs_len == 4 || (tvb_reported_length(tvb) >= 64 && trailer_reported_length >= 4)) { /* Either we know we have an FCS, or we believe we have an FCS. */ if (trailer_length < trailer_reported_length) { /* The packet is claimed to have enough data for a 4-byte FCS, but we didn't capture all of the packet. Slice off the 4-byte FCS from the reported length, and trim the captured length so it's no more than the reported length; that will slice off what of the FCS, if any, is in the captured packet. */ trailer_reported_length -= 4; if (trailer_length > trailer_reported_length) trailer_length = trailer_reported_length; has_fcs = TRUE; } else { /* We captured all of the packet, including what appears to be a 4-byte FCS. Slice it off. */ trailer_length -= 4; trailer_reported_length -= 4; has_fcs = TRUE; } } } /* Create a new tvb without the padding and/or the (assumed) fcs */ if (fcs_len==4) real_trailer_tvb = tvb_new_subset(trailer_tvb, padding_length, trailer_length, trailer_reported_length); else real_trailer_tvb = tvb_new_subset_remaining(trailer_tvb, padding_length); /* Call all ethernet trailer dissectors to dissect the trailer if we actually have a trailer. */ if (tvb_reported_length(real_trailer_tvb) != 0) { if (dissector_try_heuristic(eth_trailer_subdissector_list, real_trailer_tvb, pinfo, tree, &hdtbl_entry, NULL) ) { /* If we're not sure that there is a FCS, all trailer data has been given to the ethernet-trailer dissector, so stop dissecting here */ if (fcs_len!=4) return; } else { /* No luck with the trailer dissectors, so just display the extra bytes as general trailer */ if (trailer_length != 0) { tvb_ensure_bytes_exist(tvb, 0, trailer_length); proto_tree_add_item(fh_tree, trailer_id, real_trailer_tvb, 0, trailer_length, ENC_NA); } } } if (has_fcs) { guint32 sent_fcs = tvb_get_ntohl(trailer_tvb, padding_length+trailer_length); if(eth_check_fcs){ guint32 fcs = crc32_802_tvb(tvb, tvb_captured_length(tvb) - 4); if (fcs == sent_fcs) { item = proto_tree_add_uint_format_value(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "0x%08x [correct]", sent_fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, TRUE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format_value(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "0x%08x [incorrect, should be 0x%08x]", sent_fcs, fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, TRUE); PROTO_ITEM_SET_GENERATED(item); expert_add_info(pinfo, item, &ei_eth_fcs_bad); col_append_str(pinfo->cinfo, COL_INFO, " [ETHERNET FRAME CHECK SEQUENCE INCORRECT]"); } }else{ item = proto_tree_add_uint_format_value(fh_tree, hf_eth_fcs, trailer_tvb, padding_length+trailer_length, 4, sent_fcs, "0x%08x [validiation disabled]", sent_fcs); checksum_tree = proto_item_add_subtree(item, ett_eth_fcs); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb, padding_length+trailer_length, 4, FALSE); PROTO_ITEM_SET_GENERATED(item); } trailer_length += 4; } proto_tree_set_appendix(fh_tree, tvb, tvb_captured_length(tvb) - padding_length - trailer_length, padding_length + trailer_length); } }
/* Parse Short Message, only if UDH present * (otherwise this function is not called). * Call WSP dissector if port matches WSP traffic. */ static void parse_gsm_sms_ud_message(proto_tree *sm_tree, tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree) { tvbuff_t *sm_tvb = NULL; proto_item *ti; proto_tree *subtree, *tree; guint8 udh_len, udh, len; guint sm_len = tvb_reported_length(tvb); guint sm_data_len; guint32 i = 0; /* Multiple Messages UDH */ gboolean is_fragmented = FALSE; fragment_head *fd_sm = NULL; guint16 sm_id = 0; guint16 frags = 0; guint16 frag = 0; gboolean save_fragmented = FALSE; gboolean try_gsm_sms_ud_reassemble = FALSE; /* SMS Message reassembly */ gboolean reassembled = FALSE; guint32 reassembled_in = 0; /* Port Number UDH */ guint16 p_src = 0; guint16 p_dst = 0; gboolean ports_available = FALSE; udh_len = tvb_get_guint8(tvb, i++); ti = proto_tree_add_uint(sm_tree, hf_gsm_sms_udh_length, tvb, 0, 1, udh_len); tree = proto_item_add_subtree(ti, ett_udh); while (i < udh_len) { udh = tvb_get_guint8(tvb, i++); len = tvb_get_guint8(tvb, i++); subtree = proto_tree_add_uint(tree, hf_gsm_sms_udh_iei, tvb, i-2, 2+len, udh); switch (udh) { case 0x00: /* Multiple messages - 8-bit message ID */ if (len == 3) { sm_id = tvb_get_guint8(tvb, i++); frags = tvb_get_guint8(tvb, i++); frag = tvb_get_guint8(tvb, i++); if (frags > 1) is_fragmented = TRUE; proto_item_append_text(subtree, ": message %u, part %u of %u", sm_id, frag, frags); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_id, tvb, i-3, 1, sm_id); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_parts, tvb, i-2, 1, frags); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_part, tvb, i-1, 1, frag); } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; case 0x08: /* Multiple messages - 16-bit message ID */ if (len == 4) { sm_id = tvb_get_ntohs(tvb, i); i += 2; frags = tvb_get_guint8(tvb, i++); frag = tvb_get_guint8(tvb, i++); if (frags > 1) is_fragmented = TRUE; proto_item_append_text(subtree, ": message %u, part %u of %u", sm_id, frag, frags); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_id, tvb, i-4, 2, sm_id); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_parts, tvb, i-2, 1, frags); proto_tree_add_uint(subtree, hf_gsm_sms_udh_multiple_messages_msg_part, tvb, i-1, 1, frag); } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; case 0x04: /* Port Number UDH - 8-bit address */ if (len == 2) { /* Port fields */ p_dst = tvb_get_guint8(tvb, i++); p_src = tvb_get_guint8(tvb, i++); proto_item_append_text(subtree, ": source port %u, destination port %u", p_src, p_dst); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_dst, tvb, i-2, 1, p_dst); proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_src, tvb, i-1, 1, p_src); ports_available = TRUE; } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; case 0x05: /* Port Number UDH - 16-bit address */ if (len == 4) { /* Port fields */ p_dst = tvb_get_ntohs(tvb, i); i += 2; p_src = tvb_get_ntohs(tvb, i); i += 2; proto_item_append_text(subtree, ": source port %u, destination port %u", p_src, p_dst); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_dst, tvb, i-4, 2, p_dst); proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_src, tvb, i-2, 2, p_src); ports_available = TRUE; } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; case 0x24: /* National Language Single Shift */ if (len == 1) { subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_item(subtree, hf_gsm_sms_udh_national_single_shift, tvb, i++, 1, ENC_BIG_ENDIAN); } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; case 0x25: /* National Language Locking Shift */ if (len == 1) { subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_item(subtree, hf_gsm_sms_udh_national_locking_shift, tvb, i++, 1, ENC_BIG_ENDIAN); } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; default: i += len; break; } } if (tvb_reported_length_remaining(tvb, i) <= 0) return; /* No more data */ /* * XXX - where does the "1" come from? If it weren't there, * "sm_data_len" would, I think, be the same as * "tvb_reported_length_remaining(tvb, i)". * * I think that the above check ensures that "sm_len" won't * be less than or equal to "udh_len", so it ensures that * "sm_len" won't be less than "1 + udh_len", so we don't * have to worry about "sm_data_len" being negative. */ sm_data_len = sm_len - (1 + udh_len); if (sm_data_len == 0) return; /* no more data */ /* * Try reassembling the packets. * XXX - fragment numbers are 1-origin, but the fragment number * field could be 0. * Should we flag a fragmented message with a fragment number field * of 0? * What if the fragment count is 0? Should we flag that as well? */ if (is_fragmented && frag != 0 && frags != 0 && tvb_bytes_exist(tvb, i, sm_data_len)) { try_gsm_sms_ud_reassemble = TRUE; save_fragmented = pinfo->fragmented; pinfo->fragmented = TRUE; fd_sm = fragment_add_seq_check(&sm_reassembly_table, tvb, i, pinfo, sm_id, /* guint32 ID for fragments belonging together */ NULL, frag-1, /* guint32 fragment sequence number */ sm_data_len, /* guint32 fragment length */ (frag != frags)); /* More fragments? */ if (fd_sm) { reassembled = TRUE; reassembled_in = fd_sm->reassembled_in; } sm_tvb = process_reassembled_data(tvb, i, pinfo, "Reassembled Short Message", fd_sm, &sm_frag_items, NULL, sm_tree); if (reassembled) { /* Reassembled */ col_append_str(pinfo->cinfo, COL_INFO, " (Short Message Reassembled)"); } else { /* Not last packet of reassembled Short Message */ col_append_fstr(pinfo->cinfo, COL_INFO, " (Short Message fragment %u of %u)", frag, frags); } } /* Else: not fragmented */ if (! sm_tvb) /* One single Short Message, or not reassembled */ sm_tvb = tvb_new_subset_remaining(tvb, i); /* Try calling a subdissector */ if (sm_tvb) { if ((reassembled && pinfo->num == reassembled_in) || frag==0 || (frag==1 && try_dissect_1st_frag)) { /* Try calling a subdissector only if: * - the Short Message is reassembled in this very packet, * - the Short Message consists of only one "fragment", * - the preference "Always Try Dissection for 1st SM fragment" * is switched on, and this is the SM's 1st fragment. */ if (ports_available) { gboolean disallow_write = FALSE; /* TRUE if we changed writability of the columns of the summary */ if (prevent_subdissectors_changing_columns && col_get_writable(pinfo->cinfo)) { disallow_write = TRUE; col_set_writable(pinfo->cinfo, FALSE); } if (port_number_udh_means_wsp) { call_dissector(wsp_handle, sm_tvb, pinfo, top_tree); } else { if (! dissector_try_uint(gsm_sms_dissector_table, p_src, sm_tvb, pinfo, top_tree)) { if (! dissector_try_uint(gsm_sms_dissector_table, p_dst, sm_tvb, pinfo, top_tree)) { if (sm_tree) { /* Only display if needed */ proto_tree_add_item(sm_tree, hf_gsm_sms_ud_short_msg, sm_tvb, 0, -1, ENC_NA); } } } } if (disallow_write) col_set_writable(pinfo->cinfo, TRUE); } else { /* No ports IE */ proto_tree_add_item(sm_tree, hf_gsm_sms_ud_short_msg, sm_tvb, 0, -1, ENC_NA); } } else { /* The packet is not reassembled, * or it is reassembled in another packet */ proto_tree_add_bytes_format(sm_tree, hf_gsm_sms_ud_short_msg, sm_tvb, 0, -1, NULL, "Unreassembled Short Message fragment %u of %u", frag, frags); } } if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */ pinfo->fragmented = save_fragmented; return; }
parent_tree, remaining_length); } /* offset = data_offset + data_length; */ break; } return; } static enum SMB_DIRECT_HDR_TYPE is_smb_direct(tvbuff_t *tvb, packet_info *pinfo _U_) { gboolean maybe_neg_req = FALSE; gboolean maybe_data = FALSE; guint len = tvb_reported_length(tvb); if (len < 20) { return SMB_DIRECT_HDR_UNKNOWN; } if (len == 32 && tvb_get_letohs(tvb, 0) == 0x0100 && /* min version */ tvb_get_letohs(tvb, 2) == 0x0100 && /* max version */ tvb_get_letohs(tvb, 4) == 0x0100 && /* negotiated version */ tvb_get_letohs(tvb, 6) == 0x0000) /* reserved */ { /* Negotiate Response */ return SMB_DIRECT_HDR_NEG_REP; }
static int dissect_pbb_addressblock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint maxoffset, guint8 addressType, guint8 addressSize) { guint8 addr[MAX_ADDR_SIZE]; guint8 numAddr; guint8 address_flags; guint8 head_length = 0, tail_length = 0; guint block_length = 0, midSize = 0; guint block_index = 0, head_index = 0, tail_index = 0, mid_index = 0, prefix_index = 0; proto_tree *addr_tree = NULL; proto_tree *addrFlags_tree = NULL; proto_tree *addrValue_tree = NULL; proto_item *addr_item = NULL; proto_item *addrFlags_item = NULL; proto_item *addrValue_item = NULL; int i = 0; if (maxoffset - offset < 2) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for minimal addressblock header"); return tvb_reported_length(tvb); } DISSECTOR_ASSERT(addressSize <= MAX_ADDR_SIZE); memset(addr, 0, addressSize); block_length = 2; block_index = offset; midSize = addressSize; numAddr = tvb_get_guint8(tvb, offset++); address_flags = tvb_get_guint8(tvb, offset++); if ((address_flags & ADDR_HASHEAD) != 0) { head_index = offset; if (maxoffset - offset <= 0) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock head"); return tvb_reported_length(tvb); } head_length = tvb_get_guint8(tvb, offset++); if (head_length > addressSize-1) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "address head length is too long"); return tvb_reported_length(tvb); } if (maxoffset - offset < head_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock head"); return tvb_reported_length(tvb); } tvb_memcpy(tvb, addr, offset, head_length); midSize -= head_length; block_length += (head_length+1); offset += head_length; } if ((address_flags & ADDR_HASZEROTAIL) != 0) { tail_index = offset; if (maxoffset - offset <= 0) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock tail"); return tvb_reported_length(tvb); } tail_length = tvb_get_guint8(tvb, offset++); if (tail_length > addressSize-1-head_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "address tail length is too long"); return tvb_reported_length(tvb); } midSize -= tail_length; block_length++; } else if ((address_flags & ADDR_HASFULLTAIL) != 0) { tail_index = offset; if (maxoffset - offset <= 0) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock tail"); return tvb_reported_length(tvb); } tail_length = tvb_get_guint8(tvb, offset++); if (tail_length > addressSize-1-head_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "address tail length is too long"); return tvb_reported_length(tvb); } if (maxoffset - offset < tail_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock tail"); return tvb_reported_length(tvb); } tvb_memcpy(tvb, &addr[addressSize - tail_length], offset, tail_length); midSize -= tail_length; block_length += (tail_length+1); offset += tail_length; } mid_index = offset; block_length += numAddr * midSize; offset += numAddr * midSize; if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) { prefix_index = offset; block_length++; } else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) { prefix_index = offset; block_length += numAddr; } if (maxoffset < block_index + block_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for address block"); return maxoffset; } /* add address tree */ addr_item = proto_tree_add_item(tree, hf_packetbb_addr, tvb, block_index, block_length, ENC_NA); addr_tree = proto_item_add_subtree(addr_item, ett_packetbb_addr); proto_item_append_text(addr_item, " (%d addresses)", numAddr); /* add num-addr */ proto_tree_add_item(addr_tree, hf_packetbb_addr_num, tvb, block_index, 1, ENC_BIG_ENDIAN); /* add flags */ addrFlags_item = proto_tree_add_item(addr_tree, hf_packetbb_addr_flags, tvb, block_index+1, 1, ENC_BIG_ENDIAN); addrFlags_tree = proto_item_add_subtree(addrFlags_item, ett_packetbb_addr_flags); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hashead, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasfulltail, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_haszerotail, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hassingleprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasmultiprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN); if ((address_flags & ADDR_HASHEAD) != 0) { /* add head */ proto_tree_add_item(addr_tree, hf_packetbb_addr_head, tvb, head_index, head_length+1, ENC_NA); } if ((address_flags & ADDR_HASFULLTAIL) != 0) { /* add full tail */ proto_tree_add_item(addr_tree, hf_packetbb_addr_tail, tvb, tail_index, tail_length+1, ENC_NA); } else if ((address_flags & ADDR_HASZEROTAIL) != 0) { /* add zero tail */ proto_tree_add_item(addr_tree, hf_packetbb_addr_tail, tvb, tail_index, 1, ENC_NA); } for (i=0; i<numAddr; i++) { guint32 ipv4 = (addr[0] << 24) + (addr[1] << 16) + (addr[2] << 8) + addr[3]; guint8 prefix = addressSize * 8; tvb_memcpy(tvb, &addr[head_length], mid_index + midSize*i, midSize); switch (addressType) { case 0: addrValue_item = proto_tree_add_ipv4(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, ipv4); break; case 1: addrValue_item = proto_tree_add_ipv6(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, (struct e_in6_addr *)addr); break; case 2: addrValue_item = proto_tree_add_ether(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, addr); break; case 3: addrValue_item = proto_tree_add_bytes(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, addr); break; default: break; } addrValue_tree = proto_item_add_subtree(addrValue_item, ett_packetbb_addr_value); proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_mid, tvb, mid_index + midSize*i, midSize, ENC_NA); if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) { prefix = tvb_get_guint8(tvb, prefix_index); proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index, 1, ENC_BIG_ENDIAN); } else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) { prefix = tvb_get_guint8(tvb, prefix_index + i); proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index + i, 1, ENC_BIG_ENDIAN); } proto_item_append_text(addrValue_item, "/%d", prefix); } offset = dissect_pbb_tlvblock(tvb, pinfo, addr_tree, block_index + block_length, maxoffset, numAddr); return offset; }
static void dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto) { proto_tree *udp_tree = NULL; proto_item *ti, *hidden_item, *port_item; guint len; guint reported_len; vec_t cksum_vec[4]; guint32 phdr[2]; guint16 computed_cksum; int offset = 0; e_udphdr *udph; proto_tree *checksum_tree; proto_item *item; conversation_t *conv = NULL; struct udp_analysis *udpd = NULL; proto_tree *process_tree; udph=ep_new(e_udphdr); SET_ADDRESS(&udph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data); SET_ADDRESS(&udph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data); col_set_str(pinfo->cinfo, COL_PROTOCOL, (ip_proto == IP_PROTO_UDP) ? "UDP" : "UDPlite"); col_clear(pinfo->cinfo, COL_INFO); udph->uh_sport=tvb_get_ntohs(tvb, offset); udph->uh_dport=tvb_get_ntohs(tvb, offset+2); col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s Destination port: %s", get_udp_port(udph->uh_sport), get_udp_port(udph->uh_dport)); if (tree) { if (udp_summary_in_tree) { if (ip_proto == IP_PROTO_UDP) { ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8, "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport); } else { ti = proto_tree_add_protocol_format(tree, proto_udplite, tvb, offset, 8, "Lightweight User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport); } } else { ti = proto_tree_add_item(tree, (ip_proto == IP_PROTO_UDP) ? proto_udp : proto_udplite, tvb, offset, 8, ENC_NA); } udp_tree = proto_item_add_subtree(ti, ett_udp); port_item = proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, udph->uh_sport, "Source port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport); /* The beginning port number, 32768 + 666 (33434), is from LBL's traceroute.c source code and this code * further assumes that 3 attempts are made per hop */ if(udph->uh_sport > 32768 + 666 && udph->uh_sport <= 32768 + 666 + 30) expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u", ((udph->uh_sport - 32768 - 666 - 1) / 3) + 1, ((udph->uh_sport - 32768 - 666 - 1) % 3) + 1 ); port_item = proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, udph->uh_dport, "Destination port: %s (%u)", get_udp_port(udph->uh_dport), udph->uh_dport); if(udph->uh_dport > 32768 + 666 && udph->uh_dport <= 32768 + 666 + 30) expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u", ((udph->uh_dport - 32768 - 666 - 1) / 3) + 1, ((udph->uh_dport - 32768 - 666 - 1) % 3) + 1 ); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset, 2, udph->uh_sport); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset+2, 2, udph->uh_dport); PROTO_ITEM_SET_HIDDEN(hidden_item); } if (ip_proto == IP_PROTO_UDP) { udph->uh_ulen = udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4); if (udph->uh_ulen < 8) { /* Bogus length - it includes the header, so it must be >= 8. */ /* XXX - should handle IPv6 UDP jumbograms (RFC 2675), where the length is zero */ item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen, "Length: %u (bogus, must be >= 8)", udph->uh_ulen); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u < 8", udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u < 8]", udph->uh_ulen); return; } if ((udph->uh_ulen > tvb_reported_length(tvb)) && ! pinfo->fragmented && ! pinfo->flags.in_error_pkt) { /* Bogus length - it goes past the end of the IP payload */ item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen, "Length: %u (bogus, payload length %u)", udph->uh_ulen, tvb_reported_length(tvb)); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u > IP payload length", udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u > IP PAYLOAD LENGTH]", udph->uh_ulen); } else { if (tree) { proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen); /* XXX - why is this here, given that this is UDP, not Lightweight UDP? */ hidden_item = proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 0, udph->uh_sum_cov); PROTO_ITEM_SET_HIDDEN(hidden_item); } } } else { udph->uh_ulen = pinfo->iplen - pinfo->iphdrlen; udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4); if (((udph->uh_sum_cov > 0) && (udph->uh_sum_cov < 8)) || (udph->uh_sum_cov > udph->uh_ulen)) { /* Bogus length - it includes the header, so it must be >= 8, and no larger then the IP payload size. */ if (tree) { hidden_item = proto_tree_add_boolean(udp_tree, hf_udplite_checksum_coverage_bad, tvb, offset + 4, 2, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen); PROTO_ITEM_SET_HIDDEN(hidden_item); } item = proto_tree_add_uint_format(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov, "Checksum coverage: %u (bogus, must be >= 8 and <= %u (ip.len-ip.hdr_len))", udph->uh_sum_cov, udph->uh_ulen); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad checksum coverage length value %u < 8 or > %u", udph->uh_sum_cov, udph->uh_ulen); col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD LIGHTWEIGHT UDP CHECKSUM COVERAGE LENGTH %u < 8 or > %u]", udph->uh_sum_cov, udph->uh_ulen); if (!udplite_ignore_checksum_coverage) return; } else { if (tree) { hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov); } } } udph->uh_sum_cov = (udph->uh_sum_cov) ? udph->uh_sum_cov : udph->uh_ulen; udph->uh_sum = tvb_get_ntohs(tvb, offset+6); reported_len = tvb_reported_length(tvb); len = tvb_length(tvb); if (udph->uh_sum == 0) { /* No checksum supplied in the packet. */ if ((ip_proto == IP_PROTO_UDP) && (pinfo->src.type == AT_IPv4)) { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0, "Checksum: 0x%04x (none)", 0); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0, "Checksum: 0x%04x (Illegal)", 0); expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Illegal Checksum value (0)"); col_append_fstr(pinfo->cinfo, COL_INFO, " [ILLEGAL CHECKSUM (0)]"); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); } } else if (!pinfo->fragmented && len >= reported_len && len >= udph->uh_sum_cov && reported_len >= udph->uh_sum_cov && udph->uh_sum_cov >=8) { /* The packet isn't part of a fragmented datagram and isn't truncated, so we can checksum it. XXX - make a bigger scatter-gather list once we do fragment reassembly? */ if (((ip_proto == IP_PROTO_UDP) && (udp_check_checksum)) || ((ip_proto == IP_PROTO_UDPLITE) && (udplite_check_checksum))) { /* Set up the fields of the pseudo-header. */ cksum_vec[0].ptr = (const guint8 *)pinfo->src.data; cksum_vec[0].len = pinfo->src.len; cksum_vec[1].ptr = (const guint8 *)pinfo->dst.data; cksum_vec[1].len = pinfo->dst.len; cksum_vec[2].ptr = (const guint8 *)&phdr; switch (pinfo->src.type) { case AT_IPv4: if (ip_proto == IP_PROTO_UDP) phdr[0] = g_htonl((ip_proto<<16) | udph->uh_ulen); else phdr[0] = g_htonl((ip_proto<<16) | reported_len); cksum_vec[2].len = 4; break; case AT_IPv6: if (ip_proto == IP_PROTO_UDP) phdr[0] = g_htonl(udph->uh_ulen); else phdr[0] = g_htonl(reported_len); phdr[1] = g_htonl(ip_proto); cksum_vec[2].len = 8; break; default: /* UDP runs only atop IPv4 and IPv6.... */ DISSECTOR_ASSERT_NOT_REACHED(); break; } cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, udph->uh_sum_cov); cksum_vec[3].len = udph->uh_sum_cov; computed_cksum = in_cksum(&cksum_vec[0], 4); if (computed_cksum == 0) { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [correct]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"UDP checksum offload\"?)]", udph->uh_sum, in_cksum_shouldbe(udph->uh_sum, computed_cksum)); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, TRUE); PROTO_ITEM_SET_GENERATED(item); expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum"); col_append_fstr(pinfo->cinfo, COL_INFO, " [UDP CHECKSUM INCORRECT]"); } } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [validation disabled]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } } else { item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [unchecked, not all data available]", udph->uh_sum); checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb, offset + 6, 2, FALSE); PROTO_ITEM_SET_GENERATED(item); } /* Skip over header */ offset += 8; pinfo->ptype = PT_UDP; pinfo->srcport = udph->uh_sport; pinfo->destport = udph->uh_dport; tap_queue_packet(udp_tap, pinfo, udph); /* find(or create if needed) the conversation for this udp session */ if (udp_process_info) { conv=find_or_create_conversation(pinfo); udpd=get_udp_conversation_data(conv,pinfo); } if (udpd && ((udpd->fwd && udpd->fwd->command) || (udpd->rev && udpd->rev->command))) { ti = proto_tree_add_text(udp_tree, tvb, offset, 0, "Process Information"); PROTO_ITEM_SET_GENERATED(ti); process_tree = proto_item_add_subtree(ti, ett_udp_process_info); if (udpd->fwd && udpd->fwd->command) { proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_uid, tvb, 0, 0, udpd->fwd->process_uid, "%u", udpd->fwd->process_uid); proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_pid, tvb, 0, 0, udpd->fwd->process_pid, "%u", udpd->fwd->process_pid); proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_uname, tvb, 0, 0, udpd->fwd->username, "%s", udpd->fwd->username); proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_cmd, tvb, 0, 0, udpd->fwd->command, "%s", udpd->fwd->command); } if (udpd->rev->command) { proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_uid, tvb, 0, 0, udpd->rev->process_uid, "%u", udpd->rev->process_uid); proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_pid, tvb, 0, 0, udpd->rev->process_pid, "%u", udpd->rev->process_pid); proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_uname, tvb, 0, 0, udpd->rev->username, "%s", udpd->rev->username); proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_cmd, tvb, 0, 0, udpd->rev->command, "%s", udpd->rev->command); } } /* * Call sub-dissectors. * * XXX - should we do this if this is included in an error packet? * It might be nice to see the details of the packet that caused the * ICMP error, but it might not be nice to have the dissector update * state based on it. * Also, we probably don't want to run UDP taps on those packets. * * We definitely don't want to do it for an error packet if there's * nothing left in the packet. */ if (!pinfo->flags.in_error_pkt || tvb_length_remaining(tvb, offset) > 0) decode_udp_ports(tvb, offset, pinfo, tree, udph->uh_sport, udph->uh_dport, udph->uh_ulen); }