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_ep_str(tvb, offset, ad_len); }
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_ep_str(tvb, offset, value_length)); }
static proto_tree * add_octetstring_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int name_length, int value_length) { return proto_tree_add_subtree_format(tree, tvb, offset, 1 + 2 + name_length + 2 + value_length, ett_ipp_attr, NULL, "%s: %s", tvb_format_text(tvb, offset + 1 + 2, name_length), tvb_bytes_to_ep_str(tvb, offset + 1 + 2 + name_length + 2, value_length)); }
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_ep_str(tvb, offset, ad_len); }
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; len = tvb_length(tvb->ws_tvb); str = ep_strdup_printf("TVB(%i) : %s",len,tvb_bytes_to_ep_str(tvb->ws_tvb,0,len)); lua_pushstring(L,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_ep_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, const 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_ep_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; }
static int dissect_bt_dht_nodes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const 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_ep_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; }
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_ep_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); } }
static void dissect_bfd_authentication(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 24; guint8 auth_type; guint8 auth_len; proto_item *ti = NULL; proto_item *auth_item = NULL; proto_tree *auth_tree = NULL; guint8 *password; auth_type = tvb_get_guint8(tvb, offset); auth_len = tvb_get_guint8(tvb, offset + 1); if (tree) { auth_tree = proto_tree_add_subtree_format(tree, tvb, offset, auth_len, ett_bfd_auth, NULL, "Authentication: %s", val_to_str(auth_type, bfd_control_auth_type_values, "Unknown Authentication Type (%d)") ); proto_tree_add_item(auth_tree, hf_bfd_auth_type, tvb, offset, 1, ENC_BIG_ENDIAN); ti = proto_tree_add_item(auth_tree, hf_bfd_auth_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); proto_item_append_text(ti, " bytes"); proto_tree_add_item(auth_tree, hf_bfd_auth_key, tvb, offset + 2, 1, ENC_BIG_ENDIAN); } switch (auth_type) { case BFD_AUTH_SIMPLE: if (tree) { password = tvb_get_string_enc(wmem_packet_scope(), tvb, offset+3, auth_len-3, ENC_ASCII); proto_tree_add_string(auth_tree, hf_bfd_auth_password, tvb, offset+3, auth_len-3, password); proto_item_append_text(auth_item, ": %s", password); } break; case BFD_AUTH_MD5: case BFD_AUTH_MET_MD5: case BFD_AUTH_SHA1: case BFD_AUTH_MET_SHA1: if (auth_len != get_bfd_required_auth_len(auth_type)) { if (tree) { ti = proto_tree_add_text(auth_tree, tvb, offset, auth_len, "Length of authentication is invalid (%d)", auth_len); proto_item_append_text(auth_item, ": Invalid Authentication Section"); } expert_add_info_format(pinfo, ti, &ei_bfd_auth_len_invalid, "Length of authentication section is invalid for Authentication Type: %s", val_to_str(auth_type, bfd_control_auth_type_values, "Unknown Authentication Type (%d)") ); } if (tree) { proto_tree_add_item(auth_tree, hf_bfd_auth_seq_num, tvb, offset+4, 4, ENC_BIG_ENDIAN); proto_tree_add_text(auth_tree, tvb, offset+8, get_bfd_checksum_len(auth_type), "Checksum: 0x%s", tvb_bytes_to_ep_str(tvb, offset+8, get_bfd_checksum_len(auth_type)) ); } break; default: break; } }
/* * dissect_pgm - The dissector for Pragmatic General Multicast */ static void dissect_pgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 pgmhdr_sport; guint16 pgmhdr_dport; guint8 pgmhdr_type; guint8 pgmhdr_opts; guint16 pgmhdr_cksum; guint16 pgmhdr_tsdulen; guint32 sqn; guint16 afi; guint plen = 0; proto_item *ti; const char *pktname; const char *pollstname; char *gsi; gboolean isdata = FALSE; guint pgmlen, reportedlen; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PGM"); col_clear(pinfo->cinfo, COL_INFO); if (tvb_reported_length_remaining(tvb, 0) < 18) { col_set_str(pinfo->cinfo, COL_INFO, "Packet too small"); return; } pinfo->srcport = pgmhdr_sport = tvb_get_ntohs(tvb, 0); pinfo->destport = pgmhdr_dport = tvb_get_ntohs(tvb, 2); pgmhdr_type = tvb_get_guint8(tvb, 4); pktname = val_to_str(pgmhdr_type, type_vals, "Unknown (0x%02x)"); pgmhdr_opts = tvb_get_guint8(tvb, 5); pgmhdr_cksum = tvb_get_ntohs(tvb, 6); gsi = tvb_bytes_to_ep_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: col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s", pktname, sqn, gsi); break; case PGM_RDATA_PCKT: case PGM_ODATA_PCKT: col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s tsdulen %d", pktname, sqn, gsi, pgmhdr_tsdulen); isdata = TRUE; break; case PGM_POLL_PCKT: { guint16 poll_stype = tvb_get_ntohs(tvb, 22); pollstname = val_to_str(poll_stype, poll_subtype_vals, "Unknown (0x%02x)"); col_add_fstr(pinfo->cinfo, COL_INFO, "%-5s sqn 0x%x gsi %s subtype %s", pktname, sqn, gsi, pollstname); } break; default: return; } { proto_tree *pgm_tree = NULL; proto_tree *opt_tree = NULL; proto_tree *type_tree = NULL; proto_item *tf, *hidden_item; ptvcursor_t* cursor; ti = proto_tree_add_protocol_format(tree, proto_pgm, tvb, 0, -1, "Pragmatic General Multicast: Type %s" " Src Port %u, Dst Port %u, GSI %s", pktname, pgmhdr_sport, pgmhdr_dport, gsi); pgm_tree = proto_item_add_subtree(ti, ett_pgm); cursor = ptvcursor_new(pgm_tree, tvb, 0); hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 0, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 2, 2, ENC_BIG_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); ptvcursor_add(cursor, hf_pgm_main_sport, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_dport, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_type, 1, ENC_BIG_ENDIAN); tf = proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_opts, tvb, ptvcursor_current_offset(cursor), 1, pgmhdr_opts, "%s (0x%x)", optsstr(pgmhdr_opts), pgmhdr_opts); opt_tree = proto_item_add_subtree(tf, ett_pgm_optbits); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_opt, 1, ENC_BIG_ENDIAN); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_netsig, 1, ENC_BIG_ENDIAN); ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_varlen, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_main_opts_parity, 1, ENC_BIG_ENDIAN); ptvcursor_set_tree(cursor, pgm_tree); /* Checksum may be 0 (not available), but not for DATA packets */ if ((pgmhdr_type != PGM_RDATA_PCKT) && (pgmhdr_type != PGM_ODATA_PCKT) && (pgmhdr_cksum == 0)) { proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "not available"); } else { reportedlen = tvb_reported_length(tvb); pgmlen = tvb_length(tvb); if (pgm_check_checksum && pgmlen >= reportedlen) { vec_t cksum_vec[1]; guint16 computed_cksum; SET_CKSUM_VEC_TVB(cksum_vec[0], tvb, 0, pgmlen); computed_cksum = in_cksum(&cksum_vec[0], 1); if (computed_cksum == 0) { proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "0x%04x [correct]", pgmhdr_cksum); } else { hidden_item = proto_tree_add_boolean(pgm_tree, hf_pgm_main_cksum_bad, tvb, ptvcursor_current_offset(cursor), 2, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb, ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "0x%04x [incorrect, should be 0x%04x]", pgmhdr_cksum, in_cksum_shouldbe(pgmhdr_cksum, computed_cksum)); } } else { ptvcursor_add_no_advance(cursor, hf_pgm_main_cksum, 2, ENC_BIG_ENDIAN); } } ptvcursor_advance(cursor, 2); ptvcursor_add(cursor, hf_pgm_main_gsi, 6, ENC_NA); ptvcursor_add(cursor, hf_pgm_main_tsdulen, 2, ENC_BIG_ENDIAN); switch(pgmhdr_type) { case PGM_SPM_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_spm, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_lead, 4, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_spm_pathafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_res, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_spm_path, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_spm_path6, 16, ENC_NA); break; default: expert_add_info(pinfo, ti, &ei_address_format_invalid); ptvcursor_free(cursor); return; } break; case PGM_RDATA_PCKT: case PGM_ODATA_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_data, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN); break; case PGM_NAK_PCKT: case PGM_NNAK_PCKT: case PGM_NCF_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_nak, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_nak_sqn, 4, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_nak_srcafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_nak_srcres, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_nak_src, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_nak_src6, 16, ENC_NA); break; default: expert_add_info(pinfo, ti, &ei_address_format_invalid); break; } afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_nak_grpafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_nak_grpres, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_nak_grp, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_nak_grp6, 16, ENC_NA); break; default: expert_add_info(pinfo, ti, &ei_address_format_invalid); ptvcursor_free(cursor); return; } break; case PGM_POLL_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_poll, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_poll_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_round, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_subtype, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ti = ptvcursor_add(cursor, hf_pgm_poll_pathafi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_res, 2, ENC_BIG_ENDIAN); switch (afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_poll_path, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_poll_path6, 16, ENC_NA); break; default: expert_add_info(pinfo, ti, &ei_address_format_invalid); break; } ptvcursor_add(cursor, hf_pgm_poll_backoff_ivl, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_rand_str, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_poll_matching_bmask, 4, ENC_BIG_ENDIAN); break; case PGM_POLR_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_polr, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_polr_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_polr_round, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_polr_res, 2, ENC_BIG_ENDIAN); break; case PGM_ACK_PCKT: type_tree = proto_tree_add_subtree_format(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, ett_pgm_ack, NULL, "%s Packet", pktname); ptvcursor_set_tree(cursor, type_tree); ptvcursor_add(cursor, hf_pgm_ack_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_ack_bitmap, 4, ENC_BIG_ENDIAN); break; } if (pgmhdr_opts & PGM_OPT) dissect_pgmopts(cursor, pinfo, pktname); if (isdata) decode_pgm_ports(tvb, ptvcursor_current_offset(cursor), pinfo, tree, pgmhdr_sport, pgmhdr_dport); ptvcursor_free(cursor); } }