static void dissect_epmd_response(ptvcursor_t *cursor) { tvbuff_t *tvb; guint32 port; guint8 type; tvb = ptvcursor_tvbuff(cursor); port = tvb_get_ntohl(tvb, 0); if (port == EPMD_PORT) { dissect_epmd_response_names(cursor); return; } type = tvb_get_guint8(tvb, 0); ptvcursor_add(cursor, hf_epmd_type, 1, FALSE); switch (type) { case EPMD_PORT_PLEASE2_OK: { ptvcursor_advance(cursor, 1); /* 'w', 0, Port(16), Type(8), Proto(8), High(16), Low(16), NLen(16), Name(x) */ ptvcursor_add(cursor, hf_epmd_tcp_port, 2, FALSE); ptvcursor_advance(cursor, 2); /* 'M', 0 */ ptvcursor_add(cursor, hf_epmd_dist_high, 2, FALSE); ptvcursor_add(cursor, hf_epmd_dist_low, 2, FALSE); ptvcursor_add(cursor, hf_epmd_name_len, 2, FALSE); ptvcursor_add(cursor, hf_epmd_name, -1, FALSE); } case EPMD_ALIVE_OK: case EPMD_ALIVE2_OK: { ptvcursor_add(cursor, hf_epmd_result, 1, FALSE); ptvcursor_add(cursor, hf_epmd_creation, 2, FALSE); } default: break; } }
static void dissect_epmd_request(ptvcursor_t *cursor) { tvbuff_t *tvb; guint8 type; tvb = ptvcursor_tvbuff(cursor); ptvcursor_add(cursor, hf_epmd_len, 2, FALSE); type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_epmd_type, 1, FALSE); switch (type) { case EPMD_ALIVE2: { guint16 name_length, elen; ptvcursor_add(cursor, hf_epmd_tcp_port, 2, FALSE); ptvcursor_advance(cursor,2); /* 'M', 0 */ ptvcursor_add(cursor, hf_epmd_dist_high, 2, FALSE); ptvcursor_add(cursor, hf_epmd_dist_low, 2, FALSE); name_length = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_epmd_name_len, 2, FALSE); ptvcursor_add(cursor, hf_epmd_name, name_length, FALSE); elen = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_epmd_elen, 2, FALSE); if (elen > 0) ptvcursor_add(cursor, hf_epmd_edata, elen, FALSE); break; } case EPMD_PORT_PLEASE: case EPMD_PORT_PLEASE2: /*ptvcursor_add(cursor, hf_epmd_name, tvb_length(tvb)-3, FALSE);*/ ptvcursor_add(cursor, hf_epmd_name, -1, FALSE); break; case EPMD_ALIVE: { ptvcursor_add(cursor, hf_epmd_tcp_port, 2, FALSE); /*ptvcursor_add(cursor, hf_epmd_name, tvb_length(tvb)-3, FALSE);*/ ptvcursor_add(cursor, hf_epmd_name, -1, FALSE); break; } case EPMD_NAMES: 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"); 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); } }
static void dissect_pgmopts(ptvcursor_t* cursor, const char *pktname) { proto_item *tf; proto_tree *opts_tree = NULL; proto_tree *opt_tree = NULL; tvbuff_t *tvb = ptvcursor_tvbuff(cursor); gboolean theend = FALSE; guint16 opts_total_len; guint8 genopts_type; guint8 genopts_len; guint8 opts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); if (opts_type != PGM_OPT_LENGTH) { proto_tree_add_text(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), 1, "%s Options - initial option is %s, should be %s", pktname, val_to_str(opts_type, opt_vals, "Unknown (0x%02x)"), val_to_str(PGM_OPT_LENGTH, opt_vals, "Unknown (0x%02x)")); return; } opts_total_len = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)+2); if (opts_total_len < 4) { proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor)+2, 2, "%s Options (Total Length %u - invalid, must be >= 4)", pktname, opts_total_len); return; } tf = proto_tree_add_text(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), opts_total_len, "%s Options (Total Length %d)", pktname, opts_total_len); opts_tree = proto_item_add_subtree(tf, ett_pgm_opts); ptvcursor_set_tree(cursor, opts_tree); ptvcursor_add(cursor, hf_pgm_opt_type, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_tlen, 2, ENC_BIG_ENDIAN); for (opts_total_len -= 4; !theend && opts_total_len != 0;){ if (opts_total_len < 4) { proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), opts_total_len, "Remaining total options length doesn't have enough for an options header"); break; } genopts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); genopts_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)+1); if (genopts_type & PGM_OPT_END) { genopts_type &= ~PGM_OPT_END; theend = TRUE; } if (genopts_len < 4) { proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len, "Option: %s, Length: %u (invalid, must be >= 4)", val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"), genopts_len); break; } if (opts_total_len < genopts_len) { proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len, "Option: %s, Length: %u (> remaining total options length)", val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"), genopts_len); break; } tf = proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len, "Option: %s, Length: %u", val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"), genopts_len); switch(genopts_type) { case PGM_OPT_JOIN:{ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_join); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_JOIN_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_JOIN_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_join_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_join_minjoin, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_PARITY_PRM:{ guint8 optdata_po; opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_parityprm); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PARITY_PRM_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_PARITY_PRM_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); optdata_po = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); proto_tree_add_uint_format(opt_tree, hf_pgm_opt_parity_prm_po, tvb, ptvcursor_current_offset(cursor), 1, optdata_po, "Parity Parameters: %s (0x%x)", paritystr(optdata_po), optdata_po); ptvcursor_advance(cursor, 1); ptvcursor_add(cursor, hf_pgm_opt_parity_prm_prmtgsz, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_PARITY_GRP:{ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_paritygrp); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PARITY_GRP_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_PARITY_GRP_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_parity_grp_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_parity_grp_prmgrp, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_NAK_LIST:{ guint8 optdata_len; guint32 naklist[PGM_MAX_NAK_LIST_SZ+1]; unsigned char *nakbuf; gboolean firsttime; int i, j, naks, soffset; opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_naklist); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); optdata_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_res, 1, ENC_BIG_ENDIAN); optdata_len -= PGM_OPT_NAK_LIST_SIZE; tvb_memcpy(tvb, (guint8 *)naklist, ptvcursor_current_offset(cursor), optdata_len); firsttime = TRUE; soffset = 0; naks = (optdata_len/sizeof(guint32)); nakbuf = ep_alloc(8192); j = 0; /* * Print out 8 per line */ for (i=0; i < naks; i++) { soffset += MIN(8192-soffset, g_snprintf(nakbuf+soffset, 8192-soffset, "0x%lx ", (unsigned long)g_ntohl(naklist[i]))); if ((++j % 8) == 0) { if (firsttime) { proto_tree_add_bytes_format(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "List(%d): %s", naks, nakbuf); soffset = 0; firsttime = FALSE; } else { proto_tree_add_bytes_format(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "List: %s", nakbuf); soffset = 0; } ptvcursor_advance(cursor, j*4); j = 0; } } if (j) { if (firsttime) { proto_tree_add_bytes_format(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "List(%d): %s", naks, nakbuf); } else { proto_tree_add_bytes_format(opt_tree, hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4, nakbuf, "List: %s", nakbuf); } ptvcursor_advance(cursor, j*4); } break; } case PGM_OPT_PGMCC_DATA:{ guint16 optdata_afi; opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PGMCC_DATA_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_PGMCC_DATA_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccdata_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccdata_tsp, 4, ENC_BIG_ENDIAN); optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_opt_ccdata_afi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccdata_res2, 2, ENC_BIG_ENDIAN); switch (optdata_afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker6, 16, ENC_NA); break; default: proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } break; } case PGM_OPT_PGMCC_FEEDBACK:{ guint16 optdata_afi; opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_PGMCC_FEEDBACK_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_PGMCC_FEEDBACK_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_tsp, 4, ENC_BIG_ENDIAN); optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_afi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_lossrate, 2, ENC_BIG_ENDIAN); switch (optdata_afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker6, 16, ENC_NA); break; default: proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } break; } case PGM_OPT_NAK_BO_IVL:{ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_ivl); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_NAK_BO_IVL_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_NAK_BO_IVL_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl_sqn, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_NAK_BO_RNG:{ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_rng); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_NAK_BO_RNG_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_NAK_BO_RNG_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_min_bo_ivl, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_max_bo_ivl, 4, ENC_BIG_ENDIAN); break; } case PGM_OPT_REDIRECT:{ guint16 optdata_afi; opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_redirect); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_REDIRECT_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_REDIRECT_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_redirect_res, 1, ENC_BIG_ENDIAN); optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_pgm_opt_redirect_afi, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_redirect_res2, 2, ENC_BIG_ENDIAN); switch (optdata_afi) { case AFNUM_INET: ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr, 4, ENC_BIG_ENDIAN); break; case AFNUM_INET6: ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr6, 16, ENC_NA); break; default: proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1, "Can't handle this address format"); break; } break; } case PGM_OPT_FRAGMENT:{ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_fragment); ptvcursor_set_tree(cursor, opt_tree); ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN); if (genopts_len < PGM_OPT_FRAGMENT_SIZE) { proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb, ptvcursor_current_offset(cursor), 1, genopts_len, "Length: %u (bogus, must be >= %u)", genopts_len, PGM_OPT_FRAGMENT_SIZE); break; } ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_res, 1, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_first_sqn, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_offset, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_pgm_opt_fragment_total_length, 4, ENC_BIG_ENDIAN); break; } default:{ ptvcursor_advance(cursor, genopts_len); break; } } opts_total_len -= genopts_len; } return; }
static void dissect_omapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *omapi_tree; ptvcursor_t* cursor; guint32 authlength; guint32 msglength; guint32 objlength; col_set_str(pinfo->cinfo, COL_PROTOCOL, "OMAPI"); col_clear(pinfo->cinfo, COL_INFO); ti = proto_tree_add_item(tree, proto_omapi, tvb, 0, -1, ENC_NA); omapi_tree = proto_item_add_subtree(ti, ett_omapi); cursor = ptvcursor_new(omapi_tree, tvb, 0); if (tvb_reported_length_remaining(tvb, 0) < 8) { /* Payload too small for OMAPI */ DISSECTOR_ASSERT_NOT_REACHED(); } else if (tvb_reported_length_remaining(tvb, 0) < 24) { /* This is a startup message */ ptvcursor_add(cursor, hf_omapi_version, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_hlength, 4, ENC_BIG_ENDIAN); col_set_str(pinfo->cinfo, COL_INFO, "Status message"); proto_item_append_text(ti, ", Status message"); return; } else if ( !(tvb_get_ntohl(tvb, 8) || tvb_get_ntohl(tvb, 12)) ) { /* This is a startup message, and more */ ptvcursor_add(cursor, hf_omapi_version, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_hlength, 4, ENC_BIG_ENDIAN); col_append_str(pinfo->cinfo, COL_INFO, "Status message"); proto_item_append_text(ti, ", Status message"); } ptvcursor_add(cursor, hf_omapi_auth_id, 4, ENC_BIG_ENDIAN); authlength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_omapi_auth_len, 4, ENC_BIG_ENDIAN); col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)), omapi_opcode_vals, "Unknown opcode (0x%04x)")); proto_item_append_text(ti, ", Opcode: %s", val_to_str(tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)), omapi_opcode_vals, "Unknown opcode (0x%04x)")); ptvcursor_add(cursor, hf_omapi_opcode, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_handle, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_id, 4, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_rid, 4, ENC_BIG_ENDIAN); msglength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); while (msglength) { ptvcursor_add(cursor, hf_omapi_msg_name_len, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_msg_name, msglength, ENC_ASCII|ENC_NA); msglength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_omapi_msg_value_len, 4, ENC_BIG_ENDIAN); if (msglength == 0) { proto_tree_add_text(omapi_tree, tvb, 0, 0, "Empty string"); } else if (msglength == (guint32)~0) { proto_tree_add_text(omapi_tree, tvb, 0, 0, "No value"); } else { ptvcursor_add(cursor, hf_omapi_msg_value, msglength, ENC_ASCII|ENC_NA); } msglength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); } proto_tree_add_text(omapi_tree, tvb, ptvcursor_current_offset(cursor), 2, "Message end tag"); ptvcursor_advance(cursor, 2); objlength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); while (objlength) { ptvcursor_add(cursor, hf_omapi_obj_name_len, 2, ENC_BIG_ENDIAN); ptvcursor_add(cursor, hf_omapi_obj_name, objlength, ENC_ASCII|ENC_NA); objlength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)); ptvcursor_add(cursor, hf_omapi_obj_value_len, 4, ENC_BIG_ENDIAN); if (objlength == 0) { proto_tree_add_text(omapi_tree, tvb, 0, 0, "Empty string"); } else if (objlength == (guint32)~0) { proto_tree_add_text(omapi_tree, tvb, 0, 0, "No value"); } else { ptvcursor_add(cursor, hf_omapi_obj_value, objlength, ENC_NA); } objlength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)); } proto_tree_add_text(omapi_tree, tvb, ptvcursor_current_offset(cursor), 2, "Object end tag"); ptvcursor_advance(cursor, 2); if (authlength > 0) { ptvcursor_add(cursor, hf_omapi_signature, authlength, ENC_NA); } }