static void dissect_fcsp_dhchap_reply (tvbuff_t *tvb, proto_tree *tree) { int offset = 12; guint32 param_len; if (tree) { proto_tree_add_item (tree, hf_auth_dhchap_rsp_len, tvb, offset, 4, 0); param_len = tvb_get_ntohl (tvb, offset); proto_tree_add_bytes (tree, hf_auth_dhchap_rsp_value, tvb, offset+4, param_len, tvb_get_ptr (tvb, offset+4, param_len)); offset += (param_len + 4); proto_tree_add_item (tree, hf_auth_dhchap_val_len, tvb, offset, 4, 0); param_len = tvb_get_ntohl (tvb, offset); proto_tree_add_bytes (tree, hf_auth_dhchap_dhvalue, tvb, offset+4, param_len, tvb_get_ptr (tvb, offset+4, param_len)); offset += (param_len + 4); proto_tree_add_item (tree, hf_auth_dhchap_chal_len, tvb, offset, 4, 0); param_len = tvb_get_ntohl (tvb, offset); proto_tree_add_bytes (tree, hf_auth_dhchap_chal_value, tvb, offset+4, param_len, tvb_get_ptr (tvb, offset+4, param_len)); } }
static void dissect_ap1394(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *fh_tree = NULL; const guint8 *src_addr, *dst_addr; guint16 etype; tvbuff_t *next_tvb; col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP/IEEE1394"); col_clear(pinfo->cinfo, COL_INFO); src_addr=tvb_get_ptr(tvb, 8, 8); SET_ADDRESS(&pinfo->dl_src, AT_EUI64, 8, src_addr); SET_ADDRESS(&pinfo->src, AT_EUI64, 8, src_addr); dst_addr=tvb_get_ptr(tvb, 0, 8); SET_ADDRESS(&pinfo->dl_dst, AT_EUI64, 8, dst_addr); SET_ADDRESS(&pinfo->dst, AT_EUI64, 8, dst_addr); if (tree) { ti = proto_tree_add_protocol_format(tree, proto_ap1394, tvb, 0, 18, "Apple IP-over-IEEE 1394, Src: %s, Dst: %s", bytes_to_ep_str(src_addr, 8), bytes_to_ep_str(dst_addr, 8)); fh_tree = proto_item_add_subtree(ti, ett_ap1394); proto_tree_add_bytes(fh_tree, hf_ap1394_dst, tvb, 0, 8, dst_addr); proto_tree_add_bytes(fh_tree, hf_ap1394_src, tvb, 8, 8, src_addr); } etype = tvb_get_ntohs(tvb, 16); if (tree) proto_tree_add_uint(fh_tree, hf_ap1394_type, tvb, 16, 2, etype); next_tvb = tvb_new_subset_remaining(tvb, 18); if (!dissector_try_uint(ethertype_subdissector_table, etype, next_tvb, pinfo, tree)) call_dissector(data_handle, next_tvb, pinfo, tree); }
static void dissect_fcsp_dhchap_challenge (tvbuff_t *tvb, proto_tree *tree) { int offset = 12; guint16 name_type; guint16 param_len, name_len; if (tree) { proto_tree_add_item (tree, hf_auth_responder_name_type, tvb, offset, 2, 0); name_type = tvb_get_ntohs (tvb, offset); proto_tree_add_item (tree, hf_auth_responder_name_len, tvb, offset+2, 2, 0); name_len = tvb_get_ntohs (tvb, offset+2); if (name_type == FC_AUTH_NAME_TYPE_WWN) { proto_tree_add_string (tree, hf_auth_responder_wwn, tvb, offset+4, 8, fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8))); } else { proto_tree_add_bytes (tree, hf_auth_responder_name, tvb, offset+4, name_len, tvb_get_ptr (tvb, offset+4, name_len)); } offset += (4+name_len); proto_tree_add_item (tree, hf_auth_dhchap_hash_type, tvb, offset, 4, 0); proto_tree_add_item (tree, hf_auth_dhchap_group_type, tvb, offset+4, 4, 0); proto_tree_add_item (tree, hf_auth_dhchap_chal_len, tvb, offset+8, 4, 0); param_len = tvb_get_ntohl (tvb, offset+8); proto_tree_add_bytes (tree, hf_auth_dhchap_chal_value, tvb, offset+12, param_len, tvb_get_ptr (tvb, offset+12, param_len)); offset += (param_len + 12); proto_tree_add_item (tree, hf_auth_dhchap_val_len, tvb, offset, 4, 0); param_len = tvb_get_ntohl (tvb, offset); proto_tree_add_bytes (tree, hf_auth_dhchap_dhvalue, tvb, offset+4, param_len, tvb_get_ptr (tvb, offset+4, param_len)); } }
static void dissect_fcip_sf (tvbuff_t *tvb, proto_tree *tree, gint offset) { if (tree) { proto_tree_add_string (tree, hf_fcip_src_wwn, tvb, offset, 8, fcwwn_to_str (tvb_get_ptr (tvb, offset, 8))); proto_tree_add_bytes (tree, hf_fcip_src_entity_id, tvb, offset+8, 8, tvb_get_ptr (tvb, offset+8, 8)); proto_tree_add_bytes (tree, hf_fcip_conn_nonce, tvb, offset+16, 8, tvb_get_ptr (tvb, offset+16, 8)); /* XXX - break out these flags */ proto_tree_add_item (tree, hf_fcip_conn_flags, tvb, offset+24, 1, 0); proto_tree_add_item (tree, hf_fcip_conn_code, tvb, offset+26, 2, 0); proto_tree_add_string (tree, hf_fcip_dst_wwn, tvb, offset+30, 8, fcwwn_to_str (tvb_get_ptr (tvb, offset+30, 8))); proto_tree_add_item (tree, hf_fcip_katov, tvb, offset+38, 4, 0); } }
static void dissect_fcsp_auth_negotiate (tvbuff_t *tvb, proto_tree *tree) { int offset = 12; guint16 name_type, name_len, proto_type, param_len; guint32 num_protos, i; if (tree) { proto_tree_add_item (tree, hf_auth_initiator_name_type, tvb, offset, 2, 0); name_type = tvb_get_ntohs (tvb, offset); proto_tree_add_item (tree, hf_auth_initiator_name_len, tvb, offset+2, 2, 0); name_len = tvb_get_ntohs (tvb, offset+2); if (name_type == FC_AUTH_NAME_TYPE_WWN) { proto_tree_add_string (tree, hf_auth_initiator_wwn, tvb, offset+4, 8, fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8))); } else { proto_tree_add_bytes (tree, hf_auth_initiator_name, tvb, offset+4, name_len, tvb_get_ptr (tvb, offset+4, name_len)); } offset += (4+name_len); proto_tree_add_item (tree, hf_auth_usable_proto, tvb, offset, 4, 0); num_protos = tvb_get_ntohl (tvb, offset); offset += 4; for (i = 0; i < num_protos; i++) { proto_tree_add_item (tree, hf_auth_proto_param_len, tvb, offset, 4, 0); param_len = tvb_get_ntohl (tvb, offset); offset += 4; if (tvb_bytes_exist (tvb, offset, param_len)) { proto_type = tvb_get_ntohl (tvb, offset); proto_tree_add_item (tree, hf_auth_proto_type, tvb, offset, 4, 0); switch (proto_type) { case FC_AUTH_PROTO_TYPE_DHCHAP: dissect_fcsp_dhchap_auth_param (tvb, tree, offset+4, param_len); break; case FC_AUTH_PROTO_TYPE_FCAP: break; default: break; } } offset += param_len; } } }
/* Heartbeat Data */ static void dissect_m2tp_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item) { guint16 length, heartbeat_data_length; if (parameter_tree) { length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET); heartbeat_data_length = length - PARAMETER_HEADER_LENGTH; proto_tree_add_bytes(parameter_tree, hf_m2tp_heartbeat_data, parameter_tvb, PARAMETER_VALUE_OFFSET, heartbeat_data_length, tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, heartbeat_data_length)); proto_item_set_text(parameter_item, "Heartbeat data (%u byte%s)", heartbeat_data_length, plurality(heartbeat_data_length, "", "s")); } }
/* Diagnostic Information */ static void dissect_m2tp_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item) { guint16 length, diagnostic_info_length; if (parameter_tree) { length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET); diagnostic_info_length = length - PARAMETER_HEADER_LENGTH; proto_tree_add_bytes(parameter_tree, hf_m2tp_diagnostic_info, parameter_tvb, PARAMETER_VALUE_OFFSET, diagnostic_info_length, tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, diagnostic_info_length)); proto_item_set_text(parameter_item, "Diagnostic information (%u byte%s)", diagnostic_info_length, plurality(diagnostic_info_length, "", "s")); } }
/* Unknown Parameter */ static void dissect_m2tp_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item) { guint16 tag, length, parameter_value_length; if (parameter_tree) { tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET); length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET); parameter_value_length = length - PARAMETER_HEADER_LENGTH; proto_tree_add_bytes(parameter_tree, hf_m2tp_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length)); proto_item_set_text(parameter_item, "Parameter with tag %u and %u byte%s value", tag, parameter_value_length, plurality(parameter_value_length, "", "s")); } }
static void dissect_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *echo_tree = NULL; proto_item *ti, *hidden_item; int offset = 0; gboolean request = FALSE; const guint8 *data = tvb_get_ptr(tvb, offset, -1); if (pinfo->destport == ECHO_PORT) { request = TRUE; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "ECHO"); if (check_col(pinfo->cinfo, COL_INFO)) { col_set_str(pinfo->cinfo, COL_INFO, (request) ? "Request" : "Response"); } if (tree) { ti = proto_tree_add_item(tree, proto_echo, tvb, offset, -1, FALSE); echo_tree = proto_item_add_subtree(ti, ett_echo); if (request) { hidden_item = proto_tree_add_boolean(echo_tree, hf_echo_request, tvb, 0, 0, 1); } else { hidden_item = proto_tree_add_boolean(echo_tree, hf_echo_response, tvb, 0, 0, 1); } PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_bytes(echo_tree, hf_echo_data, tvb, offset, -1, data); } } /* dissect_echo */
/* Transfers happen in response to broadcasts, they are always TCP and are * used to send the file to the port mentioned in the broadcast. There are * 2 types of transfers: Pushes, which are direct responses to searches, * in which the peer that has the file connects to the peer that doesn't and * sends it, then disconnects. The other type of transfer is a pull, where * the peer that doesn't have the file connects to the peer that does and * requests it be sent. * * Pulls have a file request which identifies the desired file, * while pushes simply send the file. In practice this works because every * file the implementation sends searches for is on a different TCP port * on the searcher's machine. */ static int dissect_ldss_transfer (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { conversation_t *transfer_conv; ldss_transfer_info_t *transfer_info; struct tcpinfo *transfer_tcpinfo; proto_tree *ti, *line_tree = NULL, *ldss_tree = NULL; nstime_t broadcast_response_time; /* Reject the packet if data is NULL */ if (data == NULL) return 0; transfer_tcpinfo = (struct tcpinfo *)data; col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDSS"); /* Look for the transfer conversation; this was created during * earlier broadcast dissection (see prepare_ldss_transfer_conv) */ transfer_conv = find_conversation (pinfo->num, &pinfo->src, &pinfo->dst, PT_TCP, pinfo->srcport, pinfo->destport, 0); transfer_info = (ldss_transfer_info_t *)conversation_get_proto_data(transfer_conv, proto_ldss); /* For a pull, the first packet in the TCP connection is the file request. * First packet is identified by relative seq/ack numbers of 1. * File request only appears on a pull (triggered by an offer - see above * about broadcasts) */ if (transfer_tcpinfo->seq == 1 && transfer_tcpinfo->lastackseq == 1 && transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND) { /* LDSS pull transfers look a lot like HTTP. * Sample request: * md5:01234567890123... * Size: 2550 * Start: 0 * Compression: 0 * (remote end sends the file identified by the digest) */ guint offset = 0; gboolean already_dissected = TRUE; col_set_str(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Requesting file - pull)"); if (highest_num_seen == 0 || highest_num_seen < pinfo->num) { already_dissected = FALSE; transfer_info->req = wmem_new0(wmem_file_scope(), ldss_file_request_t); transfer_info->req->file = wmem_new0(wmem_file_scope(), ldss_file_t); highest_num_seen = pinfo->num; } if (tree) { ti = proto_tree_add_item(tree, proto_ldss, tvb, 0, tvb_reported_length(tvb), ENC_NA); ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer); } /* Populate digest data into the file struct in the request */ transfer_info->file = transfer_info->req->file; /* Grab each line from the packet, there should be 4 but lets * not walk off the end looking for more. */ while (tvb_offset_exists(tvb, offset)) { gint next_offset; const guint8 *line; int linelen; gboolean is_digest_line; guint digest_type_len; linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); /* Include new-line in line */ line = (guint8 *)tvb_memdup(NULL, tvb, offset, linelen+1); /* XXX - memory leak? */ line_tree = proto_tree_add_subtree(ldss_tree, tvb, offset, linelen, ett_ldss_transfer_req, NULL, tvb_format_text(tvb, offset, next_offset-offset)); /* Reduce code duplication processing digest lines. * There are too many locals to pass to a function - the signature * looked pretty ugly when I tried! */ is_digest_line = FALSE; if (strncmp(line,"md5:",4)==0) { is_digest_line = TRUE; digest_type_len = 4; transfer_info->file->digest_type = DIGEST_TYPE_MD5; } else if (strncmp(line, "sha1:", 5)==0) { is_digest_line = TRUE; digest_type_len = 5; transfer_info->file->digest_type = DIGEST_TYPE_SHA1; } else if (strncmp(line, "sha256:", 7)==0) { is_digest_line = TRUE; digest_type_len = 7; transfer_info->file->digest_type = DIGEST_TYPE_SHA256; } else if (strncmp(line, "unknown:", 8)==0) { is_digest_line = TRUE; digest_type_len = 8; transfer_info->file->digest_type = DIGEST_TYPE_UNKNOWN; } else if (strncmp(line, "Size: ", 6)==0) { /* Sample size line: * Size: 2550\n */ transfer_info->req->size = g_ascii_strtoull(line+6, NULL, 10); if (tree) { ti = proto_tree_add_uint64(line_tree, hf_ldss_size, tvb, offset+6, linelen-6, transfer_info->req->size); PROTO_ITEM_SET_GENERATED(ti); } } else if (strncmp(line, "Start: ", 7)==0) { /* Sample offset line: * Start: 0\n */ transfer_info->req->offset = g_ascii_strtoull(line+7, NULL, 10); if (tree) { ti = proto_tree_add_uint64(line_tree, hf_ldss_offset, tvb, offset+7, linelen-7, transfer_info->req->offset); PROTO_ITEM_SET_GENERATED(ti); } } else if (strncmp(line, "Compression: ", 13)==0) { /* Sample compression line: * Compression: 0\n */ transfer_info->req->compression = (gint8)strtol(line+13, NULL, 10); /* XXX - bad cast */ if (tree) { ti = proto_tree_add_uint(line_tree, hf_ldss_compression, tvb, offset+13, linelen-13, transfer_info->req->compression); PROTO_ITEM_SET_GENERATED(ti); } } else { proto_tree_add_expert(line_tree, pinfo, &ei_ldss_unrecognized_line, tvb, offset, linelen); } if (is_digest_line) { /* Sample digest-type/digest line: * md5:0123456789ABCDEF\n */ if (!already_dissected) { GByteArray *digest_bytes; digest_bytes = g_byte_array_new(); hex_str_to_bytes( tvb_get_ptr(tvb, offset+digest_type_len, linelen-digest_type_len), digest_bytes, FALSE); if(digest_bytes->len >= DIGEST_LEN) digest_bytes->len = (DIGEST_LEN-1); /* Ensure the digest is zero-padded */ transfer_info->file->digest = (guint8 *)wmem_alloc0(wmem_file_scope(), DIGEST_LEN); memcpy(transfer_info->file->digest, digest_bytes->data, digest_bytes->len); g_byte_array_free(digest_bytes, TRUE); } if (tree) { proto_item *tii = NULL; tii = proto_tree_add_uint(line_tree, hf_ldss_digest_type, tvb, offset, digest_type_len, transfer_info->file->digest_type); PROTO_ITEM_SET_GENERATED(tii); tii = proto_tree_add_bytes(line_tree, hf_ldss_digest, tvb, offset+digest_type_len, MIN(linelen-digest_type_len, DIGEST_LEN), transfer_info->file->digest); PROTO_ITEM_SET_GENERATED(tii); } } offset = next_offset; } /* Link forwards to the response for this pull. */ if (tree && transfer_info->resp_num != 0) { ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_in, tvb, 0, 0, transfer_info->resp_num); PROTO_ITEM_SET_GENERATED(ti); } transfer_info->req->num = pinfo->num; transfer_info->req->ts = pinfo->abs_ts; } /* Remaining packets are the file response */ else { guint64 size; guint64 offset; guint8 compression; /* size, digest, compression come from the file request for a pull but * they come from the broadcast for a push. Pushes don't bother * with a file request - they just send the data. We have to get file * info from the offer broadcast which triggered this transfer. * If we cannot find the file request, default to the broadcast. */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL) { transfer_info->file = transfer_info->req->file; size = transfer_info->req->size; offset = transfer_info->req->offset; compression = transfer_info->req->compression; } else { transfer_info->file = transfer_info->broadcast->file; size = transfer_info->broadcast->size; offset = transfer_info->broadcast->offset; compression = transfer_info->broadcast->compression; } /* Remaining data in this TCP connection is all file data. * Always desegment if the size is 0 (ie. unknown) */ if (pinfo->can_desegment) { if (size == 0 || tvb_captured_length(tvb) < size) { pinfo->desegment_offset = 0; pinfo->desegment_len = DESEGMENT_UNTIL_FIN; return 0; } } /* OK. Now we have the whole file that was transferred. */ transfer_info->resp_num = pinfo->num; transfer_info->resp_ts = pinfo->abs_ts; col_add_fstr(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Sending file - %s)", transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND ? "pull" : "push"); if (tree) { ti = proto_tree_add_item(tree, proto_ldss, tvb, 0, tvb_reported_length(tvb), ENC_NA); ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer); proto_tree_add_bytes_format(ldss_tree, hf_ldss_file_data, tvb, 0, tvb_captured_length(tvb), NULL, compression == COMPRESSION_GZIP ? "Gzip compressed data: %d bytes" : "File data: %d bytes", tvb_captured_length(tvb)); #ifdef HAVE_ZLIB /* Be nice and uncompress the file data. */ if (compression == COMPRESSION_GZIP) { tvbuff_t *uncomp_tvb; uncomp_tvb = tvb_child_uncompress(tvb, tvb, 0, tvb_captured_length(tvb)); if (uncomp_tvb != NULL) { /* XXX: Maybe not a good idea to add a data_source for what may very well be a large buffer since then the full uncompressed buffer will be shown in a tab in the hex bytes pane ? However, if we don't, bytes in an unrelated tab will be highlighted. */ add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Data"); proto_tree_add_bytes_format_value(ldss_tree, hf_ldss_file_data, uncomp_tvb, 0, tvb_captured_length(uncomp_tvb), NULL, "Uncompressed data: %d bytes", tvb_captured_length(uncomp_tvb)); } } #endif ti = proto_tree_add_uint(ldss_tree, hf_ldss_digest_type, tvb, 0, 0, transfer_info->file->digest_type); PROTO_ITEM_SET_GENERATED(ti); if (transfer_info->file->digest != NULL) { /* This is ugly. You can't add bytes of nonzero length and have * filtering work correctly unless you give a valid location in * the packet. This hack pretends the first 32 bytes of the packet * are the digest, which they aren't: they're actually the first 32 * bytes of the file that was sent. */ ti = proto_tree_add_bytes(ldss_tree, hf_ldss_digest, tvb, 0, DIGEST_LEN, transfer_info->file->digest); } PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint64(ldss_tree, hf_ldss_size, tvb, 0, 0, size); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint64(ldss_tree, hf_ldss_offset, tvb, 0, 0, offset); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint(ldss_tree, hf_ldss_compression, tvb, 0, 0, compression); PROTO_ITEM_SET_GENERATED(ti); /* Link to the request for a pull. */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL && transfer_info->req->num != 0) { ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_to, tvb, 0, 0, transfer_info->req->num); PROTO_ITEM_SET_GENERATED(ti); } } } /* Print the pull response time */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL && transfer_info->resp_num != 0) { nstime_t pull_response_time; nstime_delta(&pull_response_time, &transfer_info->resp_ts, &transfer_info->req->ts); ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_response_time, tvb, 0, 0, &pull_response_time); PROTO_ITEM_SET_GENERATED(ti); } /* Link the transfer back to the initiating broadcast. Response time is * calculated as the time from broadcast to completed transfer. */ ti = proto_tree_add_uint(ldss_tree, hf_ldss_initiated_by, tvb, 0, 0, transfer_info->broadcast->num); PROTO_ITEM_SET_GENERATED(ti); if (transfer_info->resp_num != 0) { nstime_delta(&broadcast_response_time, &transfer_info->resp_ts, &transfer_info->broadcast->ts); ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_completed_in, tvb, 0, 0, &broadcast_response_time); PROTO_ITEM_SET_GENERATED(ti); } /* This conv got its addr2/port2 set by the TCP dissector because a TCP * connection was established. Make a new one to handle future connections * to the addr/port mentioned in the broadcast, because that socket is * still open. */ if (transfer_tcpinfo->seq == 1 && transfer_tcpinfo->lastackseq == 1) { prepare_ldss_transfer_conv(transfer_info->broadcast); } return tvb_captured_length(tvb); }
static int dissect_ccn_contentobject(const unsigned char *ccnb, size_t ccnb_size, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *signature_tree; proto_tree *name_tree; proto_tree *signedinfo_tree; proto_tree *content_tree; proto_item *titem; struct ccn_parsed_ContentObject co; struct ccn_parsed_ContentObject *pco = &co; struct ccn_charbuf *c; struct ccn_indexbuf *comps; const unsigned char *comp; size_t comp_size; size_t blob_size; const unsigned char *blob; int l; unsigned int i; double dt; nstime_t timestamp; int res; comps = ccn_indexbuf_create(); res = ccn_parse_ContentObject(ccnb, ccnb_size, pco, comps); if (res < 0) return (-1); /* Signature */ l = pco->offset[CCN_PCO_E_Signature] - pco->offset[CCN_PCO_B_Signature]; titem = proto_tree_add_item(tree, hf_ccn_signature, tvb, pco->offset[CCN_PCO_B_Signature], l, FALSE); signature_tree = proto_item_add_subtree(titem, ett_signature); /* DigestAlgorithm */ l = pco->offset[CCN_PCO_E_DigestAlgorithm] - pco->offset[CCN_PCO_B_DigestAlgorithm]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_DigestAlgorithm, ccnb, pco->offset[CCN_PCO_B_DigestAlgorithm], pco->offset[CCN_PCO_E_DigestAlgorithm], &blob, &blob_size); titem = proto_tree_add_item(signature_tree, hf_ccn_signaturedigestalg, tvb, blob - ccnb, blob_size, FALSE); } /* Witness */ l = pco->offset[CCN_PCO_E_Witness] - pco->offset[CCN_PCO_B_Witness]; if (l > 0) { /* add the witness item to the signature tree */ } /* Signature bits */ l = pco->offset[CCN_PCO_E_SignatureBits] - pco->offset[CCN_PCO_B_SignatureBits]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, ccnb, pco->offset[CCN_PCO_B_SignatureBits], pco->offset[CCN_PCO_E_SignatureBits], &blob, &blob_size); titem = proto_tree_add_bytes(signature_tree, hf_ccn_signaturebits, tvb, blob - ccnb, blob_size, blob); } /* /Signature */ /* Name */ l = pco->offset[CCN_PCO_E_Name] - pco->offset[CCN_PCO_B_Name]; c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, ccnb_size, 1); titem = proto_tree_add_string(tree, hf_ccn_name, tvb, pco->offset[CCN_PCO_B_Name], l, ccn_charbuf_as_string(c)); name_tree = proto_item_add_subtree(titem, ett_name); ccn_charbuf_destroy(&c); /* Name Components */ for (i = 0; i < comps->n - 1; i++) { res = ccn_name_comp_get(ccnb, comps, i, &comp, &comp_size); titem = proto_tree_add_item(name_tree, hf_ccn_name_components, tvb, comp - ccnb, comp_size, FALSE); } /* /Name */ /* SignedInfo */ l = pco->offset[CCN_PCO_E_SignedInfo] - pco->offset[CCN_PCO_B_SignedInfo]; titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_SignedInfo], l, "SignedInfo"); signedinfo_tree = proto_item_add_subtree(titem, ett_signedinfo); /* PublisherPublicKeyDigest */ l = pco->offset[CCN_PCO_E_PublisherPublicKeyDigest] - pco->offset[CCN_PCO_B_PublisherPublicKeyDigest]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, ccnb, pco->offset[CCN_PCO_B_PublisherPublicKeyDigest], pco->offset[CCN_PCO_E_PublisherPublicKeyDigest], &blob, &blob_size); titem = proto_tree_add_bytes(signedinfo_tree, hf_ccn_publisherpublickeydigest, tvb, blob - ccnb, blob_size, blob); } /* Timestamp */ l = pco->offset[CCN_PCO_E_Timestamp] - pco->offset[CCN_PCO_B_Timestamp]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp, ccnb, pco->offset[CCN_PCO_B_Timestamp], pco->offset[CCN_PCO_E_Timestamp], &blob, &blob_size); dt = 0.0; for (i = 0; i < blob_size; i++) dt = dt * 256.0 + (double)blob[i]; dt /= 4096.0; timestamp.secs = dt; /* truncates */ timestamp.nsecs = (dt - (double) timestamp.secs) * 1000000000.0; titem = proto_tree_add_time(signedinfo_tree, hf_ccn_timestamp, tvb, blob - ccnb, blob_size, ×tamp); } /* Type */ l = pco->offset[CCN_PCO_E_Type] - pco->offset[CCN_PCO_B_Type]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Type, ccnb, pco->offset[CCN_PCO_B_Type], pco->offset[CCN_PCO_E_Type], &blob, &blob_size); titem = proto_tree_add_int(signedinfo_tree, hf_ccn_contenttype, tvb, blob - ccnb, blob_size, pco->type); } else { titem = proto_tree_add_int(signedinfo_tree, hf_ccn_contenttype, NULL, 0, 0, pco->type); } /* FreshnessSeconds */ l = pco->offset[CCN_PCO_E_FreshnessSeconds] - pco->offset[CCN_PCO_B_FreshnessSeconds]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds], &blob, &blob_size); i = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds]); titem = proto_tree_add_uint(signedinfo_tree, hf_ccn_freshnessseconds, tvb, blob - ccnb, blob_size, i); } /* FinalBlockID */ l = pco->offset[CCN_PCO_E_FinalBlockID] - pco->offset[CCN_PCO_B_FinalBlockID]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb, pco->offset[CCN_PCO_B_FinalBlockID], pco->offset[CCN_PCO_E_FinalBlockID], &blob, &blob_size); titem = proto_tree_add_item(signedinfo_tree, hf_ccn_finalblockid, tvb, blob - ccnb, blob_size, FALSE); } /* TODO: KeyLocator */ /* /SignedInfo */ /* Content */ l = pco->offset[CCN_PCO_E_Content] - pco->offset[CCN_PCO_B_Content]; res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, ccnb, pco->offset[CCN_PCO_B_Content], pco->offset[CCN_PCO_E_Content], &blob, &blob_size); titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_Content], l, "Content: %d bytes", blob_size); if (blob_size > 0) { content_tree = proto_item_add_subtree(titem, ett_content); titem = proto_tree_add_item(content_tree, hf_ccn_contentdata, tvb, blob - ccnb, blob_size, FALSE); } return (ccnb_size); }
/* M2TP Parameter */ static void dissect_m2tp_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *m2tp_tree, proto_item *m2tp_item, proto_tree *tree) { guint16 tag, length, padding_length, total_length; proto_item *parameter_item = NULL; proto_tree *parameter_tree = NULL; /* extract tag and length from the parameter */ tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET); length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET); /* calculate padding and total length */ padding_length = nr_of_padding_bytes(length); total_length = length + padding_length; if (tree) { /* create proto_tree stuff */ parameter_item = proto_tree_add_text(m2tp_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, total_length, "Incomplete parameter"); parameter_tree = proto_item_add_subtree(parameter_item, ett_m2tp_parameter); /* add tag and length to the m2tp tree */ proto_tree_add_uint(parameter_tree, hf_m2tp_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, tag); proto_tree_add_uint(parameter_tree, hf_m2tp_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, length); } switch(tag) { case INTERFACE_IDENTIFIER_PARAMETER_TAG: dissect_m2tp_interface_identifier_parameter(parameter_tvb, parameter_tree, parameter_item); break; case MASTER_SLAVE_INDICATOR_PARAMETER_TAG: dissect_m2tp_master_slave_parameter(parameter_tvb, parameter_tree, parameter_item); break; case M2TP_USER_IDENTIFIER_PARAMETER_TAG: dissect_m2tp_user_identifier_parameter(parameter_tvb, parameter_tree, parameter_item); break; case INFO_PARAMETER_TAG: dissect_m2tp_info_parameter(parameter_tvb, parameter_tree, parameter_item); break; case DIAGNOSTIC_INFORMATION_PARAMETER_TAG: dissect_m2tp_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item); break; case HEARTBEAT_DATA_PARAMETER_TAG: dissect_m2tp_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item); break; case REASON_PARAMETER_TAG: dissect_m2tp_reason_parameter(parameter_tvb, parameter_tree, parameter_item); break; case ERROR_CODE_PARAMETER_TAG: dissect_m2tp_error_code_parameter(parameter_tvb, parameter_tree, parameter_item); break; case PROTOCOL_DATA_PARAMETER_TAG: dissect_m2tp_protocol_data_parameter(parameter_tvb, parameter_tree, parameter_item, pinfo, m2tp_item, tree); break; default: dissect_m2tp_unknown_parameter(parameter_tvb, parameter_tree, parameter_item); break; }; if ((parameter_tree) && (padding_length > 0)) proto_tree_add_bytes(parameter_tree, hf_m2tp_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, tvb_get_ptr(parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length)); }
/*FUNCTION:------------------------------------------------------ * NAME * dissect_zbee_secure * DESCRIPTION * Dissects and decrypts secured ZigBee frames. * * Will return a valid tvbuff only if security processing was * successful. If processing fails, then this function will * handle internally and return NULL. * 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. * guint offset - pointer to the start of the auxiliary security header. * guint64 src64 - extended source address, or 0 if unknown. * RETURNS * tvbuff_t * *--------------------------------------------------------------- */ tvbuff_t * dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset) { proto_tree *sec_tree; zbee_security_packet packet; guint mic_len; gint payload_len; tvbuff_t *payload_tvb; #ifdef HAVE_LIBGCRYPT proto_item *ti; proto_item *key_item; guint8 *enc_buffer; guint8 *dec_buffer; gboolean decrypted; GSList **nwk_keyring; GSList *GSList_i; key_record_t *key_rec = NULL; #endif zbee_nwk_hints_t *nwk_hints; ieee802154_hints_t *ieee_hints; ieee802154_map_rec *map_rec = NULL; static const int * sec_flags[] = { &hf_zbee_sec_key_id, &hf_zbee_sec_nonce, NULL }; /* Init */ memset(&packet, 0, sizeof(zbee_security_packet)); /* Get pointers to any useful frame data from lower layers */ nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK), 0); ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0); /* Create a subtree for the security information. */ sec_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_zbee_sec, NULL, "ZigBee Security Header"); /* Get and display the Security control field */ packet.control = tvb_get_guint8(tvb, offset); /* Patch the security level. */ packet.control &= ~ZBEE_SEC_CONTROL_LEVEL; packet.control |= (ZBEE_SEC_CONTROL_LEVEL & gPREF_zbee_sec_level); /* * Eww, I think I just threw up a little... ZigBee requires this field * to be patched before computing the MIC, but we don't have write-access * to the tvbuff. So we need to allocate a copy of the whole thing just * so we can fix these 3 bits. Memory allocated by tvb_memdup(wmem_packet_scope(),...) * is automatically freed before the next packet is processed. */ #ifdef HAVE_LIBGCRYPT enc_buffer = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, tvb_captured_length(tvb)); /* * Override the const qualifiers and patch the security level field, we * know it is safe to overide the const qualifiers because we just * allocated this memory via tvb_memdup(wmem_packet_scope(),...). */ enc_buffer[offset] = packet.control; #endif /* HAVE_LIBGCRYPT */ packet.level = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL); packet.key_id = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY); packet.nonce = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_NONCE); proto_tree_add_bitmask(sec_tree, tvb, offset, hf_zbee_sec_field, ett_zbee_sec_control, sec_flags, ENC_NA); offset += 1; /* Get and display the frame counter field. */ packet.counter = tvb_get_letohl(tvb, offset); proto_tree_add_uint(sec_tree, hf_zbee_sec_counter, tvb, offset, 4, packet.counter); offset += 4; if (packet.nonce) { /* Get and display the source address of the device that secured this payload. */ packet.src64 = tvb_get_letoh64(tvb, offset); proto_tree_add_item(sec_tree, hf_zbee_sec_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN); #if 1 if (!pinfo->fd->flags.visited) { switch ( packet.key_id ) { case ZBEE_SEC_KEY_LINK: if (nwk_hints && ieee_hints) { /* Map this long address with the nwk layer short address. */ nwk_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, nwk_hints->src, ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->num); } break; case ZBEE_SEC_KEY_NWK: if (ieee_hints) { /* Map this long address with the ieee short address. */ ieee_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, ieee_hints->src16, ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->num); } break; /* We ignore the extended source addresses used to encrypt payloads with these * types of keys, because they can emerge from APS tunnels created by nodes whose * short address is not recorded in the packet. */ case ZBEE_SEC_KEY_TRANSPORT: case ZBEE_SEC_KEY_LOAD: break; } } #endif offset += 8; } else { /* Look for a source address in hints */ switch ( packet.key_id ) { case ZBEE_SEC_KEY_NWK: /* use the ieee extended source address for NWK decryption */ if ( ieee_hints && (map_rec = ieee_hints->map_rec) ) packet.src64 = map_rec->addr64; else proto_tree_add_expert(sec_tree, pinfo, &ei_zbee_sec_extended_source_unknown, tvb, 0, 0); break; default: /* use the nwk extended source address for APS decryption */ if ( nwk_hints && (map_rec = nwk_hints->map_rec) ) packet.src64 = map_rec->addr64; else proto_tree_add_expert(sec_tree, pinfo, &ei_zbee_sec_extended_source_unknown, tvb, 0, 0); break; } } if (packet.key_id == ZBEE_SEC_KEY_NWK) { /* Get and display the key sequence number. */ packet.key_seqno = tvb_get_guint8(tvb, offset); proto_tree_add_uint(sec_tree, hf_zbee_sec_key_seqno, tvb, offset, 1, packet.key_seqno); offset += 1; } /* Determine the length of the MIC. */ switch (packet.level) { case ZBEE_SEC_ENC: case ZBEE_SEC_NONE: default: mic_len=0; break; case ZBEE_SEC_ENC_MIC32: case ZBEE_SEC_MIC32: mic_len=4; break; case ZBEE_SEC_ENC_MIC64: case ZBEE_SEC_MIC64: mic_len=8; break; case ZBEE_SEC_ENC_MIC128: case ZBEE_SEC_MIC128: mic_len=16; break; } /* switch */ /* Get and display the MIC. */ if (mic_len) { /* Display the MIC. */ proto_tree_add_item(sec_tree, hf_zbee_sec_mic, tvb, (gint)(tvb_captured_length(tvb)-mic_len), mic_len, ENC_NA); } /* Check for null payload. */ payload_len = tvb_reported_length_remaining(tvb, offset+mic_len); if (payload_len == 0) return NULL; /********************************************** * Perform Security Operations on the Frame * ********************************************** */ if ((packet.level == ZBEE_SEC_NONE) || (packet.level == ZBEE_SEC_MIC32) || (packet.level == ZBEE_SEC_MIC64) || (packet.level == ZBEE_SEC_MIC128)) { /* Payload is only integrity protected. Just return the sub-tvbuff. */ return tvb_new_subset_length(tvb, offset, payload_len); } #ifdef HAVE_LIBGCRYPT /* Have we captured all the payload? */ if (tvb_captured_length_remaining(tvb, offset+mic_len) < payload_len) { /* * No - don't try to decrypt it. * * XXX - it looks as if the decryption code is assuming we have the * MIC, which won't be the case if the packet was cut short. Is * that in fact that case, or can we still make this work with a * partially-captured packet? */ /* Add expert info. */ expert_add_info(pinfo, sec_tree, &ei_zbee_sec_encrypted_payload_sliced); /* Create a buffer for the undecrypted payload. */ payload_tvb = tvb_new_subset_length(tvb, offset, payload_len); /* Dump the payload to the data dissector. */ call_data_dissector(payload_tvb, pinfo, tree); /* Couldn't decrypt, so return NULL. */ return NULL; } /* Allocate memory to decrypt the payload into. */ dec_buffer = (guint8 *)g_malloc(payload_len); decrypted = FALSE; if ( packet.src64 ) { if (pinfo->fd->flags.visited) { if ( nwk_hints ) { /* Use previously found key */ switch ( packet.key_id ) { case ZBEE_SEC_KEY_NWK: if ( (key_rec = nwk_hints->nwk) ) { decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, payload_len, mic_len, nwk_hints->nwk->key); } break; default: if ( (key_rec = nwk_hints->link) ) { decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, payload_len, mic_len, nwk_hints->link->key); } break; } } } /* ( !pinfo->fd->flags.visited ) */ else { /* We only search for sniffed keys in the first pass, * to save time, and because decrypting with keys * transported in future packets is cheating */ /* Lookup NWK and link key in hash for this pan. */ /* This overkill approach is a placeholder for a hash that looks up * a key ring for a link key associated with a pair of devices. */ if ( nwk_hints ) { nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &nwk_hints->src_pan); if ( nwk_keyring ) { GSList_i = *nwk_keyring; while ( GSList_i && !decrypted ) { decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key); if (decrypted) { /* save pointer to the successful key record */ switch (packet.key_id) { case ZBEE_SEC_KEY_NWK: key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data); break; default: key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data); break; } } else { GSList_i = g_slist_next(GSList_i); } } } /* Loop through user's password table for preconfigured keys, our last resort */ GSList_i = zbee_pc_keyring; while ( GSList_i && !decrypted ) { decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer, payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key); if (decrypted) { /* save pointer to the successful key record */ switch (packet.key_id) { case ZBEE_SEC_KEY_NWK: key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data); break; default: key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data); break; } } else { GSList_i = g_slist_next(GSList_i); } } } } /* ( ! pinfo->fd->flags.visited ) */ } /* ( packet.src64 ) */ if ( decrypted ) { if ( tree && key_rec ) { key_item = proto_tree_add_bytes(sec_tree, hf_zbee_sec_key, tvb, 0, ZBEE_SEC_CONST_KEYSIZE, key_rec->key); PROTO_ITEM_SET_GENERATED(key_item); if ( key_rec->frame_num == ZBEE_SEC_PC_KEY ) { ti = proto_tree_add_string(sec_tree, hf_zbee_sec_decryption_key, tvb, 0, 0, key_rec->label); } else { ti = proto_tree_add_uint(sec_tree, hf_zbee_sec_key_origin, tvb, 0, 0, key_rec->frame_num); } PROTO_ITEM_SET_GENERATED(ti); } /* Found a key that worked, setup the new tvbuff_t and return */ payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len); tvb_set_free_cb(payload_tvb, g_free); /* set up callback to free dec_buffer */ add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload"); /* Done! */ return payload_tvb; } g_free(dec_buffer); #endif /* HAVE_LIBGCRYPT */ /* Add expert info. */ expert_add_info(pinfo, sec_tree, &ei_zbee_sec_encrypted_payload); /* Create a buffer for the undecrypted payload. */ payload_tvb = tvb_new_subset_length(tvb, offset, payload_len); /* Dump the payload to the data dissector. */ call_data_dissector(payload_tvb, pinfo, tree); /* Couldn't decrypt, so return NULL. */ return NULL; } /* dissect_zbee_secure */
/*FUNCTION:------------------------------------------------------ * NAME * dissect_zbee_secure * DESCRIPTION * Dissects and decrypts secured ZigBee frames. * * Will return a valid tvbuff only if security processing was * successful. If processing fails, then this function will * handle internally and return NULL. * PARAMETERS * tvbuff_t *tvb - pointer to buffer containing raw packet. * packet_into *pinfo - pointer to packet information fields * proto_tree *tree - pointer to data tree Wireshark uses to display packet. * guint offset - pointer to the start of the auxilliary security header. * guint64 src - extended source address, or 0 if unknown. * RETURNS * tvbuff_t * *--------------------------------------------------------------- */ tvbuff_t * dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset, guint64 src) { proto_tree * sec_tree = NULL; proto_item * sec_root; proto_tree * field_tree; proto_item * ti; zbee_security_packet packet; guint mic_len; guint payload_len; tvbuff_t * payload_tvb; #ifdef HAVE_LIBGCRYPT const guint8 * enc_buffer; guint8 * dec_buffer; guint8 * key_buffer; guint8 nonce[ZBEE_SEC_CONST_NONCE_LEN]; #endif /* Create a substree for the security information. */ if (tree) { sec_root = proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "ZigBee Security Header"); sec_tree = proto_item_add_subtree(sec_root, ett_zbee_sec); } /* Get and display the Security control field */ packet.control = tvb_get_guint8(tvb, offset); /* Patch the security level. */ packet.control &= ~ZBEE_SEC_CONTROL_LEVEL; packet.control |= (ZBEE_SEC_CONTROL_LEVEL & gPREF_zbee_sec_level); /* * Eww, I think I just threw up a little... ZigBee requires this field * to be patched before computing the MIC, but we don't have write-access * to the tvbuff. So we need to allocate a copy of the whole thing just * so we can fix these 3 bits. */ #ifdef HAVE_LIBGCRYPT enc_buffer = ep_tvb_memdup(tvb, 0, tvb_length(tvb)); /* * Override the const qualifiers and patch the security level field, we * know it is safe to overide the const qualifiers because we just * allocated this memory via ep_tvb_memdup(). */ ((guint8 *)(enc_buffer))[offset] = packet.control; #endif /* HAVE_LIBGCRYPT */ packet.level = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL); packet.key = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY); packet.nonce = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_NONCE); if (tree) { ti = proto_tree_add_text(sec_tree, tvb, offset, sizeof(guint8), "Security Control Field"); field_tree = proto_item_add_subtree(ti, ett_zbee_sec_control); proto_tree_add_uint(field_tree, hf_zbee_sec_key, tvb, offset, sizeof(guint8), packet.control & ZBEE_SEC_CONTROL_KEY); proto_tree_add_boolean(field_tree, hf_zbee_sec_nonce, tvb, offset, sizeof(guint8), packet.control & ZBEE_SEC_CONTROL_NONCE); } offset += sizeof(guint8); /* Get and display the frame counter field. */ packet.counter = tvb_get_letohl(tvb, offset); if (tree) { proto_tree_add_uint(sec_tree, hf_zbee_sec_counter, tvb, offset, sizeof(guint32), packet.counter); } offset += sizeof(guint32); if (packet.nonce) { /* Get and display the source address. */ packet.src = tvb_get_letoh64(tvb, offset); if (tree) { proto_tree_add_eui64(sec_tree, hf_zbee_sec_src, tvb, offset, sizeof(guint64), packet.src); } offset += sizeof(guint64); } else { /* This field is required in the security decryption process, so * fill it in in case the higher layer provided it. */ packet.src = src; } if (packet.key == ZBEE_SEC_KEY_NWK) { /* Get and display the key sequence number. */ packet.key_seqno = tvb_get_guint8(tvb, offset); if (tree) { proto_tree_add_uint(sec_tree, hf_zbee_sec_key_seqno, tvb, offset, sizeof(guint8), packet.key_seqno); } offset += sizeof(guint8); } /* Determine the length of the MIC. */ switch (packet.level){ case ZBEE_SEC_ENC: case ZBEE_SEC_NONE: default: mic_len=0; break; case ZBEE_SEC_ENC_MIC32: case ZBEE_SEC_MIC32: mic_len=4; break; case ZBEE_SEC_ENC_MIC64: case ZBEE_SEC_MIC64: mic_len=8; break; case ZBEE_SEC_ENC_MIC128: case ZBEE_SEC_MIC128: mic_len=16; break; } /* switch */ /* Ensure that the payload exists (length >= 1) for this length. */ payload_len = tvb_ensure_length_remaining(tvb, offset+mic_len+1)+1; /* Get and display the MIC. */ if (mic_len) { /* Display the MIC. */ if (tree) { ti = proto_tree_add_bytes(sec_tree, hf_zbee_sec_mic, tvb, tvb_length(tvb)-mic_len, mic_len, ep_tvb_memdup(tvb, tvb_length(tvb)-mic_len, mic_len)); } } /********************************************** * Perform Security Operations on the Frame * ********************************************** */ if ((packet.level == ZBEE_SEC_NONE) || (packet.level == ZBEE_SEC_MIC32) || (packet.level == ZBEE_SEC_MIC64) || (packet.level == ZBEE_SEC_MIC128)) { /* Payload is only integrity protected. Just return the sub-tvbuff. */ return tvb_new_subset(tvb, offset, payload_len, payload_len); } #ifdef HAVE_LIBGCRYPT /* Ensure we have enough security material to decrypt this payload. */ switch (packet.key) { /* Network Keys use the shared network key. */ case ZBEE_SEC_KEY_NWK: if (!zbee_sec_have_nwk_key) { /* Without a key we can't decrypt (if we could what good would security be?)*/ goto decrypt_failed; } if (packet.src == 0) { /* Without the extended source address, we can't create the nonce. */ goto decrypt_failed; } /* The key, is the network key. */ key_buffer = zbee_sec_nwk_key; break; /* Link Key might use the trust center link key. */ case ZBEE_SEC_KEY_LINK: if (!zbee_sec_have_tclink_key) { /* Without a key we can't decrypt. */ goto decrypt_failed; } if ((packet.src == 0) && (zbee_sec_tcaddr == 0)){ /* Without the extended source address, we can't create the nonce. */ goto decrypt_failed; } else if (packet.src == 0) { packet.src = zbee_sec_tcaddr; } key_buffer = zbee_sec_tclink_key; break; /* Key-Transport Key should use the trust center link key. */ case ZBEE_SEC_KEY_TRANSPORT: if (!zbee_sec_have_tclink_key) { /* Without a key we can't decrypt. */ goto decrypt_failed; } if ((packet.src == 0) && (zbee_sec_tcaddr == 0)){ /* Without the extended source address, we can't create the nonce. */ goto decrypt_failed; } else if (packet.src == 0) { packet.src = zbee_sec_tcaddr; } key_buffer = zbee_sec_key_hash(zbee_sec_tclink_key, 0x00, pinfo); break; /* Key-Load Key should use the trust center link key. */ case ZBEE_SEC_KEY_LOAD: if (!zbee_sec_have_tclink_key) { /* Without a key we can't decrypt. */ goto decrypt_failed; } if ((packet.src == 0) && (zbee_sec_tcaddr == 0)){ /* Without the extended source address, we can't create the nonce. */ goto decrypt_failed; } else if (packet.src == 0) { packet.src = zbee_sec_tcaddr; } key_buffer = zbee_sec_key_hash(zbee_sec_tclink_key, 0x02, pinfo); break; default: goto decrypt_failed; } /* switch */ /* Create the nonce. */ zbee_sec_make_nonce(nonce, &packet); /* Allocate memory to decrypt the payload into. */ dec_buffer = g_malloc(payload_len); /* Perform Decryption. */ if (!zbee_sec_ccm_decrypt(key_buffer, /* key */ nonce, /* Nonce */ enc_buffer, /* a, length l(a) */ enc_buffer+offset, /* c, length l(c) = l(m) + M */ dec_buffer, /* m, length l(m) */ offset, /* l(a) */ payload_len, /* l(m) */ mic_len)) { /* M */ /* Decryption Failed! */ g_free(dec_buffer); goto decrypt_failed; } /* Setup the new tvbuff_t and return */ payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len); add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload"); /* Done! */ return payload_tvb; decrypt_failed: #endif /* HAVE_LIBGCRYPT */ /* Add expert info. */ expert_add_info_format(pinfo, sec_tree, PI_UNDECODED, PI_WARN, "Encrypted Payload"); /* Create a buffer for the undecrypted payload. */ payload_tvb = tvb_new_subset(tvb, offset, payload_len, -1); /* Dump the payload to the data dissector. */ call_dissector(data_handle, payload_tvb, pinfo, tree); /* Couldn't decrypt, so return NULL. */ return NULL; } /* dissect_zbee_secure */
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; /* * 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++); switch (tag) { case TZSP_HDR_PAD: length = 0; break; case TZSP_HDR_END: /* Fill in header with information from other tags. */ if (seen_fcs_err) { if (tree) proto_item_append_text(ti,"%s", fcs_err?"FCS Error":(encr?"Encrypted":"Good")); } return pos; case TZSP_HDR_ORIGINAL_LENGTH: length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_int (tree, hf_original_length, tvb, pos-2, 4, tvb_get_ntohs(tvb, pos)); pos += length; break; case WLAN_RADIO_HDR_SIGNAL: length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_int (tree, hf_signal, tvb, pos-2, 3, (char)tvb_get_guint8(tvb, pos)); pos += length; break; case WLAN_RADIO_HDR_NOISE: length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_int (tree, hf_silence, tvb, pos-2, 3, (char)tvb_get_guint8(tvb, pos)); pos += length; break; case WLAN_RADIO_HDR_RATE: length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_uint (tree, hf_rate, tvb, pos-2, 3, tvb_get_guint8(tvb, pos)); pos += length; break; case WLAN_RADIO_HDR_TIMESTAMP: length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_uint (tree, hf_time, tvb, pos-2, 6, tvb_get_ntohl(tvb, pos)); pos += length; break; case WLAN_RADIO_HDR_MSG_TYPE: length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_uint (tree, hf_status_msg_type, tvb, pos-2, 3, tvb_get_guint8(tvb, pos)); pos += length; break; case WLAN_RADIO_HDR_CF: length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_boolean (tree, hf_status_pcf, tvb, pos-2, 3, tvb_get_guint8(tvb, pos)); pos += length; break; case WLAN_RADIO_HDR_UN_DECR: length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_boolean (tree, hf_status_undecrypted, tvb, pos-2, 3, tvb_get_guint8(tvb, pos)); encr = tvb_get_guint8(tvb, pos); pos += length; break; case WLAN_RADIO_HDR_FCS_ERR: seen_fcs_err = 1; length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_boolean (tree, hf_status_fcs_error, tvb, pos-2, 3, tvb_get_guint8(tvb, pos)); fcs_err = tvb_get_guint8(tvb, pos); pos += length; break; case WLAN_RADIO_HDR_CHANNEL: length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_uint (tree, hf_channel, tvb, pos-2, 3, tvb_get_guint8(tvb, pos)); pos += length; break; case TZSP_HDR_SENSOR: length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_ether(tree, hf_sensormac, tvb, pos-2, 6, tvb_get_ptr (tvb, pos, 6)); pos += length; break; default: length = tvb_get_guint8(tvb, pos++); if (tree) proto_tree_add_bytes(tree, hf_unknown, tvb, pos-2, length+2, tvb_get_ptr(tvb, pos, length)); pos += length; break; } } }
/* Header */ static void dissect_cpfi_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint32 word1; #if 0 guint32 word2; #endif guint32 tda; guint32 src; guint8 src_instance = 0; guint8 src_board = 0; guint8 src_port = 0; guint32 dst; guint8 dst_instance = 0; guint8 dst_board = 0; guint8 dst_port = 0; proto_tree *extra_tree = NULL; /* add a tree for the header */ if ( tree != NULL) { proto_item *extra_item; extra_item = proto_tree_add_protocol_format(tree, proto_cpfi, tvb, 0, -1, "Header"); extra_tree = proto_item_add_subtree(extra_item, ett_cpfi_header); } /* Extract the common header, and get the bits we need */ word1 = tvb_get_ntohl (tvb, 0); #if 0 word2 = tvb_get_ntohl (tvb, sizeof(word1)); #endif /* Figure out where the frame came from. dstTDA is source of frame! */ tda = (word1 & CPFI_DEST_MASK) >> CPFI_DEST_SHIFT; if ( tda >= FIRST_TIO_CARD_ADDRESS ) { g_strlcpy(src_str, " CPFI", sizeof(src_str)); src = 0; /* Make it smallest */ } else { const guint8 *srcmac; /* Make sure this is an Ethernet address. */ DISSECTOR_ASSERT(pinfo->src.type == AT_ETHER); srcmac = (const guint8 *)pinfo->src.data; src_instance = srcmac[2]-1; src_board = tda >> 4; src_port = tda & 0x0f; src = (1 << 24) + (src_instance << 16) + (src_board << 8) + src_port; g_snprintf(src_str, sizeof(src_str), "%u.%u.%u", src_instance, src_board, src_port); } /* Figure out where the frame is going. srcTDA is destination of frame! */ tda = (word1 & CPFI_SOURCE_MASK) >> CPFI_SOURCE_SHIFT; if ( tda >= FIRST_TIO_CARD_ADDRESS ) { g_strlcpy(dst_str, " CPFI", sizeof(dst_str)); dst = 0; /* Make it smallest */ } else { const guint8 *dstmac; /* Make sure this is an Ethernet address. */ DISSECTOR_ASSERT(pinfo->dst.type == AT_ETHER); dstmac = (const guint8 *)pinfo->dst.data; dst_instance = dstmac[2]-1; dst_board = tda >> 4; dst_port = tda & 0x0f; dst = (1 << 24) + (dst_instance << 16) + (dst_board << 8) + dst_port; g_snprintf(dst_str, sizeof(dst_str), "%u.%u.%u", dst_instance, dst_board, dst_port); } /* Set up the source and destination and arrow per user configuration. */ if ( cpfi_arrow_moves && (dst < src) ) { left = dst_str; arrow = r_to_l_arrow; right = src_str; } else { left = src_str; arrow = l_to_r_arrow; right = dst_str; } if (extra_tree) { proto_item *hidden_item; /* For "real" TDAs (i.e. not for microTDAs), add hidden addresses to allow filtering */ if ( src != 0 ) { hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_instance, tvb, 0, 1, &src_instance); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_src_instance, tvb, 0, 1, &src_instance); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_board, tvb, 0, 1, &src_board); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_src_board, tvb, 0, 1, &src_board); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_port, tvb, 0, 1, &src_port); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_src_port, tvb, 0, 1, &src_port); PROTO_ITEM_SET_HIDDEN(hidden_item); } if ( dst != 0 ) { hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_instance, tvb, 0, 1, &dst_instance); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_dst_instance, tvb, 0, 1, &dst_instance); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_board, tvb, 0, 1, &dst_board); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_dst_board, tvb, 0, 1, &dst_board); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_port, tvb, 0, 1, &dst_port); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_dst_port, tvb, 0, 1, &dst_port); PROTO_ITEM_SET_HIDDEN(hidden_item); } /* add word 1 components to the protocol tree */ proto_tree_add_item(extra_tree, hf_cpfi_word_one , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_frame_type, tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_source , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_dest , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_SOF_type , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_speed , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_OPM_error , tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(extra_tree, hf_cpfi_from_LCM , tvb, 0, 4, ENC_BIG_ENDIAN); /* add word 2 components to the protocol tree */ proto_tree_add_item(extra_tree, hf_cpfi_word_two , tvb, 4, 4, ENC_BIG_ENDIAN); }; }
static int dissect_pbb_addressblock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint maxoffset, guint8 addressType, guint8 addressSize) { guint8 addr[MAX_ADDR_SIZE]; guint8 numAddr; guint8 address_flags; guint8 head_length = 0, tail_length = 0; guint block_length = 0, midSize = 0; guint block_index = 0, head_index = 0, tail_index = 0, mid_index = 0, prefix_index = 0; proto_tree *addr_tree = NULL; proto_tree *addrFlags_tree = NULL; proto_tree *addrValue_tree = NULL; proto_item *addr_item = NULL; proto_item *addrFlags_item = NULL; proto_item *addrValue_item = NULL; int i = 0; if (maxoffset - offset < 2) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for minimal addressblock header"); return tvb_reported_length(tvb); } DISSECTOR_ASSERT(addressSize <= MAX_ADDR_SIZE); memset(addr, 0, addressSize); block_length = 2; block_index = offset; midSize = addressSize; numAddr = tvb_get_guint8(tvb, offset++); address_flags = tvb_get_guint8(tvb, offset++); if ((address_flags & ADDR_HASHEAD) != 0) { head_index = offset; if (maxoffset - offset <= 0) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock head"); return tvb_reported_length(tvb); } head_length = tvb_get_guint8(tvb, offset++); if (head_length > addressSize-1) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "address head length is too long"); return tvb_reported_length(tvb); } if (maxoffset - offset < head_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock head"); return tvb_reported_length(tvb); } tvb_memcpy(tvb, addr, offset, head_length); midSize -= head_length; block_length += (head_length+1); offset += head_length; } if ((address_flags & ADDR_HASZEROTAIL) != 0) { tail_index = offset; if (maxoffset - offset <= 0) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock tail"); return tvb_reported_length(tvb); } tail_length = tvb_get_guint8(tvb, offset++); if (tail_length > addressSize-1-head_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "address tail length is too long"); return tvb_reported_length(tvb); } midSize -= tail_length; block_length++; } else if ((address_flags & ADDR_HASFULLTAIL) != 0) { tail_index = offset; if (maxoffset - offset <= 0) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock tail"); return tvb_reported_length(tvb); } tail_length = tvb_get_guint8(tvb, offset++); if (tail_length > addressSize-1-head_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "address tail length is too long"); return tvb_reported_length(tvb); } if (maxoffset - offset < tail_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for addressblock tail"); return tvb_reported_length(tvb); } tvb_memcpy(tvb, &addr[addressSize - tail_length], offset, tail_length); midSize -= tail_length; block_length += (tail_length+1); offset += tail_length; } mid_index = offset; block_length += numAddr * midSize; offset += numAddr * midSize; if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) { prefix_index = offset; block_length++; } else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) { prefix_index = offset; block_length += numAddr; } if (maxoffset < block_index + block_length) { proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset, "Not enough octets for address block"); return maxoffset; } /* add address tree */ addr_item = proto_tree_add_item(tree, hf_packetbb_addr, tvb, block_index, block_length, ENC_NA); addr_tree = proto_item_add_subtree(addr_item, ett_packetbb_addr); proto_item_append_text(addr_item, " (%d addresses)", numAddr); /* add num-addr */ proto_tree_add_item(addr_tree, hf_packetbb_addr_num, tvb, block_index, 1, ENC_BIG_ENDIAN); /* add flags */ addrFlags_item = proto_tree_add_item(addr_tree, hf_packetbb_addr_flags, tvb, block_index+1, 1, ENC_BIG_ENDIAN); addrFlags_tree = proto_item_add_subtree(addrFlags_item, ett_packetbb_addr_flags); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hashead, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasfulltail, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_haszerotail, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hassingleprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasmultiprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN); if ((address_flags & ADDR_HASHEAD) != 0) { /* add head */ proto_tree_add_item(addr_tree, hf_packetbb_addr_head, tvb, head_index, head_length+1, ENC_NA); } if ((address_flags & ADDR_HASFULLTAIL) != 0) { /* add full tail */ proto_tree_add_item(addr_tree, hf_packetbb_addr_tail, tvb, tail_index, tail_length+1, ENC_NA); } else if ((address_flags & ADDR_HASZEROTAIL) != 0) { /* add zero tail */ proto_tree_add_item(addr_tree, hf_packetbb_addr_tail, tvb, tail_index, 1, ENC_NA); } for (i=0; i<numAddr; i++) { guint32 ipv4 = 0; guint8 prefix = addressSize * 8; tvb_memcpy(tvb, &addr[head_length], mid_index + midSize*i, midSize); ipv4 = (addr[3] << 24) + (addr[2] << 16) + (addr[1] << 8) + addr[0]; switch (addressType) { case 0: addrValue_item = proto_tree_add_ipv4(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, ipv4); break; case 1: addrValue_item = proto_tree_add_ipv6(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, (struct e_in6_addr *)addr); break; case 2: addrValue_item = proto_tree_add_ether(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, addr); break; case 3: addrValue_item = proto_tree_add_bytes(addr_tree, hf_packetbb_addr_value[addressType], tvb, mid_index, block_index + block_length - mid_index, addr); break; default: break; } addrValue_tree = proto_item_add_subtree(addrValue_item, ett_packetbb_addr_value); proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_mid, tvb, mid_index + midSize*i, midSize, ENC_NA); if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) { prefix = tvb_get_guint8(tvb, prefix_index); proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index, 1, ENC_BIG_ENDIAN); } else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) { prefix = tvb_get_guint8(tvb, prefix_index + i); proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index + i, 1, ENC_BIG_ENDIAN); } proto_item_append_text(addrValue_item, "/%d", prefix); } offset = dissect_pbb_tlvblock(tvb, pinfo, addr_tree, block_index + block_length, maxoffset, numAddr); return offset; }
static void dissect_asterix_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree* asterix_tree[5]; int tree_depth = 0; proto_item* t_head_item; proto_item* t_item = NULL; static fulliautomatix_data* pDataList = NULL; fulliautomatix_data* pData = NULL; guint32 offset = 0; guint8 category; guint32 payload_len; char tmpstr[256]; char tmp2[64]; int error=0; tmpstr[0] = 0; while(offset < tvb_length(tvb) && strlen(tmpstr)<200) { category = tvb_get_guint8(tvb,offset); offset+=1; payload_len = tvb_get_ntohs(tvb,offset); offset+=2; offset += payload_len-3; sprintf(tmp2,"CAT%03d (%-3d bytes),", category, payload_len); strcat(tmpstr, tmp2); } if (offset != tvb_length(tvb)) { sprintf(tmp2, "Total= %d bytes - Wrong length !!!! ", offset); } else { sprintf(tmp2, "Total = %d bytes", offset); } strcat(tmpstr, tmp2); if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "Asterix"); if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, tmpstr); if(!tree) return; t_head_item = proto_tree_add_protocol_format(tree, proto_asterix, tvb, 0, -1, "All Purpose Structured Eurocontrol Surveillance Information Exhange (Asterix) Protocol"); asterix_tree[tree_depth] = proto_item_add_subtree(t_head_item, ett_asterix[tree_depth]); pDataList = fulliautomatix_parse(tvb_get_ptr(tvb,0,tvb_length(tvb)), tvb_length(tvb)); pData = pDataList; while(pData) { if (pData->tree == 1) { t_item = proto_tree_add_text(asterix_tree[tree_depth], tvb, pData->bytenr, pData->length, pData->description); if (tree_depth < MAX_TREE_DEPTH-1) { tree_depth++; } asterix_tree[tree_depth] = proto_item_add_subtree(t_item, ett_asterix[tree_depth]); } else if (pData->tree == -1) { if (tree_depth > 0) { tree_depth--; } } else { if (pData->pid < 0 || pData->pid > maxpid) { logTraceFunc("Wrong PID.\n"); } else if (pData->type == FT_STRINGZ) { t_item = proto_tree_add_string(asterix_tree[tree_depth], def_pid[pData->pid], tvb, pData->bytenr, pData->length, pData->val.str); } else if (pData->type == FT_UINT32) { t_item = proto_tree_add_uint(asterix_tree[tree_depth], def_pid[pData->pid], tvb, pData->bytenr, pData->length, pData->val.ul); } else if (pData->type == FT_INT32) { t_item = proto_tree_add_int(asterix_tree[tree_depth], def_pid[pData->pid], tvb, pData->bytenr, pData->length, pData->val.sl); } else if (pData->type == FT_BYTES) { t_item = proto_tree_add_bytes(asterix_tree[tree_depth], def_pid[pData->pid], tvb, pData->bytenr, pData->length, pData->val.str); } else if (pData->type == FT_NONE) { t_item = proto_tree_add_text(asterix_tree[tree_depth], tvb, pData->bytenr, pData->length, pData->val.str); } //TODO add other types } if (pData->value_description) { proto_item_append_text(t_item, pData->value_description); } if (pData->err == 1) { proto_item_set_expert_flags(t_item, PI_GROUP_MASK, PI_WARN); expert_add_info_format(pinfo, t_item, PI_UNDECODED, PI_WARN, "Warning in Asterix message"); if (error==0) error=1; } else if (pData->err == 2) { proto_item_set_expert_flags(t_item, PI_REASSEMBLE, PI_ERROR); expert_add_info_format(pinfo, t_item, PI_MALFORMED, PI_ERROR, "Error in Asterix message"); if (error<2) error=2; } pData = pData->next; } if (error == 1) { proto_item_set_expert_flags(t_head_item, PI_GROUP_MASK, PI_WARN); } else if (error == 2) { proto_item_set_expert_flags(t_head_item, PI_REASSEMBLE, PI_ERROR); } fulliautomatix_data_destroy(pDataList); }