/* ================================================================= */ static void dissect_serialization(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *ser_tree = NULL; proto_item *ti; col_set_str(pinfo->cinfo, COL_PROTOCOL, "NW_SERIAL"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { ti = proto_tree_add_item(tree, proto_serialization, tvb, 0, -1, ENC_NA); ser_tree = proto_item_add_subtree(ti, ett_serialization); } if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "Serial number %s", tvb_bytes_to_str(tvb, 0, 6)); } if (tree) { proto_tree_add_text(ser_tree, tvb, 0, 6, "Serial number: %s", tvb_bytes_to_str(tvb, 0, 6)); } }
static int dissect_bencoded_string(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, guint offset, char **result, gboolean tohex, char *label ) { guint string_len_start; guint string_len; string_len_start = offset; while( tvb_get_guint8(tvb,offset) != ':' ) offset += 1; string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) ); /* skip the ':' */ offset += 1; /* fill the return data */ if( tohex ) *result = tvb_bytes_to_str(tvb, offset, string_len ); else *result = tvb_get_ephemeral_string( tvb, offset, string_len ); proto_tree_add_string_format( tree, hf_bencoded_string, tvb, offset, string_len, *result, "%s: %s", label, *result ); offset += string_len; return offset; }
static void add_octetstring_value(const gchar *tag_desc, proto_tree *tree, tvbuff_t *tvb, int offset, int name_length, int value_length) { offset = add_value_head(tag_desc, tree, tvb, offset, name_length, value_length, NULL); proto_tree_add_text(tree, tvb, offset, value_length, "Value: %s", tvb_bytes_to_str(tvb, offset, value_length)); }
static gchar * tvb_aarpproaddr_to_str(tvbuff_t *tvb, gint offset, int ad_len, guint16 type) { if (AARP_PRO_IS_ATALK(type, ad_len)) { /* Appletalk address. */ return tvb_atalkid_to_str(tvb, offset); } return tvb_bytes_to_str(tvb, offset, ad_len); }
static gint dissect_om2k_attr_unkn(tvbuff_t *tvb, gint offset, gint len, gint iei, proto_tree *tree) { proto_tree_add_bytes_format(tree, hf_om2k_unknown_val, tvb, offset, len, NULL, "%s: %s", val_to_str_ext(iei, &om2k_attr_vals_ext, "0x%02x"), tvb_bytes_to_str(wmem_packet_scope(), tvb, offset, len)); return len; }
static const gchar * tvb_aarphrdaddr_to_str(tvbuff_t *tvb, gint offset, int ad_len, guint16 type) { if (AARP_HW_IS_ETHER(type, ad_len)) { /* Ethernet address (or Token Ring address, which is the same type of address). */ return tvb_ether_to_str(tvb, offset); } return tvb_bytes_to_str(tvb, offset, ad_len); }
static int dissect_bt_dht_nodes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char **result, char *label ) { proto_item *ti; proto_tree *sub_tree; proto_item *node_ti; proto_tree *node_tree; guint node_index; guint string_len_start; guint string_len; address addr; guint16 port; guint8 *id; ti = proto_tree_add_item( tree, hf_bt_dht_nodes, tvb, offset, 0, ENC_NA ); sub_tree = proto_item_add_subtree( ti, ett_bt_dht_nodes); node_index = 0; string_len_start = offset; while( tvb_get_guint8(tvb,offset) != ':' ) offset += 1; string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) ); /* skip the ':' */ offset += 1; /* 20 bytes id, 4 bytes ip, 2 bytes port */ for( ; string_len>=26; string_len-=26, offset+=26 ) { node_index += 1; id = tvb_bytes_to_str(tvb, offset, 20 ); SET_ADDRESS( &addr, AT_IPv4, 4, tvb_get_ptr( tvb, offset, 4) ); port = tvb_get_letohl( tvb, offset+24 ); node_ti = proto_tree_add_none_format( sub_tree, hf_bt_dht_node, tvb, offset, 26, "%d\t%s %s:%u", node_index, id, ep_address_to_str( &addr ), port ); node_tree = proto_item_add_subtree( node_ti, ett_bt_dht_peers); proto_tree_add_item( node_tree, hf_bt_dht_id, tvb, offset, 20, ENC_NA); proto_tree_add_item( node_tree, hf_ip, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item( node_tree, hf_port, tvb, offset+24, 2, ENC_BIG_ENDIAN); } if( string_len>0 ) { proto_tree_add_item( tree, hf_truncated_data, tvb, offset, string_len, ENC_NA ); offset += string_len; } proto_item_set_text( ti, "%s: %d nodes", label, node_index ); col_append_fstr( pinfo->cinfo, COL_INFO, "reply=%d nodes ", node_index ); *result = ep_strdup_printf("%d", node_index); return offset; }
/* Add a default subtree to a tree item */ void rmt_ext_decode_default_subtree(struct _ext *e, tvbuff_t *tvb, proto_item *ti, gint ett) { proto_tree *ext_tree; ext_tree = proto_item_add_subtree(ti, ett); rmt_ext_decode_default_header(e, tvb, ext_tree); if (ext_tree) proto_tree_add_text(ext_tree, tvb, e->hec_offset, e->hec_size, "Header Extension Content (HEC): %s", tvb_bytes_to_str(tvb, e->hec_offset, e->hec_size)); }
const gchar * tvb_arphrdaddr_to_str(tvbuff_t *tvb, gint offset, int ad_len, guint16 type) { if (ad_len == 0) return "<No address>"; if (ARP_HW_IS_ETHER(type, ad_len)) { /* Ethernet address (or IEEE 802.x address, which is the same type of address). */ return tvb_ether_to_str(tvb, offset); } return tvb_bytes_to_str(tvb, offset, ad_len); }
static proto_tree * add_octetstring_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int name_length, int value_length) { proto_item *ti; ti = proto_tree_add_text(tree, tvb, offset, 1 + 2 + name_length + 2 + value_length, "%s: %s", tvb_format_text(tvb, offset + 1 + 2, name_length), tvb_bytes_to_str(tvb, offset + 1 + 2 + name_length + 2, value_length)); return proto_item_add_subtree(ti, ett_ipp_attr); }
WSLUA_METAMETHOD Tvb__tostring(lua_State* L) { /* Convert the bytes of a `Tvb` into a string, to be used for debugging purposes, as '...' will be appended if the string is too long. */ Tvb tvb = checkTvb(L,1); int len = tvb_captured_length(tvb->ws_tvb); char* str = tvb_bytes_to_str(NULL,tvb->ws_tvb,0,len); lua_pushfstring(L, "TVB(%d) : %s", len, str); wmem_free(NULL, str); WSLUA_RETURN(1); /* The string. */ }
WSLUA_METAMETHOD TvbRange__tostring(lua_State* L) { /* Converts the TvbRange into a string. As the string gets truncated you should use this only for debugging purposes or if what you want is to have a truncated string in the format 67:89:AB:... */ TvbRange tvbr = checkTvbRange(L,1); if (!(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } lua_pushstring(L,tvb_bytes_to_str(tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len)); return 1; }
static int dissect_bencoded_string(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, guint offset, char **result, gboolean tohex, const char *label ) { guint string_len; string_len = bencoded_string_length(tvb, &offset); /* fill the return data */ if( tohex ) *result = tvb_bytes_to_str(tvb, offset, string_len ); else *result = tvb_get_string( wmem_packet_scope(), tvb, offset, string_len ); proto_tree_add_string_format( tree, hf_bencoded_string, tvb, offset, string_len, *result, "%s: %s", label, *result ); offset += string_len; return offset; }
WSLUA_METAMETHOD Tvb__tostring(lua_State* L) { /* Convert the bytes of a Tvb into a string, to be used for debugging purposes as '...' will be appended in case the string is too long. */ Tvb tvb = checkTvb(L,1); int len; gchar* str; if (!tvb) return 0; if (tvb->expired) { luaL_error(L,"expired tvb"); return 0; } len = tvb_length(tvb->ws_tvb); str = ep_strdup_printf("TVB(%i) : %s",len,tvb_bytes_to_str(tvb->ws_tvb,0,len)); lua_pushstring(L,str); WSLUA_RETURN(1); /* The string. */ }
static int dissect_bt_dht_nodes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char **result, const char *label ) { proto_item *ti; proto_tree *sub_tree; proto_item *node_ti; proto_tree *node_tree; guint node_index; guint string_len; string_len = bencoded_string_length(tvb, &offset); ti = proto_tree_add_item( tree, hf_bt_dht_nodes, tvb, offset, string_len, ENC_NA ); sub_tree = proto_item_add_subtree( ti, ett_bt_dht_nodes); node_index = 0; /* 20 bytes id, 4 bytes ip, 2 bytes port */ for( ; string_len>=26; string_len-=26, offset+=26 ) { node_index += 1; node_ti = proto_tree_add_item( sub_tree, hf_bt_dht_node, tvb, offset, 26, ENC_NA); proto_item_append_text(node_ti, " %d", node_index); node_tree = proto_item_add_subtree( node_ti, ett_bt_dht_peers); proto_tree_add_item( node_tree, hf_bt_dht_id, tvb, offset, 20, ENC_NA); proto_item_append_text(node_ti, " (id: %s", tvb_bytes_to_str(tvb, offset, 20)); proto_tree_add_item( node_tree, hf_ip, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_item_append_text(node_ti, ", IP/Port: %s", tvb_ip_to_str(tvb, offset+20)); proto_tree_add_item( node_tree, hf_port, tvb, offset+24, 2, ENC_BIG_ENDIAN); proto_item_append_text(node_ti, ":%u)", tvb_get_ntohs( tvb, offset+24 )); } if( string_len>0 ) { proto_tree_add_item( tree, hf_truncated_data, tvb, offset, string_len, ENC_NA ); offset += string_len; } proto_item_set_text( ti, "%s: %d nodes", label, node_index ); col_append_fstr( pinfo->cinfo, COL_INFO, "reply=%d nodes ", node_index ); *result = wmem_strdup_printf(wmem_packet_scope(), "%d", node_index); return offset; }
WSLUA_METAMETHOD TvbRange__tostring(lua_State* L) { /* Converts the `TvbRange` into a string. Since the string gets truncated, you should use this only for debugging purposes or if what you want is to have a truncated string in the format 67:89:AB:... */ TvbRange tvbr = checkTvbRange(L,1); char* str = NULL; if (!(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } str = tvb_bytes_to_str(NULL,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len); lua_pushstring(L,str); wmem_free(NULL, str); WSLUA_RETURN(1); /* A Lua hex string of the first 24 binary bytes in the `TvbRange`. */ }
static int add_session_id(proto_tree *tree, int hf, int hf_str, tvbuff_t *tvb, int offset) { guint count; guint i; guint64 session_id; header_field_info *hfinfo; count = tvb_get_guint8(tvb, offset); if (count == 0) proto_tree_add_string (tree, hf_str, tvb, offset, count+1, "NULL"); else if (count <= 8) { session_id = 0; for (i = 0; i < count; i++) session_id = (session_id << 8) | tvb_get_guint8(tvb, offset + i); proto_tree_add_uint64 (tree, hf, tvb, offset, count+1, session_id); } else { hfinfo = proto_registrar_get_nth(hf); proto_tree_add_text (tree, tvb, offset, count+1, "%s: %s", hfinfo->name, tvb_bytes_to_str(tvb, offset+1, count)); } return offset+1+count; }
/* * dissect_pgm - The dissector for Pragmatic General Multicast */ static void dissect_pgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 pgmhdr_sport; guint16 pgmhdr_dport; guint8 pgmhdr_type; guint8 pgmhdr_opts; guint16 pgmhdr_cksum; guint16 pgmhdr_tsdulen; guint32 sqn; guint16 afi; guint plen = 0; proto_item *ti; const char *pktname; const char *pollstname; char *gsi; gboolean isdata = FALSE; guint pgmlen, reportedlen; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PGM"); if (check_col(pinfo->cinfo, COL_INFO)) { col_clear(pinfo->cinfo, COL_INFO); if (tvb_reported_length_remaining(tvb, 0) < 18) { col_set_str(pinfo->cinfo, COL_INFO, "Packet too small"); return; } } pinfo->srcport = pgmhdr_sport = tvb_get_ntohs(tvb, 0); pinfo->destport = pgmhdr_dport = tvb_get_ntohs(tvb, 2); pgmhdr_type = tvb_get_guint8(tvb, 4); pktname = val_to_str(pgmhdr_type, type_vals, "Unknown (0x%02x)"); pgmhdr_opts = tvb_get_guint8(tvb, 5); pgmhdr_cksum = tvb_get_ntohs(tvb, 6); gsi = tvb_bytes_to_str(tvb, 8, 6); pgmhdr_tsdulen = tvb_get_ntohs(tvb, 14); sqn = tvb_get_ntohl(tvb, 16); switch(pgmhdr_type) { case PGM_SPM_PCKT: case PGM_NAK_PCKT: case PGM_NNAK_PCKT: case PGM_NCF_PCKT: case PGM_POLR_PCKT: case PGM_ACK_PCKT: if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s", pktname, sqn, gsi); } break; case PGM_RDATA_PCKT: case PGM_ODATA_PCKT: if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s tsdulen %d", pktname, sqn, gsi, pgmhdr_tsdulen); } isdata = TRUE; break; case PGM_POLL_PCKT: { guint16 poll_stype = tvb_get_ntohs(tvb, 22); pollstname = val_to_str(poll_stype, poll_subtype_vals, "Unknown (0x%02x)"); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s subtype %s", pktname, sqn, gsi, pollstname); } } break; default: return; } { proto_tree *pgm_tree = NULL; proto_tree *opt_tree = NULL; proto_tree *type_tree = NULL; proto_item *tf, *hidden_item; ptvcursor_t* cursor; ti = proto_tree_add_protocol_format(tree, proto_pgm, tvb, 0, -1, "Pragmatic General Multicast: Type %s" " Src Port %u, Dst Port %u, GSI %s", pktname, pgmhdr_sport, pgmhdr_dport, gsi); pgm_tree = proto_item_add_subtree(ti, ett_pgm); cursor = ptvcursor_new(pgm_tree, tvb, 0); hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 0, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 2, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); ptvcursor_add(cursor, hf_pgm_main_sport, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_dport, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_type, 1, ENC_BIG_ENDIAN); tf = proto_tree_add_uint_format(pgm_tree, hf_pgm_main_opts, tvb, ptvcursor_current_offset(cursor), 1, pgmhdr_opts, "Options: %s (0x%x)", optsstr(pgmhdr_opts), pgmhdr_opts); opt_tree = proto_item_add_subtree(tf, ett_pgm_optbits); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_opt, 1, ENC_BIG_ENDIAN); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_netsig, 1, ENC_BIG_ENDIAN); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_varlen, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_opts_parity, 1, ENC_BIG_ENDIAN); ptvcursor_set_tree(cursor, pgm_tree); /* Checksum may be 0 (not available), but not for DATA packets */ if ((pgmhdr_type != PGM_RDATA_PCKT) && (pgmhdr_type != PGM_ODATA_PCKT) && (pgmhdr_cksum == 0)) { proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: not available"); } else { reportedlen = tvb_reported_length(tvb); pgmlen = tvb_length(tvb); if (pgm_check_checksum && pgmlen >= reportedlen) { vec_t cksum_vec[1]; guint16 computed_cksum; cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pgmlen); cksum_vec[0].len = pgmlen; computed_cksum = in_cksum(&cksum_vec[0], 1); if (computed_cksum == 0) { proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: 0x%04x [correct]", pgmhdr_cksum); } else { hidden_item = proto_tree_add_boolean(pgm_tree, hf_pgm_main_cksum_bad, tvb, ptvcursor_current_offset(cursor), 2, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: 0x%04x [incorrect, should be 0x%04x]", pgmhdr_cksum, in_cksum_shouldbe(pgmhdr_cksum, computed_cksum)); } } else { ptvcursor_add_no_advance(cursor, hf_pgm_main_cksum, 2, ENC_BIG_ENDIAN); } } ptvcursor_advance(cursor, 2); ptvcursor_add(cursor, hf_pgm_main_gsi, 6, ENC_NA); ptvcursor_add(cursor, hf_pgm_main_tsdulen, 2, ENC_BIG_ENDIAN); tf = proto_tree_add_text(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, "%s Packet", pktname); switch(pgmhdr_type) { case PGM_SPM_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_spm); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_lead, 4, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_spm_pathafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_res, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_spm_path, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_spm_path6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); return; } break; case PGM_RDATA_PCKT: case PGM_ODATA_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_data); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN); break; case PGM_NAK_PCKT: case PGM_NNAK_PCKT: case PGM_NCF_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_nak); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_nak_sqn, 4, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_nak_srcafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_nak_srcres, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_nak_src, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_nak_src6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_nak_grpafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_nak_grpres, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_nak_grp, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_nak_grp6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); return; } break; case PGM_POLL_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_poll); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_poll_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_round, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_subtype, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_poll_pathafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_res, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_poll_path, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_poll_path6, 16, ENC_NA); break; default: proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } ptvcursor_add(cursor, hf_pgm_poll_backoff_ivl, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_rand_str, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_matching_bmask, 4, ENC_BIG_ENDIAN); break; case PGM_POLR_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_polr); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_polr_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_polr_round, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_polr_res, 2, ENC_BIG_ENDIAN); break; case PGM_ACK_PCKT: type_tree = proto_item_add_subtree(tf, ett_pgm_ack); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_ack_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_ack_bitmap, 4, ENC_BIG_ENDIAN); break; } if (pgmhdr_opts & PGM_OPT) dissect_pgmopts(cursor, pktname); if (isdata) decode_pgm_ports(tvb, ptvcursor_current_offset(cursor), pinfo, tree, pgmhdr_sport, pgmhdr_dport); } }
void dissect_nhrp_hdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *pOffset, gint *pMandLen, gint *pExtLen, oui_info_t **pOuiInfo, e_nhrp_hdr *hdr) { gint offset = *pOffset; const gchar *pro_type_str; guint total_len = tvb_reported_length(tvb); guint16 ipcsum, rx_chksum; proto_item *nhrp_tree_item = NULL; proto_tree *nhrp_tree = NULL; proto_item *shtl_tree_item = NULL; proto_tree *shtl_tree = NULL; proto_item *sstl_tree_item = NULL; proto_tree *sstl_tree = NULL; proto_item *ti; nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, 20, "NHRP Fixed Header"); nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_hdr); hdr->ar_pktsz = tvb_get_ntohs(tvb, 10); if (total_len > hdr->ar_pktsz) { total_len = hdr->ar_pktsz; } hdr->ar_afn = tvb_get_ntohs(tvb, offset); proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_afn, tvb, offset, 2, FALSE); offset += 2; hdr->ar_pro_type = tvb_get_ntohs(tvb, offset); if (hdr->ar_pro_type <= 0xFF) { /* It's an NLPID */ pro_type_str = val_to_str(hdr->ar_pro_type, nlpid_vals, "Unknown NLPID"); } else if (hdr->ar_pro_type <= 0x3FF) { /* Reserved for future use by the IETF */ pro_type_str = "Reserved for future use by the IETF"; } else if (hdr->ar_pro_type <= 0x04FF) { /* Allocated for use by the ATM Forum */ pro_type_str = "Allocated for use by the ATM Forum"; } else if (hdr->ar_pro_type <= 0x05FF) { /* Experimental/Local use */ pro_type_str = "Experimental/Local use"; } else { pro_type_str = val_to_str(hdr->ar_pro_type, etype_vals, "Unknown Ethertype"); } proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_pro_type, tvb, offset, 2, hdr->ar_pro_type, "Protocol Type (short form): %s (0x%04x)", pro_type_str, hdr->ar_pro_type); offset += 2; if (hdr->ar_pro_type == NLPID_SNAP) { /* * The long form protocol type is a SNAP OUI and PID. */ hdr->ar_pro_type_oui = tvb_get_ntoh24(tvb, offset); proto_tree_add_uint(nhrp_tree, hf_nhrp_hdr_pro_snap_oui, tvb, offset, 3, hdr->ar_pro_type_oui); offset += 3; hdr->ar_pro_type_pid = tvb_get_ntohs(tvb, offset); *pOuiInfo = get_snap_oui_info(hdr->ar_pro_type_oui); if (*pOuiInfo != NULL) { proto_tree_add_uint(nhrp_tree, *(*pOuiInfo)->field_info->p_id, tvb, offset, 2, hdr->ar_pro_type_pid); } else { proto_tree_add_uint(nhrp_tree, hf_nhrp_hdr_pro_snap_pid, tvb, offset, 2, hdr->ar_pro_type_pid); } } else { /* * XXX - we should check that this is zero, as RFC 2332 * says it should be zero. */ proto_tree_add_text(nhrp_tree, tvb, offset, 5, "Protocol Type (long form): %s", tvb_bytes_to_str(tvb, offset, 5)); offset += 5; } proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_hopcnt, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_pktsz, tvb, offset, 2, FALSE); offset += 2; rx_chksum = tvb_get_ntohs(tvb, offset); if (tvb_bytes_exist(tvb, 0, total_len)) { ipcsum = nhrp_checksum(tvb_get_ptr(tvb, 0, total_len), total_len); if (ipcsum == 0) { proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_chksum, tvb, offset, 2, rx_chksum, "NHRP Packet checksum: 0x%04x [correct]", rx_chksum); } else { proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_chksum, tvb, offset, 2, rx_chksum, "NHRP Packet checksum: 0x%04x [incorrect, should be 0x%04x]", rx_chksum, in_cksum_shouldbe(rx_chksum, ipcsum)); } } else { proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_chksum, tvb, offset, 2, rx_chksum, "NHRP Packet checksum: 0x%04x [not all data available]", rx_chksum); } offset += 2; hdr->ar_extoff = tvb_get_ntohs(tvb, offset); ti = proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_extoff, tvb, offset, 2, FALSE); if (hdr->ar_extoff != 0 && hdr->ar_extoff < 20) { expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Extension offset is less than the fixed header length"); } offset += 2; hdr->ar_op_version = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_version, tvb, offset, 1, hdr->ar_op_version, "Version : %u (%s)", hdr->ar_op_version, (hdr->ar_op_version == 1) ? "NHRP - rfc2332" : "Unknown"); offset += 1; proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_op_type, tvb, offset, 1, FALSE); offset += 1; hdr->ar_shtl = tvb_get_guint8(tvb, offset); shtl_tree_item = proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_shtl, tvb, offset, 1, hdr->ar_shtl, "Source Address Type/Len: %s/%u", val_to_str(NHRP_SHTL_TYPE(hdr->ar_shtl), nhrp_shtl_type_vals, "Unknown Type"), NHRP_SHTL_LEN(hdr->ar_shtl)); shtl_tree = proto_item_add_subtree(shtl_tree_item, ett_nhrp_hdr_shtl); proto_tree_add_item(shtl_tree, hf_nhrp_hdr_shtl_type, tvb, offset, 1, FALSE); proto_tree_add_item(shtl_tree, hf_nhrp_hdr_shtl_len, tvb, offset, 1, FALSE); offset += 1; hdr->ar_sstl = tvb_get_guint8(tvb, offset); sstl_tree_item = proto_tree_add_uint_format(nhrp_tree, hf_nhrp_hdr_sstl, tvb, offset, 1, hdr->ar_sstl, "Source SubAddress Type/Len: %s/%u", val_to_str(NHRP_SHTL_TYPE(hdr->ar_sstl), nhrp_shtl_type_vals, "Unknown Type"), NHRP_SHTL_LEN(hdr->ar_sstl)); sstl_tree = proto_item_add_subtree(sstl_tree_item, ett_nhrp_hdr_sstl); proto_tree_add_item(sstl_tree, hf_nhrp_hdr_sstl_type, tvb, offset, 1, FALSE); proto_tree_add_item(sstl_tree, hf_nhrp_hdr_sstl_len, tvb, offset, 1, FALSE); offset += 1; *pOffset = offset; if (hdr->ar_extoff != 0) { if (hdr->ar_extoff >= 20) { *pMandLen = hdr->ar_extoff - 20; *pExtLen = total_len - hdr->ar_extoff; } else { /* Error */ *pMandLen = 0; *pExtLen = 0; } } else { if (total_len >= 20) *pMandLen = total_len - 20; else { /* "Can't happen" - we would have thrown an exception */ *pMandLen = 0; } *pExtLen = 0; } }
/* * XXX - shouldn't there be a centralized routine for dissecting NSAPs? * See also "dissect_nsap()" in epan/dissectors/packet-isup.c and * "print_nsap_net_buf()" and "print_nsap_net()" in epan/osi=utils.c. */ void dissect_atm_nsap(tvbuff_t *tvb, int offset, int len, proto_tree *tree) { guint8 afi; afi = tvb_get_guint8(tvb, offset); switch (afi) { case 0x39: /* DCC ATM format */ case 0xBD: /* DCC ATM group format */ proto_tree_add_text(tree, tvb, offset + 0, 3, "Data Country Code%s: 0x%04X", (afi == 0xBD) ? " (group)" : "", tvb_get_ntohs(tvb, offset + 1)); proto_tree_add_text(tree, tvb, offset + 3, 10, "High Order DSP: %s", tvb_bytes_to_str(tvb, offset + 3, 10)); proto_tree_add_text(tree, tvb, offset + 13, 6, "End System Identifier: %s", tvb_bytes_to_str(tvb, offset + 13, 6)); proto_tree_add_text(tree, tvb, offset + 19, 1, "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19)); break; case 0x47: /* ICD ATM format */ case 0xC5: /* ICD ATM group format */ proto_tree_add_text(tree, tvb, offset + 0, 3, "International Code Designator%s: 0x%04X", (afi == 0xC5) ? " (group)" : "", tvb_get_ntohs(tvb, offset + 1)); proto_tree_add_text(tree, tvb, offset + 3, 10, "High Order DSP: %s", tvb_bytes_to_str(tvb, offset + 3, 10)); proto_tree_add_text(tree, tvb, offset + 13, 6, "End System Identifier: %s", tvb_bytes_to_str(tvb, offset + 13, 6)); proto_tree_add_text(tree, tvb, offset + 19, 1, "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19)); break; case 0x45: /* E.164 ATM format */ case 0xC3: /* E.164 ATM group format */ proto_tree_add_text(tree, tvb, offset + 0, 9, "E.164 ISDN%s: %s", (afi == 0xC3) ? " (group)" : "", tvb_bytes_to_str(tvb, offset + 1, 8)); proto_tree_add_text(tree, tvb, offset + 9, 4, "High Order DSP: %s", tvb_bytes_to_str(tvb, offset + 3, 10)); proto_tree_add_text(tree, tvb, offset + 13, 6, "End System Identifier: %s", tvb_bytes_to_str(tvb, offset + 13, 6)); proto_tree_add_text(tree, tvb, offset + 19, 1, "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19)); break; default: proto_tree_add_text(tree, tvb, offset, 1, "Unknown AFI: 0x%02X", afi); proto_tree_add_text(tree, tvb, offset + 1, len - 1, "Rest of address: %s", tvb_bytes_to_str(tvb, offset + 1, len - 1)); break; } }
void dissect_cie_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, gint cieEnd, e_nhrp_hdr *hdr, gint isReq, gboolean codeinfo) { proto_item *cli_addr_tree_item = NULL; proto_tree *cli_addr_tree = NULL; proto_item *cli_saddr_tree_item = NULL; proto_tree *cli_saddr_tree = NULL; guint8 val; while ((offset + 12) <= cieEnd) { guint cli_addr_len = tvb_get_guint8(tvb, offset + 8); guint cli_saddr_len = tvb_get_guint8(tvb, offset + 9); guint cli_prot_len = tvb_get_guint8(tvb, offset + 10); guint cie_len = 12 + cli_addr_len + cli_saddr_len + cli_prot_len; proto_item *cie_tree_item = proto_tree_add_text(tree, tvb, offset, cie_len, "Client Information Entry"); proto_tree *cie_tree = proto_item_add_subtree(cie_tree_item, ett_nhrp_cie); if (isReq) { proto_tree_add_item(cie_tree, hf_nhrp_code, tvb, offset, 1, FALSE); } else { guint8 code = tvb_get_guint8(tvb, offset); if ( codeinfo ) { col_append_fstr(pinfo->cinfo, COL_INFO, ", Code=%s", val_to_str(code, nhrp_cie_code_vals, "Unknown (%u)")); } proto_tree_add_text(cie_tree, tvb, offset, 1, "Code: %s", val_to_str(code, nhrp_cie_code_vals, "Unknown (%u)")); } offset += 1; proto_tree_add_item(cie_tree, hf_nhrp_prefix_len, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(cie_tree, hf_nhrp_unused, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(cie_tree, hf_nhrp_mtu, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(cie_tree, hf_nhrp_holding_time, tvb, offset, 2, FALSE); offset += 2; val = tvb_get_guint8(tvb, offset); cli_addr_tree_item = proto_tree_add_uint_format(cie_tree, hf_nhrp_cli_addr_tl, tvb, offset, 1, val, "Client Address Type/Len: %s/%u", val_to_str(NHRP_SHTL_TYPE(val), nhrp_shtl_type_vals, "Unknown Type"), NHRP_SHTL_LEN(val)); cli_addr_tree = proto_item_add_subtree(cli_addr_tree_item, ett_nhrp_cie_cli_addr_tl); proto_tree_add_item(cli_addr_tree, hf_nhrp_cli_addr_tl_type, tvb, offset, 1, FALSE); proto_tree_add_item(cli_addr_tree, hf_nhrp_cli_addr_tl_len, tvb, offset, 1, FALSE); offset += 1; val = tvb_get_guint8(tvb, offset); cli_saddr_tree_item = proto_tree_add_uint_format(cie_tree, hf_nhrp_cli_saddr_tl, tvb, offset, 1, val, "Client Sub Address Type/Len: %s/%u", val_to_str(NHRP_SHTL_TYPE(val), nhrp_shtl_type_vals, "Unknown Type"), NHRP_SHTL_LEN(val)); cli_saddr_tree = proto_item_add_subtree(cli_saddr_tree_item, ett_nhrp_cie_cli_saddr_tl); proto_tree_add_item(cli_saddr_tree, hf_nhrp_cli_saddr_tl_type, tvb, offset, 1, FALSE); proto_tree_add_item(cli_saddr_tree, hf_nhrp_cli_saddr_tl_len, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(cie_tree, hf_nhrp_cli_prot_len, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(cie_tree, hf_nhrp_pref, tvb, offset, 1, FALSE); offset += 1; if (cli_addr_len) { switch (hdr->ar_afn) { case AFNUM_INET: if (cli_addr_len == 4) proto_tree_add_item(cie_tree, hf_nhrp_client_nbma_addr, tvb, offset, 4, FALSE); else { proto_tree_add_text(cie_tree, tvb, offset, cli_addr_len, "Client NBMA Address: %s", tvb_bytes_to_str(tvb, offset, cli_addr_len)); } break; default: proto_tree_add_text(cie_tree, tvb, offset, cli_addr_len, "Client NBMA Address: %s", tvb_bytes_to_str(tvb, offset, cli_addr_len)); break; } offset += cli_addr_len; } if (cli_saddr_len) { proto_tree_add_text(cie_tree, tvb, offset, cli_saddr_len, "Client NBMA Sub Address: %s", tvb_bytes_to_str(tvb, offset, cli_saddr_len)); } if (cli_prot_len) { if (cli_prot_len == 4) proto_tree_add_ipv4(cie_tree, hf_nhrp_client_prot_addr, tvb, offset, 4, FALSE); else { proto_tree_add_text(cie_tree, tvb, offset, cli_prot_len, "Client Protocol Address: %s", tvb_bytes_to_str(tvb, offset, cli_prot_len)); } offset += cli_prot_len; } } }
void dissect_nhrp_mand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *pOffset, gint mandLen, oui_info_t *oui_info, e_nhrp_hdr *hdr, guint *srcLen, gboolean codeinfo) { gint offset = *pOffset; gint mandEnd = offset + mandLen; guint8 ssl, shl; guint16 flags; guint dstLen; gboolean isReq = 0; gboolean isErr = 0; gboolean isInd = 0; proto_item *nhrp_tree_item = NULL; proto_item *flag_item = NULL; proto_tree *nhrp_tree = NULL; proto_tree *flag_tree = NULL; tvb_ensure_bytes_exist(tvb, offset, mandLen); switch (hdr->ar_op_type) { case NHRP_RESOLUTION_REPLY: case NHRP_REGISTRATION_REPLY: case NHRP_PURGE_REPLY: break; case NHRP_RESOLUTION_REQ: case NHRP_REGISTRATION_REQ: case NHRP_PURGE_REQ: isReq = 1; break; case NHRP_ERROR_INDICATION: /* This needs special treatment */ isErr = 1; isInd = 1; break; case NHRP_TRAFFIC_INDICATION: isInd = 1; break; } nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, mandLen, "NHRP Mandatory Part"); nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_mand); *srcLen = tvb_get_guint8(tvb, offset); proto_tree_add_item(nhrp_tree, hf_nhrp_src_proto_len, tvb, offset, 1, FALSE); offset += 1; dstLen = tvb_get_guint8(tvb, offset); proto_tree_add_item(nhrp_tree, hf_nhrp_dst_proto_len, tvb, offset, 1, FALSE); offset += 1; if (!isInd) { flags = tvb_get_ntohs(tvb, offset); flag_item = proto_tree_add_uint(nhrp_tree, hf_nhrp_flags, tvb, offset, 2, flags); flag_tree = proto_item_add_subtree(flag_item, ett_nhrp_mand_flag); switch (hdr->ar_op_type) { case NHRP_RESOLUTION_REQ: case NHRP_RESOLUTION_REPLY: proto_tree_add_boolean(flag_tree, hf_nhrp_flag_Q, tvb, offset, 2, flags); proto_tree_add_boolean(flag_tree, hf_nhrp_flag_A, tvb, offset, 2, flags); proto_tree_add_boolean(flag_tree, hf_nhrp_flag_D, tvb, offset, 2, flags); proto_tree_add_boolean(flag_tree, hf_nhrp_flag_U1, tvb, offset, 2, flags); proto_tree_add_boolean(flag_tree, hf_nhrp_flag_S, tvb, offset, 2, flags); break; case NHRP_REGISTRATION_REQ: case NHRP_REGISTRATION_REPLY: proto_tree_add_boolean(flag_tree, hf_nhrp_flag_U2, tvb, offset, 2, flags); break; case NHRP_PURGE_REQ: case NHRP_PURGE_REPLY: proto_tree_add_boolean(flag_tree, hf_nhrp_flag_N, tvb, offset, 2, flags); break; } proto_tree_add_boolean(flag_tree, hf_nhrp_flag_NAT, tvb, offset, 2, flags); offset += 2; col_append_fstr(pinfo->cinfo, COL_INFO, ", ID=%u", tvb_get_ntohl(tvb, offset)); proto_tree_add_item(nhrp_tree, hf_nhrp_request_id, tvb, offset, 4, FALSE); offset += 4; } else if (isErr) { offset += 2; col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str(tvb_get_ntohs(tvb, offset), nhrp_error_code_vals, "Unknown Error (%u)")); proto_tree_add_item(nhrp_tree, hf_nhrp_error_code, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nhrp_tree, hf_nhrp_error_offset, tvb, offset, 2, FALSE); offset += 2; } else { offset += 6; } shl = NHRP_SHTL_LEN(hdr->ar_shtl); if (shl) { switch (hdr->ar_afn) { case AFNUM_INET: if (shl == 4) proto_tree_add_item(nhrp_tree, hf_nhrp_src_nbma_addr, tvb, offset, 4, FALSE); else { proto_tree_add_text(nhrp_tree, tvb, offset, shl, "Source NBMA Address: %s", tvb_bytes_to_str(tvb, offset, shl)); } break; default: proto_tree_add_text(nhrp_tree, tvb, offset, shl, "Source NBMA Address: %s", tvb_bytes_to_str(tvb, offset, shl)); break; } offset += shl; } ssl = NHRP_SHTL_LEN(hdr->ar_sstl); if (ssl) { proto_tree_add_text(nhrp_tree, tvb, offset, ssl, "Source NBMA Sub Address: %s", tvb_bytes_to_str(tvb, offset, ssl)); offset += ssl; } if (*srcLen == 4) { proto_tree_add_item(nhrp_tree, hf_nhrp_src_prot_addr, tvb, offset, 4, FALSE); offset += 4; } else if (*srcLen) { proto_tree_add_text(nhrp_tree, tvb, offset, *srcLen, "Source Protocol Address: %s", tvb_bytes_to_str(tvb, offset, *srcLen)); offset += *srcLen; } if (dstLen == 4) { proto_tree_add_item(nhrp_tree, hf_nhrp_dst_prot_addr, tvb, offset, 4, FALSE); offset += 4; } else if (dstLen) { proto_tree_add_text(nhrp_tree, tvb, offset, dstLen, "Destination Protocol Address: %s", tvb_bytes_to_str(tvb, offset, dstLen)); offset += dstLen; } if (isInd) { gboolean save_in_error_pkt; gint pkt_len = mandEnd - offset; proto_item *ind_tree_item = proto_tree_add_text(tree, tvb, offset, pkt_len, "Packet Causing Indication"); proto_tree *ind_tree = proto_item_add_subtree(ind_tree_item, ett_nhrp_indication); gboolean dissected; tvbuff_t *sub_tvb; save_in_error_pkt = pinfo->in_error_pkt; pinfo->in_error_pkt = TRUE; sub_tvb = tvb_new_subset_remaining(tvb, offset); if (isErr) { _dissect_nhrp(sub_tvb, pinfo, ind_tree, TRUE, FALSE); } else { if (hdr->ar_pro_type <= 0xFF) { /* It's an NLPID */ if (hdr->ar_pro_type == NLPID_SNAP) { /* * Dissect based on the SNAP OUI * and PID. */ if (hdr->ar_pro_type_oui == 0x000000) { /* * "Should not happen", as * the protocol type should * be the Ethertype, but.... */ dissected = dissector_try_port( ethertype_subdissector_table, hdr->ar_pro_type_pid, sub_tvb, pinfo, ind_tree); } else { /* * If we have a dissector * table, use it, otherwise * just dissect as data. */ if (oui_info != NULL) { dissected = dissector_try_port( oui_info->table, hdr->ar_pro_type_pid, sub_tvb, pinfo, ind_tree); } else dissected = FALSE; } } else { /* * Dissect based on the NLPID. */ dissected = dissector_try_port( osinl_subdissector_table, hdr->ar_pro_type, sub_tvb, pinfo, ind_tree) || dissector_try_port( osinl_excl_subdissector_table, hdr->ar_pro_type, sub_tvb, pinfo, ind_tree); } } else if (hdr->ar_pro_type <= 0x3FF) { /* Reserved for future use by the IETF */ dissected = FALSE; } else if (hdr->ar_pro_type <= 0x04FF) { /* Allocated for use by the ATM Forum */ dissected = FALSE; } else if (hdr->ar_pro_type <= 0x05FF) { /* Experimental/Local use */ dissected = FALSE; } else { dissected = dissector_try_port( ethertype_subdissector_table, hdr->ar_pro_type, sub_tvb, pinfo, ind_tree); } if (!dissected) { call_dissector(data_handle, sub_tvb, pinfo, ind_tree); } } pinfo->in_error_pkt = save_in_error_pkt; offset = mandEnd; } /* According to RFC 2332, section 5.2.7, there shouldn't be any extensions * in the Error Indication packet. */ if (isErr && tvb_reported_length_remaining(tvb, offset)) { expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "Extensions not allowed per RFC2332 section 5.2.7"); } dissect_cie_list(tvb, pinfo, nhrp_tree, offset, mandEnd, hdr, isReq, codeinfo); *pOffset = mandEnd; }
static void dissect_bacnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_item *ct; proto_tree *bacnet_tree; proto_tree *control_tree; gint offset; guint8 bacnet_version; guint8 bacnet_control; guint8 bacnet_dlen; guint8 bacnet_slen; guint8 bacnet_mesgtyp; guint8 bacnet_rejectreason; guint8 bacnet_rportnum; guint8 bacnet_pinfolen; guint8 i; tvbuff_t *next_tvb; guint32 vendor_id; col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-NPDU"); col_set_str(pinfo->cinfo, COL_INFO, "Building Automation and Control Network NPDU"); offset = 0; bacnet_version = tvb_get_guint8(tvb, offset); bacnet_control = tvb_get_guint8(tvb, offset+1); /* I don't know the length of the NPDU yet; Setting the length after dissection */ ti = proto_tree_add_item(tree, proto_bacnet, tvb, 0, -1, ENC_NA); bacnet_tree = proto_item_add_subtree(ti, ett_bacnet); proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_version, tvb, offset, 1, bacnet_version,"0x%02x (%s)",bacnet_version, (bacnet_version == 0x01)?"ASHRAE 135-1995":"unknown"); offset ++; ct = proto_tree_add_uint(bacnet_tree, hf_bacnet_control, tvb, offset, 1, bacnet_control); control_tree = proto_item_add_subtree(ct, ett_bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_net, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_res1, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_dest, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_res2, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_src, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_expect, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_high, tvb, offset, 1, bacnet_control); proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_low, tvb, offset, 1, bacnet_control); offset ++; if (bacnet_control & BAC_CONTROL_DEST) { /* DNET, DLEN, DADR */ proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; bacnet_dlen = tvb_get_guint8(tvb, offset); /* DLEN = 0 is broadcast on dest.network */ if( bacnet_dlen == 0) { /* append to hf_bacnet_dlen: broadcast */ proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen, "%d indicates Broadcast on Destination Network", bacnet_dlen); offset ++; /* going to SNET */ } else if (bacnet_dlen==6) { proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen); offset ++; /* Ethernet MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_dadr_eth, tvb, offset, bacnet_dlen, ENC_NA); offset += bacnet_dlen; } else if (bacnet_dlen==1) { proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen); offset ++; /* MS/TP or ARCNET MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_dadr_mstp, tvb, offset, bacnet_dlen, ENC_BIG_ENDIAN); offset += bacnet_dlen; } else if (bacnet_dlen<7) { proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen); offset ++; /* Other MAC formats should be included here */ proto_tree_add_item(bacnet_tree, hf_bacnet_dadr_tmp, tvb, offset, bacnet_dlen, ENC_NA); offset += bacnet_dlen; } else { proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen, "%d invalid!", bacnet_dlen); } } if (bacnet_control & BAC_CONTROL_SRC) { /* SNET, SLEN, SADR */ /* SNET */ proto_tree_add_uint(bacnet_tree, hf_bacnet_snet, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset += 2; bacnet_slen = tvb_get_guint8(tvb, offset); if( bacnet_slen == 0) { /* SLEN = 0 invalid */ proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen, "%d invalid!", bacnet_slen); offset ++; } else if (bacnet_slen==6) { /* SLEN */ proto_tree_add_uint(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen); offset ++; /* Ethernet MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_sadr_eth, tvb, offset, bacnet_slen, ENC_NA); offset += bacnet_slen; } else if (bacnet_slen==1) { /* SLEN */ proto_tree_add_uint(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen); offset ++; /* MS/TP or ARCNET MAC */ proto_tree_add_item(bacnet_tree, hf_bacnet_sadr_mstp, tvb, offset, bacnet_slen, ENC_BIG_ENDIAN); offset += bacnet_slen; } else if (bacnet_slen<6) { /* LON MAC */ /* SLEN */ proto_tree_add_uint(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen); offset ++; /* Other MAC formats should be included here */ proto_tree_add_item(bacnet_tree, hf_bacnet_sadr_tmp, tvb, offset, bacnet_slen, ENC_NA); offset += bacnet_slen; } else { proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_slen, tvb, offset, 1, bacnet_slen, "%d invalid!", bacnet_slen); offset ++; } } if (bacnet_control & BAC_CONTROL_DEST) { /* Hopcount */ proto_tree_add_item(bacnet_tree, hf_bacnet_hopc, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; } /* Network Layer Message Type */ if (bacnet_control & BAC_CONTROL_NET) { bacnet_mesgtyp = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_mesgtyp, tvb, offset, 1, bacnet_mesgtyp, "%02x (%s)", bacnet_mesgtyp, bacnet_mesgtyp_name(bacnet_mesgtyp)); /* Put the NPDU Type in the info column */ col_add_str(pinfo->cinfo, COL_INFO, bacnet_mesgtyp_name(bacnet_mesgtyp)); offset ++; /* Vendor ID * The standard says: "If Bit 7 of the control octet is 1 and * the Message Type field contains a value in the range * X'80' - X'FF', then a Vendor ID field shall be present (...)." * We should not go any further in dissecting the packet if it's * not present, but we don't know about that: No length field... */ if (bacnet_mesgtyp > 0x7f) { /* Note: our next_tvb includes message type and vendor id! */ next_tvb = tvb_new_subset_remaining(tvb, offset-1); vendor_id = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(bacnet_tree, hf_bacnet_vendor, tvb, offset, 2, vendor_id); offset += 2; /* vendor_id */ if (dissector_try_uint(bacnet_dissector_table, vendor_id, next_tvb, pinfo, bacnet_tree)) { /* we parsed it so skip over length and we are done */ /* Note: offset has now been bumped for message type and vendor id so we take that out of our next_tvb size */ offset += tvb_length(next_tvb) -3; } } /* Performance Index (in I-Could-Be-Router-To-Network) */ if (bacnet_mesgtyp == BAC_NET_ICB_R) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(bacnet_tree, hf_bacnet_perf, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; } /* Reason, DNET (in Reject-Message-To-Network) */ if (bacnet_mesgtyp == BAC_NET_REJ) { bacnet_rejectreason = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_rejectreason, tvb, offset, 1, bacnet_rejectreason, "%d (%s)", bacnet_rejectreason, bacnet_rejectreason_name(bacnet_rejectreason)); offset ++; proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } /* N*DNET (in Router-Busy-To-Network,Router-Available-To-Network) */ if ((bacnet_mesgtyp == BAC_NET_R_BUSY) || (bacnet_mesgtyp == BAC_NET_WHO_R) || (bacnet_mesgtyp == BAC_NET_R_AVA) || (bacnet_mesgtyp == BAC_NET_IAM_R) ) { while(tvb_reported_length_remaining(tvb, offset) > 1 ) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } } /* Initialize-Routing-Table */ if ( (bacnet_mesgtyp == BAC_NET_INIT_RTAB) || (bacnet_mesgtyp == BAC_NET_INIT_RTAB_ACK) ) { bacnet_rportnum = tvb_get_guint8(tvb, offset); /* number of ports */ proto_tree_add_uint(bacnet_tree, hf_bacnet_rportnum, tvb, offset, 1, bacnet_rportnum); offset ++; for(i=0; i<bacnet_rportnum; i++) { /* Connected DNET */ proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Port ID */ proto_tree_add_item(bacnet_tree, hf_bacnet_portid, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; /* Port Info Length */ bacnet_pinfolen = tvb_get_guint8(tvb, offset); proto_tree_add_uint(bacnet_tree, hf_bacnet_pinfolen, tvb, offset, 1, bacnet_pinfolen); offset ++; proto_tree_add_text(bacnet_tree, tvb, offset, bacnet_pinfolen, "Port Info: %s", tvb_bytes_to_str(tvb, offset, bacnet_pinfolen)); offset += bacnet_pinfolen; } } /* Establish-Connection-To-Network */ if (bacnet_mesgtyp == BAC_NET_EST_CON) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(bacnet_tree, hf_bacnet_term_time_value, tvb, offset, 1, ENC_BIG_ENDIAN); offset ++; } /* Disconnect-Connection-To-Network */ if (bacnet_mesgtyp == BAC_NET_DISC_CON) { proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } } /* Now set NPDU length */ proto_item_set_len(ti, offset); /* dissect BACnet APDU */ next_tvb = tvb_new_subset_remaining(tvb,offset); if (bacnet_control & BAC_CONTROL_NET) { /* Unknown function - dissect the payload as data */ call_dissector(data_handle, next_tvb, pinfo, tree); } else { /* APDU - call the APDU dissector */ call_dissector(bacapp_handle, next_tvb, pinfo, tree); } }
void dissect_nhrp_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *pOffset, gint extLen, e_nhrp_hdr *hdr, guint srcLen, gboolean nested) { gint offset = *pOffset; gint extEnd = offset + extLen; proto_item *nhrp_tree_item = NULL; proto_tree *nhrp_tree = NULL; proto_item *ti = NULL; tvb_ensure_bytes_exist(tvb, offset, extLen); while ((offset + 4) <= extEnd) { gint extTypeC = tvb_get_ntohs(tvb, offset); gint extType = extTypeC & 0x3FFF; guint len = tvb_get_ntohs(tvb, offset+2); if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) { /* Assume it's not really a Cisco NAT extension, but a device * capabilities extension instead (see RFC 2735). */ nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, len + 4, "Device Capabilities Extension"); } else { nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, len + 4, "%s", val_to_str(extType, ext_type_vals, "Unknown (%u)")); } nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_ext); proto_tree_add_boolean(nhrp_tree, hf_nhrp_ext_C, tvb, offset, 2, extTypeC); proto_tree_add_item(nhrp_tree, hf_nhrp_ext_type, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(nhrp_tree, hf_nhrp_ext_len, tvb, offset, 2, FALSE); offset += 2; if (len && (extType != NHRP_EXT_NULL)) { tvb_ensure_bytes_exist(tvb, offset, len); if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) { /* Assume it's not really a Cisco NAT extension, but a device * capabilities extension instead (see RFC 2735). */ proto_item *devcap_item; proto_tree *devcap_tree; proto_item *cap_item; proto_tree *cap_tree; devcap_item = proto_tree_add_text(nhrp_tree, tvb, offset, len, "Extension Data: Src is %sVPN-aware; Dst is %sVPN-aware", tvb_get_ntohl(tvb, offset) & 1 ? "" : "non-", tvb_get_ntohl(tvb, offset + 4) & 1 ? "" : "non-"); devcap_tree = proto_item_add_subtree(devcap_item, ett_nhrp_devcap_ext); cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_srccap, tvb, offset, 4, FALSE); cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_srccap); proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_srccap_V, tvb, offset, 4, FALSE); cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_dstcap, tvb, offset + 4, 4, FALSE); cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_dstcap); proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_dstcap_V, tvb, offset + 4, 4, FALSE); goto skip_switch; } switch (extType) { case NHRP_EXT_RESP_ADDR: case NHRP_EXT_FWD_RECORD: case NHRP_EXT_REV_RECORD: case NHRP_EXT_NAT_ADDRESS: dissect_cie_list(tvb, pinfo, nhrp_tree, offset, offset + len, hdr, 0, FALSE); break; case NHRP_EXT_AUTH: case NHRP_EXT_MOBILE_AUTH: if (len < (4 + srcLen)) { ti = proto_tree_add_text(nhrp_tree, tvb, offset, len, "Malformed Extension: %s", tvb_bytes_to_str(tvb, offset, len)); expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Incomplete Authentication Extension"); } else { proto_item *auth_item; proto_tree *auth_tree; auth_item = proto_tree_add_text(nhrp_tree, tvb, offset, len, "Extension Data: SPI=%u: Data=%s", tvb_get_ntohs(tvb, offset + 2), tvb_bytes_to_str(tvb, offset + 4, len - 4)); auth_tree = proto_item_add_subtree(auth_item, ett_nhrp_auth_ext); proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_reserved, tvb, offset, 2, FALSE); proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_spi, tvb, offset + 2, 2, FALSE); if (srcLen == 4) proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_src_addr, tvb, offset + 4, 4, FALSE); else if (srcLen) { proto_tree_add_text(auth_tree, tvb, offset + 4, srcLen, "Source Address: %s", tvb_bytes_to_str(tvb, offset + 4, srcLen)); } if (len > (4 + srcLen)) { proto_tree_add_text(auth_tree, tvb, offset + 4 + srcLen, len - (4 + srcLen), "Data: %s", tvb_bytes_to_str(tvb, offset + 4 + srcLen, len - (4 + srcLen))); } } break; case NHRP_EXT_VENDOR_PRIV: if (len < 3) { ti = proto_tree_add_text(nhrp_tree, tvb, offset, len, "Malformed Extension: %s", tvb_bytes_to_str(tvb, offset, len)); expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Incomplete Vendor-Private Extension"); } else { proto_item *vendor_item; proto_tree *vendor_tree; gchar manuf[3]; tvb_memcpy(tvb, manuf, offset, 3); vendor_item = proto_tree_add_text(nhrp_tree, tvb, offset, len, "Extension Data: Vendor ID=%s, Data=%s", get_manuf_name(manuf), tvb_bytes_to_str(tvb, offset + 3, len - 3)); vendor_tree = proto_item_add_subtree(vendor_item, ett_nhrp_vendor_ext); proto_tree_add_bytes_format(vendor_tree, hf_nhrp_vendor_ext_id, tvb, offset, 3, manuf, "Vendor ID: %s", get_manuf_name(manuf)); if (len > 3) { proto_tree_add_text(vendor_tree, tvb, offset + 3, len - 3, "Data: %s", tvb_bytes_to_str(tvb, offset + 3, len - 3)); } } break; default: proto_tree_add_text(nhrp_tree, tvb, offset, len, "Extension Value: %s", tvb_bytes_to_str(tvb, offset, len)); break; } skip_switch: offset += len; } if (!nested) { len = tvb_reported_length_remaining(tvb, offset); if ((extType == NHRP_EXT_NULL) && len) { ti = proto_tree_add_text(tree, tvb, offset, len, "Unknown Data (%d bytes)", len); expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Superfluous data follows End Extension"); break; } } } *pOffset = extEnd; }
static void dissect_dlsw_capex(tvbuff_t *tvb, proto_tree *tree, proto_tree *ti2) { int mlen,vlen,vtype,offset=4,gdsid,sap,i=0; proto_tree *ti,*dlsw_vector_tree; mlen=tvb_get_ntohs(tvb,0); gdsid=tvb_get_ntohs(tvb,2); proto_tree_add_text (tree,tvb,0,2,"Capabilities Length = %d",mlen) ; proto_tree_add_text (tree,tvb,2,2,"%s",val_to_str_const( gdsid, dlsw_gds_vals, "Invalid GDS ID")); proto_item_append_text(ti2," - %s",val_to_str_const( gdsid, dlsw_gds_vals, "Invalid GDS ID")); switch (gdsid) { case DLSW_GDSID_ACK: break; case DLSW_GDSID_REF: proto_tree_add_text (tree,tvb,4,2,"Error pointer = %d",tvb_get_ntohs(tvb,4)); proto_tree_add_text (tree,tvb,6,2,"Error cause = %s", val_to_str_const(tvb_get_ntohs(tvb,6), dlsw_refuse_vals, "Unknown refuse cause")); break; case DLSW_GDSID_SEND: while (offset < mlen){ vlen=tvb_get_guint8(tvb,offset); if (vlen < 3) THROW(ReportedBoundsError); vtype=tvb_get_guint8(tvb,offset+1); ti=proto_tree_add_text (tree,tvb,offset,vlen,"%s", val_to_str_const(vtype,dlsw_vector_vals,"Unknown vector type")); dlsw_vector_tree = proto_item_add_subtree(ti, ett_dlsw_vector); proto_tree_add_text (dlsw_vector_tree,tvb,offset,1, "Vector Length = %d",vlen); proto_tree_add_text (dlsw_vector_tree,tvb,offset+1,1,"Vector Type = %s (0x%02x)", val_to_str_const(vtype,dlsw_vector_vals,"Unknown vector type"), vtype); switch (vtype){ case 0x81: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "OUI = 0x%06x",tvb_get_ntoh24(tvb,offset+2)); break; case 0x82: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "DLSw Version = %d.%d",tvb_get_guint8(tvb,offset+2),tvb_get_guint8(tvb,offset+3)); break; case 0x83: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "Initial Pacing Window = %d",tvb_get_ntohs(tvb,offset+2)); break; case 0x84: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "Version String = %s",tvb_format_text(tvb,offset+2,vlen-2)); break; case 0x85: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "MAC Address Exclusivity = %s",tvb_get_guint8(tvb,offset+2)==1?"On":"Off"); break; case 0x86: while (i<vlen-2) { sap=tvb_get_guint8(tvb,offset+2+i); proto_tree_add_text (dlsw_vector_tree,tvb,offset+2+i,1, "SAP List Support = 0x%x0=%s 0x%x2=%s 0x%x4=%s 0x%x6=%s 0x%x8=%s 0x%xa=%s 0x%xc=%s 0x%xe=%s", i,sap&0x80?"on ":"off",i,sap&0x40?"on ":"off",i,sap&0x20?"on ":"off",i,sap&0x10?"on ":"off", i,sap&0x08?"on ":"off",i,sap&0x04?"on ":"off",i,sap&0x02?"on ":"off",i,sap&0x01?"on ":"off"); i++; } break; case 0x87: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "TCP connections = %d",tvb_get_guint8(tvb,offset+2)); break; case 0x88: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "NetBIOS Name Exclusivity = %s",tvb_get_guint8(tvb,offset+2)==1?"On":"Off"); break; case 0x89: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "MAC Address List = %s / %s",tvb_bytes_to_str(tvb,offset+2,6) ,tvb_bytes_to_str(tvb,offset+8,6)); break; case 0x8a: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, /* %s */ "NetBIOS name = %s",/* tvb_get_guint8(tvb,offset+2)==0?"Individual":"Group",*/ tvb_format_text(tvb,offset+2,vlen-2)); break; case 0x8b: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "Vendor OUI = 0x%06x",tvb_get_ntoh24(tvb,offset+2)); break; case 0x8c: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "Multicast Version Number = %d",tvb_get_guint8(tvb,offset+2)); break; default: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,"Vector Data = ???"); } offset+=vlen; }; break; default: proto_tree_add_text (tree,tvb,4,mlen - 4,"Unknown data"); } }
static void dissect_dlsw_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint version,hlen = 0,mlen = 0,mtype,dlchlen = 0,direction,flags; proto_tree *dlsw_tree = NULL, *ti,*ti2, *dlsw_header_tree = NULL; proto_tree *dlsw_flags_tree,*dlsw_data_tree; col_set_str(pinfo->cinfo, COL_PROTOCOL, "DLSw"); version=tvb_get_guint8(tvb,0); col_add_fstr(pinfo->cinfo, COL_INFO, "DLSw %s",val_to_str_const(version , dlsw_version_vals, "Unknown Version")); if (tree) { ti = proto_tree_add_item(tree, proto_dlsw, tvb, 0, -1, ENC_NA); dlsw_tree = proto_item_add_subtree(ti, ett_dlsw); hlen=tvb_get_guint8(tvb,1); ti2 = proto_tree_add_text (dlsw_tree, tvb, 0, hlen,"DLSw header, %s", val_to_str_const(version , dlsw_version_vals, "Unknown Version")); dlsw_header_tree = proto_item_add_subtree(ti2, ett_dlsw_header); proto_tree_add_text (dlsw_header_tree,tvb,0 ,1,"Version = %s", val_to_str_const(version , dlsw_version_vals, "Unknown Version, dissection may be inaccurate")); proto_tree_add_text (dlsw_header_tree,tvb,1 ,1,"Header Length = %u",hlen) ; mlen=tvb_get_ntohs(tvb,2); proto_tree_add_text (dlsw_header_tree,tvb,2 ,2,"Message Length = %u",mlen); proto_tree_add_text (dlsw_header_tree,tvb,4 ,4,"Remote DLC = %u",tvb_get_ntohl(tvb,4)) ; proto_tree_add_text (dlsw_header_tree,tvb,8 ,4,"Remote DLC PID = %u",tvb_get_ntohl(tvb,8)) ; proto_tree_add_text (dlsw_header_tree,tvb,12,2,"Reserved") ; } ; mtype=tvb_get_guint8(tvb,14); col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",val_to_str_const(mtype , dlsw_type_vals, "Unknown message Type")); if (tree) { proto_tree_add_text (dlsw_header_tree,tvb,14,1,"Message Type = %s (0x%02x)", val_to_str_const(mtype , dlsw_type_vals, "Unknown Type"),mtype); if (mtype==CAP_EXCHANGE) { proto_tree_add_text (dlsw_header_tree,tvb, 15,1,"Not used for CapEx") ; } else { flags = tvb_get_guint8(tvb,15); ti2 = proto_tree_add_text (dlsw_header_tree, tvb, 15,1,"Flow ctrl byte = 0x%02x",flags); dlsw_flags_tree = proto_item_add_subtree(ti2, ett_dlsw_fc); proto_tree_add_item(dlsw_flags_tree, hf_dlsw_flow_control_indication, tvb, 15, 1, ENC_BIG_ENDIAN); if (flags & 0x80) { proto_tree_add_item(dlsw_flags_tree, hf_dlsw_flow_control_ack, tvb, 15, 1, ENC_BIG_ENDIAN); proto_tree_add_item(dlsw_flags_tree, hf_dlsw_flow_control_operator, tvb, 15, 1, ENC_BIG_ENDIAN); } } if (hlen != DLSW_INFO_HEADER) { if (mtype==CAP_EXCHANGE) { proto_tree_add_text (dlsw_header_tree,tvb, 16,1,"Protocol ID = 0x%02x",tvb_get_guint8(tvb,16)) ; proto_tree_add_text (dlsw_header_tree,tvb, 17,1,"Header Number = 0x%02x",tvb_get_guint8(tvb,17)) ; proto_tree_add_text (dlsw_header_tree,tvb, 18,5,"Not used for CapEx") ; proto_tree_add_text (dlsw_header_tree,tvb, 23,1,"Old message type = %s (0x%02x)", val_to_str_const(tvb_get_guint8(tvb,23) , dlsw_type_vals, "Unknown Type"), tvb_get_guint8(tvb,23)); direction=tvb_get_guint8(tvb,38); proto_tree_add_text (dlsw_header_tree,tvb, 24,14,"Not used for CapEx") ; proto_tree_add_text (dlsw_header_tree,tvb, 38,1,"Frame direction = %s (0x%02x)", val_to_str_const(direction , dlsw_capex_type_vals, "Unknown Direction"), direction); proto_tree_add_text (dlsw_header_tree,tvb, 39,33,"Not used for CapEx") ; } else { proto_tree_add_text (dlsw_header_tree,tvb, 16,1,"Protocol ID = 0x%02x",tvb_get_guint8(tvb,16)) ; proto_tree_add_text (dlsw_header_tree,tvb, 17,1,"Header Number = 0x%02x",tvb_get_guint8(tvb,17)) ; proto_tree_add_text (dlsw_header_tree,tvb, 18,2,"Reserved") ; proto_tree_add_text (dlsw_header_tree,tvb, 20,1,"Largest Frame size = %u",tvb_get_guint8(tvb,20)) ; flags = tvb_get_guint8(tvb,21); ti2 = proto_tree_add_text (dlsw_header_tree,tvb, 21,1,"SSP Flags = 0x%02x",flags) ; dlsw_flags_tree = proto_item_add_subtree(ti2, ett_dlsw_sspflags); proto_tree_add_item (dlsw_flags_tree, hf_dlsw_flags_explorer_msg, tvb, 21, 1, ENC_BIG_ENDIAN); proto_tree_add_text (dlsw_header_tree,tvb, 22,1,"Circuit priority = %s", val_to_str((tvb_get_guint8(tvb,22)&7),dlsw_pri_vals, "Unknown (%d)")) ; proto_tree_add_text (dlsw_header_tree,tvb, 23,1,"Old message type = %s (0x%02x)", val_to_str_const(tvb_get_guint8(tvb,23) , dlsw_type_vals, "Unknown Type"), tvb_get_guint8(tvb,23)); proto_tree_add_text (dlsw_header_tree,tvb, 24,6,"Target MAC Address = %s",tvb_bytes_to_str(tvb,24,6)) ; proto_tree_add_text (dlsw_header_tree,tvb, 30,6,"Origin MAC Address = %s",tvb_bytes_to_str(tvb,30,6)) ; proto_tree_add_text (dlsw_header_tree,tvb, 36,1,"Origin Link SAP = 0x%02x",tvb_get_guint8(tvb,36)) ; proto_tree_add_text (dlsw_header_tree,tvb, 37,1,"Target Link SAP = 0x%02x",tvb_get_guint8(tvb,37)) ; direction=tvb_get_guint8(tvb,38); proto_tree_add_text (dlsw_header_tree,tvb, 38,1,"Frame direction = %s (0x%02x)", val_to_str_const(direction , dlsw_frame_direction_vals, "Unknown Direction"), direction); proto_tree_add_text (dlsw_header_tree,tvb, 39,3,"Reserved") ; dlchlen=tvb_get_ntohs(tvb,42); if ( dlchlen > mlen ) { proto_tree_add_text (dlsw_header_tree,tvb, 42,2,"DLC Header Length = %u (bogus, must be <= message length %u)",dlchlen, mlen) ; return; } proto_tree_add_text (dlsw_header_tree,tvb, 42,2,"DLC Header Length = %u",dlchlen) ; proto_tree_add_text (dlsw_header_tree,tvb, 44,4,"Origin DLC Port ID = %u",tvb_get_ntohl(tvb,44)) ; proto_tree_add_text (dlsw_header_tree,tvb, 48,4,"Origin DLC = %u",tvb_get_ntohl(tvb,48)) ; proto_tree_add_text (dlsw_header_tree,tvb, 52,4,"Origin Transport ID = %u",tvb_get_ntohl(tvb,52)) ; proto_tree_add_text (dlsw_header_tree,tvb, 56,4,"Target DLC Port ID = %u",tvb_get_ntohl(tvb,56)) ; proto_tree_add_text (dlsw_header_tree,tvb, 60,4,"Target DLC = %u",tvb_get_ntohl(tvb,60)) ; proto_tree_add_text (dlsw_header_tree,tvb, 64,4,"Target Transport ID = %u",tvb_get_ntohl(tvb,64)) ; proto_tree_add_text (dlsw_header_tree,tvb, 68,4,"Reserved") ; } } /* end of header dissector */ ti2 = proto_tree_add_text (dlsw_tree, tvb, hlen, mlen,"DLSw data"); dlsw_data_tree = proto_item_add_subtree(ti2, ett_dlsw_data); switch (mtype) { case CAP_EXCHANGE: dissect_dlsw_capex(tvb_new_subset(tvb, hlen, mlen, -1), dlsw_data_tree,ti2); break; case IFCM: case INFOFRAME: case KEEPALIVE: proto_tree_add_text (dlsw_data_tree,tvb,hlen,mlen,"Data") ; break; default: if (dlchlen!=0) { proto_tree_add_text (dlsw_data_tree,tvb,hlen,1,"DLC Header - AC byte : 0x%02x",tvb_get_guint8(tvb,hlen)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+1,1,"DLC Header - FC byte : 0x%02x",tvb_get_guint8(tvb,hlen+1)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+2,6,"DLC Header - DA : %s",tvb_bytes_to_str(tvb,hlen+2,6)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+8,6,"DLC Header - SA : %s",tvb_bytes_to_str(tvb,hlen+8,6)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+14,18,"DLC Header - RIF : %s",tvb_bytes_to_str(tvb,hlen+14,18)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+32,1,"DLC Header - DSAP : 0x%02x",tvb_get_guint8(tvb,hlen+32)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+33,1,"DLC Header - SSAP : 0x%02x",tvb_get_guint8(tvb,hlen+33)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+34,1,"DLC Header - Ctrl : 0x%02x",tvb_get_guint8(tvb,hlen+34)) ; } proto_tree_add_text (dlsw_data_tree,tvb,hlen+dlchlen,mlen-dlchlen,"Data") ; } } }