static void dissect_cnip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tvbuff_t *next_tvb; gint offset; gint type, exth_len, pf_pcode; proto_tree *ti; proto_tree *cnip_tree; static const gint *pf_fields[] = { &hf_cnip_pf_sec, &hf_cnip_pf_pcode, NULL }; col_set_str(pinfo->cinfo, COL_PROTOCOL, "CN/IP"); col_clear(pinfo->cinfo, COL_INFO); type = tvb_get_guint8(tvb, 3); col_add_fstr(pinfo->cinfo, COL_INFO,"Priority: %s Type: %s", (pinfo->destport == 1629 )? "urgent":"normal", val_to_str_const(type, type_tuple, "Unknown")); exth_len = tvb_get_guint8(tvb, 4); pf_pcode = tvb_get_guint8(tvb, 5) & 0x1F; offset = 0; /* Take whole packet for now, we'll adjust it later */ ti = proto_tree_add_item(tree, proto_cnip, tvb, offset, -1, ENC_NA); cnip_tree = proto_item_add_subtree(ti, ett_cnip); proto_tree_add_item(cnip_tree, hf_cnip_len, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(cnip_tree, hf_cnip_ver, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(cnip_tree, hf_cnip_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(cnip_tree, hf_cnip_exth, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_bitmask(cnip_tree, tvb, offset, hf_cnip_pf, ett_pf, pf_fields, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(cnip_tree, hf_cnip_vcode, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(cnip_tree, hf_cnip_sessid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(cnip_tree, hf_cnip_seqno, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(cnip_tree, hf_cnip_tstamp, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Jump over any unknown header extensions */ offset += 4 * exth_len; proto_item_set_len(ti, offset); next_tvb = tvb_new_subset_remaining(tvb, offset); if (type == DATA_PACKET) { if (dissector_try_uint(cnip_dissector_table, pf_pcode, next_tvb, pinfo, tree)) return; } else { expert_add_info_format_text(pinfo, cnip_tree, &ei_cnip_type_unknown, "This dissector doesn't yet decode packets of type %s (0x%x)", val_to_str_const(type, type_tuple, "Unknown"), type); } call_dissector(data_handle, next_tvb, pinfo, tree); }
static void dissect_btatt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; proto_item *ti, *item; proto_tree *st, *ltree; guint8 opcode; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATT"); switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_add_str(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_add_str(pinfo->cinfo, COL_INFO, "Rcvd "); break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ", pinfo->p2p_dir); break; } if (tvb_length_remaining(tvb, 0) < 1) return; ti = proto_tree_add_item(tree, proto_btatt, tvb, 0, -1, ENC_NA); st = proto_item_add_subtree(ti, ett_btatt); item = proto_tree_add_item(st, hf_btatt_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN); opcode = tvb_get_guint8(tvb, 0); offset++; col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_const(opcode, opcode_vals, "<unknown>")); switch (opcode) { case 0x01: /* Error Response */ proto_tree_add_item(st, hf_btatt_req_opcode_in_error, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; proto_tree_add_item(st, hf_btatt_handle_in_error, tvb, offset, 2, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, " - %s, Handle: 0x%04x", val_to_str_const(tvb_get_guint8(tvb, offset+2), error_vals, "<unknown>"), tvb_get_letohs(tvb, offset)); offset += 2; proto_tree_add_item(st, hf_btatt_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; break; case 0x02: /* Exchange MTU Request */ col_append_fstr(pinfo->cinfo, COL_INFO, ", Client Rx MTU: %u", tvb_get_letohs(tvb, offset)); proto_tree_add_item(st, hf_btatt_client_rx_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; break; case 0x03: /* Exchange MTU Response */ col_append_fstr(pinfo->cinfo, COL_INFO, ", Server Rx MTU: %u", tvb_get_letohs(tvb, offset)); proto_tree_add_item(st, hf_btatt_server_rx_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; break; case 0x04: /* Find Information Request */ col_append_fstr(pinfo->cinfo, COL_INFO, ", Handles: 0x%04x..0x%04x", tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2)); proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; break; case 0x05: /* Find Information Response */ { guint8 format = tvb_get_guint8(tvb, offset); item = proto_tree_add_item(st, hf_btatt_uuid_format, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; if( format == 1 ) { while( tvb_length_remaining(tvb, offset) > 0) { proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } } else if( format == 2 ) { while( tvb_length_remaining(tvb, offset) > 0) { proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btatt_uuid128, tvb, offset, 16, ENC_NA); offset += 16; } } else { expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "Unknown format"); } } break; case 0x06: /* Find By Type Value Request */ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, Handles: 0x%04x..0x%04x", val_to_str_ext_const(tvb_get_letohs(tvb, offset+4), &uuid_vals_ext, "<unknown>"), tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2)); proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; if( tvb_length_remaining(tvb, offset) > 0) proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA); break; case 0x07: /* Find By Type Value Response */ while( tvb_length_remaining(tvb, offset) > 0 ) { item = proto_tree_add_text(st, tvb, offset, 4, "Handles Info, Handle: 0x%04x, Group End Handle: 0x%04x", tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2)); ltree = proto_item_add_subtree(item, ett_btatt_list); proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(ltree, hf_btatt_group_end_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } break; case 0x08: /* Read By Type Request */ case 0x10: /* Read By Group Type Request */ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, Handles: 0x%04x..0x%04x", val_to_str_ext_const(tvb_get_letohs(tvb, offset+4), &uuid_vals_ext, "<unknown>"), tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2)); proto_tree_add_item(st, hf_btatt_starting_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btatt_ending_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; if (tvb_length_remaining(tvb, offset) == 2) { proto_tree_add_item(st, hf_btatt_uuid16, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } else if (tvb_length_remaining(tvb, offset) == 16) { item = proto_tree_add_item(st, hf_btatt_uuid128, tvb, offset, 16, ENC_NA); proto_item_append_text(item, " (%s)", val_to_str_ext_const(tvb_get_letohs(tvb, offset), &uuid_vals_ext, "<unknown>")); offset += 16; } break; case 0x09: /* Read By Type Response */ { guint8 length = tvb_get_guint8(tvb, offset); proto_tree_add_item(st, hf_btatt_length, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; if(length > 0) { col_append_fstr(pinfo->cinfo, COL_INFO, ", Attribute List Length: %u", tvb_length_remaining(tvb, offset)/length); while (tvb_length_remaining(tvb, offset) >= length) { item = proto_tree_add_text(st, tvb, offset, length, "Attribute Data, Handle: 0x%04x", tvb_get_letohs(tvb, offset)); ltree = proto_item_add_subtree(item, ett_btatt_list); proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(ltree, hf_btatt_value, tvb, offset, length - 2, ENC_NA); offset += (length-2); } } } break; case 0x0a: /* Read Request */ col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset)); proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; break; case 0x0b: /* Read Response */ case 0x0d: /* Read Blob Response */ case 0x0f: /* Multiple Read Response */ proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA); break; case 0x0c: /* Read Blob Request */ col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x, Offset: %u", tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2)); proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btatt_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; break; case 0x0e: /* Multiple Read Request */ if(tvb_length_remaining(tvb, offset) < 4) { expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "Too few handles, should be 2 or more"); break; } col_append_str(pinfo->cinfo, COL_INFO, ", Handles: "); while (tvb_length_remaining(tvb, offset) >= 2) { proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "0x%04x ", tvb_get_letohs(tvb, offset)); offset += 2; } break; case 0x11: /* Read By Group Type Response */ { guint8 length = tvb_get_guint8(tvb, offset); proto_tree_add_item(st, hf_btatt_length, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; if(length > 0) { col_append_fstr(pinfo->cinfo, COL_INFO, ", Attribute List Length: %u", tvb_length_remaining(tvb, offset)/length); while (tvb_length_remaining(tvb, offset) >= length) { item = proto_tree_add_text(st, tvb, offset, length, "Attribute Data, Handle: 0x%04x, Group End Handle: 0x%04x", tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2)); ltree = proto_item_add_subtree(item, ett_btatt_list); proto_tree_add_item(ltree, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(ltree, hf_btatt_group_end_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(ltree, hf_btatt_value, tvb, offset, length - 4, ENC_NA); offset += (length-4); } } } break; case 0x12: /* Write Request */ case 0x52: /* Write Command */ case 0x1b: /* Handle Value Notification */ case 0x1d: /* Handle Value Indication */ col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset)); proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA); break; case 0x16: /* Prepare Write Request */ case 0x17: /* Prepare Write Response */ col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x, Offset: %u", tvb_get_letohs(tvb, offset), tvb_get_letohs(tvb, offset+2)); proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btatt_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btatt_value, tvb, offset, -1, ENC_NA); break; case 0x18: /* Execute Write Request */ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(tvb_get_guint8(tvb, offset), flags_vals, "<unknown>")); proto_tree_add_item(st, hf_btatt_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; break; case 0xd2: /* Signed Write Command */ { guint8 length; col_append_fstr(pinfo->cinfo, COL_INFO, ", Handle: 0x%04x", tvb_get_letohs(tvb, offset)); proto_tree_add_item(st, hf_btatt_handle, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; length = tvb_length_remaining(tvb, offset); if (length > 12) { proto_tree_add_item(st, hf_btatt_value, tvb, offset, length-12, ENC_NA); offset+=length-12; } proto_tree_add_item(st, hf_btatt_sign_counter, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset+=4; proto_tree_add_item(st, hf_btatt_signature, tvb, offset, 8, ENC_NA); offset+=8; break; } default: break; } }
static void dissect_netrom_proto(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *netrom_tree; int offset; const guint8 *src_addr; const guint8 *dst_addr; const guint8 *user_addr; const guint8 *node_addr; #if 0 guint8 src_ssid; guint8 dst_ssid; #endif guint8 op_code; guint8 cct_index; guint8 cct_id; void *saved_private_data; tvbuff_t *next_tvb = NULL; col_set_str( pinfo->cinfo, COL_PROTOCOL, "NET/ROM" ); col_clear( pinfo->cinfo, COL_INFO ); offset = 0; /* source */ src_addr = tvb_get_ptr( tvb, offset, AX25_ADDR_LEN ); SET_ADDRESS(&pinfo->dl_src, AT_AX25, AX25_ADDR_LEN, src_addr); SET_ADDRESS(&pinfo->src, AT_AX25, AX25_ADDR_LEN, src_addr); /* src_ssid = *(src_addr + 6); */ offset += AX25_ADDR_LEN; /* step over src addr */ /* destination */ dst_addr = tvb_get_ptr( tvb, offset, AX25_ADDR_LEN ); SET_ADDRESS(&pinfo->dl_dst, AT_AX25, AX25_ADDR_LEN, dst_addr); SET_ADDRESS(&pinfo->dst, AT_AX25, AX25_ADDR_LEN, dst_addr); /* dst_ssid = *(dst_addr + 6); */ offset += AX25_ADDR_LEN; /* step over dst addr */ offset += 1; /* step over ttl */ cct_index = tvb_get_guint8( tvb, offset ); offset += 1; /* step over cct index*/ cct_id = tvb_get_guint8( tvb, offset ); offset += 1; /* step over cct id */ offset += 1; /* step over n_s */ offset += 1; /* step over n_r */ /* frame type */ op_code = tvb_get_guint8( tvb, offset ) & 0x0f; offset += 1; /* step over op_code */ col_add_fstr( pinfo->cinfo, COL_INFO, "%s", val_to_str_const( op_code, op_code_vals_text, "Unknown" )); if ( tree ) { /* create display subtree for the protocol */ ti = proto_tree_add_protocol_format( tree, proto_netrom, tvb, 0, NETROM_HEADER_SIZE, "NET/ROM, Src: %s (%s), Dst: %s (%s)", get_ax25_name( src_addr ), ax25_to_str( src_addr ), get_ax25_name( dst_addr ), ax25_to_str( dst_addr ) ); netrom_tree = proto_item_add_subtree( ti, ett_netrom ); offset = 0; /* source */ proto_tree_add_ax25( netrom_tree, hf_netrom_src, tvb, offset, AX25_ADDR_LEN, src_addr ); offset += AX25_ADDR_LEN; /* destination */ proto_tree_add_ax25( netrom_tree, hf_netrom_dst, tvb, offset, AX25_ADDR_LEN, dst_addr ); offset += AX25_ADDR_LEN; /* ttl */ proto_tree_add_item( netrom_tree, hf_netrom_ttl, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; switch ( op_code ) { case NETROM_PROTOEXT : /* cct index */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* cct id */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* unused */ offset += 1; /* unused */ offset += 1; break; case NETROM_CONNREQ : /* cct index */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* cct id */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* unused */ offset += 1; /* unused */ offset += 1; break; case NETROM_CONNACK : /* your cct index */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* your cct id */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* my cct index */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* my cct id */ proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; break; case NETROM_DISCREQ : /* your cct index */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* your cct id */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* unused */ offset += 1; /* unused */ offset += 1; break; case NETROM_DISCACK : /* your cct index */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* your cct id */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* unused */ offset += 1; /* unused */ offset += 1; break; case NETROM_INFO : /* your cct index */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* your cct id */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* n_s */ proto_tree_add_item( netrom_tree, hf_netrom_n_s, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* n_r */ proto_tree_add_item( netrom_tree, hf_netrom_n_r, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; break; case NETROM_INFOACK : /* your cct index */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* your cct id */ proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; /* unused */ offset += 1; /* n_r */ proto_tree_add_item( netrom_tree, hf_netrom_n_r, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; break; default : offset += 1; offset += 1; offset += 1; offset += 1; break; } /* type */ dissect_netrom_type( tvb, offset, pinfo, netrom_tree, hf_netrom_type, ett_netrom_type, &netrom_type_items ); offset += 1; switch ( op_code ) { case NETROM_PROTOEXT : break; case NETROM_CONNREQ : /* proposed window size */ proto_tree_add_item( netrom_tree, hf_netrom_pwindow, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; user_addr = tvb_get_ptr( tvb, offset, AX25_ADDR_LEN ); proto_tree_add_ax25( netrom_tree, hf_netrom_user, tvb, offset, AX25_ADDR_LEN, user_addr ); offset += AX25_ADDR_LEN; node_addr = tvb_get_ptr( tvb, offset, AX25_ADDR_LEN ); proto_tree_add_ax25( netrom_tree, hf_netrom_node, tvb, offset, AX25_ADDR_LEN, node_addr ); offset += AX25_ADDR_LEN; break; case NETROM_CONNACK : /* accepted window size */ proto_tree_add_item( netrom_tree, hf_netrom_awindow, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1; break; case NETROM_DISCREQ : break; case NETROM_DISCACK : break; case NETROM_INFO : break; case NETROM_INFOACK : break; default : break; } } /* Call sub-dissectors here */ saved_private_data = pinfo->private_data; next_tvb = tvb_new_subset_remaining(tvb, offset); switch ( op_code ) { case NETROM_PROTOEXT : if ( cct_index == NETROM_PROTO_IP && cct_id == NETROM_PROTO_IP ) call_dissector( ip_handle , next_tvb, pinfo, tree ); else call_dissector( default_handle , next_tvb, pinfo, tree ); break; case NETROM_INFO : default : call_dissector( default_handle , next_tvb, pinfo, tree ); break; } pinfo->private_data = saved_private_data; }
static void dissect_mqpcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, mq_parm_t* p_mq_parm) { gint offset = 0; gboolean bLittleEndian; bLittleEndian = ((p_mq_parm->mq_cur_ccsid.encod & MQ_MQENC_INTEGER_MASK) == MQ_MQENC_INTEGER_REVERSED) ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN; if (tvb_length(tvb) >= 36) { gint iSizeMQCFH = 36; guint32 iCommand = tvb_get_guint32_endian(tvb, offset + 12, bLittleEndian); if (tree) { proto_item *ti; proto_tree *mq_tree; proto_tree *mqroot_tree; char sTmp[256]; guint32 uCnt; guint32 uTyp; guint32 uCmd; guint32 uCC; guint32 uRC; uTyp = tvb_get_guint32_endian(tvb, offset , bLittleEndian); uCmd = tvb_get_guint32_endian(tvb, offset + 12, bLittleEndian); uCC = tvb_get_guint32_endian(tvb, offset + 24, bLittleEndian); uRC = tvb_get_guint32_endian(tvb, offset + 28, bLittleEndian); uCnt = tvb_get_guint32_endian(tvb, offset + 32, bLittleEndian); if (uCC || uRC) { g_snprintf(sTmp, (gulong)sizeof(sTmp)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d) CC(%d-%s) RC(%d-%s)", MQ_TEXT_CFH, uTyp, val_to_str_const(uTyp, GET_VALSV(mqcft), "Unknown"), uCmd, val_to_str_const(uCmd, GET_VALSV(mqcmd), "Unknown"), uCnt, uCC, val_to_str_const(uCC, GET_VALSV(mqcc), "Unknown"), uRC, val_to_str_const(uRC, GET_VALSV(mqrc), "Unknown")); } else { g_snprintf(sTmp, (gulong)sizeof(sTmp)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d)", MQ_TEXT_CFH, uTyp, val_to_str_const(uTyp, GET_VALSV(mqcft), "Unknown"), uCmd, val_to_str_const(uCmd, GET_VALSV(mqcmd), "Unknown"), uCnt); } ti = proto_tree_add_item(tree, proto_mqpcf, tvb, offset, -1, ENC_NA); proto_item_append_text(ti, " (%s)", val_to_str(iCommand, GET_VALSV(mqcmd), "Unknown (0x%02x)")); mqroot_tree = proto_item_add_subtree(ti, ett_mqpcf); ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeMQCFH, "%s", sTmp); mq_tree = proto_item_add_subtree(ti, ett_mqpcf_cfh); proto_tree_add_item(mq_tree, hf_mqpcf_cfh_type , tvb, offset + 0, 4, bLittleEndian); proto_tree_add_item(mq_tree, hf_mqpcf_cfh_length , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(mq_tree, hf_mqpcf_cfh_version , tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(mq_tree, hf_mqpcf_cfh_command , tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(mq_tree, hf_mqpcf_cfh_MsgSeqNbr, tvb, offset + 16, 4, bLittleEndian); proto_tree_add_item(mq_tree, hf_mqpcf_cfh_control , tvb, offset + 20, 4, bLittleEndian); proto_tree_add_item(mq_tree, hf_mqpcf_cfh_compcode , tvb, offset + 24, 4, bLittleEndian); proto_tree_add_item(mq_tree, hf_mqpcf_cfh_reason , tvb, offset + 28, 4, bLittleEndian); proto_tree_add_item(mq_tree, hf_mqpcf_cfh_ParmCount, tvb, offset + 32, 4, bLittleEndian); dissect_mqpcf_parm(tvb, pinfo, mqroot_tree, offset + iSizeMQCFH, uCnt, bLittleEndian, TRUE); } } }
tap_packet_status BluetoothDevicesDialog::tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *data) { bluetooth_devices_tapinfo_t *tapinfo = static_cast<bluetooth_devices_tapinfo_t *>(tapinfo_ptr); BluetoothDevicesDialog *dialog = static_cast<BluetoothDevicesDialog *>(tapinfo->ui); bluetooth_device_tap_t *tap_device = static_cast<bluetooth_device_tap_t *>(const_cast<void *>(data)); QString bd_addr; QString bd_addr_oui; const gchar *manuf; QTreeWidgetItem *item = NULL; if (dialog->file_closed_) return TAP_PACKET_DONT_REDRAW; if (pinfo->rec->rec_type != REC_TYPE_PACKET) return TAP_PACKET_DONT_REDRAW; if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) { gchar *interface; const char *interface_name; interface_name = epan_get_interface_name(pinfo->epan, pinfo->rec->rec_header.packet_header.interface_id); interface = wmem_strdup_printf(wmem_packet_scope(), "%u: %s", pinfo->rec->rec_header.packet_header.interface_id, interface_name); if (dialog->ui->interfaceComboBox->findText(interface) == -1) dialog->ui->interfaceComboBox->addItem(interface); if (interface && dialog->ui->interfaceComboBox->currentIndex() > 0) { if (dialog->ui->interfaceComboBox->currentText() != interface) return TAP_PACKET_REDRAW; } } if (tap_device->has_bd_addr) { bd_addr.sprintf("%02x:%02x:%02x:%02x:%02x:%02x", tap_device->bd_addr[0], tap_device->bd_addr[1], tap_device->bd_addr[2], tap_device->bd_addr[3], tap_device->bd_addr[4], tap_device->bd_addr[5]); manuf = get_ether_name(tap_device->bd_addr); if (manuf) { int pos; bd_addr_oui = QString(manuf); pos = bd_addr_oui.indexOf('_'); if (pos < 0) { manuf = NULL; } else { bd_addr_oui.remove(pos, bd_addr_oui.size()); } } if (!manuf) bd_addr_oui = ""; } if (dialog->ui->showInformationStepsCheckBox->checkState() != Qt::Checked) { QTreeWidgetItemIterator i_item(dialog->ui->tableTreeWidget); while (*i_item) { QTreeWidgetItem *current_item = static_cast<QTreeWidgetItem*>(*i_item); bluetooth_item_data_t *item_data = VariantPointer<bluetooth_item_data_t>::asPtr(current_item->data(0, Qt::UserRole)); if ((tap_device->has_bd_addr && current_item->text(column_number_bd_addr) == bd_addr) || (tap_device->is_local && item_data->interface_id == tap_device->interface_id && item_data->adapter_id == tap_device->adapter_id && !current_item->text(column_number_is_local_adapter).isEmpty())) { item = current_item; break; } ++i_item; } } if (!item) { item = new QTreeWidgetItem(dialog->ui->tableTreeWidget); item->setText(column_number_bd_addr, bd_addr); item->setText(column_number_bd_addr_oui, bd_addr_oui); if (tap_device->is_local) { item->setText(column_number_is_local_adapter, tr("true")); } bluetooth_item_data_t *item_data = wmem_new(wmem_file_scope(), bluetooth_item_data_t); item_data->interface_id = tap_device->interface_id; item_data->adapter_id = tap_device->adapter_id; item_data->frame_number = pinfo->num; item->setData(0, Qt::UserRole, VariantPointer<bluetooth_item_data_t>::asQVariant(item_data)); } if (tap_device->type == BLUETOOTH_DEVICE_BD_ADDR) { item->setText(column_number_bd_addr, bd_addr); item->setText(column_number_bd_addr_oui, bd_addr_oui); } if (tap_device->type == BLUETOOTH_DEVICE_NAME) { item->setText(column_number_name, tap_device->data.name); } if (tap_device->type == BLUETOOTH_DEVICE_LOCAL_ADAPTER) item->setText(column_number_is_local_adapter, tr("true")); if (tap_device->type == BLUETOOTH_DEVICE_LOCAL_VERSION) { item->setText(column_number_hci_version, val_to_str_const(tap_device->data.local_version.hci_version, bthci_evt_hci_version, "Unknown 0x%02x")); item->setText(column_number_hci_revision, QString("").sprintf("%u", tap_device->data.local_version.hci_revision)); item->setText(column_number_lmp_version, val_to_str_const(tap_device->data.local_version.lmp_version, bthci_evt_lmp_version, "Unknown 0x%02x")); item->setText(column_number_lmp_subversion, QString("").sprintf("%u", tap_device->data.local_version.lmp_subversion)); item->setText(column_number_manufacturer, val_to_str_ext_const(tap_device->data.local_version.manufacturer, &bluetooth_company_id_vals_ext, "Unknown 0x%04x")); } if (tap_device->type == BLUETOOTH_DEVICE_REMOTE_VERSION) { item->setText(column_number_lmp_version, val_to_str_const(tap_device->data.remote_version.lmp_version, bthci_evt_lmp_version, "Unknown 0x%02x")); item->setText(column_number_lmp_subversion, QString("").sprintf("%u", tap_device->data.remote_version.lmp_subversion)); item->setText(column_number_manufacturer, val_to_str_ext_const(tap_device->data.remote_version.manufacturer, &bluetooth_company_id_vals_ext, "Unknown 0x%04x")); } for (int i = 0; i < dialog->ui->tableTreeWidget->columnCount(); i++) { dialog->ui->tableTreeWidget->resizeColumnToContents(i); } dialog->ui->hintLabel->setText(QString(tr("%1 items; Right click for more option; Double click for device details")).arg(dialog->ui->tableTreeWidget->topLevelItemCount())); return TAP_PACKET_REDRAW; }
static void dissect_dtp_tlv(packet_info *pinfo, tvbuff_t *tvb, int offset, int length, proto_tree *tree, proto_item *ti, proto_item *tlv_length_item, guint8 type) { switch (type) { case DTP_TLV_DOMAIN: if (length <= 33) { /* VTP domain name is at most 32 bytes long and is null-terminated */ proto_item_append_text(ti, ": %s", tvb_format_text(tvb, offset, length - 1)); proto_tree_add_item(tree, hf_dtp_domain, tvb, offset, length, ENC_NA); } else expert_add_info(pinfo, tlv_length_item, &ei_dtp_tlv_length_invalid); break; case DTP_TLV_TRSTATUS: if (length == 1) { /* Value field length must be 1 byte */ proto_item * value_item = NULL; proto_tree * field_tree = NULL; guint8 trunk_status = tvb_get_guint8(tvb, offset); proto_item_append_text(ti, " (Operating/Administrative): %s/%s (0x%02x)", val_to_str_const(DTP_TOSVALUE(trunk_status), dtp_tos_vals, "Unknown operating status"), val_to_str_const(DTP_TASVALUE(trunk_status), dtp_tas_vals, "Unknown administrative status"), trunk_status); value_item = proto_tree_add_text(tree, tvb, offset, length, "Value: %s/%s (0x%02x)", val_to_str_const(DTP_TOSVALUE(trunk_status), dtp_tos_vals, "Unknown operating status"), val_to_str_const(DTP_TASVALUE(trunk_status), dtp_tas_vals, "Unknown administrative status"), trunk_status); field_tree = proto_item_add_subtree(value_item, ett_dtp_status); proto_tree_add_item(field_tree, hf_dtp_tos, tvb, offset, length, ENC_NA); proto_tree_add_item(field_tree, hf_dtp_tas, tvb, offset, length, ENC_NA); } else expert_add_info(pinfo, tlv_length_item, &ei_dtp_tlv_length_invalid); break; case DTP_TLV_TRTYPE: if (length == 1) { /* Value field length must be 1 byte */ proto_item * value_item = NULL; proto_tree * field_tree = NULL; guint8 trunk_type = tvb_get_guint8(tvb, offset); proto_item_append_text(ti, " (Operating/Administrative): %s/%s (0x%02x)", val_to_str_const(DTP_TOTVALUE(trunk_type), dtp_tot_vals, "Unknown operating type"), val_to_str_const(DTP_TATVALUE(trunk_type), dtp_tat_vals, "Unknown administrative type"), trunk_type); value_item = proto_tree_add_text(tree, tvb, offset, length, "Value: %s/%s (0x%02x)", val_to_str_const(DTP_TOTVALUE(trunk_type), dtp_tot_vals, "Unknown operating type"), val_to_str_const(DTP_TATVALUE(trunk_type), dtp_tat_vals, "Unknown administrative type"), trunk_type); field_tree = proto_item_add_subtree(value_item, ett_dtp_type); proto_tree_add_item(field_tree, hf_dtp_tot, tvb, offset, length, ENC_NA); proto_tree_add_item(field_tree, hf_dtp_tat, tvb, offset, length, ENC_NA); } else expert_add_info(pinfo, tlv_length_item, &ei_dtp_tlv_length_invalid); break; case DTP_TLV_SENDERID: if (length == 6) { /* Value length must be 6 bytes for a MAC address */ proto_item_append_text(ti, ": %s", tvb_ether_to_str(tvb, offset)); /* XXX - resolve? */ proto_tree_add_item(tree, hf_dtp_senderid, tvb, offset, length, ENC_NA); } else expert_add_info(pinfo, tlv_length_item, &ei_dtp_tlv_length_invalid); break; default: proto_tree_add_text(tree, tvb, offset, length, "Data"); break; } }
/* * Returns TRUE if there's a User Information field in this SPDU, FALSE * otherwise. */ static gboolean dissect_parameters(tvbuff_t *tvb, int offset, guint16 len, proto_tree *tree, proto_tree *ses_tree, packet_info *pinfo, guint8 *enclosure_item_flags, struct SESSION_DATA_STRUCTURE *session) { gboolean has_user_information = TRUE; proto_item *ti; proto_tree *param_tree; guint8 param_type; const char *param_str; int len_len; guint16 param_len; while (len != 0) { param_type = tvb_get_guint8(tvb, offset); ti = proto_tree_add_text(ses_tree, tvb, offset, -1, "%s", val_to_str(param_type, param_vals, "Unknown parameter type (0x%02x)")); param_tree = proto_item_add_subtree(ti, ett_ses_param); param_str = val_to_str_const(param_type, param_vals, "Unknown"); proto_tree_add_text(param_tree, tvb, offset, 1, "Parameter type: %s", param_str); offset++; len--; param_len = get_item_len(tvb, offset, &len_len); if (len_len > len) { proto_item_set_len(ti, len + 1 ); proto_tree_add_text(param_tree, tvb, offset, len, "Parameter length doesn't fit in parameter"); return has_user_information; } len -= len_len; if (param_len > len) { proto_item_set_len(ti, len + 1 + len_len); proto_tree_add_text(param_tree, tvb, offset, len, "Parameter length: %u, should be <= %u", param_len, len); return has_user_information; } proto_item_set_len(ti, 1 + len_len + param_len); proto_tree_add_text(param_tree, tvb, offset, len_len, "Parameter length: %u", param_len); offset += len_len; if (param_str != NULL) { switch(param_type) { case Extended_User_Data: call_pres_dissector(tvb, offset, param_len, pinfo, tree, param_tree, session); break; case User_Data: call_pres_dissector(tvb, offset, param_len, pinfo, tree, param_tree, session); break; /* handle PGI's */ case Connect_Accept_Item: case Connection_Identifier: case Linking_Information: /* Yes. */ if (!dissect_parameter_group(tvb, offset, tree, param_tree, pinfo, param_len, enclosure_item_flags, session)) has_user_information = FALSE; break; /* everything else is a PI */ default: if (!dissect_parameter(tvb, offset, tree, param_tree, pinfo, param_type, param_len, enclosure_item_flags, session)) has_user_information = FALSE; break; } } offset += param_len; len -= param_len; } return has_user_information; }
/* 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 void dissect_nflog(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { const int start_tlv_offset = 4; proto_tree *nflog_tree = NULL; proto_item *ti; int offset = 0; tvbuff_t *next_tvb = NULL; int aftype; int enc; guint16 (*val16_get)(tvbuff_t *, int); col_set_str(pinfo->cinfo, COL_PROTOCOL, "NFLOG"); col_clear(pinfo->cinfo, COL_INFO); aftype = tvb_get_guint8(tvb, 0); enc = nflog_tvb_byte_order(tvb, start_tlv_offset); switch (enc) { case ENC_LITTLE_ENDIAN: val16_get = tvb_get_letohs; break; case ENC_BIG_ENDIAN: default: val16_get = tvb_get_ntohs; break; } /* Header */ if (proto_field_is_referenced(tree, hfi_nflog->id)) { ti = proto_tree_add_item(tree, hfi_nflog, tvb, 0, -1, ENC_NA); nflog_tree = proto_item_add_subtree(ti, ett_nflog); proto_tree_add_item(nflog_tree, &hfi_nflog_family, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(nflog_tree, &hfi_nflog_version, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(nflog_tree, &hfi_nflog_resid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; ti = proto_tree_add_uint(nflog_tree, &hfi_nflog_encoding, tvb, offset, tvb_length_remaining(tvb, offset), enc); PROTO_ITEM_SET_GENERATED(ti); } offset = start_tlv_offset; /* TLVs */ while (tvb_length_remaining(tvb, offset) >= 4) { guint16 tlv_len = val16_get(tvb, offset + 0); guint16 tlv_type; guint16 value_len; proto_tree *tlv_tree; /* malformed */ if (tlv_len < 4) return; value_len = tlv_len - 4; tlv_type = (val16_get(tvb, offset + 2) & 0x7fff); if (nflog_tree) { gboolean handled = FALSE; ti = proto_tree_add_bytes_format(nflog_tree, hfi_nflog_tlv.id, tvb, offset, tlv_len, NULL, "TLV Type: %s (%u), Length: %u", val_to_str_const(tlv_type, nflog_tlv_vals, "Unknown"), tlv_type, tlv_len); tlv_tree = proto_item_add_subtree(ti, ett_nflog_tlv); proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_length, tvb, offset + 0, 2, enc); proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_type, tvb, offset + 2, 2, enc); switch (tlv_type) { case WS_NFULA_PAYLOAD: handled = TRUE; break; case WS_NFULA_PREFIX: if (value_len >= 1) { proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_prefix, tvb, offset + 4, value_len, ENC_NA); handled = TRUE; } break; case WS_NFULA_UID: if (value_len == 4) { proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_uid, tvb, offset + 4, value_len, ENC_BIG_ENDIAN); handled = TRUE; } break; case WS_NFULA_GID: if (value_len == 4) { proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_gid, tvb, offset + 4, value_len, ENC_BIG_ENDIAN); handled = TRUE; } break; case WS_NFULA_TIMESTAMP: if (value_len == 16) { nstime_t ts; ts.secs = (time_t)tvb_get_ntoh64(tvb, offset + 4); /* XXX - add an "expert info" warning if this is >= 10^9? */ ts.nsecs = (int)tvb_get_ntoh64(tvb, offset + 12); proto_tree_add_time(tlv_tree, &hfi_nflog_tlv_timestamp, tvb, offset + 4, value_len, &ts); handled = TRUE; } break; } if (!handled) proto_tree_add_item(tlv_tree, &hfi_nflog_tlv_unknown, tvb, offset + 4, value_len, ENC_NA); } if (tlv_type == WS_NFULA_PAYLOAD) next_tvb = tvb_new_subset(tvb, offset + 4, value_len, value_len); offset += ((tlv_len + 3) & ~3); /* next TLV aligned to 4B */ } if (next_tvb) { switch (aftype) { case LINUX_AF_INET: call_dissector(ip_handle, next_tvb, pinfo, tree); break; case LINUX_AF_INET6: call_dissector(ip6_handle, next_tvb, pinfo, tree); break; default: call_dissector(data_handle, next_tvb, pinfo, tree); break; } } }
proto_tree *wow_tree, *wow_realms_tree; gchar *string, *realm_name; guint8 cmd, srp_i_len, srp_g_len, srp_n_len; guint16 num_realms; guint32 offset = 0; gint len, ii; col_set_str(pinfo->cinfo, COL_PROTOCOL, "WOW"); col_clear(pinfo->cinfo, COL_INFO); cmd = tvb_get_guint8(tvb, offset); col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(cmd, cmd_vs, "Unrecognized packet type")); if(tree) { ti = proto_tree_add_item(tree, proto_wow, tvb, 0, -1, ENC_NA); wow_tree = proto_item_add_subtree(ti, ett_wow); proto_tree_add_item(wow_tree, hf_wow_command, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; switch(cmd) { case AUTH_LOGON_CHALLENGE : if(WOW_CLIENT_TO_SERVER) { proto_tree_add_item(wow_tree, hf_wow_error, tvb,
static void dissect_nettl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *nettl_tree; proto_item *nettl_item; pinfo->current_proto = "nettl"; if (tree) { nettl_item = proto_tree_add_protocol_format(tree, proto_nettl, tvb, 0, -1, "HP-UX Network Tracing and Logging (nettl) header"); nettl_tree = proto_item_add_subtree(nettl_item, ett_nettl); proto_tree_add_uint_format(nettl_tree, hf_nettl_subsys, tvb, 0, 0, pinfo->pseudo_header->nettl.subsys, "Subsystem: %d (%s)", pinfo->pseudo_header->nettl.subsys, val_to_str_const(pinfo->pseudo_header->nettl.subsys, subsystem, "Unknown")); proto_tree_add_int(nettl_tree, hf_nettl_devid, tvb, 0, 0, pinfo->pseudo_header->nettl.devid); proto_tree_add_uint_format(nettl_tree, hf_nettl_kind, tvb, 0, 0, pinfo->pseudo_header->nettl.kind, "Trace Kind: 0x%08x (%s)", pinfo->pseudo_header->nettl.kind, val_to_str_const(pinfo->pseudo_header->nettl.kind & ~NETTL_HDR_SUBSYSTEM_BITS_MASK, trace_kind, "Unknown")); proto_tree_add_int(nettl_tree, hf_nettl_pid, tvb, 0, 0, pinfo->pseudo_header->nettl.pid); proto_tree_add_uint(nettl_tree, hf_nettl_uid, tvb, 0, 0, pinfo->pseudo_header->nettl.uid); } switch (pinfo->fd->lnk_t) { case WTAP_ENCAP_NETTL_ETHERNET: call_dissector(eth_withoutfcs_handle, tvb, pinfo, tree); break; case WTAP_ENCAP_NETTL_TOKEN_RING: call_dissector(tr_handle, tvb, pinfo, tree); break; case WTAP_ENCAP_NETTL_FDDI: if (!dissector_try_uint(wtap_dissector_table, WTAP_ENCAP_FDDI_BITSWAPPED, tvb, pinfo, tree)) call_dissector(data_handle, tvb, pinfo, tree); break; case WTAP_ENCAP_NETTL_RAW_IP: if ( (pinfo->pseudo_header->nettl.kind & NETTL_HDR_PDU_MASK) == 0 ) /* not actually a data packet (PDU) trace record */ call_dissector(data_handle, tvb, pinfo, tree); else if (pinfo->pseudo_header->nettl.subsys == NETTL_SUBSYS_NS_LS_SCTP ) call_dissector(sctp_handle, tvb, pinfo, tree); else if (!dissector_try_uint(wtap_dissector_table, WTAP_ENCAP_RAW_IP, tvb, pinfo, tree)) call_dissector(data_handle, tvb, pinfo, tree); break; case WTAP_ENCAP_NETTL_RAW_ICMP: if (!dissector_try_uint(ip_proto_dissector_table, IP_PROTO_ICMP, tvb, pinfo, tree)) call_dissector(data_handle, tvb, pinfo, tree); break; case WTAP_ENCAP_NETTL_RAW_ICMPV6: if (!dissector_try_uint(ip_proto_dissector_table, IP_PROTO_ICMPV6, tvb, pinfo, tree)) call_dissector(data_handle, tvb, pinfo, tree); break; case WTAP_ENCAP_NETTL_X25: if (pinfo->pseudo_header->nettl.kind == NETTL_HDR_PDUIN) pinfo->p2p_dir = P2P_DIR_RECV; else if (pinfo->pseudo_header->nettl.kind == NETTL_HDR_PDUOUT) pinfo->p2p_dir = P2P_DIR_SENT; if (pinfo->pseudo_header->nettl.subsys == NETTL_SUBSYS_SX25L2) call_dissector(lapb_handle, tvb, pinfo, tree); else call_dissector(x25_handle, tvb, pinfo, tree); break; case WTAP_ENCAP_NETTL_RAW_TELNET: if (!dissector_try_uint(tcp_subdissector_table, TCP_PORT_TELNET, tvb, pinfo, tree)) call_dissector(data_handle, tvb, pinfo, tree); break; default: col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN"); if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "Unsupported nettl subsytem: %d (%s)", pinfo->pseudo_header->nettl.subsys, val_to_str_const(pinfo->pseudo_header->nettl.subsys, subsystem, "Unknown")); call_dissector(data_handle, tvb, pinfo, tree); } }
static void dissect_rip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; proto_tree *rip_tree = NULL; proto_item *ti; guint8 command; guint8 version; guint16 family; gint trailer_len = 0; gboolean is_md5_auth = FALSE; col_set_str(pinfo->cinfo, COL_PROTOCOL, "RIP"); col_clear(pinfo->cinfo, COL_INFO); command = tvb_get_guint8(tvb, 0); version = tvb_get_guint8(tvb, 1); col_set_str(pinfo->cinfo, COL_PROTOCOL, val_to_str_const(version, version_vals, "RIP")); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(command, command_vals, "Unknown command (%u)")); if (tree) { ti = proto_tree_add_item(tree, hfi_rip, tvb, 0, -1, ENC_NA); rip_tree = proto_item_add_subtree(ti, ett_rip); proto_tree_add_uint(rip_tree, &hfi_rip_command, tvb, 0, 1, command); proto_tree_add_uint(rip_tree, &hfi_rip_version, tvb, 1, 1, version); if (version == RIPv2 && pref_display_routing_domain == TRUE) proto_tree_add_uint(rip_tree, &hfi_rip_routing_domain, tvb, 2, 2, tvb_get_ntohs(tvb, 2)); /* skip header */ offset = RIP_HEADER_LENGTH; /* zero or more entries */ while (tvb_reported_length_remaining(tvb, offset) > trailer_len ) { family = tvb_get_ntohs(tvb, offset); switch (family) { case AFVAL_UNSPEC: /* Unspecified */ /* * There should be one entry in the request, and a metric * of infinity, meaning "show the entire routing table". */ dissect_unspec_rip_vektor(tvb, offset, version, rip_tree); break; case AFVAL_IP: /* IP */ dissect_ip_rip_vektor(tvb, offset, version, rip_tree); break; case 0xFFFF: if( offset == RIP_HEADER_LENGTH ) { trailer_len=dissect_rip_authentication(tvb, offset, rip_tree); is_md5_auth = TRUE; break; } if(is_md5_auth && tvb_reported_length_remaining(tvb, offset) == 20) break; /* Intentional fall through: auth Entry MUST be the first! */ default: proto_tree_add_text(rip_tree, tvb, offset, RIP_ENTRY_LENGTH, "Unknown address family %u", family); break; } offset += RIP_ENTRY_LENGTH; } } }
static void dissect_ieee802a(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *ieee802a_tree = NULL; proto_item *ti; tvbuff_t *next_tvb; guint32 oui; guint16 pid; oui_info_t *oui_info; dissector_table_t subdissector_table; int hf; col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE802a"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { ti = proto_tree_add_item(tree, proto_ieee802a, tvb, 0, 5, ENC_NA); ieee802a_tree = proto_item_add_subtree(ti, ett_ieee802a); } oui = tvb_get_ntoh24(tvb, 0); pid = tvb_get_ntohs(tvb, 3); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "OUI 0x%06X (%s), PID 0x%04X", oui, val_to_str_const(oui, oui_vals, "Unknown"), pid); } if (tree) { proto_tree_add_uint(ieee802a_tree, hf_ieee802a_oui, tvb, 0, 3, oui); } /* * Do we have information for this OUI? */ if (oui_info_table != NULL && (oui_info = g_hash_table_lookup(oui_info_table, GUINT_TO_POINTER(oui))) != NULL) { /* * Yes - use it. */ hf = *oui_info->field_info->p_id; subdissector_table = oui_info->table; } else { /* * No, use hf_ieee802a_pid for the PID and just dissect * the payload as data. */ hf = hf_ieee802a_pid; subdissector_table = NULL; } if (tree) proto_tree_add_uint(ieee802a_tree, hf, tvb, 3, 2, pid); next_tvb = tvb_new_subset_remaining(tvb, 5); if (subdissector_table != NULL) { /* do lookup with the subdissector table */ if (dissector_try_uint(subdissector_table, pid, next_tvb, pinfo, tree)) return; } call_dissector(data_handle, next_tvb, pinfo, tree); }
/* This function is only called from the IGMP dissector */ int dissect_igap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { proto_tree *tree; proto_item *item; guint8 type, tsecs, subtype, asize, msize; guchar account[ACCOUNT_SIZE+1], message[MESSAGE_SIZE+1]; if (!proto_is_protocol_enabled(find_protocol_by_id(proto_igap))) { /* we are not enabled, skip entire packet to be nice to the igmp layer. (so clicking on IGMP will display the data) */ return offset + tvb_length_remaining(tvb, offset); } item = proto_tree_add_item(parent_tree, proto_igap, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_igap); col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGAP"); col_clear(pinfo->cinfo, COL_INFO); type = tvb_get_guint8(tvb, offset); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, igap_types, "Unknown Type: 0x%02x")); proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type); offset += 1; tsecs = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(tree, hf_max_resp, tvb, offset, 1, tsecs, "%.1f sec (0x%02x)", tsecs * 0.1, tsecs); offset += 1; igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_uint(tree, hf_version, tvb, offset, 1, tvb_get_guint8(tvb, offset)); offset += 1; subtype = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_subtype, tvb, offset, 1, subtype); offset += 2; proto_tree_add_uint(tree, hf_challengeid, tvb, offset, 1, tvb_get_guint8(tvb, offset)); offset += 1; asize = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_asize, tvb, offset, 1, asize); offset += 1; msize = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_msize, tvb, offset, 1, msize); offset += 3; if (asize > 0) { if (asize > ACCOUNT_SIZE) { /* Bogus account size. XXX - flag this? */ asize = ACCOUNT_SIZE; } tvb_memcpy(tvb, account, offset, asize); account[asize] = '\0'; proto_tree_add_string(tree, hf_account, tvb, offset, asize, account); } offset += ACCOUNT_SIZE; if (msize > 0) { if (msize > MESSAGE_SIZE) { /* Bogus message size. XXX - flag this? */ msize = MESSAGE_SIZE; } tvb_memcpy(tvb, message, offset, msize); switch (subtype) { case IGAP_SUBTYPE_PASSWORD_JOIN: case IGAP_SUBTYPE_PASSWORD_LEAVE: /* Challenge field is user's password */ message[msize] = '\0'; proto_tree_add_text(tree, tvb, offset, msize, "User password: %s", message); break; case IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN: case IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE: /* Challenge field is the results of MD5 calculation */ proto_tree_add_text(tree, tvb, offset, msize, "Result of MD5 calculation: 0x%s", bytes_to_ep_str(message, msize)); break; case IGAP_SUBTYPE_CHALLENGE: /* Challenge field is the challenge value */ proto_tree_add_text(tree, tvb, offset, msize, "Challenge: 0x%s", bytes_to_ep_str(message, msize)); break; case IGAP_SUBTYPE_AUTH_MESSAGE: /* Challenge field indicates the result of the authenticaion */ proto_tree_add_text(tree, tvb, offset, msize, "Authentication result: %s (0x%x)", val_to_str_const(message[0], igap_auth_result, "Unknown"), message[0]); break; case IGAP_SUBTYPE_ACCOUNTING_MESSAGE: /* Challenge field indicates the accounting status */ proto_tree_add_text(tree, tvb, offset, msize, "Accounting status: %s (0x%x)", val_to_str_const(message[0], igap_account_status, "Unknown"), message[0]); break; default: proto_tree_add_text(tree, tvb, offset, msize, "Message: (Unknown)"); } } offset += MESSAGE_SIZE; if (item) proto_item_set_len(item, offset); return offset; }
/* Code to actually dissect the packets */ static void dissect_dlm3_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length, int offset) { guint32 m_type; m_type = tvb_get_letohl(tvb, offset); proto_tree_add_uint(tree, hf_dlm3_m_type, tvb, offset, 4, m_type); col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(m_type, dlm3_msg, "Unknown")); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_nodeid, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_pid, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_lkid, tvb, offset, 4, ENC_LITTLE_ENDIAN); /* TODO: See `create_lkb' lkid has some structure. We dissect more. */ offset += 4; proto_tree_add_item(tree, hf_dlm3_m_remid, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_parent_lkid, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_parent_remid, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_bitmask(tree, tvb, offset, hf_dlm3_m_exflags, ett_dlm3_m_exflags, m_exflags_fields, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_bitmask(tree, tvb, offset, hf_dlm3_m_sbflags, ett_dlm3_sbflags, m_sbflags_fields, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_bitmask(tree, tvb, offset, hf_dlm3_m_flags, ett_dlm3_m_flags, m_flags_fields, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_lvbseq, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_hash, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_status, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_grmode, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_rqmode, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_bastmode, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_bitmask(tree, tvb, offset, hf_dlm3_m_asts, ett_dlm3_m_asts, m_asts_fields, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_m_result, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; if ((length - offset) > 0) { proto_tree_add_item(tree, hf_dlm3_m_extra, tvb, offset, -1, ENC_NA); } }
static void dissect_lwres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 version, flags, authtype, authlength ; guint32 length, opcode, result, recvlength, serial; guint32 message_type; proto_item* lwres_item; proto_tree* lwres_tree; col_set_str(pinfo->cinfo, COL_PROTOCOL, "lw_res"); length = tvb_get_ntohl(tvb, LW_LENGTH_OFFSET); version = tvb_get_ntohs(tvb, LW_VERSION_OFFSET); flags = tvb_get_ntohs(tvb, LW_PKTFLASG_OFFSET); serial = tvb_get_ntohl(tvb, LW_SERIAL_OFFSET); opcode = tvb_get_ntohl(tvb,LW_OPCODE_OFFSET); result = tvb_get_ntohl(tvb, LW_RESULT_OFFSET); recvlength = tvb_get_ntohl(tvb, LW_RECVLEN_OFFSET); authtype = tvb_get_ntohs(tvb, LW_AUTHTYPE_OFFSET); authlength = tvb_get_ntohs(tvb, LW_AUTHLEN_OFFSET); message_type = (flags & LWRES_LWPACKETFLAG_RESPONSE) ? 2 : 1; col_clear(pinfo->cinfo, COL_INFO); if(flags & LWRES_LWPACKETFLAG_RESPONSE) { col_add_fstr(pinfo->cinfo, COL_INFO, "%s, opcode=%s, serial=0x%x, result=%s", val_to_str_const((guint32)message_type,message_types_values,"unknown"), val_to_str_const(opcode, opcode_values, "unknown"), serial, val_to_str_const(result,result_values,"unknown")); } else { col_add_fstr(pinfo->cinfo, COL_INFO, "%s, opcode=%s, serial=0x%x", val_to_str_const((guint32)message_type,message_types_values,"unknown"), val_to_str_const(opcode, opcode_values, "unknown"), serial); } if(tree) { lwres_item = proto_tree_add_item(tree,proto_lwres, tvb,0, -1, ENC_NA); lwres_tree = proto_item_add_subtree(lwres_item, ett_lwres); } else return; proto_tree_add_uint(lwres_tree, hf_length, tvb, LW_LENGTH_OFFSET, sizeof(guint32), length); proto_tree_add_uint(lwres_tree, hf_version, tvb, LW_VERSION_OFFSET, sizeof(guint16), version); proto_tree_add_uint(lwres_tree, hf_flags, tvb, LW_PKTFLASG_OFFSET, sizeof(guint16), flags); proto_tree_add_uint(lwres_tree, hf_serial, tvb, LW_SERIAL_OFFSET, sizeof(guint32), serial); proto_tree_add_uint(lwres_tree, hf_opcode, tvb, LW_OPCODE_OFFSET, sizeof(guint32), opcode); proto_tree_add_uint(lwres_tree, hf_result, tvb, LW_RESULT_OFFSET, sizeof(guint32), result); proto_tree_add_uint(lwres_tree, hf_recvlen, tvb, LW_RECVLEN_OFFSET, sizeof(guint32), recvlength); proto_tree_add_uint(lwres_tree, hf_authtype, tvb, LW_AUTHTYPE_OFFSET, sizeof(guint16), authtype); proto_tree_add_uint(lwres_tree, hf_authlen, tvb, LW_AUTHLEN_OFFSET, sizeof(guint16), authlength); if(!result) { switch(opcode) { case LWRES_OPCODE_NOOP: dissect_noop(tvb, lwres_tree); break; case LWRES_OPCODE_GETADDRSBYNAME: dissect_getaddrsbyname(tvb, lwres_tree, message_type); break; case LWRES_OPCODE_GETNAMEBYADDR: dissect_getnamebyaddr(tvb, lwres_tree, message_type); break; case LWRES_OPCODE_GETRDATABYNAME: dissect_getrdatabyname(tvb, lwres_tree, message_type); break; } } }
static void dissect_dlm3_rcom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint length, int offset) { guint32 rc_type; proto_item *sub_item; proto_tree *sub_tree; rc_type = tvb_get_letohl(tvb, offset); proto_tree_add_uint(tree, hf_dlm3_rc_type, tvb, offset, 4, rc_type); col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(rc_type, dlm3_rcom, "Unknown")); offset += 4; proto_tree_add_item(tree, hf_dlm3_rc_result, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_dlm3_rc_id, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; proto_tree_add_item(tree, hf_dlm3_rc_seq, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; proto_tree_add_item(tree, hf_dlm3_rc_seq_reply, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; if ((length - offset) == 0) { /* No rc_buf: Just return */ return; } /* Decode rc_buf */ sub_item = proto_tree_add_item(tree, hf_dlm3_rc_buf, tvb, offset, -1, ENC_NA); offset += 0; if (rc_type == DLM3_RCOM_LOCK) { sub_tree = proto_item_add_subtree(sub_item, ett_dlm3_rcom_lock); dissect_dlm3_rcom_lock(tvb, sub_tree, length, offset); } else if (rc_type == DLM3_RCOM_STATUS_REPLY) { sub_tree = proto_item_add_subtree(sub_item, ett_dlm3_rcom_config); dissect_dlm3_rcom_config(tvb, sub_tree, length, offset); } }
/* Code to actually dissect the packets */ static void dissect_sm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *sm_tree; tvbuff_t *next_tvb = NULL; guint32 sm_message_type; guint32 bsn_num = 0; guint32 bh_event_code = 0; guint16 protocol; guint16 msg_type = 0; guint16 length; guint16 tag; int offset = 0; sm_message_type = tvb_get_ntohl(tvb,offset); col_set_str(pinfo->cinfo, COL_PROTOCOL, "SM"); col_add_fstr(pinfo->cinfo, COL_INFO, "Cisco SM Packet (%s)", val_to_str_const(sm_message_type, sm_message_type_value_info,"reserved")); ti = proto_tree_add_item(tree, proto_sm, tvb, offset, 0, ENC_NA); sm_tree = proto_item_add_subtree(ti, ett_sm); proto_tree_add_uint_format(sm_tree, hf_sm_sm_msg_type, tvb, offset, 4, sm_message_type, "SM Message type: %s (0x%0x)", val_to_str_const(sm_message_type, sm_message_type_value, "reserved"), sm_message_type); offset = offset + 4; if (sm_message_type == MESSAGE_TYPE_PDU) { proto_tree_add_item(sm_tree, hf_sm_protocol, tvb, offset, 2, ENC_BIG_ENDIAN); protocol = tvb_get_ntohs(tvb,offset); offset = offset + 2; switch(protocol){ /* start case RUDP BSM v.1 ---------------------------------------------------------- */ case SM_PROTOCOL_X004: if (!tree) return; proto_tree_add_item(sm_tree, hf_sm_msg_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset +2; msg_type = tvb_get_ntohs(tvb,offset); proto_tree_add_uint_format(sm_tree, hf_sm_msg_type, tvb, offset, 2, msg_type, "Message type: %s (0x%0x)", val_to_str_const(msg_type, sm_pdu_type_value, "reserved"), msg_type); msg_type = tvb_get_ntohs(tvb,offset); offset = offset + 2; proto_tree_add_item(sm_tree, hf_sm_channel, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; proto_tree_add_item(sm_tree, hf_sm_bearer, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset +2; proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN); length = tvb_get_ntohs(tvb,offset); offset = offset +2; proto_item_set_len(ti, 16); if (length > 0) { next_tvb = tvb_new_subset(tvb, offset, length, length); if ((msg_type == PDU_MTP3_TO_SLT || msg_type == PDU_MTP3_FROM_SLT)) { call_dissector(q931_handle, next_tvb, pinfo, tree); } else { call_dissector(data_handle, next_tvb, pinfo, tree); } } break; /* end case RUDP BSM v.1 ---------------------------------------------------------- */ case SM_PROTOCOL_X100: case SM_PROTOCOL_X122: if (!tree) return; /* Protocol 0x100/0x122 only contains a length and then an EISUP packet */ proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN); length = tvb_get_ntohs(tvb,offset); offset = offset + 2; proto_item_set_len(ti, 8); /* This should be the EISUP dissector but we havent got one * right now - so decode it as data for now ... */ next_tvb = tvb_new_subset(tvb, offset, length, length); call_dissector(data_handle, next_tvb, pinfo, sm_tree); break; case SM_PROTOCOL_X101: if (!tree) return; /* XXX Reverse enginered so this may not be correct!!! * EISUP - used between Cisco HSI and Cisco PGW devices, * uses RUDP with default port number 8003. * Protocol stack is RUDP->Cisco SM->SDP. * This implementation is PROPRIETARY */ proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN); length = tvb_get_ntohs(tvb,offset); offset = offset + 2; proto_item_set_len(ti, length + offset); /* The next stuff seems to be IP addr */ proto_tree_add_item(sm_tree, hf_sm_ip_addr, tvb, offset, 4, ENC_BIG_ENDIAN); offset = offset + 4; /* This part looks to be the same per session */ proto_tree_add_item(sm_tree, hf_sm_context, tvb, offset, 4, ENC_BIG_ENDIAN); offset = offset +4; /* Some sort of message type? */ proto_tree_add_item(sm_tree, hf_sm_eisup_msg_id, tvb, offset, 1, ENC_BIG_ENDIAN); offset = offset + 1; /* XXX Problem are tags 1 or two bytes???*/ proto_tree_add_item(sm_tree, hf_sm_tag, tvb, offset, 2, ENC_BIG_ENDIAN); tag = tvb_get_ntohs(tvb,offset); offset = offset +2; if (tag== 0x01ac) { proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN); length = tvb_get_ntohs(tvb,offset); offset = offset +2; next_tvb = tvb_new_subset(tvb, offset, length, length); call_dissector(sdp_handle, next_tvb, pinfo, sm_tree); offset = offset+length; } /*return;*/ break; case SM_PROTOCOL_X114: if (!tree) return; /* XXX Reverse enginered so this may not be correct!!! */ proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN); length = tvb_get_ntohs(tvb,offset); offset = offset + 2; proto_item_set_len(ti, length + offset); /* The next stuff seems to be IP addr */ proto_tree_add_item(sm_tree, hf_sm_ip_addr, tvb, offset, 4, ENC_BIG_ENDIAN); offset = offset + 4; proto_tree_add_item(sm_tree, hf_sm_context, tvb, offset, 4, ENC_BIG_ENDIAN); offset = offset +4; /* Some sort of message type? */ proto_tree_add_item(sm_tree, hf_sm_eisup_msg_id, tvb, offset, 1, ENC_BIG_ENDIAN); offset = offset + 1; /* XXX Problem are tags 1 or two bytes???*/ proto_tree_add_item(sm_tree, hf_sm_tag, tvb, offset, 2, ENC_BIG_ENDIAN); tag = tvb_get_ntohs(tvb,offset); offset = offset +2; if (tag== 0x01ac) { proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN); length = tvb_get_ntohs(tvb,offset); offset = offset +2; next_tvb = tvb_new_subset(tvb, offset, length, length); call_dissector(sdp_handle, next_tvb, pinfo, sm_tree); offset = offset+length; } break; default: proto_tree_add_item(sm_tree, hf_sm_msg_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset +2; msg_type = tvb_get_ntohs(tvb,offset); proto_tree_add_uint_format(sm_tree, hf_sm_msg_type, tvb, offset, 2, msg_type, "Message type: %s (0x%0x)", val_to_str_const(msg_type, sm_pdu_type_value, "reserved"), msg_type); msg_type = tvb_get_ntohs(tvb,offset); offset = offset + 2; proto_tree_add_item(sm_tree, hf_sm_channel, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset + 2; proto_tree_add_item(sm_tree, hf_sm_bearer, tvb, offset, 2, ENC_BIG_ENDIAN); offset = offset +2; proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN); length = tvb_get_ntohs(tvb,offset); offset = offset +2; proto_item_set_len(ti, 16); if (length > 0) { next_tvb = tvb_new_subset(tvb, offset, length, length); switch (msg_type) { case PDU_MTP3_TO_SLT: case PDU_MTP3_FROM_SLT: call_dissector(mtp3_handle, next_tvb, pinfo, tree); break; case PDU_CONNECT_REQUEST: case PDU_CONNECT_CONFIRM: proto_tree_add_item(sm_tree, hf_sm_alignment_type, tvb, offset, 4, ENC_BIG_ENDIAN); break; case PDU_DISCONNECT_CONFIRM: case PDU_DISCONNECT_INDICATION: proto_tree_add_item(sm_tree, hf_sm_backhaul_reason_code, tvb, offset, 4, ENC_BIG_ENDIAN); break; case PDU_RETRIEVAL_REQUEST: case PDU_RETRIEVAL_CONFIRM: proto_tree_add_item(sm_tree, hf_sm_retrieval_type, tvb, offset, 4, ENC_BIG_ENDIAN); if (msg_type == PDU_RETRIEVAL_CONFIRM && tvb_get_ntohl(tvb,offset) == 0x01) { offset += 4; bsn_num = tvb_get_ntohl(tvb,offset); proto_tree_add_uint_format(sm_tree, hf_sm_bsn_num, tvb, offset, 4, bsn_num, "BSN: %d", bsn_num); } break; case PDU_LSC_REQUEST: case PDU_LSC_CONFIRM: proto_tree_add_item(sm_tree, hf_sm_lsc_state_type, tvb, offset, 4, ENC_BIG_ENDIAN); break; case PDU_LSC_INDICATION: proto_tree_add_item(sm_tree, hf_sm_backhaul_event_code, tvb, offset, 4, ENC_BIG_ENDIAN); bh_event_code = tvb_get_ntohl(tvb,offset); if (bh_event_code == 0x02 || bh_event_code == 0x04) { offset += 4; proto_tree_add_item(sm_tree, hf_sm_linkdown_cause_code, tvb, offset, 4, ENC_BIG_ENDIAN); } else if (bh_event_code == 0x06) { offset += 4; proto_tree_add_item(sm_tree, hf_sm_backhaul_cause_code, tvb, offset, 4, ENC_BIG_ENDIAN); } break; case PDU_STAT_REQUEST: proto_tree_add_item(sm_tree, hf_sm_stat_request_type, tvb, offset, 4, ENC_BIG_ENDIAN); break; default: call_dissector(data_handle, next_tvb, pinfo, tree); } } } } }
/* Broadcasts are searches, offers or promises. * * Searches are sent by * a peer when it needs a file (ie. while applying its policy, when it needs * files such as installers to install software.) * * Each broadcast relates to one file and each file is identified only by its * checksum - no file names are ever used. A search times out after 10 seconds * (configurable) and the peer will then attempt to act on any offers by * downloading (via push or pull - see dissect_ldss_transfer) from those peers. * * If no offers are received, the search fails and the peer fetches the file * from a remote server, generally a HTTP server on the other side of a WAN. * The protocol exists to minimize the number of WAN downloads needed. * * While downloading from WAN the peer sends promises to inform other peers * when it will be available for them to download. This prevents multiple peers * simultaneously downloading the same file. Promises also inform other peers * how much download bandwidth is being used by their download. Other peers use * this information and the configured knowledge of the WAN bandwidth to avoid * saturating the WAN link, as file downloads are a non-time-critical and * non-business-critical network function. LDSS is intended for networks of * 5-20 machines connected by slow WAN link. The current implementation of the * protocol allows administrator to configure "time windows" when WAN usage is * throttled/unthrottled, though this isn't visible in LDSS. * * Once a WAN download or a LAN transfer (see below above dissect_ldss_transfer) * has complete the peer will offer the file to other peers on the LAN so they * don't need to download it themselves. * * Peers also notify when they shut down in case any other peer is waiting for * a file. */ static int dissect_ldss_broadcast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 messageID; guint8 digest_type; guint8 compression; guint32 cookie; guint8 *digest; guint64 size; guint64 offset; guint32 targetTime; guint16 port; guint16 rate; guint16 messageDetail = INFERRED_NONE; proto_tree *ti, *ldss_tree; const gchar *packet_type, *packet_detail; messageID = tvb_get_ntohs (tvb, 0); digest_type = tvb_get_guint8 (tvb, 2); compression = tvb_get_guint8 (tvb, 3); cookie = tvb_get_ntohl (tvb, 4); digest = (guint8 *)tvb_memdup (NULL, tvb, 8, DIGEST_LEN); size = tvb_get_ntoh64 (tvb, 40); offset = tvb_get_ntoh64 (tvb, 48); targetTime = tvb_get_ntohl (tvb, 56); port = tvb_get_ntohs (tvb, 64); rate = tvb_get_ntohs (tvb, 66); packet_type = val_to_str_const(messageID, ldss_message_id_value, "unknown"); if (messageID == MESSAGE_ID_WILLSEND) { if (cookie == 0) { /* Shutdown: Dishonor promises from this peer. Current * implementation abuses WillSend for this. */ messageDetail = INFERRED_PEERSHUTDOWN; } else if (size == 0 && offset == 0) { /* NeedFile search failed - going to WAN */ messageDetail = INFERRED_WANDOWNLOAD; } else if (size > 0) { /* Size is known (not always the case) */ if (size == offset) { /* File is available for pull on this peer's TCP port */ messageDetail = INFERRED_OFFER; } else { /* WAN download progress announcement from this peer */ messageDetail = INFERRED_PROMISE; } } } else if (messageID == MESSAGE_ID_NEEDFILE) { messageDetail = INFERRED_SEARCH; } packet_detail = val_to_str_const(messageDetail, ldss_inferred_info, "unknown"); /* Set the info column */ col_add_fstr(pinfo->cinfo, COL_INFO, "LDSS Broadcast (%s%s)", packet_type, packet_detail); /* If we have a non-null tree (ie we are building the proto_tree * instead of just filling out the columns), then give more detail. */ if (tree) { ti = proto_tree_add_item(tree, proto_ldss, tvb, 0, (tvb_captured_length(tvb) > 72) ? tvb_captured_length(tvb) : 72, ENC_NA); ldss_tree = proto_item_add_subtree(ti, ett_ldss_broadcast); proto_tree_add_item(ldss_tree, hf_ldss_message_id, tvb, 0, 2, ENC_BIG_ENDIAN); ti = proto_tree_add_uint(ldss_tree, hf_ldss_message_detail, tvb, 0, 0, messageDetail); PROTO_ITEM_SET_GENERATED(ti); proto_tree_add_item(ldss_tree, hf_ldss_digest_type, tvb, 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ldss_tree, hf_ldss_compression, tvb, 3, 1, ENC_BIG_ENDIAN); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_cookie, tvb, 4, 4, FALSE, "0x%x%s", cookie, (cookie == 0) ? " - shutdown (promises from this peer are no longer valid)" : ""); proto_tree_add_item(ldss_tree, hf_ldss_digest, tvb, 8, DIGEST_LEN, ENC_NA); proto_tree_add_item(ldss_tree, hf_ldss_size, tvb, 40, 8, ENC_BIG_ENDIAN); proto_tree_add_item(ldss_tree, hf_ldss_offset, tvb, 48, 8, ENC_BIG_ENDIAN); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_target_time, tvb, 56, 4, FALSE, "%d:%02d:%02d", (int)(targetTime / 3600), (int)((targetTime / 60) % 60), (int)(targetTime % 60)); proto_tree_add_item(ldss_tree, hf_ldss_reserved_1, tvb, 60, 4, ENC_BIG_ENDIAN); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_port, tvb, 64, 2, FALSE, "%d%s", port, (messageID == MESSAGE_ID_WILLSEND && size > 0 && size == offset) ? " - file can be pulled at this TCP port" : (messageID == MESSAGE_ID_NEEDFILE ? " - file can be pushed to this TCP port" : "")); proto_tree_add_uint_format_value(ldss_tree, hf_ldss_rate, tvb, 66, 2, FALSE, "%ld", (rate > 0) ? (long)floor(exp(rate * G_LN2 / 2048)) : 0); proto_tree_add_item(ldss_tree, hf_ldss_priority, tvb, 68, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ldss_tree, hf_ldss_property_count, tvb, 70, 2, ENC_BIG_ENDIAN); if (tvb_reported_length(tvb) > 72) { proto_tree_add_item(ldss_tree, hf_ldss_properties, tvb, 72, tvb_captured_length(tvb) - 72, ENC_NA); } } /* Finally, store the broadcast and register ourselves to dissect * any pushes or pulls that result from this broadcast. All data * is pushed/pulled over TCP using the port from the broadcast * packet's port field. * Track each by a TCP conversation with the remote end wildcarded. * The TCP conv tracks back to a broadcast conv to determine what it * is in response to. * * These steps only need to be done once per packet, so a variable * tracks the highest frame number seen. Handles the case of first frame * being frame zero. */ if (messageDetail != INFERRED_PEERSHUTDOWN && (highest_num_seen == 0 || highest_num_seen < pinfo->num)) { ldss_broadcast_t *data; /* Populate data from the broadcast */ data = wmem_new0(wmem_file_scope(), ldss_broadcast_t); data->num = pinfo->num; data->ts = pinfo->abs_ts; data->message_id = messageID; data->message_detail = messageDetail; data->port = port; data->size = size; data->offset = offset; data->compression = compression; data->file = wmem_new0(wmem_file_scope(), ldss_file_t); data->file->digest = digest; data->file->digest_type = digest_type; data->broadcaster = wmem_new0(wmem_file_scope(), ldss_broadcaster_t); copy_address(&data->broadcaster->addr, &pinfo->src); data->broadcaster->port = port; /* Dissect any future pushes/pulls */ if (port > 0) { prepare_ldss_transfer_conv(data); } /* Record that the frame was processed */ highest_num_seen = pinfo->num; } return tvb_captured_length(tvb); }
/* * Dissect SNAP header; used elsewhere, e.g. in the Frame Relay dissector. */ void dissect_snap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, proto_tree *snap_tree, int control, int hf_oui, int hf_type, int hf_pid, int bridge_pad) { guint32 oui; guint16 etype; tvbuff_t *next_tvb; oui_info_t *oui_info; dissector_table_t subdissector_table; int hf; int mesh_header_len; /* * XXX - what about non-UI frames? */ oui = tvb_get_ntoh24(tvb, offset); etype = tvb_get_ntohs(tvb, offset+3); col_append_fstr(pinfo->cinfo, COL_INFO, "; SNAP, OUI 0x%06X (%s), PID 0x%04X", oui, val_to_str_const(oui, oui_vals, "Unknown"), etype); proto_tree_add_uint(snap_tree, hf_oui, tvb, offset, 3, oui); switch (oui) { case OUI_HP_2: oui_info = get_snap_oui_info(oui); hf = *oui_info->field_info->p_id; proto_tree_add_uint(snap_tree, hf, tvb, offset+3, 2, etype); next_tvb = tvb_new_subset_remaining(tvb, offset+5); if(!dissector_try_uint(hpteam_subdissector_table,etype, next_tvb, pinfo, tree)) call_dissector(data_handle, next_tvb, pinfo, tree); break; case OUI_ENCAP_ETHER: case OUI_CISCO_90: case OUI_APPLE_ATALK: /* No, I have no idea why Apple used one of their own OUIs, rather than OUI_ENCAP_ETHER, and an Ethernet packet type as protocol ID, for AppleTalk data packets - but used OUI_ENCAP_ETHER and an Ethernet packet type for AARP packets. */ if (XDLC_IS_INFORMATION(control)) { if (tree) { proto_tree_add_uint(snap_tree, hf_type, tvb, offset+3, 2, etype); } next_tvb = tvb_new_subset_remaining(tvb, offset+5); if (!dissector_try_uint(ethertype_subdissector_table, etype, next_tvb, pinfo, tree)) call_dissector(data_handle, next_tvb, pinfo, tree); } else { next_tvb = tvb_new_subset_remaining(tvb, offset+5); call_dissector(data_handle, next_tvb, pinfo, tree); } break; case OUI_BRIDGED: /* * MAC frames bridged over ATM (RFC 2684) or Frame Relay * (RFC 2427). * * We have to figure out how much padding to put * into the frame. We were handed a "bridge_pad" * argument which should be 0 for Frame Relay and * 2 for ATM; we add to that the amount of padding * common to both bridging types. */ if (tree) { proto_tree_add_uint(snap_tree, hf_pid, tvb, offset+3, 2, etype); } switch (etype) { case BPID_ETH_WITH_FCS: next_tvb = tvb_new_subset_remaining(tvb, offset+5+bridge_pad); call_dissector(eth_withfcs_handle, next_tvb, pinfo, tree); break; case BPID_ETH_WITHOUT_FCS: next_tvb = tvb_new_subset_remaining(tvb, offset+5+bridge_pad); call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree); break; case BPID_802_5_WITH_FCS: case BPID_802_5_WITHOUT_FCS: /* * We treat the last padding byte as the Access * Control byte, as that's what the Token * Ring dissector expects the first byte to * be. */ next_tvb = tvb_new_subset_remaining(tvb, offset+5+bridge_pad); call_dissector(tr_handle, next_tvb, pinfo, tree); break; case BPID_FDDI_WITH_FCS: case BPID_FDDI_WITHOUT_FCS: next_tvb = tvb_new_subset_remaining(tvb, offset+5+1+bridge_pad); call_dissector(fddi_handle, next_tvb, pinfo, tree); break; case BPID_BPDU: next_tvb = tvb_new_subset_remaining(tvb, offset+5); call_dissector(bpdu_handle, next_tvb, pinfo, tree); break; default: next_tvb = tvb_new_subset_remaining(tvb, offset+5); call_dissector(data_handle, next_tvb, pinfo, tree); break; } break; case OUI_CABLE_BPDU: /* DOCSIS cable modem spanning tree BPDU */ if (tree) { proto_tree_add_uint(snap_tree, hf_pid, tvb, offset+3, 2, etype); } next_tvb = tvb_new_subset_remaining(tvb, offset+5); call_dissector(bpdu_handle, next_tvb, pinfo, tree); break; case OUI_TURBOCELL: next_tvb = tvb_new_subset_remaining(tvb, offset+3); call_dissector(turbo_handle, next_tvb, pinfo, tree); break; case OUI_MARVELL: /* * OLPC packet. The PID is an Ethertype, but * there's a mesh header between the PID and * the payload. */ if (XDLC_IS_INFORMATION(control)) { if (tree) { proto_tree_add_uint(snap_tree, hf_type, tvb, offset+3, 2, etype); } next_tvb = tvb_new_subset_remaining(tvb, offset+5); mesh_header_len = call_dissector(mesh_handle, next_tvb, pinfo, tree); next_tvb = tvb_new_subset_remaining(tvb, offset+5+mesh_header_len); if (!dissector_try_uint(ethertype_subdissector_table, etype, next_tvb, pinfo, tree)) call_dissector(data_handle, next_tvb, pinfo, tree); } else { next_tvb = tvb_new_subset_remaining(tvb, offset+5); call_dissector(data_handle, next_tvb, pinfo, tree); } break; default: /* * Do we have information for this OUI? */ oui_info = get_snap_oui_info(oui); if (oui_info != NULL) { /* * Yes - use it. */ hf = *oui_info->field_info->p_id; subdissector_table = oui_info->table; } else { /* * No, use hf_pid for the PID and just dissect * the payload as data. */ hf = hf_pid; subdissector_table = NULL; } if (tree) { proto_tree_add_uint(snap_tree, hf, tvb, offset+3, 2, etype); } next_tvb = tvb_new_subset_remaining(tvb, offset+5); if (XDLC_IS_INFORMATION(control)) { if (subdissector_table != NULL) { /* do lookup with the subdissector table */ if (dissector_try_uint(subdissector_table, etype, next_tvb, pinfo, tree)) break; } } call_dissector(data_handle, next_tvb, pinfo, tree); break; } }
static void dissect_mqpcf_parm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mq_tree, guint offset, guint32 uCount, guint bLittleEndian, gboolean bParse) { guint32 u = 0; guint32 tOfs = 0; guint32 uLenF; char strPrm[256]; guint32 uTyp; guint32 uLen = 0; guint32 uPrm; guint32 uCnt; guint32 uCCS; guint32 uSLn; guint32 uVal; guint64 uVal64; guint32 uDig; const char sMaxLst[] = " Max # of List reached. DECODE interrupted (actual %u of %u)"; const char sPrmLn0[] = " MQPrm[%3u] has a zero length. DECODE Failed (MQPrm Count: %u)"; const char sMaxPrm[] = " Max # of Parm reached. DECODE interrupted (actual %u of %u)"; const char sPrmCnt[] = " Cnt=-1 and Length(%u) < 16. DECODE interrupted for elem %u"; proto_item *ti = NULL; proto_tree *tree = NULL; if (uCount == (guint32)-1) { guint32 xOfs = offset; uCnt = 0; while (tvb_length_remaining(tvb, xOfs) >= 16) { uLen = tvb_get_guint32_endian(tvb, xOfs + 4, bLittleEndian); if (uLen < 16) { ti = proto_tree_add_text(mq_tree, tvb, xOfs, 16, sPrmCnt, uLen, uCnt); expert_add_info(pinfo, ti, &ei_mq_pcf_PrmCnt); break; } uCnt++; xOfs += uLen; } uCount = uCnt; } uDig = dissect_mqpcf_getDigits(uCount); for (u = 0; u < uCount && u < mq_pcf_maxprm; u++) { tOfs = offset; uTyp = tvb_get_guint32_endian(tvb, offset , bLittleEndian); uLen = tvb_get_guint32_endian(tvb, offset + 4, bLittleEndian); if (uLen == 0) { ti = proto_tree_add_text(mq_tree, tvb, offset, 12, sPrmLn0, u+1, uCount); expert_add_info(pinfo, ti, &ei_mq_pcf_prmln0); u = uCount; break; } uPrm = tvb_get_guint32_endian(tvb, offset + 8, bLittleEndian); uLenF = 12; if (bParse) g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d-%-30.30s", "MQPrm", uDig, u+1, uTyp, val_to_str_const(uTyp, GET_VALSV(PrmTyp), " Unknown") + 6, uPrm, uPrm, val_to_str_const(uPrm, GET_VALSV(PrmId), "Unknown")); else g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d", "XtraD", uDig, u+1, uTyp, val_to_str_const(uTyp, GET_VALSV(PrmTyp), " Unknown") + 6, uPrm, uPrm); switch (uTyp) { case MQ_MQCFT_NONE: break; case MQ_MQCFT_COMMAND: break; case MQ_MQCFT_RESPONSE: break; case MQ_MQCFT_INTEGER: { const guint8 *pVal = NULL; uVal = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian); if (bParse) pVal = dissect_mqpcf_parm_getintval(uPrm, uVal); if (pVal) { ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %d-%s", strPrm, uVal, pVal); } else { ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %8x-%d", strPrm, uVal, uVal); } tree = proto_item_add_subtree(ti, ett_mqpcf_prm); proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); dissect_mqpcf_parm_int(tvb, tree, offset+uLenF, uPrm, uVal, hf_mq_pcf_int, 0, 0, 0, bParse); } break; case MQ_MQCFT_STRING: { guint8 *sStr; uCCS = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian); uSLn = tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian); sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC); if (*sStr) strip_trailing_blanks(sStr, uSLn); if (*sStr) format_text_chr(sStr, strlen(sStr), '.'); ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %s", strPrm, sStr); tree = proto_item_add_subtree(ti, ett_mqpcf_prm); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 8, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC); } break; case MQ_MQCFT_INTEGER_LIST: { guint32 u2; guint32 uDigit = 0; uCnt = tvb_get_guint32_endian(tvb, offset+uLenF, bLittleEndian); uDigit = dissect_mqpcf_getDigits(uCnt); ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s Cnt(%d)", strPrm, uCnt); tree = proto_item_add_subtree(ti, ett_mqpcf_prm); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian); offset += uLenF+4; for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++) { uVal = tvb_get_guint32_endian(tvb, offset, bLittleEndian); dissect_mqpcf_parm_int(tvb, tree, offset, uPrm, uVal, hf_mq_pcf_intlist, u2+1, uCnt, uDigit, bParse); offset += 4; } if (u2 != uCnt) { ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt); expert_add_info(pinfo, ti, &ei_mq_pcf_MaxInt); } } break; case MQ_MQCFT_STRING_LIST: { guint32 u2; guint32 uDigit; guint8 *sStr; header_field_info *hfinfo; hfinfo = proto_registrar_get_nth(hf_mq_pcf_stringlist); uCCS = tvb_get_guint32_endian(tvb, offset + uLenF , bLittleEndian); uCnt = tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian); uSLn = tvb_get_guint32_endian(tvb, offset + uLenF + 8, bLittleEndian); ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s Cnt(%d)", strPrm, uCnt); tree = proto_item_add_subtree(ti, ett_mqpcf_prm); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmcount , tvb, offset + 16, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian); uDigit = dissect_mqpcf_getDigits(uCnt); offset += uLenF+12; for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++) { sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC); if (*sStr) strip_trailing_blanks(sStr, uSLn); if (*sStr) format_text_chr(sStr, strlen(sStr), '.'); proto_tree_add_string_format(tree, hf_mq_pcf_stringlist, tvb, offset, uSLn, sStr, "%s[%*d]: %s", hfinfo->name, uDigit, u2+1, sStr); offset += uSLn; } if (u2 != uCnt) { ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt); expert_add_info(pinfo, ti, &ei_mq_pcf_MaxStr); } } break; case MQ_MQCFT_EVENT: break; case MQ_MQCFT_USER: { ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s", strPrm); tree = proto_item_add_subtree(ti, ett_mqpcf_prm); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + 8, uLen - 8, bLittleEndian); } break; case MQ_MQCFT_BYTE_STRING: { uSLn = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian); if (uSLn) { guint8 *sStrA = format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_ASCII) , uSLn, '.'); guint8 *sStrE = format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_EBCDIC), uSLn, '.'); if (uSLn > 35) { ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s [Truncated] A(%-.35s) E(%-.35s)", strPrm, sStrA, sStrE); } else { ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s A(%s) E(%s)", strPrm, sStrA, sStrE); } } else { ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s <MISSING>", strPrm); } tree = proto_item_add_subtree(ti, ett_mqpcf_prm); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 4 , uSLn, bLittleEndian); } break; case MQ_MQCFT_TRACE_ROUTE: break; case MQ_MQCFT_REPORT: break; case MQ_MQCFT_INTEGER_FILTER: { guint32 uOpe; uOpe = tvb_get_guint32_endian(tvb, offset + uLenF , bLittleEndian); uVal = tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian); ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %s %d", strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, uVal); tree = proto_item_add_subtree(ti, ett_mqpcf_prm); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_int, tvb, offset + uLenF + 4, 4, bLittleEndian); } break; case MQ_MQCFT_STRING_FILTER: { guint8 *sStr; guint32 uOpe; uOpe = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian); uCCS = tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian); uSLn = tvb_get_guint32_endian(tvb, offset + uLenF + 8, bLittleEndian); sStr = format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC), uSLn, '.'); strip_trailing_blanks(sStr, uSLn); ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %s %s", strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, sStr); tree = proto_item_add_subtree(ti, ett_mqpcf_prm); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 16, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC); } break; case MQ_MQCFT_BYTE_STRING_FILTER: { guint32 uOpe; uOpe = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian); uSLn = tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian); if (uSLn) { guint8 *sStrA = format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_ASCII), uSLn, '.'); guint8 *sStrE = format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_EBCDIC), uSLn, '.'); ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %s A(%s) E(%s)", strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, sStrA, sStrE); } else { ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %s <MISSING>", strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7); } tree = proto_item_add_subtree(ti, ett_mqpcf_prm); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 8 , uSLn, bLittleEndian); } break; case MQ_MQCFT_COMMAND_XR: break; case MQ_MQCFT_XR_MSG: break; case MQ_MQCFT_XR_ITEM: break; case MQ_MQCFT_XR_SUMMARY: break; case MQ_MQCFT_GROUP: break; case MQ_MQCFT_STATISTICS: break; case MQ_MQCFT_ACCOUNTING: break; case MQ_MQCFT_INTEGER64: { uVal64 = tvb_get_guint64_endian(tvb, offset + uLenF + 4, bLittleEndian); ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)", strPrm, uVal64, uVal64); tree = proto_item_add_subtree(ti, ett_mqpcf_prm); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmunused, tvb, offset + 12, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_int64, tvb, offset + uLenF + 4, 8, bLittleEndian); } break; case MQ_MQCFT_INTEGER64_LIST: { guint32 u2; guint32 uDigit; header_field_info *hfinfo; hfinfo = proto_registrar_get_nth(hf_mq_pcf_int64list); uCnt = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian); ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s Cnt(%d)", strPrm, uCnt); tree = proto_item_add_subtree(ti, ett_mqpcf_prm); uDigit = dissect_mqpcf_getDigits(uCnt); proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian); proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian); proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian); offset += uLenF + 4; for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++) { uVal64 = tvb_get_guint64_endian(tvb, offset, bLittleEndian); proto_tree_add_int64_format(tree, hf_mq_pcf_int64list, tvb, offset, 8, uVal64, "%s[%*d]: %" G_GINT64_MODIFIER "d", hfinfo->name, uDigit, u2+1, uVal64); offset += 8; } if (u2 != uCnt) { ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt); expert_add_info(pinfo, ti, &ei_mq_pcf_MaxI64); } } break; } offset = tOfs+uLen; } if (u != uCount) { ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, sMaxPrm, u, uCount); expert_add_info(pinfo, ti, &ei_mq_pcf_MaxPrm); } }
static int add_option_info(tvbuff_t *tvb, int pos, proto_tree *tree, proto_item *ti) { guint8 tag, length, fcs_err = 0, encr = 0, seen_fcs_err = 0; proto_tree *tag_tree; proto_item *tag_item; /* * Read all option tags in an endless loop. If the packet is malformed this * loop might be a problem. */ while (TRUE) { tag = tvb_get_guint8(tvb, pos); if ((tag != TZSP_HDR_PAD) && (tag != TZSP_HDR_END)) { length = tvb_get_guint8(tvb, pos+1); tag_item = proto_tree_add_text(tree, tvb, pos, 2+length, "%s", val_to_str_const(tag, option_tag_vals, "Unknown")); } else { tag_item = proto_tree_add_text(tree, tvb, pos, 1, "%s", val_to_str_const(tag, option_tag_vals, "Unknown")); length = 0; } tag_tree = proto_item_add_subtree(tag_item, ett_tag); proto_tree_add_item(tag_tree, hf_option_tag, tvb, pos, 1, ENC_NA); pos++; if ((tag != TZSP_HDR_PAD) && (tag != TZSP_HDR_END)) { proto_tree_add_item(tag_tree, hf_option_length, tvb, pos, 1, ENC_NA); pos++; } switch (tag) { case TZSP_HDR_PAD: break; case TZSP_HDR_END: /* Fill in header with information from other tags. */ if (seen_fcs_err) { proto_item_append_text(ti,"%s", fcs_err?"FCS Error":(encr?"Encrypted":"Good")); } return pos; case TZSP_HDR_ORIGINAL_LENGTH: proto_tree_add_item(tag_tree, hf_original_length, tvb, pos, 2, ENC_BIG_ENDIAN); break; case WLAN_RADIO_HDR_SIGNAL: proto_tree_add_item(tag_tree, hf_signal, tvb, pos, 1, ENC_NA); break; case WLAN_RADIO_HDR_NOISE: proto_tree_add_item(tag_tree, hf_silence, tvb, pos, 1, ENC_NA); break; case WLAN_RADIO_HDR_RATE: proto_tree_add_item(tag_tree, hf_rate, tvb, pos, 1, ENC_NA); break; case WLAN_RADIO_HDR_TIMESTAMP: proto_tree_add_item(tag_tree, hf_time, tvb, pos, 4, ENC_BIG_ENDIAN); break; case WLAN_RADIO_HDR_MSG_TYPE: proto_tree_add_item(tag_tree, hf_status_msg_type, tvb, pos, 1, ENC_NA); break; case WLAN_RADIO_HDR_CF: proto_tree_add_item(tag_tree, hf_status_pcf, tvb, pos, 1, ENC_NA); break; case WLAN_RADIO_HDR_UN_DECR: proto_tree_add_item(tag_tree, hf_status_undecrypted, tvb, pos, 1, ENC_NA); encr = tvb_get_guint8(tvb, pos); break; case WLAN_RADIO_HDR_FCS_ERR: seen_fcs_err = 1; proto_tree_add_item(tag_tree, hf_status_fcs_error, tvb, pos, 1, ENC_NA); fcs_err = tvb_get_guint8(tvb, pos); break; case WLAN_RADIO_HDR_CHANNEL: proto_tree_add_item(tag_tree, hf_channel, tvb, pos, 1, ENC_NA); break; case TZSP_HDR_SENSOR: proto_tree_add_item(tag_tree, hf_sensormac, tvb, pos, 6, ENC_NA); break; default: proto_tree_add_item(tag_tree, hf_unknown, tvb, pos, length, ENC_NA); break; } pos += length; } }
static void llc_sap_value( gchar *result, guint32 sap ) { g_snprintf( result, ITEM_LABEL_LENGTH, "%s", val_to_str_const(sap<<1, sap_vals, "Unknown")); }
static proto_tree * add_integer_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int name_length, int value_length, guint8 tag) { proto_tree *subtree; guint8 bool_val; switch (tag) { case TAG_BOOLEAN: if (value_length != 1) { subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1 + 2 + name_length + 2 + value_length, ett_ipp_attr, NULL, "%s: Invalid boolean (length is %u, should be 1)", tvb_format_text(tvb, offset + 1 + 2, name_length), value_length); } else { bool_val = tvb_get_guint8(tvb, offset + 1 + 2 + name_length + 2); subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1 + 2 + name_length + 2 + value_length, ett_ipp_attr, NULL, "%s: %s", tvb_format_text(tvb, offset + 1 + 2, name_length), val_to_str(bool_val, bool_vals, "Unknown (0x%02x)")); } break; case TAG_INTEGER: case TAG_ENUM: if (value_length != 4) { subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1 + 2 + name_length + 2 + value_length, ett_ipp_attr, NULL, "%s: Invalid integer (length is %u, should be 4)", tvb_format_text(tvb, offset + 1 + 2, name_length), value_length); } else { const char *name_val; /* Some fields in IPP are really unix timestamps but IPP * transports these as 4 byte integers. * A simple heuristic to make the display of these fields * more human readable is to assume that if the field name * ends in '-time' then assume they are timestamps instead * of integers. */ name_val=tvb_get_ptr(tvb, offset + 1 + 2, name_length); if ((name_length > 5) && name_val && !tvb_memeql(tvb, offset + 1 + 2 + name_length - 5, "-time", 5)) { subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1 + 2 + name_length + 2 + value_length, ett_ipp_attr, NULL, "%s: %s", format_text(name_val, name_length), abs_time_secs_to_str(wmem_packet_scope(), tvb_get_ntohl(tvb, offset + 1 + 2 + name_length + 2), ABSOLUTE_TIME_LOCAL, TRUE)); } else if ((name_length > 5) && name_val && !tvb_memeql(tvb, offset + 1 + 2, "printer-state", 13)) { subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1 + 2 + name_length + 2 + value_length, ett_ipp_attr, NULL, "%s: %s", format_text(name_val, name_length), val_to_str_const(tvb_get_ntohl(tvb, offset + 1 + 2 + name_length + 2), printer_state_vals, "Unknown Printer State")); } else if ((name_length > 5) && name_val && !tvb_memeql(tvb, offset + 1 + 2, "job-state", 9)) { subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1 + 2 + name_length + 2 + value_length, ett_ipp_attr, NULL, "%s: %s", format_text(name_val, name_length), val_to_str_const(tvb_get_ntohl(tvb, offset + 1 + 2 + name_length + 2), job_state_vals, "Unknown Job State")); } else { subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1 + 2 + name_length + 2 + value_length, ett_ipp_attr, NULL, "%s: %u", format_text(name_val, name_length), tvb_get_ntohl(tvb, offset + 1 + 2 + name_length + 2)); } } break; default: subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1 + 2 + name_length + 2 + value_length, ett_ipp_attr, NULL, "%s: Unknown integer type 0x%02x", tvb_format_text(tvb, offset + 1 + 2, name_length), tag); break; } return subtree; }
/* Dissect details of packet */ static void rlogin_display(rlogin_hash_entry_t *hash_info, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, struct tcpinfo *tcpinfo) { /* Display the proto tree */ int offset = 0; proto_tree *rlogin_tree, *user_info_tree, *window_tree; proto_item *ti; guint length; int str_len; gint ti_offset; proto_item *user_info_item, *window_info_item; /* Create rlogin subtree */ ti = proto_tree_add_item(tree, proto_rlogin, tvb, 0, -1, ENC_NA); rlogin_tree = proto_item_add_subtree(ti, ett_rlogin); /* Return if data empty */ length = tvb_captured_length(tvb); if (length == 0) { return; } /* * XXX - this works only if the urgent pointer points to something * in this segment; to make it work if the urgent pointer points * to something past this segment, we'd have to remember the urgent * pointer setting for this conversation. */ if (tcpinfo && IS_TH_URG(tcpinfo->flags) && /* if urgent pointer set */ length >= tcpinfo->urgent_pointer) /* and it's in this frame */ { /* Get urgent byte into Temp */ int urgent_offset = tcpinfo->urgent_pointer - 1; guint8 control_byte; /* Check for text data in front */ if (urgent_offset > offset) { proto_tree_add_item(rlogin_tree, hf_data, tvb, offset, urgent_offset, ENC_ASCII|ENC_NA); } /* Show control byte */ proto_tree_add_item(rlogin_tree, hf_control_message, tvb, urgent_offset, 1, ENC_BIG_ENDIAN); control_byte = tvb_get_guint8(tvb, urgent_offset); col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str_const(control_byte, control_message_vals, "Unknown")); offset = urgent_offset + 1; /* adjust offset */ } else if (tvb_get_guint8(tvb, offset) == '\0') { /* Startup */ if (pinfo->srcport == RLOGIN_PORT) /* from server */ { proto_tree_add_item(rlogin_tree, hf_startup_info_received_flag, tvb, offset, 1, ENC_BIG_ENDIAN); } else { proto_tree_add_item(rlogin_tree, hf_client_startup_flag, tvb, offset, 1, ENC_BIG_ENDIAN); } ++offset; } if (!tvb_offset_exists(tvb, offset)) { /* No more data to check */ return; } if (hash_info->info_framenum == pinfo->num) { gint info_len; gint slash_offset; /* First frame of conversation, assume user info... */ info_len = tvb_captured_length_remaining(tvb, offset); if (info_len <= 0) return; /* User info tree */ user_info_item = proto_tree_add_string_format(rlogin_tree, hf_user_info, tvb, offset, info_len, FALSE, "User info (%s)", tvb_format_text(tvb, offset, info_len)); user_info_tree = proto_item_add_subtree(user_info_item, ett_rlogin_user_info); /* Client user name. */ str_len = tvb_strsize(tvb, offset); proto_tree_add_item(user_info_tree, hf_user_info_client_user_name, tvb, offset, str_len, ENC_ASCII|ENC_NA); offset += str_len; /* Server user name. */ str_len = tvb_strsize(tvb, offset); proto_tree_add_item(user_info_tree, hf_user_info_server_user_name, tvb, offset, str_len, ENC_ASCII|ENC_NA); offset += str_len; /* Terminal type/speed. */ slash_offset = tvb_find_guint8(tvb, offset, -1, '/'); if (slash_offset != -1) { guint8* str = NULL; guint32 term_len = 0; gboolean term_len_valid; proto_item* pi = NULL; /* Terminal type */ proto_tree_add_item(user_info_tree, hf_user_info_terminal_type, tvb, offset, slash_offset-offset, ENC_ASCII|ENC_NA); offset = slash_offset + 1; /* Terminal speed */ str_len = tvb_strsize(tvb, offset); str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, str_len, ENC_NA|ENC_ASCII); term_len_valid = ws_strtou32(str, NULL, &term_len); pi = proto_tree_add_uint(user_info_tree, hf_user_info_terminal_speed, tvb, offset, str_len, term_len); if (!term_len_valid) expert_add_info(pinfo, pi, &ei_rlogin_termlen_invalid); offset += str_len; } } if (!tvb_offset_exists(tvb, offset)) { /* No more data to check */ return; } /* Test for terminal information, the data will have 2 0xff bytes */ /* look for first 0xff byte */ ti_offset = tvb_find_guint8(tvb, offset, -1, 0xff); /* Next byte must also be 0xff */ if (ti_offset != -1 && tvb_bytes_exist(tvb, ti_offset + 1, 1) && tvb_get_guint8(tvb, ti_offset + 1) == 0xff) { guint16 rows, columns; /* Have found terminal info. */ if (ti_offset > offset) { /* There's data before the terminal info. */ proto_tree_add_item(rlogin_tree, hf_data, tvb, offset, ti_offset - offset, ENC_ASCII|ENC_NA); } /* Create window info tree */ window_info_item = proto_tree_add_item(rlogin_tree, hf_window_info, tvb, offset, 12, ENC_NA); window_tree = proto_item_add_subtree(window_info_item, ett_rlogin_window); /* Cookie */ proto_tree_add_item(window_tree, hf_magic_cookie, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* These bytes should be "ss" */ proto_tree_add_item(window_tree, hf_window_info_ss, tvb, offset, 2, ENC_ASCII|ENC_NA); offset += 2; /* Character rows */ rows = tvb_get_ntohs(tvb, offset); proto_tree_add_item(window_tree, hf_window_info_rows, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Characters per row */ columns = tvb_get_ntohs(tvb, offset); proto_tree_add_item(window_tree, hf_window_info_cols, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* x pixels */ proto_tree_add_item(window_tree, hf_window_info_x_pixels, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* y pixels */ proto_tree_add_item(window_tree, hf_window_info_y_pixels, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Show setting highlights in info column */ col_append_fstr(pinfo->cinfo, COL_INFO, " (rows=%u, cols=%u)", rows, columns); } if (tvb_offset_exists(tvb, offset)) { /* There's more data in the frame. */ proto_tree_add_item(rlogin_tree, hf_data, tvb, offset, -1, ENC_ASCII|ENC_NA); } }
static int dissect_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) { proto_item *pitem = NULL; guint control_type; guint8 unknown_control_type; guint8 uuid_size; guint16 uuid_dst; guint16 uuid_src; guint16 response_message; guint list_length; guint i_item; proto_tree_add_item(tree, hf_btbnep_control_type, tvb, offset, 1, ENC_BIG_ENDIAN); control_type = tvb_get_guint8(tvb, offset); offset += 1; col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", val_to_str_const(control_type, control_type_vals, "Unknown type")); switch(control_type) { case 0x00: /* Command Not Understood */ proto_tree_add_item(tree, hf_btbnep_unknown_control_type, tvb, offset, 1, ENC_BIG_ENDIAN); unknown_control_type = tvb_get_guint8(tvb, offset); offset += 1; col_append_fstr(pinfo->cinfo, COL_INFO, " - Unknown(%s)", val_to_str_const(unknown_control_type, control_type_vals, "Unknown type")); break; case 0x01: /* Setup Connection Request */ proto_tree_add_item(tree, hf_btbnep_uuid_size, tvb, offset, 1, ENC_BIG_ENDIAN); uuid_size = tvb_get_guint8(tvb, offset); offset += 1; pitem = proto_tree_add_item(tree, hf_btbnep_destination_service_uuid, tvb, offset, uuid_size, ENC_NA); uuid_dst = tvb_get_ntohs(tvb, offset); proto_item_append_text(pitem, " (%s)", val_to_str_ext(uuid_dst, &vs_service_classes_ext, "Unknown uuid")); offset += uuid_size; pitem = proto_tree_add_item(tree, hf_btbnep_source_service_uuid, tvb, offset, uuid_size, ENC_NA); uuid_src = tvb_get_ntohs(tvb, offset); proto_item_append_text(pitem, " (%s)", val_to_str_ext(uuid_src, &vs_service_classes_ext, "Unknown uuid")); offset += uuid_size; col_append_fstr(pinfo->cinfo, COL_INFO, " - dst: <%s>, src: <%s>", val_to_str_ext(uuid_dst, &vs_service_classes_ext, "Unknown uuid"), val_to_str_ext(uuid_src, &vs_service_classes_ext, "Unknown uuid")); break; case 0x02: /* Setup Connection Response */ proto_tree_add_item(tree, hf_btbnep_setup_connection_response_message, tvb, offset, 2, ENC_BIG_ENDIAN); response_message = tvb_get_ntohs(tvb, offset); offset += 2; col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", val_to_str_const(response_message, setup_connection_response_message_vals, "Unknown response message")); break; case 0x03: /* Filter Net Type Set */ proto_tree_add_item(tree, hf_btbnep_list_length, tvb, offset, 2, ENC_BIG_ENDIAN); list_length = tvb_get_ntohs(tvb, offset); offset += 2; for (i_item = 0; i_item < list_length; i_item += 4) { proto_tree_add_item(tree, hf_btbnep_network_type_start, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_btbnep_network_type_end, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } break; case 0x04: /* Filter Net Type Response */ proto_tree_add_item(tree, hf_btbnep_filter_net_type_response_message, tvb, offset, 2, ENC_BIG_ENDIAN); response_message = tvb_get_ntohs(tvb, offset); offset += 2; col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", val_to_str_const(response_message, filter_net_type_response_message_vals, "Unknown response message")); break; case 0x05: /*Filter Multi Addr Set*/ proto_tree_add_item(tree, hf_btbnep_list_length, tvb, offset, 2, ENC_BIG_ENDIAN); list_length = tvb_get_ntohs(tvb, offset); offset += 2; for (i_item = 0; i_item < list_length; i_item += 12) { proto_tree_add_item(tree, hf_btbnep_multicast_address_start, tvb, offset, 6, ENC_NA); offset += 6; proto_tree_add_item(tree, hf_btbnep_multicast_address_end, tvb, offset, 6, ENC_NA); offset += 6; } break; case 0x06: /* Filter Multi Addr Response */ proto_tree_add_item(tree, hf_btbnep_filter_multi_addr_response_message, tvb, offset, 2, ENC_BIG_ENDIAN); response_message = tvb_get_ntohs(tvb, offset); offset += 2; col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", val_to_str_const(response_message, filter_multi_addr_response_message_vals, "Unknown response message")); break; }; return offset; }
static void dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *asap_tree) { guint16 type, length, padding_length; proto_item *parameter_item; proto_tree *parameter_tree; /* extract tag and length from the parameter */ type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET); length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET); padding_length = tvb_reported_length(parameter_tvb) - length; /* create proto_tree stuff */ parameter_tree = proto_tree_add_subtree(asap_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, -1, ett_asap_parameter, ¶meter_item, val_to_str_const(type, parameter_type_values, "Unknown Parameter")); /* add tag and length to the asap tree */ proto_tree_add_item(parameter_tree, hf_parameter_type, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, ENC_BIG_ENDIAN); proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, ENC_BIG_ENDIAN); switch(type) { case IPV4_ADDRESS_PARAMETER_TYPE: dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item); break; case IPV6_ADDRESS_PARAMETER_TYPE: dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item); break; case DCCP_TRANSPORT_PARAMETER_TYPE: dissect_dccp_transport_parameter(parameter_tvb, parameter_tree); break; case SCTP_TRANSPORT_PARAMETER_TYPE: dissect_sctp_transport_parameter(parameter_tvb, parameter_tree); break; case TCP_TRANSPORT_PARAMETER_TYPE: dissect_tcp_transport_parameter(parameter_tvb, parameter_tree); break; case UDP_TRANSPORT_PARAMETER_TYPE: dissect_udp_transport_parameter(parameter_tvb, parameter_tree); break; case UDP_LITE_TRANSPORT_PARAMETER_TYPE: dissect_udp_lite_transport_parameter(parameter_tvb, parameter_tree); break; case POOL_MEMBER_SELECTION_POLICY_PARAMETER_TYPE: dissect_pool_member_selection_policy_parameter(parameter_tvb, parameter_tree); break; case POOL_HANDLE_PARAMETER_TYPE: dissect_pool_handle_parameter(parameter_tvb, parameter_tree); break; case POOL_ELEMENT_PARAMETER_TYPE: dissect_pool_element_parameter(parameter_tvb, parameter_tree); break; case SERVER_INFORMATION_PARAMETER_TYPE: dissect_server_information_parameter(parameter_tvb, parameter_tree); break; case OPERATION_ERROR_PARAMETER_TYPE: dissect_operation_error_parameter(parameter_tvb, parameter_tree); break; case COOKIE_PARAMETER_TYPE: dissect_cookie_parameter(parameter_tvb, parameter_tree, parameter_item); break; case PE_IDENTIFIER_PARAMETER_TYPE: dissect_pe_identifier_parameter(parameter_tvb, parameter_tree, parameter_item); break; case PE_CHECKSUM_PARAMETER_TYPE: dissect_pe_checksum_parameter(parameter_tvb, parameter_tree, parameter_item); break; case HANDLE_RESOLUTION_OPTION_PARAMETER_TYPE: dissect_handle_resolution_option_parameter(parameter_tvb, parameter_tree); break; default: dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item); break; }; if (padding_length > 0) proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, ENC_NA); }
/*FUNCTION:------------------------------------------------------ * NAME * dissect_zbee_zcl_msg * DESCRIPTION * ZigBee ZCL Messaging cluster dissector for wireshark. * PARAMETERS * tvbuff_t *tvb - pointer to buffer containing raw packet. * packet_info *pinfo - pointer to packet information fields * proto_tree *tree - pointer to data tree Wireshark uses to display packet. * RETURNS * none *--------------------------------------------------------------- */ static void dissect_zbee_zcl_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *payload_root; proto_tree *payload_tree; zbee_zcl_packet *zcl = (zbee_zcl_packet *)pinfo->private_data; guint offset = 0; guint8 cmd_id = zcl->cmd_id; gint rem_len; /* Create a subtree for the ZCL Command frame, and add the command ID to it. */ if (zcl->direction == ZBEE_ZCL_FCF_TO_SERVER) { /* Append the command name to the info column. */ col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", val_to_str_const(cmd_id, zbee_zcl_msg_srv_rx_cmd_names, "Unknown Command"), zcl->tran_seqno); /* Add the command ID. */ proto_tree_add_item(tree, hf_zbee_zcl_msg_srv_rx_cmd_id, tvb, offset, 1, cmd_id); /* Check is this command has a payload, than add the payload tree */ rem_len = tvb_reported_length_remaining(tvb, ++offset); if (rem_len > 0) { payload_root = proto_tree_add_text(tree, tvb, offset, rem_len, "Payload"); payload_tree = proto_item_add_subtree(payload_root, ett_zbee_zcl_msg); /* Call the appropriate command dissector */ switch (cmd_id) { case ZBEE_ZCL_CMD_ID_MSG_GET_LAST_MSG: /* No payload */ break; case ZBEE_ZCL_CMD_ID_MSG_MSG_CONFIRM: dissect_zcl_msg_confirm(tvb, payload_tree, &offset); break; default: break; } } } else { /* ZBEE_ZCL_FCF_TO_CLIENT */ /* Append the command name to the info column. */ col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq: %u", val_to_str_const(cmd_id, zbee_zcl_msg_srv_tx_cmd_names, "Unknown Command"), zcl->tran_seqno); /* Add the command ID. */ proto_tree_add_item(tree, hf_zbee_zcl_msg_srv_tx_cmd_id, tvb, offset, 1, cmd_id); /* Check is this command has a payload, than add the payload tree */ rem_len = tvb_reported_length_remaining(tvb, ++offset); if (rem_len > 0) { payload_root = proto_tree_add_text(tree, tvb, offset, rem_len, "Payload"); payload_tree = proto_item_add_subtree(payload_root, ett_zbee_zcl_msg); /* Call the appropriate command dissector */ switch (cmd_id) { case ZBEE_ZCL_CMD_ID_MSG_DISPLAY_MSG: dissect_zcl_msg_display(tvb, payload_tree, &offset); break; case ZBEE_ZCL_CMD_ID_MSG_CANCEL_MSG: dissect_zcl_msg_cancel(tvb, payload_tree, &offset); break; default: break; } } } } /*dissect_zbee_zcl_msg*/
static void dissect_rpl_container(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 len, type, sublen, subtyp; proto_item *ti; proto_tree *rpl_container_tree; guint16 offset; gint ett_type; gint length, reported_length; len = tvb_get_ntohs(tvb, 0); proto_tree_add_text(tree, tvb, 0, 2, "Length: %u", len); type = tvb_get_ntohs(tvb, 2); proto_tree_add_text(tree, tvb, 2, 2, "Type: %s", val_to_str_const(type, rpl_type_vals, "Unknown Type")); offset = 4; switch (type) { case 1: case 2: case 4: case 8: case 0x10: case 0x20: while (len >= offset+4) { sublen = tvb_get_ntohs(tvb, offset); subtyp = tvb_get_ntohs(tvb, offset+2); ett_type = ett_rpl_unkn; if(subtyp == 0x0004) ett_type = ett_rpl_0004; if(subtyp == 0x0008) ett_type = ett_rpl_0008; if(subtyp == 0x4003) ett_type = ett_rpl_4003; if(subtyp == 0x4006) ett_type = ett_rpl_4006; if(subtyp == 0x4007) ett_type = ett_rpl_4007; if(subtyp == 0x4009) ett_type = ett_rpl_4009; if(subtyp == 0x400a) ett_type = ett_rpl_400a; if(subtyp == 0x400b) ett_type = ett_rpl_400b; if(subtyp == 0x400c) ett_type = ett_rpl_400c; if(subtyp == 0x4011) ett_type = ett_rpl_4011; if(subtyp == 0x4018) ett_type = ett_rpl_4018; if(subtyp == 0xc005) ett_type = ett_rpl_c005; if(subtyp == 0xc014) ett_type = ett_rpl_c014; ti = proto_tree_add_text(tree, tvb, offset, sublen, "%s", val_to_str_const(subtyp, rpl_type_vals, "Unknown Type")); rpl_container_tree = proto_item_add_subtree(ti, ett_type); length = tvb_length_remaining(tvb, offset); if (length > sublen) length = sublen; reported_length = tvb_reported_length_remaining(tvb, offset); if (reported_length > sublen) reported_length = sublen; if ( length > 0) { dissect_rpl_container(tvb_new_subset(tvb, offset, length, reported_length), pinfo, rpl_container_tree); offset += reported_length; } else { /* no more data, exit the loop */ offset += reported_length; break; } } break; case 0x4003: proto_tree_add_item(tree, hf_rpl_corrval, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case 0x4006: proto_tree_add_item(tree, hf_rpl_lmac, tvb, offset, 6, ENC_NA); offset += 6; break; case 0x4007: proto_tree_add_item(tree, hf_rpl_sap, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; break; case 0x4009: proto_tree_add_item(tree, hf_rpl_maxframe, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; case 0x400a: proto_tree_add_item(tree, hf_rpl_connclass, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; case 0x400b: proto_tree_add_item(tree, hf_rpl_respval, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; break; case 0x400c: proto_tree_add_item(tree, hf_rpl_smac, tvb, offset, 6, ENC_NA); offset += 6; break; case 0x4011: proto_tree_add_item(tree, hf_rpl_sequence, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case 0x4018: proto_tree_add_item(tree, hf_rpl_data, tvb, offset, len-4, ENC_NA); offset += len - 4; break; case 0xc005: proto_tree_add_item(tree, hf_rpl_config, tvb, offset, 8, ENC_NA); offset += 8; proto_tree_add_item(tree, hf_rpl_equipment, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_memsize, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_bsmversion, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_ec, tvb, offset, 6, ENC_NA); offset += 6; proto_tree_add_item(tree, hf_rpl_adapterid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_rpl_shortname, tvb, offset, 10, ENC_NA); offset += 10; break; case 0xc014: proto_tree_add_item(tree, hf_rpl_laddress, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_rpl_xaddress, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_rpl_flags, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; break; default: call_dissector(data_handle, tvb_new_subset_remaining(tvb, 4), pinfo, tree); break; } if (tvb_reported_length(tvb) > offset) call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); }
static gint dissect_adb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *main_item; proto_tree *main_tree; proto_item *arg0_item; proto_tree *arg0_tree; proto_item *arg1_item; proto_tree *arg1_tree; proto_item *magic_item; proto_item *crc_item; proto_tree *crc_tree = NULL; proto_item *sub_item; gint offset = 0; guint32 command; guint32 arg0; guint32 arg1; guint32 data_length = 0; guint32 crc32 = 0; usb_conv_info_t *usb_conv_info = NULL; wmem_tree_key_t key[5]; guint32 interface_id; guint32 bus_id; guint32 device_address; guint32 side_id; guint32 frame_number; gboolean is_command = TRUE; gboolean is_next_fragment = FALSE; gboolean is_service = FALSE; gint proto; gint direction = P2P_DIR_UNKNOWN; wmem_tree_t *wmem_tree; command_data_t *command_data = NULL; service_data_t *service_data = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ADB"); col_clear(pinfo->cinfo, COL_INFO); main_item = proto_tree_add_item(tree, proto_adb, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_adb); frame_number = pinfo->num; /* XXX: Why? If interface is USB only first try is correct * (and seems strange...), in other cases standard check for * previous protocol is correct */ proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(/*wmem_list_frame_prev*/(wmem_list_tail(pinfo->layers)))); if (proto != proto_usb) { proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers)))); } if (proto == proto_usb) { usb_conv_info = (usb_conv_info_t *) data; DISSECTOR_ASSERT(usb_conv_info); direction = usb_conv_info->direction; } else if (proto == proto_tcp) { if (pinfo->destport == ADB_TCP_PORT) direction = P2P_DIR_SENT; else direction = P2P_DIR_RECV; } else { return offset; } if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) interface_id = pinfo->phdr->interface_id; else interface_id = 0; if (proto == proto_usb) { bus_id = usb_conv_info->bus_id; device_address = usb_conv_info->device_address; key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[1].key = &bus_id; key[2].length = 1; key[2].key = &device_address; key[3].length = 0; key[3].key = NULL; } else { /* tcp */ key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[2].length = 1; if (direction == P2P_DIR_SENT) { key[1].key = &pinfo->srcport; key[2].key = &pinfo->destport; } else { key[1].key = &pinfo->destport; key[2].key = &pinfo->srcport; } key[3].length = 0; key[3].key = NULL; } wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key); if (wmem_tree) { command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); if (command_data && command_data->completed_in_frame >= frame_number && command_data->command_in_frame <= frame_number) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; if (direction == P2P_DIR_SENT) { if (command_data->command == A_CLSE) side_id = command_data->arg1; /* OUT: local id */ else side_id = command_data->arg0; /* OUT: local id */ } else { side_id = command_data->arg1; /* IN: remote id */ } key[3].length = 1; key[3].key = &side_id; key[4].length = 0; key[4].key = NULL; wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key); if (wmem_tree) { service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); if (service_data && command_data->command == A_OPEN) { is_service = TRUE; } } } } /* Simple heuristics to check if packet is command or data */ if ((command_data && command_data->completed_in_frame <= frame_number) || !command_data) { if (tvb_reported_length(tvb) < 24) { is_command = FALSE; } else if (tvb_reported_length(tvb) >= 24) { command = tvb_get_letohl(tvb, offset); if (command != A_SYNC && command != A_CLSE && command != A_WRTE && command != A_AUTH && command != A_CNXN && command != A_OPEN && command != A_OKAY) is_command = FALSE; else if (command != (0xFFFFFFFF ^ tvb_get_letohl(tvb, offset + 20))) is_command = FALSE; if (is_command) { data_length = tvb_get_letohl(tvb, offset + 12); crc32 = tvb_get_letohl(tvb, offset + 16); } if (command == A_OPEN) is_service = TRUE; } } if (service_data && !(command_data->command == A_OPEN && is_next_fragment)) { sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service_data->service); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data) { sub_item = proto_tree_add_uint(main_tree, hf_service_start_in_frame, tvb, offset, 0, service_data->start_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); if (service_data->close_local_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_local_in_frame, tvb, offset, 0, service_data->close_local_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data->close_remote_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_remote_in_frame, tvb, offset, 0, service_data->close_remote_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } } if (is_command) { proto_tree_add_item(main_tree, hf_command, tvb, offset, 4, ENC_LITTLE_ENDIAN); command = tvb_get_letohl(tvb, offset); offset += 4; col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(command, command_vals, "Unknown command")); arg0_item = proto_tree_add_item(main_tree, hf_argument_0, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg0_tree = proto_item_add_subtree(arg0_item, ett_adb_arg0); arg0 = tvb_get_letohl(tvb, offset); offset += 4; arg1_item = proto_tree_add_item(main_tree, hf_argument_1, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg1_tree = proto_item_add_subtree(arg1_item, ett_adb_arg1); arg1 = tvb_get_letohl(tvb, offset); offset += 4; switch (command) { case A_CNXN: proto_tree_add_item(arg0_tree, hf_version, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_max_data, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(version=%u.%u.%u, max_data=%u)", tvb_get_guint8(tvb, offset - 5), tvb_get_guint8(tvb, offset - 6), tvb_get_letohs(tvb, offset - 7), tvb_get_letohl(tvb, offset - 4)); break; case A_AUTH: proto_tree_add_item(arg0_tree, hf_auth_type, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(type=%s, 0)", val_to_str_const(tvb_get_letohl(tvb, offset - 8), auth_type_vals, "Unknown")); break; case A_OPEN: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, 0)", tvb_get_letohl(tvb, offset - 8)); break; case A_WRTE: proto_tree_add_item(arg0_tree, hf_zero, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(0, remote=%u)", tvb_get_letohl(tvb, offset - 4)); break; case A_CLSE: case A_OKAY: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, remote=%u)", tvb_get_letohl(tvb, offset - 8), tvb_get_letohl(tvb, offset - 4)); break; case A_SYNC: proto_tree_add_item(arg0_tree, hf_online, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_sequence, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(online=%s, sequence=%u)", tvb_get_letohl(tvb, offset - 8) ? "Yes": "No", tvb_get_letohl(tvb, offset - 4)); break; } proto_tree_add_item(main_tree, hf_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; if (data_length > 0) col_append_fstr(pinfo->cinfo, COL_INFO, " length=%u ", data_length); crc_item = proto_tree_add_item(main_tree, hf_data_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); crc32 = tvb_get_letohl(tvb, offset); offset += 4; magic_item = proto_tree_add_item(main_tree, hf_magic, tvb, offset, 4, ENC_LITTLE_ENDIAN); if ((tvb_get_letohl(tvb, offset) ^ 0xFFFFFFFF) != command) { proto_tree *expert_tree; expert_tree = proto_item_add_subtree(magic_item, ett_adb_magic); proto_tree_add_expert(expert_tree, pinfo, &ei_invalid_magic, tvb, offset, 4); } if (!pinfo->fd->flags.visited) save_command(command, arg0, arg1, data_length, crc32, service_data, proto, data, pinfo, &service_data, &command_data); offset += 4; } if (!pinfo->fd->flags.visited && command_data) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; if ((command_data->command_in_frame != frame_number && tvb_captured_length(tvb) == data_length) || (command_data->command_in_frame == frame_number && tvb_captured_length(tvb) == data_length + 24) ) { command_data->reassemble_data_length = command_data->data_length; command_data->completed_in_frame = frame_number; } } if (is_next_fragment && command_data) { sub_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_command, tvb, offset, 0, command_data->command); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_data_length, tvb, offset, 0, command_data->data_length); PROTO_ITEM_SET_GENERATED(sub_item); crc_item = proto_tree_add_uint(main_tree, hf_data_crc32, tvb, offset, 0, command_data->crc32); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); PROTO_ITEM_SET_GENERATED(crc_item); } if (command_data && command_data->completed_in_frame != frame_number) { sub_item = proto_tree_add_uint(main_tree, hf_completed_in_frame, tvb, offset, 0, command_data->completed_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (tvb_captured_length_remaining(tvb, offset) > 0 && (!is_command || data_length > 0)) { guint32 crc = 0; guint32 i_offset; if ((!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) || data_length > (guint32) tvb_captured_length_remaining(tvb, offset)) { /* need reassemble */ if (!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) { tvb_memcpy(tvb, command_data->reassemble_data + command_data->reassemble_data_length, offset, tvb_captured_length_remaining(tvb, offset)); command_data->reassemble_data_length += tvb_captured_length_remaining(tvb, offset); if (command_data->reassemble_data_length >= command_data->data_length) command_data->completed_in_frame = frame_number; } proto_tree_add_item(main_tree, hf_data_fragment, tvb, offset, -1, ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Data Fragment"); offset = tvb_captured_length(tvb); if (service_data && command_data && command_data->reassemble_data_length >= command_data->data_length && frame_number == command_data->completed_in_frame) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; next_tvb = tvb_new_child_real_data(tvb, command_data->reassemble_data, command_data->reassemble_data_length, command_data->reassemble_data_length); add_new_data_source(pinfo, next_tvb, "ADB Reassembled Data"); adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } } else { /* full message */ for (i_offset = 0; i_offset < data_length; ++i_offset) crc += tvb_get_guint8(tvb, offset + i_offset); if (crc32 > 0 && crc32 != crc) proto_tree_add_expert(crc_tree, pinfo, &ei_invalid_crc, tvb, offset, -1); if (is_service) { proto_tree_add_item(main_tree, hf_service, tvb, offset, -1, ENC_ASCII | ENC_NA); if (!pinfo->fd->flags.visited && service_data) { service_data->service = tvb_get_stringz_enc(wmem_file_scope(), tvb, offset, NULL, ENC_ASCII); } col_append_fstr(pinfo->cinfo, COL_INFO, "Service: %s", tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, NULL, ENC_ASCII)); offset = tvb_captured_length(tvb); } else if (command_data && command_data->command == A_CNXN) { gchar *info; gint len; info = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Info: %s", info); proto_tree_add_item(main_tree, hf_connection_info, tvb, offset, len, ENC_ASCII | ENC_NA); offset += len; } else { col_append_str(pinfo->cinfo, COL_INFO, "Data"); /* Decode service payload */ if (service_data) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset)); call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } else { proto_item *data_item; gchar *data_str; data_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, data_length, ENC_NA); data_str = tvb_format_text(tvb, offset, data_length); proto_item_append_text(data_item, ": %s", data_str); col_append_fstr(pinfo->cinfo, COL_INFO, " Raw: %s", data_str); } offset = tvb_captured_length(tvb); } } } return offset; }