static void dissect_smb_direct(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, enum SMB_DIRECT_HDR_TYPE hdr_type) { proto_tree *tree = NULL; proto_item *item = NULL; proto_tree *neg_req_tree = NULL; proto_tree *neg_rep_tree = NULL; proto_tree *data_tree = NULL; int offset = 0; guint32 status = 0; guint32 remaining_length = 0; guint32 data_offset = 0; guint32 data_length = 0; guint rlen = tvb_reported_length(tvb); gint len = 0; tvbuff_t *next_tvb = NULL; static const int * flags[] = { &hf_smb_direct_flags_response_requested, NULL }; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMBDirect"); col_clear(pinfo->cinfo, COL_INFO); if (parent_tree != NULL) { item = proto_tree_add_item(parent_tree, proto_smb_direct, tvb, 0, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb_direct); } switch (hdr_type) { case SMB_DIRECT_HDR_UNKNOWN: break; case SMB_DIRECT_HDR_NEG_REQ: col_append_str(pinfo->cinfo, COL_INFO, "NegotiateRequest"); if (tree == NULL) { break; } item = proto_tree_add_item(tree, hf_smb_direct_negotiate_request, tvb, 0, -1, ENC_NA); neg_req_tree = proto_item_add_subtree(item, ett_smb_direct_hdr); proto_tree_add_item(neg_req_tree, hf_smb_direct_min_version, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_req_tree, hf_smb_direct_max_version, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* 2 bytes reserved */ offset += 2; proto_tree_add_item(neg_req_tree, hf_smb_direct_credits_requested, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_req_tree, hf_smb_direct_preferred_send_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_req_tree, hf_smb_direct_max_receive_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_req_tree, hf_smb_direct_max_fragmented_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); /* offset += 4; */ break; case SMB_DIRECT_HDR_NEG_REP: col_append_str(pinfo->cinfo, COL_INFO, "NegotiateResponse"); status = tvb_get_letohl(tvb, 12); if (status != 0) { col_append_fstr( pinfo->cinfo, COL_INFO, ", Error: %s", val_to_str(status, NT_errors, "Unknown (0x%08X)")); } if (tree == NULL) { break; } item = proto_tree_add_item(tree, hf_smb_direct_negotiate_response, tvb, 0, -1, ENC_NA); neg_rep_tree = proto_item_add_subtree(item, ett_smb_direct_hdr); proto_tree_add_item(neg_rep_tree, hf_smb_direct_min_version, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_version, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_rep_tree, hf_smb_direct_negotiated_version, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* 2 bytes reserved */ offset += 2; proto_tree_add_item(neg_rep_tree, hf_smb_direct_credits_requested, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_rep_tree, hf_smb_direct_credits_granted, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(neg_rep_tree, hf_smb_direct_status, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_read_write_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_rep_tree, hf_smb_direct_preferred_send_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_receive_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_fragmented_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); /* offset += 4; */ break; case SMB_DIRECT_HDR_DATA: col_append_str(pinfo->cinfo, COL_INFO, "DataMessage"); if (tree == NULL) { break; } rlen = MIN(rlen, 24); item = proto_tree_add_item(tree, hf_smb_direct_data_message, tvb, 0, rlen, ENC_NA); data_tree = proto_item_add_subtree(item, ett_smb_direct_hdr); proto_tree_add_item(data_tree, hf_smb_direct_credits_requested, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(data_tree, hf_smb_direct_credits_granted, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_bitmask(tree, tvb, offset, hf_smb_direct_flags, ett_smb_direct_flags, flags, ENC_LITTLE_ENDIAN); offset += 2; /* 2 bytes reserved */ offset += 2; remaining_length = tvb_get_letohl(tvb, offset); proto_tree_add_item(data_tree, hf_smb_direct_remaining_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; data_offset = tvb_get_letohl(tvb, offset); proto_tree_add_item(data_tree, hf_smb_direct_data_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; data_length = tvb_get_letohl(tvb, offset); proto_tree_add_item(data_tree, hf_smb_direct_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; if (data_length > 0 && data_offset > (guint32)offset) { len = tvb_reported_length_remaining(tvb, data_offset); } if (data_length <= (guint32)len) { next_tvb = tvb_new_subset_length(tvb, data_offset, data_length); } if (next_tvb != NULL) { dissect_smb_direct_payload(next_tvb, pinfo, parent_tree, remaining_length); } /* offset = data_offset + data_length; */ break; } return; }
static void dissect_itdm_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tvbuff_t *next_tvb; proto_item *itdm_ctl_item = NULL; proto_tree *itdm_ctl_tree = NULL; int offset; guint32 flowid; guint8 command; guint32 trans_id; guint32 paired_trans_id; guint32 allocd_flowid; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ITDM-Control"); flowid = tvb_get_ntoh24(tvb, ITDM_FLOWID_OFFSET); command = tvb_get_guint8(tvb, ITDM_CTL_CMD_OFFSET); allocd_flowid = tvb_get_ntoh24(tvb, ITDM_CTL_FLOWID_OFFSET); trans_id = tvb_get_ntohl(tvb, ITDM_CTL_TRANSID_OFFSET); paired_trans_id = tvb_get_ntohl(tvb, ITDM_CTL_PAIRED_TRANSID_OFFSET); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "Flow %d Command %s ", flowid, val_to_str(command, itdm_ctl_command_vals, "Reserved")); if (command != ITDM_CTL_CMD_AFI_REQ ) { col_append_fstr(pinfo->cinfo, COL_INFO, " Alloc'd FlowID %d", allocd_flowid); } col_append_fstr(pinfo->cinfo, COL_INFO, " TransID 0x%x ", trans_id); if (command != ITDM_CTL_CMD_AFI_REQ ) { col_append_fstr(pinfo->cinfo, COL_INFO, " Paired TransID 0x%x", paired_trans_id); } } offset = 0; if (tree) { itdm_ctl_item = proto_tree_add_item(tree, proto_itdm, tvb, 0, -1, ENC_NA); itdm_ctl_tree = proto_item_add_subtree(itdm_ctl_item, ett_itdm_ctl); /* These eventually should go into a SFP.0 dissector... */ proto_tree_add_item(itdm_ctl_tree, hf_itdm_timestamp, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(itdm_ctl_tree, hf_itdm_seqnum, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(itdm_ctl_tree, hf_itdm_sop_eop, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(itdm_ctl_tree, hf_itdm_last_pack, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(itdm_ctl_tree, hf_itdm_pktlen, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(itdm_ctl_tree, hf_itdm_chksum, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(itdm_ctl_tree, hf_itdm_uid, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_transid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_command, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (command != ITDM_CTL_CMD_AFI_REQ) { proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_flowid, tvb, offset, 3, ENC_BIG_ENDIAN); } offset += 3; proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_dm, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* rsvd.. */ offset += 1; proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_emts, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_pktrate, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; if (command != ITDM_CTL_CMD_AFI_REQ) { proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_ptid, tvb, offset, 4, ENC_BIG_ENDIAN); } offset += 4; /* rsvd.. */ offset += 2; proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_cksum, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, tree); }
proto_item *ti, *op_ti; gint start_offset, offset = 0; guint8 opcode; col_set_str (pinfo->cinfo, COL_PROTOCOL, "NAT-PMP"); col_clear (pinfo->cinfo, COL_INFO); start_offset = offset; ti = proto_tree_add_item (tree, proto_nat_pmp, tvb, offset, -1, ENC_NA); nat_pmp_tree = proto_item_add_subtree (ti, ett_nat_pmp); proto_tree_add_item (nat_pmp_tree, hf_version, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; opcode = tvb_get_guint8 (tvb, offset); proto_item_append_text (ti, ", %s", val_to_str (opcode, opcode_vals, "Unknown opcode: %d")); op_ti = proto_tree_add_item (nat_pmp_tree, hf_opcode, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; col_add_str (pinfo->cinfo, COL_INFO, val_to_str (opcode, opcode_vals, "Unknown opcode: %d")); switch (opcode) { case EXTERNAL_ADDRESS_REQUEST: /* No more data */ break; case EXTERNAL_ADDRESS_RESPONSE: proto_tree_add_item (nat_pmp_tree, hf_result_code, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
/* * 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 guint dissect_ssprotocol_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *ssprotocol_tree) { proto_item* flags_item; proto_tree* flags_tree; guint8 type; guint16 data_length; guint16 info_length; guint total_length; type = tvb_get_guint8(message_tvb, MESSAGE_TYPE_OFFSET); if (pinfo && (check_col(pinfo->cinfo, COL_INFO))) { col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, message_type_values, "Unknown SSP type: %u")); } proto_tree_add_item(ssprotocol_tree, hf_message_type, message_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, FALSE); flags_item = proto_tree_add_item(ssprotocol_tree, hf_message_flags, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, FALSE); proto_tree_add_item(ssprotocol_tree, hf_message_length, message_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, FALSE); total_length = MESSAGE_LENGTH_OFFSET + MESSAGE_LENGTH_LENGTH; switch (type) { case SS_KEEPALIVE_ACK_TYPE: case SS_STATUS_TYPE: info_length = tvb_get_ntohs(message_tvb, MESSAGE_LENGTH_OFFSET) - MESSAGE_STATUS_OFFSET; if (info_length == MESSAGE_STATUS_LENGTH) { proto_tree_add_item(ssprotocol_tree, hf_message_status, message_tvb, MESSAGE_STATUS_OFFSET, MESSAGE_STATUS_LENGTH, FALSE); total_length += MESSAGE_STATUS_LENGTH; } break; case SS_UPLOAD_TYPE: case SS_DOWNLOAD_TYPE: data_length = tvb_get_ntohs(message_tvb, MESSAGE_LENGTH_OFFSET) - MESSAGE_DATA_OFFSET; if (data_length > 0) { proto_tree_add_item(ssprotocol_tree, hf_message_data, message_tvb, MESSAGE_DATA_OFFSET, data_length, FALSE); total_length += data_length; } break; case SS_READY_TYPE: info_length = tvb_get_ntohs(message_tvb, MESSAGE_LENGTH_OFFSET) - MESSAGE_RDY_INFO_OFFSET; if (info_length > 0) { proto_tree_add_item(ssprotocol_tree, hf_message_info, message_tvb, MESSAGE_RDY_INFO_OFFSET, info_length, FALSE); total_length += info_length; } break; case SS_NOTREADY_TYPE: info_length = tvb_get_ntohs(message_tvb, MESSAGE_LENGTH_OFFSET) - MESSAGE_NOTRDY_INFO_OFFSET; if (info_length > 0) { proto_tree_add_item(ssprotocol_tree, hf_message_reason, message_tvb, MESSAGE_NOTRDY_REASON_OFFSET, MESSAGE_NOTRDY_REASON_LENGTH, FALSE); proto_tree_add_item(ssprotocol_tree, hf_message_info, message_tvb, MESSAGE_NOTRDY_INFO_OFFSET, info_length, FALSE); total_length += info_length; } break; case SS_ENVIRONMENT_TYPE: flags_tree = proto_item_add_subtree(flags_item, ett_environment_flags); proto_tree_add_item(flags_tree, hf_environment_u_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, ENC_BIG_ENDIAN); proto_tree_add_item(ssprotocol_tree, hf_message_hash, message_tvb, MESSAGE_ENVIRON_HASH_OFFSET, MESSAGE_ENVIRON_HASH_LENGTH, FALSE); break; default: break; } return total_length; }
static int dissect_remunk_remqueryinterface_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) { guint32 u32Pointer; guint32 u32ArraySize; guint32 u32ItemIdx; proto_item *sub_item; proto_tree *sub_tree; guint32 u32HResult; guint32 u32SubStart; e_uuid_t iid; e_uuid_t iid_null = DCERPC_UUID_NULL; remunk_remqueryinterface_call_t *call = (remunk_remqueryinterface_call_t *)di->call_data->private_data; guint64 oxid; guint64 oid; e_uuid_t ipid; offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer); offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, &u32ArraySize); u32ItemIdx = 1; while (u32ArraySize--) { /* add subtree */ sub_item = proto_tree_add_item(tree, hf_remunk_qiresult, tvb, offset, 0, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_remunk_rqi_result); /* REMQIRESULT */ offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, &u32HResult); u32SubStart = offset - 4; offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer); /* try to read the iid from the request */ if(call != NULL && u32ItemIdx <= call->iid_count) { iid = call->iids[u32ItemIdx-1]; } else { iid = iid_null; } /* XXX - this doesn't seem to be dependent on the pointer above?!? */ /*if (u32Pointer) {*/ offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, 0 /* hfindex */, &oxid, &oid, &ipid); /*}*/ /* add interface instance to database (we currently only handle IPv4) */ if(pinfo->net_src.type == AT_IPv4) { dcom_interface_new(pinfo, (guint8 *)pinfo->net_src.data, &iid, oxid, oid, &ipid); } /* update subtree */ proto_item_append_text(sub_item, "[%u]: %s", u32ItemIdx, val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); proto_item_set_len(sub_item, offset - u32SubStart); /* update column info now */ col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]", val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)"), u32ItemIdx); u32ItemIdx++; } /* HRESULT of call */ offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, &u32HResult); /* update column info now */ col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)")); return offset; }
static int ros_try_string(const char *oid, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, struct SESSION_DATA_STRUCTURE* session) { ros_info_t *rinfo; gint32 opcode_lcl = 0; const gchar *opname = NULL; const gchar *suffix = NULL; dissector_t opdissector = NULL; const value_string *lookup; proto_item *item=NULL; proto_tree *ros_tree=NULL; if((session != NULL) && ((rinfo = (ros_info_t*)g_hash_table_lookup(protocol_table, oid)) != NULL)) { if(tree){ item = proto_tree_add_item(tree, *(rinfo->proto), tvb, 0, -1, ENC_NA); ros_tree = proto_item_add_subtree(item, *(rinfo->ett_proto)); } col_set_str(pinfo->cinfo, COL_PROTOCOL, rinfo->name); /* if this is a bind operation */ if((session->ros_op & ROS_OP_TYPE_MASK) == ROS_OP_BIND) { /* use the in-built operation codes */ if((session->ros_op & ROS_OP_PDU_MASK) == ROS_OP_ERROR) opcode_lcl = err_ros_bind; else opcode_lcl = op_ros_bind; } else /* otherwise just take the opcode */ opcode_lcl = session->ros_op & ROS_OP_OPCODE_MASK; /* default lookup in the operations */ lookup = rinfo->opr_code_strings; switch(session->ros_op & ROS_OP_PDU_MASK) { case ROS_OP_ARGUMENT: opdissector = ros_lookup_opr_dissector(opcode_lcl, rinfo->opr_code_dissectors, TRUE); suffix = "_argument"; break; case ROS_OP_RESULT: opdissector = ros_lookup_opr_dissector(opcode_lcl, rinfo->opr_code_dissectors, FALSE); suffix = "_result"; break; case ROS_OP_ERROR: opdissector = ros_lookup_err_dissector(opcode_lcl, rinfo->err_code_dissectors); lookup = rinfo->err_code_strings; break; default: break; } if(opdissector) { opname = val_to_str(opcode_lcl, lookup, "Unknown opcode (%d)"); col_set_str(pinfo->cinfo, COL_INFO, opname); if(suffix) col_append_str(pinfo->cinfo, COL_INFO, suffix); return (*opdissector)(tvb, pinfo, ros_tree, NULL); } } return 0; }
static gboolean dissect_fcip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean check_port) { gint offset = 0, start = 0, frame_len = 0; gint bytes_remaining = tvb_length (tvb); guint8 pflags, sof = 0, eof = 0; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *fcip_tree = NULL; tvbuff_t *next_tvb; if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) { return FALSE; } if (check_port && ((pinfo->srcport != fcip_port) && (pinfo->destport != fcip_port))) { return FALSE; } while (bytes_remaining > FCIP_ENCAP_HEADER_LEN) { if ((offset = get_next_fcip_header_offset (tvb, pinfo, offset)) == -1) { return FALSE; } else if (offset == -2) { /* We need more data to desegment */ return (TRUE); } start = offset; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCIP"); frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4; if (bytes_remaining < frame_len) { if(fcip_desegment && pinfo->can_desegment) { /* * This frame doesn't have all of the data for * this message, but we can do reassembly on it. * * Tell the TCP dissector where the data for this * message starts in the data it handed us, and * how many more bytes we need, and return. */ pinfo->desegment_offset = offset; pinfo->desegment_len = frame_len - bytes_remaining; return (TRUE); } } pflags = tvb_get_guint8 (tvb, start+8); if (tree) { if (FCIP_IS_SF (pflags)) { ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0, FCIP_ENCAP_HEADER_LEN, "FCIP"); } else if (tvb_bytes_exist (tvb, offset, offset+frame_len-4)) { sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN); eof = tvb_get_guint8 (tvb, offset+frame_len - 4); ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0, FCIP_ENCAP_HEADER_LEN, "FCIP (%s/%s)", val_to_str (sof, fcip_sof_vals, "0x%x"), val_to_str (eof, fcip_eof_vals, "0x%x")); } else { sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN); ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0, FCIP_ENCAP_HEADER_LEN, "FCIP (%s/%s)", val_to_str (sof, fcip_sof_vals, "0x%x"), "NA"); } fcip_tree = proto_item_add_subtree (ti, ett_fcip); /* Dissect the Common FC Encap header */ dissect_fcencap_header (tvb, fcip_tree, offset); offset += FCIP_ENCAP_HEADER_LEN; if (!FCIP_IS_SF (pflags)) { /* print SOF */ proto_tree_add_item (fcip_tree, hf_fcip_sof, tvb, offset, 1, 0); proto_tree_add_item (fcip_tree, hf_fcip_sof_c, tvb, offset+2, 1, 0); /* print EOF */ offset += (frame_len-FCIP_ENCAP_HEADER_LEN-4); if (tvb_bytes_exist (tvb, offset, 4)) { proto_tree_add_item (fcip_tree, hf_fcip_eof, tvb, offset, 1, 0); proto_tree_add_item (fcip_tree, hf_fcip_eof_c, tvb, offset+2, 1, 0); } } } /* Call the FC Dissector if this is carrying an FC frame */ if (!FCIP_IS_SF(pflags)) { /* Set the SOF/EOF flags in the packet_info header */ pinfo->sof_eof = 0; if (sof) { if ((sof == FCIP_SOFi3) || (sof == FCIP_SOFi2) || (sof == FCIP_SOFi4)) { pinfo->sof_eof = PINFO_SOF_FIRST_FRAME; } else if (sof == FCIP_SOFf) { pinfo->sof_eof = PINFO_SOF_SOFF; } if (eof != FCIP_EOFn) { pinfo->sof_eof |= PINFO_EOF_LAST_FRAME; } else if (eof != FCIP_EOFt) { pinfo->sof_eof |= PINFO_EOF_INVALID; } } /* Special frame bit is not set */ next_tvb = tvb_new_subset_remaining (tvb, FCIP_ENCAP_HEADER_LEN+4); if (fc_handle) { call_dissector (fc_handle, next_tvb, pinfo, tree); } else if (data_handle) { call_dissector (data_handle, next_tvb, pinfo, tree); } } else { col_set_str(pinfo->cinfo, COL_INFO, "Special Frame"); if (FCIP_IS_CH (pflags)) { col_append_str(pinfo->cinfo, COL_INFO, "(Changed)"); } dissect_fcip_sf (tvb, fcip_tree, offset+4); } bytes_remaining -= frame_len; } return (TRUE); }
/* This function is only called from the IGMP dissector */ int dissect_pimv1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) { guint8 pim_type; guint8 pim_ver; guint length, pim_length; guint16 pim_cksum, computed_cksum; vec_t cksum_vec[1]; proto_tree *pim_tree = NULL; proto_item *ti; proto_tree *pimopt_tree = NULL; proto_item *tiopt; if (!proto_is_protocol_enabled(find_protocol_by_id(proto_pim))) { /* * We are not enabled; skip entire packet to be nice to the * IGMP layer (so clicking on IGMP will display the data). */ return offset+tvb_length_remaining(tvb, offset); } col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIMv1"); col_clear(pinfo->cinfo, COL_INFO); ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, FALSE); pim_tree = proto_item_add_subtree(ti, ett_pim); /* Put IGMP type, 0x14, into the tree */ proto_tree_add_text(pim_tree, tvb, offset, 1, "Type: PIM (0x14)"); offset += 1; pim_type = tvb_get_guint8(tvb, offset); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pim_type, type1vals, "Unknown (%u)")); proto_tree_add_uint(pim_tree, hf_pim_code, tvb, offset, 1, pim_type); offset += 1; pim_cksum = tvb_get_ntohs(tvb, offset); pim_ver = PIM_VER(tvb_get_guint8(tvb, offset + 2)); if (pim_ver != 1) { /* * Not PIMv1 - what gives? */ proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb, offset, 2, pim_cksum); offset += 2; proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, FALSE); return offset+tvb_length_remaining(tvb, offset); } /* * Well, it's PIM v1, so we can check whether this is a * Register message, and thus can figure out how much to * checksum and whether to make the columns read-only. */ length = tvb_length(tvb); if (pim_type == 1) { /* * Register message - the PIM header is 8 bytes long. * Also set the columns non-writable. Otherwise the IPv4 or * IPv6 dissector for the encapsulated packet that caused * this register will overwrite the PIM info in the columns. */ pim_length = 8; col_set_writable(pinfo->cinfo, FALSE); } else { /* * Other message - checksum the entire packet. */ pim_length = tvb_reported_length(tvb); } if (!pinfo->fragmented && length >= pim_length) { /* * The packet isn't part of a fragmented datagram and isn't * truncated, so we can checksum it. */ cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length); cksum_vec[0].len = pim_length; computed_cksum = in_cksum(&cksum_vec[0], 1); if (computed_cksum == 0) { proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb, offset, 2, pim_cksum, "Checksum: 0x%04x [correct]", pim_cksum); } else { proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb, offset, 2, pim_cksum, "Checksum: 0x%04x [incorrect, should be 0x%04x]", pim_cksum, in_cksum_shouldbe(pim_cksum, computed_cksum)); } } else { proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb, offset, 2, pim_cksum); } offset += 2; proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, FALSE); offset += 1; offset += 3; /* skip reserved stuff */ if (tvb_reported_length_remaining(tvb, offset) > 0) { tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1, "PIM options"); pimopt_tree = proto_item_add_subtree(tiopt, ett_pim_opts); } else goto done; /* version 1 decoder */ switch (pim_type) { case 0: /* query */ { guint16 holdtime; proto_tree_add_item(pimopt_tree, hf_pim_mode, tvb, offset, 1, FALSE); offset += 2; holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; break; } case 1: /* register */ { guint8 v_hl; tvbuff_t *next_tvb; /* * The rest of the packet is a multicast data packet. */ next_tvb = tvb_new_subset_remaining(tvb, offset); /* * It's an IP packet - determine whether it's IPv4 or IPv6. */ v_hl = tvb_get_guint8(tvb, offset); switch((v_hl & 0xf0) >> 4) { case 0: /* Null-Register dummy header. * Has the same address family as the encapsulating PIM packet, * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet. */ if (pinfo->src.type == AT_IPv4) { proto_tree_add_text(pimopt_tree, tvb, offset, -1, "IPv4 dummy header"); proto_tree_add_text(pimopt_tree, tvb, offset + 12, 4, "Source: %s", tvb_ip_to_str(tvb, offset + 12)); proto_tree_add_text(pimopt_tree, tvb, offset + 16, 4, "Group: %s", tvb_ip_to_str(tvb, offset + 16)); } else if (pinfo->src.type == AT_IPv6) { proto_tree_add_text(pimopt_tree, tvb, offset, -1, "IPv6 dummy header"); proto_tree_add_text(pimopt_tree, tvb, offset + 8, 16, "Source: %s", tvb_ip6_to_str(tvb, offset + 8)); proto_tree_add_text(pimopt_tree, tvb, offset + 8 + 16, 16, "Group: %s", tvb_ip6_to_str(tvb, offset + 8)); } else proto_tree_add_text(pimopt_tree, tvb, offset, -1, "Dummy header for an unknown protocol"); break; case 4: /* IPv4 */ #if 0 call_dissector(ip_handle, next_tvb, pinfo, tree); #else call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree); #endif break; case 6: /* IPv6 */ #if 0 call_dissector(ipv6_handle, next_tvb, pinfo, tree); #else call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree); #endif break; default: proto_tree_add_text(pimopt_tree, tvb, offset, -1, "Unknown IP version %d", (v_hl & 0xf0) >> 4); break; } break; } case 2: /* register-stop */ { proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group: %s", tvb_ip_to_str(tvb, offset)); offset += 4; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Source: %s", tvb_ip_to_str(tvb, offset)); offset += 4; break; } case 3: /* join/prune */ case 6: /* graft */ case 7: /* graft-ack */ { int off; const char *s; int ngroup, i, njoin, nprune, j; guint16 holdtime; guint8 mask_len; guint8 adr_len; proto_tree *grouptree = NULL; proto_item *tigroup; proto_tree *subtree = NULL; proto_item *tisub; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Upstream-neighbor: %s", tvb_ip_to_str(tvb, offset)); offset += 4; offset += 2; /* skip reserved stuff */ holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; offset += 1; /* skip reserved stuff */ mask_len = tvb_get_guint8(tvb, offset); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Mask length: %u", mask_len); offset += 1; adr_len = tvb_get_guint8(tvb, offset); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Address length: %u", adr_len); offset += 1; ngroup = tvb_get_guint8(tvb, offset); proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, FALSE); offset += 1; for (i = 0; i < ngroup; i++) { /* * XXX - does the group address have the length "adr_len" * and the group mask the length "mask_len"? */ tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group %d: %s", i, tvb_ip_to_str(tvb, offset)); grouptree = proto_item_add_subtree(tigroup, ett_pim); offset += 4; proto_tree_add_text(grouptree, tvb, offset, 4, "Group %d Mask: %s", i, tvb_ip_to_str(tvb, offset)); offset += 4; njoin = tvb_get_ntohs(tvb, offset); nprune = tvb_get_ntohs(tvb, offset + 2); tisub = proto_tree_add_item(grouptree, hf_pim_numjoins, tvb, offset, 2, FALSE); subtree = proto_item_add_subtree(tisub, ett_pim); off = offset + 4; for (j = 0; j < njoin; j++) { s = dissect_pimv1_addr(tvb, off); proto_tree_add_text(subtree, tvb, off, 6, "IP address: %s", s); off += 6; } tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb, offset + 2, 2, FALSE); subtree = proto_item_add_subtree(tisub, ett_pim); for (j = 0; j < nprune; j++) { s = dissect_pimv1_addr(tvb, off); proto_tree_add_text(subtree, tvb, off, 6, "IP address: %s", s); off += 6; } offset = off; } break; } case 4: /* rp-reachability */ { guint16 holdtime; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group Address: %s", tvb_ip_to_str(tvb, offset)); offset += 4; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group Mask: %s", tvb_ip_to_str(tvb, offset)); offset += 4; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "RP Address: %s", tvb_ip_to_str(tvb, offset)); offset += 4; offset += 2; /* skip reserved stuff */ holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; break; } case 5: /* assert */ { guint32 pref; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group Address: %s", tvb_ip_to_str(tvb, offset)); offset += 4; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group Mask: %s", tvb_ip_to_str(tvb, offset)); offset += 4; proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, FALSE); pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff; proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb, offset, 4, pref, "Metric Preference: %u", pref); offset += 4; proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, FALSE); offset += 4; break; } default: break; } done:; return offset+tvb_length_remaining(tvb, offset); }
static void dissect_eapol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; guint8 eapol_type; guint8 keydesc_type; guint16 eapol_len; guint len; guint16 eapol_key_len, eapol_data_len; guint8 key_index; guint16 keyinfo; proto_tree *ti = NULL; proto_tree *eapol_tree = NULL; proto_tree *keyinfo_item = NULL; proto_tree *keyinfo_tree = NULL; proto_tree *key_index_tree, *keydes_tree; tvbuff_t *next_tvb; col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAPOL"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { ti = proto_tree_add_item(tree, proto_eapol, tvb, 0, -1, ENC_NA); eapol_tree = proto_item_add_subtree(ti, ett_eapol); proto_tree_add_item(eapol_tree, hf_eapol_version, tvb, offset, 1, ENC_BIG_ENDIAN); } offset++; eapol_type = tvb_get_guint8(tvb, offset); if (tree) proto_tree_add_uint(eapol_tree, hf_eapol_type, tvb, offset, 1, eapol_type); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, val_to_str(eapol_type, eapol_type_vals, "Unknown type (0x%02X)")); offset++; eapol_len = tvb_get_ntohs(tvb, offset); len = EAPOL_HDR_LEN + eapol_len; set_actual_length(tvb, len); if (tree) { proto_item_set_len(ti, len); proto_tree_add_uint(eapol_tree, hf_eapol_len, tvb, offset, 2, eapol_len); } offset += 2; switch (eapol_type) { case EAP_PACKET: next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(eap_handle, next_tvb, pinfo, eapol_tree); break; case EAPOL_KEY: if (tree) { keydesc_type = tvb_get_guint8(tvb, offset); proto_tree_add_item(eapol_tree, hf_eapol_keydes_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (keydesc_type == EAPOL_WPA_KEY || keydesc_type == EAPOL_RSN_KEY) { keyinfo = tvb_get_ntohs(tvb, offset); if (check_col(pinfo->cinfo, COL_INFO)) { if (keyinfo & KEY_INFO_REQUEST_MASK) { col_set_str(pinfo->cinfo, COL_INFO, "Key (Request)"); if (keyinfo & KEY_INFO_ERROR_MASK) col_set_str(pinfo->cinfo, COL_INFO, "Key (Request, Error)"); } else if (keyinfo & KEY_INFO_KEY_TYPE_MASK) { guint16 masked; masked = keyinfo & (KEY_INFO_INSTALL_MASK | KEY_INFO_KEY_ACK_MASK | KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK); switch (masked) { case KEY_INFO_KEY_ACK_MASK: col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 1/4)"); break; case KEY_INFO_KEY_MIC_MASK: col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 2/4)"); break; case (KEY_INFO_INSTALL_MASK | KEY_INFO_KEY_ACK_MASK | KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK): col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 3/4)"); break; case (KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK): col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 4/4)"); break; } } else { if (keyinfo & KEY_INFO_KEY_ACK_MASK) col_set_str(pinfo->cinfo, COL_INFO, "Key (Group msg 1/2)"); else col_set_str(pinfo->cinfo, COL_INFO, "Key (Group msg 2/2)"); } } keyinfo_item = proto_tree_add_uint(eapol_tree, hf_eapol_wpa_keydes_keyinfo, tvb, offset, 2, keyinfo); keyinfo_tree = proto_item_add_subtree(keyinfo_item, ett_keyinfo); proto_tree_add_uint(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_keydes_ver, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_type, tvb, offset, 2, keyinfo); proto_tree_add_uint(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_index, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_install, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_ack, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_mic, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_secure, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_error, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_request, tvb, offset, 2, keyinfo); proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_encr_key_data, tvb, offset, 2, keyinfo); offset += 2; proto_tree_add_uint(eapol_tree, hf_eapol_keydes_keylen, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset += 2; proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_nonce, tvb, offset, 32, ENC_NA); offset += 32; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb, offset, 16, ENC_NA); offset += 16; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_rsc, tvb, offset, 8, ENC_NA); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_id, tvb, offset, 8, ENC_NA); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_mic, tvb, offset, 16, ENC_NA); offset += 16; eapol_data_len = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(eapol_tree, hf_eapol_wpa_keydes_datalen, tvb, offset, 2, eapol_data_len); offset += 2; if (eapol_data_len != 0) { ti = proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_data, tvb, offset, eapol_data_len, ENC_NA); if ((keyinfo & KEY_INFO_ENCR_KEY_DATA_MASK) || !(keyinfo & KEY_INFO_KEY_TYPE_MASK)) { /* RSN: EAPOL-Key Key Data is encrypted. * WPA: Group Keys use encrypted Key Data. * Cannot parse this without knowing the key. * IEEE 802.11i-2004 8.5.2. */ } else { keydes_tree = proto_item_add_subtree(ti, ett_eapol_keydes_data); ieee_80211_add_tagged_parameters(tvb, offset, pinfo, keydes_tree, eapol_data_len, -1); } } } else { eapol_key_len = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(eapol_tree, hf_eapol_keydes_keylen, tvb, offset, 2, eapol_key_len); offset += 2; proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb, offset, 16, ENC_NA); offset += 16; key_index = tvb_get_guint8(tvb, offset); ti = proto_tree_add_text(eapol_tree, tvb, offset, 1, "Key Index: %s, index %u", (key_index & 0x80) ? "unicast" : "broadcast", key_index & 0x7F); key_index_tree = proto_item_add_subtree(ti, ett_eapol_key_index); proto_tree_add_boolean(key_index_tree, hf_eapol_keydes_key_index_keytype, tvb, offset, 1, key_index); proto_tree_add_uint(key_index_tree, hf_eapol_keydes_key_index_indexnum, tvb, offset, 1, key_index); offset += 1; proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_signature, tvb, offset, 16, ENC_NA); offset += 16; if (eapol_key_len != 0) { if (eapol_len > 44) { /* Size of rc4 key with no key content */ proto_tree_add_item(eapol_tree, hf_eapol_keydes_key, tvb, offset, eapol_key_len, ENC_NA); } else { /* IEEE 802.1X-2004 7.6.3.6: If no bytes remain, then */ proto_tree_add_text(eapol_tree, tvb, offset, 0, "Key: Use key locally generated by peer"); } } } } break; case EAPOL_ENCAP_ASF_ALERT: /* XXX - is this an SNMP trap? */ default: next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, eapol_tree); break; } }
/* XXX: Are all the tests against tvb_length() really the right way to handle invalid fields ? * It seems to me that invalid fields should just add an expert item * or cause a "Malformed" exception. */ static void dissect_elcom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gboolean is_request, length_ok; proto_tree *elcom_tree; proto_item *ti, *hidden_item; gint offset = 0; guint elcom_len; guint8 elcom_msg_type; guint8 *suffix; /* Check that there's enough data */ if (tvb_length(tvb) < 3) return; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ELCOM"); col_clear(pinfo->cinfo, COL_INFO); is_request = (pinfo->match_port == pinfo->destport); elcom_len = tvb_get_ntohs(tvb, 0); length_ok = (tvb_reported_length(tvb) == (elcom_len+2)); col_add_fstr(pinfo->cinfo, COL_INFO, "%s Len=%d%s", is_request ? "Request" : "Response", elcom_len, length_ok ? "" : " (incorrect)"); elcom_msg_type = tvb_get_guint8(tvb, 2); switch (elcom_msg_type) { case P_CONRQ: case P_CONRS: /* starting after elcom_len and elcom_msg_type, initiator + responder + userdata fields must be there */ if (tvb_length_remaining(tvb, 3+TOTAL_LEN+TOTAL_LEN+3) < 0) return; /* check also that those field lengths are valid */ if (tvb_get_guint8(tvb, 3) != LOWADR_LEN) return; if (tvb_get_guint8(tvb, 3+1+LOWADR_LEN) != SUFFIX_LEN) return; if (tvb_get_guint8(tvb, 3+TOTAL_LEN) != LOWADR_LEN) return; if (tvb_get_guint8(tvb, 3+1+TOTAL_LEN+LOWADR_LEN) != SUFFIX_LEN) return; /* finally believe that there is valid suffix */ suffix = tvb_get_string(wmem_packet_scope(), tvb, 3+2+LOWADR_LEN, 2); col_append_fstr(pinfo->cinfo, COL_INFO, " %s Connect", suffix); break; case P_RELRQ: case P_RELRS: col_append_str(pinfo->cinfo, COL_INFO, " Release"); break; case P_DATRQ: col_append_str(pinfo->cinfo, COL_INFO, " Data"); break; } switch (elcom_msg_type) { case P_CONRQ: case P_RELRQ: col_append_str(pinfo->cinfo, COL_INFO, " Request"); break; case P_CONRS: case P_RELRS: col_append_str(pinfo->cinfo, COL_INFO, " Response"); break; } if (!tree) return; ti = proto_tree_add_item(tree, proto_elcom, tvb, offset, -1, ENC_NA); elcom_tree = proto_item_add_subtree(ti, ett_elcom); hidden_item = proto_tree_add_boolean(elcom_tree, is_request ? hf_elcom_request : hf_elcom_response, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); /* 2 first bytes are the frame length */ offset = 0; ti = proto_tree_add_item(elcom_tree, hf_elcom_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset = +2; if (! length_ok) { proto_item_append_text(ti, " (incorrect)"); } elcom_msg_type = tvb_get_guint8(tvb, offset); ti = proto_tree_add_item(elcom_tree, hf_elcom_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(elcom_tree, " ( %s)", val_to_str(elcom_msg_type, type_vals, "Unknown %d")); offset++; if (tvb_length_remaining(tvb, offset) <= 0) return; switch (elcom_msg_type) { case P_CONRQ: case P_CONRS: /* * Connection request/release assiciated PDU's, * /ELCOM-90 P Protocol spec/ p. 85... */ /* We need the length here, hardcode the LOWADR_LEN = 21 */ ti = proto_tree_add_item(elcom_tree, hf_elcom_initiator, tvb, offset, TOTAL_LEN, ENC_BIG_ENDIAN); offset = dissect_lower_address(ti, ett_elcom_initiator, tvb, offset, hf_elcom_initiator_endian, hf_elcom_initiator_ip, hf_elcom_initiator_port, hf_elcom_initiator_suff); if (tvb_length_remaining(tvb, offset) <= 0) return; ti = proto_tree_add_item(elcom_tree, hf_elcom_responder, tvb, offset, TOTAL_LEN, ENC_BIG_ENDIAN); offset = dissect_lower_address(ti, ett_elcom_responder, tvb, offset, hf_elcom_responder_endian, hf_elcom_responder_ip, hf_elcom_responder_port, hf_elcom_responder_suff); if (tvb_length_remaining(tvb, offset) <= 0) return; /* Rest of the payload is USER-DATA, 0..82 bytes */ ti = proto_tree_add_item(elcom_tree, hf_elcom_userdata, tvb, offset, -1, ENC_NA); offset = dissect_userdata(ti, ett_elcom_userdata, tvb, offset); break; case P_RELRQ: proto_tree_add_item(elcom_tree, hf_elcom_release_reason, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case P_RELRS: proto_tree_add_item(elcom_tree, hf_elcom_release_result, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; case P_DATRQ: ti = proto_tree_add_item(elcom_tree, hf_elcom_datarequest, tvb, offset, -1, ENC_NA); offset = dissect_datarequest(ti, ett_elcom_datarequest, tvb, offset); break; default: proto_item_append_text(ti, " <<--- meaning WHAT??"); break; } if (tvb_length_remaining(tvb, offset) <= 0) return; /* We should not get here, but if we do, show what is left over: */ ti = proto_tree_add_item(elcom_tree, hf_elcom_strangeleftover, tvb, offset, -1, ENC_NA); while (tvb_length_remaining(tvb, offset) > 0) { proto_item_append_text(ti, elcom_show_hex ? " %02x" : " %03o", tvb_get_guint8(tvb, offset)); offset++; } }
static void dissect_http2_frame_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) { proto_item *ti; proto_tree *http2_tree; guint32 offset = 0; http2_frame_header frame; /* tvb_memeql makes certain there are enough bytes in the buffer. * returns -1 if there are not enough bytes or if there is not a * match. Returns 0 on a match */ if ( tvb_memeql( tvb, offset, kMagicHello, MAGIC_FRAME_LENGTH ) == 0 ) { col_append_sep_str( pinfo->cinfo, COL_INFO, ", ", "Magic" ); ti = proto_tree_add_item(tree, proto_http2, tvb, offset, MAGIC_FRAME_LENGTH, ENC_NA); proto_item_append_text( ti, ", Magic" ); http2_tree = proto_item_add_subtree(ti, ett_http2); proto_tree_add_item(http2_tree, hf_http2_magic, tvb, offset, MAGIC_FRAME_LENGTH, ENC_BIG_ENDIAN); return; } frame.length = tvb_get_ntohs( tvb, offset + 0 ); frame.type = tvb_get_guint8( tvb, offset + 2 ); frame.flags = tvb_get_guint8( tvb, offset + 3 ); frame.streamid = tvb_get_ntohl( tvb, offset + 4 ); col_append_sep_fstr( pinfo->cinfo, COL_INFO, ", ", "%s", val_to_str( frame.type, frametypenames, "Unknown (0x%02X)" ) ); /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_http2, tvb, offset, FRAME_HEADER_LENGTH + frame.length, ENC_NA); proto_item_append_text( ti, ", %s", val_to_str( frame.type, frametypenames, "Unknown (0x%02X)" ) ); proto_item_append_text( ti, ", Length: %d, Flags: %d, streamid: %d", frame.length, frame.flags, frame.streamid ); http2_tree = proto_item_add_subtree(ti, ett_http2); /* Add an item to the subtree, see section 1.6 of README.developer for more * information. */ proto_tree_add_item(http2_tree, hf_http2_length, tvb, offset + 0, 2, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_type, tvb, offset + 2, 1, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_flags, tvb, offset + 3, 1, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_streamid, tvb, offset + 4, 4, ENC_BIG_ENDIAN); proto_tree_add_item(http2_tree, hf_http2_payload, tvb, offset + 8, frame.length, ENC_BIG_ENDIAN); offset += frame.length + FRAME_HEADER_LENGTH; return; }
/* Dissector for xcsl */ static void dissect_xcsl_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint offset = 0; gint length_remaining; guint8 idx; gboolean request; guint8 par; guint8 str[MAXLEN]; guint8 result; const gchar *code; guint len; gint next_offset; proto_tree *xcsl_tree = NULL; /* color support */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Xcsl"); col_clear(pinfo->cinfo, COL_INFO); /* Create display tree for the xcsl protocol */ if (tree) { proto_item *xcsl_item; xcsl_item = proto_tree_add_item(tree, hfi_xcsl, tvb, offset, -1, ENC_NA); xcsl_tree = proto_item_add_subtree(xcsl_item, ett_xcsl); } /* reset idx */ idx = 0; /* reset the parameter count */ par = 0; /* switch whether it concerns a command or an answer */ request = FALSE; while ((length_remaining = tvb_reported_length_remaining(tvb, offset)) > 0) { /* get next item */ if (!(get_next_item(tvb, offset, length_remaining, str, &next_offset, &len))) { /* do not continue when get_next_item returns false */ return; } /* do not add to the tree when the string is of zero length */ if ( strlen(str) == 0 ) { offset = next_offset + 1; continue; } /* Xcsl (Call Specification Language) protocol in brief : * * Request : * * <xcsl-version>;<transaction-id>;<command>;[parameter1;parameter2;parameter3;....] * * Reply : * * <xcsl-version>;transaction-id;<result>;[answer data;answer data];... * * If result is one or more digits, this is determined as a Reply. * * Example : * * --> xcsl-1.0;1000;offhook;+31356871234 * <-- xcsl-1.0;1000;0 <- success * * --> xcsl-1.0;1001;dial;+31356871234;+31356875678 * <-- xcsl-1.0;1001;0 <- success * * * index : 0 1 2 3 4 * * Index 2 represents the return code (see the xcsl_action_vals[] definitions) * */ /* One by one go through each item ';' separated */ switch (idx) { /* This is the protocol item */ case 0: proto_tree_add_item(xcsl_tree, &hfi_xcsl_protocol_version, tvb, offset, len, ENC_ASCII|ENC_NA); break; /* This should be the transaction ID, if non-digit, it is treated as info */ case 1: if ( g_ascii_isdigit(str[0]) ) { proto_tree_add_item(xcsl_tree, &hfi_xcsl_transaction_id, tvb, offset, len, ENC_ASCII|ENC_NA); } else { proto_tree_add_item(xcsl_tree, &hfi_xcsl_information, tvb, offset, len, ENC_ASCII|ENC_NA); } col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",str); break; /* Starting with non-digit -> Command, if it starts with a digit -> reply */ case 2: if ( g_ascii_isdigit(str[0]) ) { proto_item *xcsl_item; request = FALSE; result = atoi(str); if ( result >= XCSL_NONE ) { result = XCSL_UNDEFINED; } code = val_to_str(result, xcsl_action_vals, "Unknown: %d"); /* Print result code and description */ xcsl_item = proto_tree_add_item(xcsl_tree, &hfi_xcsl_result, tvb, offset, len, ENC_ASCII|ENC_NA); proto_item_append_text(xcsl_item, " (%s)", code); if (result != 0) col_append_fstr(pinfo->cinfo, COL_INFO, "[%s] ", code); } else { request = TRUE; proto_tree_add_item(xcsl_tree, &hfi_xcsl_command, tvb, offset, len, ENC_ASCII|ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str); } break; /* This is a command parameter */ default: proto_tree_add_item(xcsl_tree, &hfi_xcsl_parameter, tvb, offset, len, ENC_ASCII|ENC_NA); if ( request == TRUE ) { col_append_fstr(pinfo->cinfo, COL_INFO, ": %s ",str); } else { if (par == 0) { col_append_fstr(pinfo->cinfo, COL_INFO, "reply: %s ",str); } else { col_append_fstr(pinfo->cinfo, COL_INFO, ": %s ",str); } } /* increment the parameter count */ par++; break; } offset = next_offset + 1; idx++; } return; }
static const true_false_string hub_port_status_indicator_meaning = { "Software-controlled color", "Default colors" }; /* Dissector for ClearHubFeature, Chapter 11.24.2.1 Clear Hub Feature */ static void dissect_usb_hub_clear_hub_feature(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_) { proto_item *item = NULL; proto_tree *subtree = NULL; const gchar* feature_name; feature_name = val_to_str(usb_trans_info->setup.wValue, hub_class_feature_selectors_recipient_hub_vals, "UNKNOWN (0x%x)"); col_append_fstr(pinfo->cinfo, COL_INFO, " [Hub: %s]", feature_name); if (is_request) { item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); subtree = proto_item_add_subtree(item, ett_usb_hub_wValue); proto_tree_add_item(subtree, hf_usb_hub_hub_feature_selector, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex); proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
static int dissect_skype_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *skype_tree = NULL; guint32 offset = 0; guint32 packet_length; guint8 packet_type, packet_unk; conversation_t *conversation = NULL; skype_udp_conv_info_t *skype_udp_info; /* look up the conversation */ conversation = find_or_create_conversation(pinfo); /* if conversation found get the data pointer that you stored */ skype_udp_info = conversation_get_proto_data(conversation, proto_skype); if (!skype_udp_info) { /* new conversation create local data structure */ skype_udp_info = se_alloc(sizeof(skype_udp_conv_info_t)); skype_udp_info->global_src_ip = 0; skype_udp_info->global_dst_ip = 0; conversation_add_proto_data(conversation, proto_skype, skype_udp_info); } /* at this point the conversation data is ready */ packet_type = tvb_get_guint8(tvb, 2) & SKYPE_SOM_TYPE_MASK; packet_unk = (tvb_get_guint8(tvb, 2) & SKYPE_SOM_UNK_MASK) >> 4; packet_length = tvb_length(tvb); col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(packet_type, skype_type_vals, "Type 0x%1x")); if (packet_unk) { col_append_fstr(pinfo->cinfo, COL_INFO, " Unk: %1x", packet_unk); } if (tree) { /* Start of message dissection */ ti = proto_tree_add_item(tree, proto_skype, tvb, offset, -1, ENC_NA); skype_tree = proto_item_add_subtree(ti, ett_skype); proto_tree_add_item(skype_tree, hf_skype_som_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(skype_tree, hf_skype_som_unk, tvb, offset, 1, ENC_NA); proto_tree_add_item(skype_tree, hf_skype_som_type, tvb, offset, 1, ENC_NA); offset += 1; /* Body dissection */ switch (packet_type) { case SKYPE_TYPE_UNKNOWN_0: proto_tree_add_item(skype_tree, hf_skype_unknown_0_unk1, tvb, offset, -1, ENC_NA); offset = packet_length; break; case SKYPE_TYPE_PAYLOAD: proto_tree_add_item(skype_tree, hf_skype_payload_iv, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(skype_tree, hf_skype_payload_crc, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(skype_tree, hf_skype_payload_enc_data, tvb, offset, -1, ENC_NA); offset = packet_length; break; case SKYPE_TYPE_FFR: proto_tree_add_item(skype_tree, hf_skype_ffr_num, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(skype_tree, hf_skype_ffr_unk1, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(skype_tree, hf_skype_ffr_iv, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(skype_tree, hf_skype_ffr_crc, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(skype_tree, hf_skype_ffr_enc_data, tvb, offset, -1, ENC_NA); offset = packet_length; break; case SKYPE_TYPE_NAT_INFO: proto_tree_add_item(skype_tree, hf_skype_natinfo_srcip, tvb, offset, 4, ENC_BIG_ENDIAN); skype_udp_info->global_src_ip = tvb_get_ipv4(tvb, offset); offset += 4; proto_tree_add_item(skype_tree, hf_skype_natinfo_dstip, tvb, offset, 4, ENC_BIG_ENDIAN); skype_udp_info->global_dst_ip = tvb_get_ipv4(tvb, offset); offset += 4; break; case SKYPE_TYPE_NAT_REPEAT: proto_tree_add_item(skype_tree, hf_skype_natrequest_srcip, tvb, offset, 4, ENC_BIG_ENDIAN); skype_udp_info->global_src_ip = tvb_get_ipv4(tvb, offset); offset += 4; proto_tree_add_item(skype_tree, hf_skype_natrequest_dstip, tvb, offset, 4, ENC_BIG_ENDIAN); skype_udp_info->global_dst_ip = tvb_get_ipv4(tvb, offset); offset += 4; break; case SKYPE_TYPE_AUDIO: proto_tree_add_item(skype_tree, hf_skype_audio_unk1, tvb, offset, -1, ENC_NA); offset = packet_length; break; case SKYPE_TYPE_UNKNOWN_F: proto_tree_add_item(skype_tree, hf_skype_unknown_f_unk1, tvb, offset, -1, ENC_NA); offset = packet_length; break; default: proto_tree_add_item(skype_tree, hf_skype_unknown_packet, tvb, offset, -1, ENC_NA); offset = packet_length; break; } } return offset; }
/* * For PIM v2, see RFC 4601, RFC 3973 and draft-ietf-pim-sm-v2-new-03 * (when PIM is run over IPv6, the rules for computing the PIM checksum * from the draft in question, not from RFC 2362, should be used). */ static void dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; guint8 pim_typever; guint length, pim_length; guint16 pim_cksum, computed_cksum; vec_t cksum_vec[4]; guint32 phdr[2]; const char *typestr; proto_tree *pim_tree = NULL; proto_item *ti; proto_tree *pimopt_tree = NULL; proto_item *tiopt; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIM"); col_clear(pinfo->cinfo, COL_INFO); pim_typever = tvb_get_guint8(tvb, 0); switch (PIM_VER(pim_typever)) { case 2: typestr = val_to_str(PIM_TYPE(pim_typever), type2vals, "Unknown (%u)"); break; case 1: /* PIMv1 - we should never see this */ default: typestr = "Unknown"; break; } if (check_col(pinfo->cinfo, COL_PROTOCOL)) { col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "PIMv%d", PIM_VER(pim_typever)); } if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, typestr); ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, FALSE); pim_tree = proto_item_add_subtree(ti, ett_pim); proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, FALSE); proto_tree_add_item(pim_tree, hf_pim_type, tvb, offset, 1, FALSE); proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset + 1, 1, FALSE); pim_cksum = tvb_get_ntohs(tvb, offset + 2); length = tvb_length(tvb); if (PIM_VER(pim_typever) == 2) { /* * Well, it's PIM v2, so we can check whether this is a Register * message, and thus can figure out how much to checksum and * whether to make the columns read-only. */ if (PIM_TYPE(pim_typever) == 1) { /* * Register message - the PIM header is 8 bytes long. * Also set the columns non-writable. Otherwise the IPv4 or * IPv6 dissector for the encapsulated packet that caused * this register will overwrite the PIM info in the columns. */ pim_length = 8; col_set_writable(pinfo->cinfo, FALSE); } else { /* * Other message - checksum the entire packet. */ pim_length = tvb_reported_length(tvb); } } else { /* * We don't know what type of message this is, so say that * the length is 0, to force it not to be checksummed. */ pim_length = 0; } if (!pinfo->fragmented && length >= pim_length) { /* * The packet isn't part of a fragmented datagram and isn't * truncated, so we can checksum it. */ switch (pinfo->src.type) { case AT_IPv4: cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length); cksum_vec[0].len = pim_length; computed_cksum = in_cksum(&cksum_vec[0], 1); break; case AT_IPv6: /* Set up the fields of the pseudo-header. */ cksum_vec[0].ptr = pinfo->src.data; cksum_vec[0].len = pinfo->src.len; cksum_vec[1].ptr = pinfo->dst.data; cksum_vec[1].len = pinfo->dst.len; cksum_vec[2].ptr = (const guint8 *)&phdr; phdr[0] = g_htonl(pim_length); phdr[1] = g_htonl(IP_PROTO_PIM); cksum_vec[2].len = 8; cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, pim_length); cksum_vec[3].len = pim_length; computed_cksum = in_cksum(&cksum_vec[0], 4); break; default: /* PIM is available for IPv4 and IPv6 right now */ computed_cksum = 0; /* squelch GCC complaints */ DISSECTOR_ASSERT_NOT_REACHED(); break; } if (computed_cksum == 0) { proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb, offset + 2, 2, pim_cksum, "Checksum: 0x%04x [correct]", pim_cksum); } else { proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb, offset + 2, 2, pim_cksum, "Checksum: 0x%04x [incorrect, should be 0x%04x]", pim_cksum, in_cksum_shouldbe(pim_cksum, computed_cksum)); } } else { proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb, offset + 2, 2, pim_cksum); } offset += 4; if (tvb_reported_length_remaining(tvb, offset) > 0) { tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1, "PIM options"); pimopt_tree = proto_item_add_subtree(tiopt, ett_pim_opts); } else goto done; if (PIM_VER(pim_typever) != 2) goto done; /* version 2 decoder */ switch (PIM_TYPE(pim_typever)) { case 0: /*hello*/ { int opt_count = 0; while (tvb_reported_length_remaining(tvb, offset) >= 2) { guint16 hello_opt, opt_len; guint16 opt_value; proto_item *opt_item; proto_tree *opt_tree; opt_count++; hello_opt = tvb_get_ntohs(tvb, offset); opt_len = tvb_get_ntohs(tvb, offset + 2); opt_item = proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len, "Option %u: %s", hello_opt, val_to_str(hello_opt, pim_opt_vals, "Unknown: %u")); opt_tree = proto_item_add_subtree(opt_item, ett_pim_opt); proto_tree_add_item(opt_tree, hf_pim_optiontype, tvb, offset, 2, FALSE); proto_tree_add_item(opt_tree, hf_pim_optionlength, tvb, offset + 2, 2, FALSE); switch(hello_opt) { case 1: /* Hello Hold Time Option */ opt_value = tvb_get_ntohs(tvb, offset + 4); proto_tree_add_uint_format(opt_tree, hf_pim_holdtime, tvb, offset + 4, opt_len, opt_value, "Holdtime: %us %s", opt_value, opt_value == 0 ? "(goodbye)" : opt_value == 0xffff ? "(infinity)": ""); proto_item_append_text(opt_item, ": %us %s", opt_value, opt_value == 0 ? "(goodbye)" : opt_value == 0xffff ? "(infinity)": ""); break; case 2: /* LAN Prune Delay Option */ proto_tree_add_item(opt_tree, hf_pim_t, tvb, offset + 4, 1, FALSE); proto_tree_add_item(opt_tree, hf_pim_propagation_delay, tvb, offset + 4, 2, FALSE); proto_tree_add_item(opt_tree, hf_pim_override_interval, tvb, offset + 6, 2, FALSE); proto_item_append_text(opt_item, ": T = %u, Propagation Delay = %ums, Override Interval = %ums", tvb_get_guint8(tvb, offset + 4) & 0x80 ? 1 : 0, tvb_get_ntohs(tvb, offset + 4) & 0x7fff, tvb_get_ntohs(tvb, offset + 6)); break; case 19: /* DR priority */ proto_tree_add_item(opt_tree, hf_pim_dr_priority, tvb, offset + 4, 4, FALSE); proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4)); break; case 20: /* Generation ID */ proto_tree_add_item(opt_tree, hf_pim_generation_id, tvb, offset + 4, 4, FALSE); proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4)); break; case 21: /* State Refresh Capable Option */ proto_tree_add_item(opt_tree, hf_pim_state_refresh_version, tvb, offset + 4, 1, FALSE); proto_tree_add_item(opt_tree, hf_pim_state_refresh_interval, tvb, offset + 5, 1, FALSE); proto_tree_add_item(opt_tree, hf_pim_state_refresh_reserved, tvb, offset + 6, 2, FALSE); proto_item_append_text(opt_item, ": Version = %u, Interval = %us", tvb_get_guint8(tvb, offset + 4), tvb_get_guint8(tvb, offset + 5)); break; case 24: /* address list */ case 65001: /* address list (old implementations) */ { int i; proto_tree *sub_tree = NULL; proto_item *addrlist_option; addrlist_option = proto_tree_add_text(opt_tree, tvb, offset, 4 + opt_len, "%sAddress List (%u)", hello_opt == 65001 ? "old " : "", hello_opt); sub_tree = proto_item_add_subtree(addrlist_option, ett_pim_opt); for (i = offset + 4; i < offset + 4 + opt_len; ) { int advance; const char *s; s = dissect_pim_addr(tvb, i, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(sub_tree, tvb, offset, advance, "Address: %s", s); i += advance; } break; } default: if (opt_len) proto_tree_add_item(opt_tree, hf_pim_optionvalue, tvb, offset + 4, opt_len, FALSE); break; } offset += 4 + opt_len; } proto_item_append_text(tiopt, ": %u", opt_count); break; } case 1: /* register */ { guint32 flags; guint8 v_hl; tvbuff_t *next_tvb; proto_tree *flag_tree = NULL; proto_item *tiflag; flags = tvb_get_ntohl(tvb, offset); tiflag = proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Flags: 0x%08x", flags); flag_tree = proto_item_add_subtree(tiflag, ett_pim); proto_tree_add_text(flag_tree, tvb, offset, 1, "%s", decode_boolean_bitfield(flags, 0x80000000, 32, "Border", "Not border")); proto_tree_add_text(flag_tree, tvb, offset, 1, "%s", decode_boolean_bitfield(flags, 0x40000000, 32, "Null-Register", "Not Null-Register")); offset += 4; /* * The rest of the packet is a multicast data packet. */ next_tvb = tvb_new_subset_remaining(tvb, offset); /* * It's an IP packet - determine whether it's IPv4 or IPv6. */ v_hl = tvb_get_guint8(tvb, offset); switch((v_hl & 0xf0) >> 4) { case 0: /* Null-Register dummy header. * Has the same address family as the encapsulating PIM packet, * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet. */ if (pinfo->src.type == AT_IPv4) { proto_tree_add_text(pimopt_tree, tvb, offset, -1, "IPv4 dummy header"); proto_tree_add_text(pimopt_tree, tvb, offset + 12, 4, "Source: %s", tvb_ip_to_str(tvb, offset + 12)); proto_tree_add_text(pimopt_tree, tvb, offset + 16, 4, "Group: %s", tvb_ip_to_str(tvb, offset + 16)); } else if (pinfo->src.type == AT_IPv6) { proto_tree_add_text(pimopt_tree, tvb, offset, -1, "IPv6 dummy header"); proto_tree_add_text(pimopt_tree, tvb, offset + 8, 16, "Source: %s", tvb_ip6_to_str(tvb, offset + 8)); proto_tree_add_text(pimopt_tree, tvb, offset + 8 + 16, 16, "Group: %s", tvb_ip6_to_str(tvb, offset + 8 + 16)); } else proto_tree_add_text(pimopt_tree, tvb, offset, -1, "Dummy header for an unknown protocol"); break; case 4: /* IPv4 */ #if 0 call_dissector(ip_handle, next_tvb, pinfo, tree); #else call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree); #endif break; case 6: /* IPv6 */ #if 0 call_dissector(ipv6_handle, next_tvb, pinfo, tree); #else call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree); #endif break; default: proto_tree_add_text(pimopt_tree, tvb, offset, -1, "Unknown IP version %d", (v_hl & 0xf0) >> 4); break; } break; } case 2: /* register-stop */ { int advance; const char *s; s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s); break; } case 3: /* join/prune */ case 6: /* graft */ case 7: /* graft-ack */ { int advance; int off; const char *s; int ngroup, i, njoin, nprune, j; guint16 holdtime; proto_tree *grouptree = NULL; proto_item *tigroup; proto_tree *subtree = NULL; proto_item *tisub; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Upstream-neighbor: %s", s); offset += advance; proto_tree_add_item(pimopt_tree, hf_pim_res_bytes, tvb, offset, 1, FALSE); offset += 1; /* skip reserved field */ ngroup = tvb_get_guint8(tvb, offset); proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, FALSE); offset += 1; holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; for (i = 0; i < ngroup; i++) { s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) goto breakbreak3; tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group %d: %s", i, s); grouptree = proto_item_add_subtree(tigroup, ett_pim); offset += advance; njoin = tvb_get_ntohs(tvb, offset); nprune = tvb_get_ntohs(tvb, offset + 2); tisub = proto_tree_add_item(grouptree, hf_pim_numjoins, tvb, offset, 2, FALSE); subtree = proto_item_add_subtree(tisub, ett_pim); off = offset + 4; for (j = 0; j < njoin; j++) { s = dissect_pim_addr(tvb, off, pimv2_source, &advance); if (s == NULL) goto breakbreak3; proto_tree_add_text(subtree, tvb, off, advance, "IP address: %s", s); off += advance; } tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb, offset + 2, 2, FALSE); subtree = proto_item_add_subtree(tisub, ett_pim); for (j = 0; j < nprune; j++) { s = dissect_pim_addr(tvb, off, pimv2_source, &advance); if (s == NULL) goto breakbreak3; proto_tree_add_text(subtree, tvb, off, advance, "IP address: %s", s); off += advance; } offset = off; } breakbreak3: break; } case 4: /* bootstrap */ { const char *s; int advance; int i, j; int frpcnt; guint16 holdtime; proto_tree *grouptree = NULL; proto_item *tigroup; proto_tree_add_text(pimopt_tree, tvb, offset, 2, "Fragment tag: 0x%04x", tvb_get_ntohs(tvb, offset)); offset += 2; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Hash mask len: %u", tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "BSR priority: %u", tvb_get_guint8(tvb, offset)); offset += 1; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "BSR: %s", s); offset += advance; for (i = 0; tvb_reported_length_remaining(tvb, offset) > 0; i++) { s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) goto breakbreak4; tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group %d: %s", i, s); grouptree = proto_item_add_subtree(tigroup, ett_pim); offset += advance; proto_tree_add_text(grouptree, tvb, offset, 1, "RP count: %u", tvb_get_guint8(tvb, offset)); offset += 1; frpcnt = tvb_get_guint8(tvb, offset); proto_tree_add_text(grouptree, tvb, offset, 1, "FRP count: %u", frpcnt); offset += 3; for (j = 0; j < frpcnt; j++) { s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) goto breakbreak4; proto_tree_add_text(grouptree, tvb, offset, advance, "RP %d: %s", j, s); offset += advance; holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(grouptree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; proto_tree_add_text(grouptree, tvb, offset, 1, "Priority: %u", tvb_get_guint8(tvb, offset)); offset += 2; /* also skips reserved field */ } } breakbreak4: break; } case 5: /* assert */ { const char *s; int advance; guint32 pref; s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s); offset += advance; proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, FALSE); pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff; proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb, offset, 4, pref, "Metric Preference: %u", pref); offset += 4; proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, FALSE); offset += 4; break; } case 8: /* Candidate-RP-Advertisement */ { const char *s; int advance; int pfxcnt; guint16 holdtime; int i; pfxcnt = tvb_get_guint8(tvb, offset); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prefix-count: %u", pfxcnt); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Priority: %u", tvb_get_guint8(tvb, offset)); offset += 1; holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "RP: %s", s); offset += advance; for (i = 0; i < pfxcnt; i++) { s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) goto breakbreak8; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group %d: %s", i, s); offset += advance; } breakbreak8: break; } case 9: /* State-Refresh */ { const char *s; int advance; guint32 pref; s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Originator: %s", s); offset += advance; proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, FALSE); pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff; proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb, offset, 4, pref, "Metric Preference: %u", pref); offset += 4; proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Masklen: %u", tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "TTL: %u", tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune indicator %s", decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x80, 8, "set", "clear")); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune now %s", decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x40, 8, "set", "clear")); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Assert override %s", decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x20, 8, "set", "clear")); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Interval: %u", tvb_get_guint8(tvb, offset)); offset += 1; break; } default: break; } done:; }
static void dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *clnp_tree = NULL; proto_item *ti; guint8 cnf_proto_id; guint8 cnf_hdr_len; guint8 cnf_vers; guint8 cnf_ttl; guint8 cnf_type; char flag_string[6+1]; const char *pdu_type_string; proto_tree *type_tree; guint16 segment_length; guint16 du_id = 0; guint16 segment_offset = 0; guint16 cnf_cksum; cksum_status_t cksum_status; int offset; guchar src_len, dst_len, nsel, opt_len = 0; const guint8 *dst_addr, *src_addr; guint next_length; proto_tree *discpdu_tree; gboolean save_in_error_pkt; fragment_data *fd_head; tvbuff_t *next_tvb; gboolean update_col_info = TRUE; gboolean save_fragmented; col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLNP"); col_clear(pinfo->cinfo, COL_INFO); cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID); if (cnf_proto_id == NLPID_NULL) { col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset"); if (tree) { ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, ENC_NA); clnp_tree = proto_item_add_subtree(ti, ett_clnp); proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1, cnf_proto_id, "Inactive subset"); } next_tvb = tvb_new_subset_remaining(tvb, 1); if (call_dissector(ositp_inactive_handle, next_tvb, pinfo, tree) == 0) call_dissector(data_handle,tvb, pinfo, tree); return; } /* return if version not known */ cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS); if (cnf_vers != ISO8473_V1) { call_dissector(data_handle,tvb, pinfo, tree); return; } /* fixed part decoding */ cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN); opt_len = cnf_hdr_len; if (tree) { ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA); clnp_tree = proto_item_add_subtree(ti, ett_clnp); proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1, cnf_proto_id); proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1, cnf_hdr_len); proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1, cnf_vers); cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL); proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1, cnf_ttl, "Holding Time : %u (%u.%u secs)", cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5); } cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE); pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals, "Unknown (0x%02x)"); flag_string[0] = '\0'; if (cnf_type & CNF_SEG_OK) g_strlcat(flag_string, "S ", 7); if (cnf_type & CNF_MORE_SEGS) g_strlcat(flag_string, "M ", 7); if (cnf_type & CNF_ERR_OK) g_strlcat(flag_string, "E ", 7); if (tree) { ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1, cnf_type, "PDU Type : 0x%02x (%s%s)", cnf_type, flag_string, pdu_type_string); type_tree = proto_item_add_subtree(ti, ett_clnp_type); proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s", decode_boolean_bitfield(cnf_type, CNF_SEG_OK, 8, "Segmentation permitted", "Segmentation not permitted")); proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s", decode_boolean_bitfield(cnf_type, CNF_MORE_SEGS, 8, "More segments", "Last segment")); proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s", decode_boolean_bitfield(cnf_type, CNF_ERR_OK, 8, "Report error if PDU discarded", "Don't report error if PDU discarded")); proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s", decode_enumerated_bitfield(cnf_type, CNF_TYPE, 8, npdu_type_vals, "%s")); } /* If we don't have the full header - i.e., not enough to see the segmentation part and determine whether this datagram is segmented or not - set the Info column now; we'll get an exception before we set it otherwise. */ if (tvb_length(tvb) < cnf_hdr_len) { col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); } segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN); cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM); cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum); if (tree) { proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2, segment_length); switch (cksum_status) { default: /* * No checksum present, or not enough of the header present to * checksum it. */ proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "Checksum : 0x%04x", cnf_cksum); break; case CKSUM_OK: /* * Checksum is correct. */ proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "Checksum : 0x%04x (correct)", cnf_cksum); break; case CKSUM_NOT_OK: /* * Checksum is not correct. */ proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2, cnf_cksum, "Checksum : 0x%04x (incorrect)", cnf_cksum); break; } opt_len -= 9; /* Fixed part of Hesder */ } /* tree */ /* address part */ offset = P_CLNP_ADDRESS_PART; dst_len = tvb_get_guint8(tvb, offset); dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len); nsel = tvb_get_guint8(tvb, offset + dst_len); src_len = tvb_get_guint8(tvb, offset + dst_len + 1); src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len); if (tree) { proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1, dst_len); proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len, dst_addr, " DA : %s", print_nsap_net(dst_addr, dst_len)); proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb, offset + 1 + dst_len, 1, src_len); proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb, offset + dst_len + 2, src_len, src_addr, " SA : %s", print_nsap_net(src_addr, src_len)); opt_len -= dst_len + src_len +2; } SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr); SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr); SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr); SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr); /* Segmentation Part */ offset += dst_len + src_len + 2; if (cnf_type & CNF_SEG_OK) { #if 0 struct clnp_segment seg; /* XXX - not used */ tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg)); /* XXX - not used */ #endif segment_offset = tvb_get_ntohs(tvb, offset + 2); du_id = tvb_get_ntohs(tvb, offset); if (tree) { proto_tree_add_text(clnp_tree, tvb, offset, 2, "Data unit identifier: %06u", du_id); proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2, "Segment offset : %6u", segment_offset); proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2, "Total length : %6u", tvb_get_ntohs(tvb, offset + 4)); } offset += 6; opt_len -= 6; } if (tree) { /* To do : decode options */ #if 0 proto_tree_add_text(clnp_tree, tvb, offset, cnf_hdr_len - offset, "Options/Data: <not shown>"); #endif /* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/ dissect_osi_options( opt_len, tvb, offset, clnp_tree ); } offset = cnf_hdr_len; /* If clnp_reassemble is on, this is a segment, we have all the * data in the segment, and the checksum is valid, then just add the * segment to the hashtable. */ save_fragmented = pinfo->fragmented; if (clnp_reassemble && (cnf_type & CNF_SEG_OK) && ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) && tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) && segment_length > cnf_hdr_len && cksum_status != CKSUM_NOT_OK) { fd_head = fragment_add_check(tvb, offset, pinfo, du_id, clnp_segment_table, clnp_reassembled_table, segment_offset, segment_length - cnf_hdr_len, cnf_type & CNF_MORE_SEGS); next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP", fd_head, &clnp_frag_items, &update_col_info, clnp_tree); } else { /* If this is the first segment, dissect its contents, otherwise just show it as a segment. XXX - if we eventually don't save the reassembled contents of all segmented datagrams, we may want to always reassemble. */ if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) { /* Not the first segment - don't dissect it. */ next_tvb = NULL; } else { /* First segment, or not segmented. Dissect what we have here. */ /* Get a tvbuff for the payload. */ next_tvb = tvb_new_subset_remaining(tvb, offset); /* * If this is the first segment, but not the only segment, * tell the next protocol that. */ if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS)) pinfo->fragmented = TRUE; else pinfo->fragmented = FALSE; } } if (next_tvb == NULL) { /* Just show this as a segment. */ col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)", pdu_type_string, flag_string, segment_offset); /* As we haven't reassembled anything, we haven't changed "pi", so we don't have to restore it. */ call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); pinfo->fragmented = save_fragmented; return; } if (tvb_offset_exists(tvb, offset)) { switch (cnf_type & CNF_TYPE) { case DT_NPDU: case MD_NPDU: /* Continue with COTP if any data. XXX - if this isn't the first Derived PDU of a segmented Initial PDU, skip that? */ if (nsel == (guchar)tp_nsap_selector || always_decode_transport) { if (call_dissector(ositp_handle, next_tvb, pinfo, tree) != 0) { pinfo->fragmented = save_fragmented; return; /* yes, it appears to be COTP or CLTP */ } } if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb, pinfo, tree)) { pinfo->fragmented = save_fragmented; return; /* yes, it appears to be one of the protocols in the heuristic list */ } break; case ER_NPDU: /* The payload is the header and "none, some, or all of the data part of the discarded PDU", i.e. it's like an ICMP error; dissect it as a CLNP PDU. */ col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); next_length = tvb_length_remaining(tvb, offset); if (next_length != 0) { /* We have payload; dissect it. */ ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length, "Discarded PDU"); discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu); /* Save the current value of the "we're inside an error packet" flag, and set that flag; subdissectors may treat packets that are the payload of error packets differently from "real" packets. */ save_in_error_pkt = pinfo->flags.in_error_pkt; pinfo->flags.in_error_pkt = TRUE; call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree); /* Restore the "we're inside an error packet" flag. */ pinfo->flags.in_error_pkt = save_in_error_pkt; } pinfo->fragmented = save_fragmented; return; /* we're done with this PDU */ case ERQ_NPDU: case ERP_NPDU: /* XXX - dissect this */ break; } } col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); call_dissector(data_handle,next_tvb, pinfo, tree); pinfo->fragmented = save_fragmented; } /* dissect_clnp */
/* Code to actually dissect the packets */ static void dissect_ehdlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 4; col_set_str(pinfo->cinfo, COL_PROTOCOL, "EHDLC"); col_clear(pinfo->cinfo, COL_INFO); while (tvb_reported_length_remaining(tvb, offset) > 0) { proto_item *ti = NULL; proto_tree *ehdlc_tree = NULL; guint16 len, msg_type; tvbuff_t *next_tvb; guint16 control; gboolean is_response = FALSE, is_extended = TRUE; gint header_length = 2; /* Address + Length field */ msg_type = tvb_get_guint8(tvb, offset); len = tvb_get_guint8(tvb, offset+1); #if 0 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(msg_type, ehdlc_protocol_vals, "unknown 0x%02x")); #endif if (tree) { /* Use MIN(...,...) in the following to prevent a premature */ /* exception before we try to dissect whatever is available. */ ti = proto_tree_add_protocol_format(tree, proto_ehdlc, tvb, offset, MIN(len, tvb_length_remaining(tvb,offset)), "Ericsson HDLC protocol, type: %s", val_to_str(msg_type, ehdlc_protocol_vals, "unknown 0x%02x")); ehdlc_tree = proto_item_add_subtree(ti, ett_ehdlc); proto_tree_add_item(ehdlc_tree, hf_ehdlc_protocol, tvb, offset, 1, ENC_BIG_ENDIAN); #if 0 proto_tree_add_item(ehdlc_tree, hf_ehdlc_sapi, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ehdlc_tree, hf_ehdlc_c_r, tvb, offset, 1, ENC_BIG_ENDIAN); #endif proto_tree_add_item(ehdlc_tree, hf_ehdlc_data_len, tvb, offset+1, 1, ENC_BIG_ENDIAN); } control = dissect_xdlc_control(tvb, offset+2, pinfo, ehdlc_tree, hf_ehdlc_control, ett_ehdlc_control, &ehdlc_cf_items, &ehdlc_cf_items_ext, NULL, NULL, is_response, is_extended, FALSE); header_length += XDLC_CONTROL_LEN(control, is_extended); if (XDLC_IS_INFORMATION(control)) { next_tvb = tvb_new_subset(tvb, offset+header_length, len-header_length, len-header_length); switch (msg_type) { case 0x20: /* len == 4 seems to be some kind of ACK */ if (len <= 4) break; call_dissector(sub_handles[SUB_RSL], next_tvb, pinfo, tree); break; case 0xbc: case 0xdc: case 0xa0: case 0xc0: /* len == 4 seems to be some kind of ACK */ if (len <= 4) break; call_dissector(sub_handles[SUB_OML], next_tvb, pinfo, tree); break; default: call_dissector(sub_handles[SUB_DATA], next_tvb, pinfo, tree); break; } } else if (control == (XDLC_U | XDLC_XID)) { /* XID is formatted like ISO 8885, typically we see * something like * 82 format identifier * 80 group identifier * 00 09 length * 07 01 05 Window Size Tx * 09 01 04 Ack Timer (msec) * 08 01 05 Window Size Rx */ proto_tree_add_item(ehdlc_tree, hf_ehdlc_xid_payload, tvb, offset+header_length, len-header_length, ENC_NA); } if (len == 0) len = 1; offset += len; } }
/* Code to actually dissect the PAGP packets */ static void dissect_pagp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint32 raw_word; guint16 raw_half_word; guint16 num_tlvs; guint16 tlv; guint16 len; guint16 i; guint16 offset = PAGP_FIRST_TLV; guint8 raw_octet; guint8 flags; struct _address device_id; const guint8 *p_sys; guchar *ch; proto_tree *pagp_tree = NULL; proto_item *pagp_item; proto_tree *flags_tree; proto_item *flags_item; proto_tree *tlv_tree; proto_item *tlv_item; const char *sep; device_id.type = AT_ETHER; device_id.len = 6; if (check_col(pinfo->cinfo, COL_PROTOCOL)) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "PAGP"); /* PAGP Protocol */ } col_clear(pinfo->cinfo, COL_INFO); pinfo->current_proto = "PAGP"; raw_octet = tvb_get_guint8(tvb, PAGP_VERSION_NUMBER); if (tree) { pagp_item = proto_tree_add_protocol_format(tree, proto_pagp, tvb, 0, -1, "Port Aggregation Protocol"); pagp_tree = proto_item_add_subtree(pagp_item, ett_pagp); proto_tree_add_uint(pagp_tree, hf_pagp_version_number, tvb, PAGP_VERSION_NUMBER, 1, raw_octet); } if (check_col(pinfo->cinfo, COL_INFO)) { col_append_str(pinfo->cinfo, COL_INFO, val_to_str(raw_octet, pdu_vers, "Unknown PDU version")); } if (raw_octet == PAGP_FLUSH_PDU) { device_id.data = tvb_get_ptr(tvb, PAGP_FLUSH_LOCAL_DEVICE_ID, 6); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s", address_to_str(&device_id)); } if (tree) { proto_tree_add_ether(pagp_tree, hf_pagp_flush_local_device_id, tvb, PAGP_FLUSH_LOCAL_DEVICE_ID, 6, device_id.data); } device_id.data = tvb_get_ptr(tvb, PAGP_FLUSH_PARTNER_DEVICE_ID, 6); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s", address_to_str(&device_id)); } if (tree) { proto_tree_add_ether(pagp_tree, hf_pagp_flush_partner_device_id, tvb, PAGP_FLUSH_PARTNER_DEVICE_ID, 6, device_id.data); } raw_word = tvb_get_ntohl(tvb, PAGP_FLUSH_TRANSACTION_ID); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, "; Transaction ID: 0x%x ", raw_word); } if (tree) { proto_tree_add_uint(pagp_tree, hf_pagp_flush_transaction_id, tvb, PAGP_FLUSH_TRANSACTION_ID, 4, raw_word); } return; } /* Info PDU */ flags = tvb_get_guint8(tvb, PAGP_FLAGS); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, "; Flags 0x%x", flags); } if (tree) { flags_item = proto_tree_add_uint(pagp_tree, hf_pagp_flags, tvb, PAGP_FLAGS, 1, flags); flags_tree = proto_item_add_subtree(flags_item, ett_pagp_flags); sep = initial_sep; APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_SLOW_HELLO, flags_item, "%sSlow Hello"); proto_tree_add_boolean(flags_tree, hf_pagp_flags_slow_hello, tvb, PAGP_FLAGS, 1, flags); APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_AUTO_MODE, flags_item, "%sAuto Mode"); proto_tree_add_boolean(flags_tree, hf_pagp_flags_auto_mode, tvb, PAGP_FLAGS, 1, flags); APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_CONSISTENT_STATE, flags_item, "%sConsistent State"); proto_tree_add_boolean(flags_tree, hf_pagp_flags_consistent_state, tvb, PAGP_FLAGS, 1, flags); sep = cont_sep; if (sep != initial_sep) { /* We put something in; put in the terminating ")" */ proto_item_append_text(flags_item, ")"); } } device_id.data = tvb_get_ptr(tvb, PAGP_LOCAL_DEVICE_ID, 6); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s", address_to_str(&device_id)); } if (tree) { proto_tree_add_ether(pagp_tree, hf_pagp_local_device_id, tvb, PAGP_LOCAL_DEVICE_ID, 6, device_id.data); } if (tree) { raw_octet = tvb_get_guint8(tvb, PAGP_LOCAL_LEARN_CAP); proto_tree_add_uint(pagp_tree, hf_pagp_local_learn_cap, tvb, PAGP_LOCAL_LEARN_CAP, 1, raw_octet); raw_octet = tvb_get_guint8(tvb, PAGP_LOCAL_PORT_PRIORITY); proto_tree_add_uint(pagp_tree, hf_pagp_local_port_priority, tvb, PAGP_LOCAL_PORT_PRIORITY, 1, raw_octet); raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_SENT_PORT_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_local_sent_port_ifindex, tvb, PAGP_LOCAL_SENT_PORT_IFINDEX, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_GROUP_CAPABILITY); proto_tree_add_uint(pagp_tree, hf_pagp_local_group_capability, tvb, PAGP_LOCAL_GROUP_CAPABILITY, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_GROUP_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_local_group_ifindex, tvb, PAGP_LOCAL_GROUP_IFINDEX, 4, raw_word); } device_id.data = tvb_get_ptr(tvb, PAGP_PARTNER_DEVICE_ID, 6); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s", address_to_str(&device_id)); } if (tree) { proto_tree_add_ether(pagp_tree, hf_pagp_partner_device_id, tvb, PAGP_PARTNER_DEVICE_ID, 6, device_id.data); } if (tree) { raw_octet = tvb_get_guint8(tvb, PAGP_PARTNER_LEARN_CAP); proto_tree_add_uint(pagp_tree, hf_pagp_partner_learn_cap, tvb, PAGP_PARTNER_LEARN_CAP, 1, raw_octet); raw_octet = tvb_get_guint8(tvb, PAGP_PARTNER_PORT_PRIORITY); proto_tree_add_uint(pagp_tree, hf_pagp_partner_port_priority, tvb, PAGP_PARTNER_PORT_PRIORITY, 1, raw_octet); raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_SENT_PORT_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_partner_sent_port_ifindex, tvb, PAGP_PARTNER_SENT_PORT_IFINDEX, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_GROUP_CAPABILITY); proto_tree_add_uint(pagp_tree, hf_pagp_partner_group_capability, tvb, PAGP_PARTNER_GROUP_CAPABILITY, 4, raw_word); raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_GROUP_IFINDEX); proto_tree_add_uint(pagp_tree, hf_pagp_partner_group_ifindex, tvb, PAGP_PARTNER_GROUP_IFINDEX, 4, raw_word); raw_half_word = tvb_get_ntohs(tvb, PAGP_PARTNER_COUNT); proto_tree_add_uint(pagp_tree, hf_pagp_partner_count, tvb, PAGP_PARTNER_COUNT, 2, raw_half_word); num_tlvs = tvb_get_ntohs(tvb, PAGP_NUM_TLVS); proto_tree_add_uint(pagp_tree, hf_pagp_num_tlvs, tvb, PAGP_NUM_TLVS, 2, num_tlvs); /* dump TLV entries */ for ( i = 1; i <= num_tlvs; i++ ) { tlv = tvb_get_ntohs(tvb, offset); len = tvb_get_ntohs(tvb, offset + 2); if ( len == 0 ) { proto_tree_add_text(pagp_tree, tvb, offset, -1, "Unknown data - TLV len=0"); return; } tlv_item = proto_tree_add_text (pagp_tree, tvb, offset, len, "TLV Entry #%d", i); tlv_tree = proto_item_add_subtree (tlv_item, ett_pagp_tlvs); proto_tree_add_uint_format (tlv_tree, hf_pagp_tlv, tvb, offset,2,tlv,"Type = %d (%s)", tlv, val_to_str(tlv,tlv_types, "Unknown")) ; proto_tree_add_text (tlv_tree, tvb, offset+2, 2, "Length = %u bytes (includes Type and Length)", len) ; if ( tvb_reported_length_remaining(tvb, offset) < len ) { proto_tree_add_text(tlv_tree, tvb, offset, -1, "TLV length too large"); return; } switch (tlv) { case PAGP_TLV_DEVICE_NAME: ch = tvb_get_ephemeral_string(tvb, offset+4, len-4); proto_tree_add_string(tlv_tree, hf_pagp_tlv_device_name, tvb, offset+4, len-4, ch); break; case PAGP_TLV_PORT_NAME: ch = tvb_get_ephemeral_string(tvb, offset+4, len-4); proto_tree_add_string(tlv_tree, hf_pagp_tlv_port_name, tvb, offset+4, len-4, ch); break; case PAGP_TLV_AGPORT_MAC: p_sys = tvb_get_ptr(tvb, offset+4, 6); proto_tree_add_ether(tlv_tree, hf_pagp_tlv_agport_mac, tvb, offset+4, 6, p_sys); break; case PAGP_TLV_RESERVED: break; } offset += len; } } }
guint32 dsi_reserved; struct aspinfo aspinfo; col_set_str(pinfo->cinfo, COL_PROTOCOL, "DSI"); col_clear(pinfo->cinfo, COL_INFO); dsi_flags = tvb_get_guint8(tvb, 0); dsi_command = tvb_get_guint8(tvb, 1); dsi_requestid = tvb_get_ntohs(tvb, 2); dsi_code = tvb_get_ntohl(tvb, 4); dsi_length = tvb_get_ntohl(tvb, 8); dsi_reserved = tvb_get_ntohl(tvb, 12); col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s (%u)", val_to_str(dsi_flags, flag_vals, "Unknown flag (0x%02x)"), val_to_str_ext(dsi_command, &func_vals_ext, "Unknown function (0x%02x)"), dsi_requestid); ti = proto_tree_add_item(tree, proto_dsi, tvb, 0, -1, ENC_NA); dsi_tree = proto_item_add_subtree(ti, ett_dsi); if (tree) { proto_tree_add_uint(dsi_tree, hf_dsi_flags, tvb, 0, 1, dsi_flags); proto_tree_add_uint(dsi_tree, hf_dsi_command, tvb, 1, 1, dsi_command); proto_tree_add_uint(dsi_tree, hf_dsi_requestid, tvb, 2, 2, dsi_requestid); switch (dsi_flags) {
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_ata_pdu(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean response, guint32 tag) { proto_item *tmp_item; guint8 aflags; guint64 lba; ata_info_t *ata_info=NULL; conversation_t *conversation; /* only create a conversation for ATA commands */ conversation = find_or_create_conversation(pinfo); if( !(pinfo->fd->flags.visited) ){ if(!response){ ata_info_t *tmp_ata_info; /* first time we see this request so add a struct for request/response matching */ ata_info=wmem_new(wmem_file_scope(), ata_info_t); ata_info->tag=tag; ata_info->conversation=conversation; ata_info->request_frame=pinfo->fd->num; ata_info->response_frame=0; ata_info->cmd=tvb_get_guint8(tvb, offset+3); ata_info->req_time=pinfo->fd->abs_ts; tmp_ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_unmatched, ata_info); if(tmp_ata_info){ g_hash_table_remove(ata_cmd_unmatched, tmp_ata_info); } g_hash_table_insert(ata_cmd_unmatched, ata_info, ata_info); } else { ata_info_t tmp_ata_info; /* first time we see this response so see if we can match it with a request */ tmp_ata_info.tag=tag; tmp_ata_info.conversation=conversation; ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_unmatched, &tmp_ata_info); /* woo hoo we could, so no need to store this in unmatched any more, move both request and response to the matched table */ if(ata_info){ ata_info->response_frame=pinfo->fd->num; g_hash_table_remove(ata_cmd_unmatched, ata_info); g_hash_table_insert(ata_cmd_matched, GUINT_TO_POINTER(ata_info->request_frame), ata_info); g_hash_table_insert(ata_cmd_matched, GUINT_TO_POINTER(ata_info->response_frame), ata_info); } } } else { ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_matched, GUINT_TO_POINTER(pinfo->fd->num)); } if(ata_info){ if(response){ if(ata_info->request_frame){ nstime_t delta_ts; tmp_item=proto_tree_add_uint(tree, hf_aoe_response_to, tvb, 0, 0, ata_info->request_frame); PROTO_ITEM_SET_GENERATED(tmp_item); nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &ata_info->req_time); tmp_item=proto_tree_add_time(tree, hf_aoe_time, tvb, offset, 0, &delta_ts); PROTO_ITEM_SET_GENERATED(tmp_item); } } else { if(ata_info->response_frame){ tmp_item=proto_tree_add_uint(tree, hf_aoe_response_in, tvb, 0, 0, ata_info->response_frame); PROTO_ITEM_SET_GENERATED(tmp_item); } } } /* aflags */ aflags=tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_aoe_aflags_e, tvb, offset, 1, ENC_BIG_ENDIAN); if(aflags&AOE_AFLAGS_E){ proto_tree_add_item(tree, hf_aoe_aflags_d, tvb, offset, 1, ENC_BIG_ENDIAN); } if(aflags&AOE_AFLAGS_W){ proto_tree_add_item(tree, hf_aoe_aflags_a, tvb, offset, 1, ENC_BIG_ENDIAN); } proto_tree_add_item(tree, hf_aoe_aflags_w, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* err/feature */ proto_tree_add_item(tree, hf_aoe_err_feature, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* sector count */ proto_tree_add_item(tree, hf_aoe_sector_count, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* ata command/status */ if(!response){ proto_tree_add_item(tree, hf_aoe_acmd, tvb, offset, 1, ENC_BIG_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, " ATA:%s", val_to_str(tvb_get_guint8(tvb, offset), ata_cmd_vals, " Unknown ATA<0x%02x>")); } else { proto_tree_add_item(tree, hf_aoe_astatus, tvb, offset, 1, ENC_BIG_ENDIAN); if(ata_info != NULL && ata_info->request_frame){ /* we don't know what command it was unless we saw the request_frame */ tmp_item=proto_tree_add_uint(tree, hf_aoe_acmd, tvb, 0, 0, ata_info->cmd); PROTO_ITEM_SET_GENERATED(tmp_item); col_append_fstr(pinfo->cinfo, COL_INFO, " ATA:%s", val_to_str(ata_info->cmd, ata_cmd_vals, " Unknown ATA<0x%02x>")); } } offset++; /*lba probably complete wrong */ lba=tvb_get_letohs(tvb, offset+4); lba=(lba<<32)|tvb_get_letohl(tvb, offset); offset+=8; proto_tree_add_uint64(tree, hf_aoe_lba, tvb, offset-8, 6, lba); }
dissect_brp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { proto_item *brp_item = NULL; proto_tree *brp_tree = NULL; gint offset = 0; guint8 type = 0; guint8 packet_type = tvb_get_guint8(tvb, 0); /* If there is a "tree" requested, we handle that request. */ col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_BRP); /* We add some snazzy bizness to the info field to quickly ascertain what type of message was sent to/from the BRS/BRC. */ col_add_fstr(pinfo->cinfo, COL_INFO, "Message Type - %s", val_to_str(packet_type, brp_packettype_names, "Unknown (0x%02x)")); /* This call adds our tree to the main dissection tree. */ if (tree) { /* we are being asked for details */ /* Here we add our tree/subtree so we can have a collapsible branch. */ brp_item = proto_tree_add_item( tree, proto_brp, tvb, 0, -1, ENC_NA ); brp_tree = proto_item_add_subtree( brp_item, ett_brp); /* We use tvb_get_guint8 to get our type value out. */ type = tvb_get_guint8(tvb, offset); offset += 0; brp_item = proto_tree_add_item( brp_tree, hf_brp_type, tvb, offset, 1, ENC_BIG_ENDIAN ); offset += 1;
static void dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *prism_tree = NULL, *prism_did_tree = NULL; proto_item *ti = NULL, *ti_did = NULL; tvbuff_t *next_tvb; int offset; guint32 msgcode, msglen, did; guint16 status; guint8 *devname_p; offset = 0; did = 0; /* handle the AVS header */ msgcode = tvb_get_ntohl(tvb, offset); if ((msgcode == WLANCAP_MAGIC_COOKIE_V1) || (msgcode == WLANCAP_MAGIC_COOKIE_V2)) { call_dissector(wlancap_handle, tvb, pinfo, tree); return; } /* * If we don't see a valid message type, assume the Prism or AVS * header was omitted and just hand off to the 802.11 dissector; * at least one capture has AVS headers on some packets and no * radio headers on others (incoming vs. outgoing?). * * XXX - check for both byte orders and use that to determine * the byte order of the fields in the Prism header? */ msgcode = tvb_get_letohl(tvb, offset); if ((msgcode != PRISM_TYPE1_MSGCODE) && (msgcode != PRISM_TYPE2_MSGCODE)) { call_dissector(ieee80211_handle, tvb, pinfo, tree); return; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "Prism"); col_clear(pinfo->cinfo, COL_INFO); if(tree) { ti = proto_tree_add_item(tree, proto_prism, tvb, 0, 144, ENC_NA); prism_tree = proto_item_add_subtree(ti, ett_prism); } /* Message Code */ if(tree) { proto_tree_add_item(prism_tree, hf_ieee80211_prism_msgcode, tvb, offset, 4, ENC_LITTLE_ENDIAN); } msgcode = tvb_get_letohl(tvb, offset); offset += 4; /* Message Length */ if(tree) { proto_tree_add_item(prism_tree, hf_ieee80211_prism_msglen, tvb, offset, 4, ENC_LITTLE_ENDIAN); } msglen = tvb_get_letohl(tvb, offset); offset += 4; /* Device Name */ if(tree) { proto_tree_add_item(prism_tree, hf_ieee80211_prism_devname, tvb, offset, 16, ENC_ASCII|ENC_NA); } devname_p = tvb_get_string(wmem_packet_scope(), tvb, offset, 16); offset += 16; col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %s, Message 0x%x, Length %d", devname_p, msgcode, msglen); while(offset < PRISM_HEADER_LENGTH) { /* DID */ if(tree) { ti_did = proto_tree_add_item(prism_tree, hf_ieee80211_prism_did, tvb, offset, 12, ENC_NA); prism_did_tree = proto_item_add_subtree(ti_did, ett_prism_did); proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_type, tvb, offset, 4, ENC_LITTLE_ENDIAN); did = tvb_get_letohl(tvb, offset); proto_item_append_text(ti_did, " %s", val_to_str(did, prism_did_vals, "Unknown %x") ); } offset += 4; /* Status */ status = tvb_get_letohs(tvb, offset); if(tree) { proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_status, tvb, offset, 2, ENC_LITTLE_ENDIAN); } offset += 2; /* Length */ if(tree) { proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); } offset += 2; /* Data, if present... */ if (status == 0) { switch(did){ case PRISM_TYPE1_HOSTTIME: case PRISM_TYPE2_HOSTTIME: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_hosttime, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_MACTIME: case PRISM_TYPE2_MACTIME: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_mactime, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_CHANNEL: case PRISM_TYPE2_CHANNEL: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_channel, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) ); } col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", tvb_get_letohl(tvb, offset)); break; case PRISM_TYPE1_RSSI: case PRISM_TYPE2_RSSI: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rssi, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) ); } col_add_fstr(pinfo->cinfo, COL_RSSI, "%d", tvb_get_letohl(tvb, offset)); break; case PRISM_TYPE1_SQ: case PRISM_TYPE2_SQ: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_sq, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_SIGNAL: case PRISM_TYPE2_SIGNAL: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_signal, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_NOISE: case PRISM_TYPE2_NOISE: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_noise, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_RATE: case PRISM_TYPE2_RATE: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rate, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " %s Mb/s", prism_rate_return(tvb_get_letohl(tvb, offset)) ); } col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%s", prism_rate_return(tvb_get_letohl(tvb, offset)) ); break; case PRISM_TYPE1_ISTX: case PRISM_TYPE2_ISTX: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_istx, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) ); } break; case PRISM_TYPE1_FRMLEN: case PRISM_TYPE2_FRMLEN: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_frmlen, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) ); } break; default: if(tree){ proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_unknown, tvb, offset, 4, ENC_LITTLE_ENDIAN); } break; } } offset += 4; } /* dissect the 802.11 header next */ next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(ieee80211_handle, next_tvb, pinfo, tree); }
static void dissect_itdm_125usec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tvbuff_t *next_tvb; proto_item *itdm_item = NULL; proto_tree *itdm_tree = NULL; int offset; guint32 flowid; guint32 chanid; guint16 chloc1; guint16 chloc2; guint8 chcmd; guint8 actbit; guint8 ackbit; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ITDM"); flowid = tvb_get_ntoh24(tvb, ITDM_FLOWID_OFFSET); chanid = tvb_get_ntoh24(tvb, ITDM_CHANID_OFFSET); chcmd = tvb_get_guint8(tvb, ITDM_CHCMD_OFFSET); chloc1 = tvb_get_ntohs(tvb, ITDM_CHLOC1_OFFSET); actbit = (chcmd & 0x10) ? 1 : 0; ackbit = (chcmd & 0x20) ? 1 : 0; chcmd = chcmd & 0x0f; if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "Flow %d Chan %d ACT %d ACK %d %s", flowid, chanid, actbit, ackbit, val_to_str(chcmd, chcmd_vals, "Reserved")); if (chcmd == ITDM_CMD_NEW_CHAN || chcmd == ITDM_CMD_CLOSE_CHAN || chcmd == ITDM_CMD_CYCLIC_REAF) { col_append_fstr(pinfo->cinfo, COL_INFO, " Loc1 %d", chloc1); } else if (chcmd == ITDM_CMD_RELOC_CHAN) { chloc2 = tvb_get_ntohs(tvb, ITDM_CHLOC2_OFFSET); col_append_fstr(pinfo->cinfo, COL_INFO, " Loc1 %d Loc2 %d", chloc1, chloc2); } } offset = 0; if (tree) { itdm_item = proto_tree_add_item(tree, proto_itdm, tvb, 0, -1, ENC_NA); itdm_tree = proto_item_add_subtree(itdm_item, ett_itdm); proto_tree_add_item(itdm_tree, hf_itdm_timestamp, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(itdm_tree, hf_itdm_seqnum, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(itdm_tree, hf_itdm_sop_eop, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(itdm_tree, hf_itdm_last_pack, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(itdm_tree, hf_itdm_pktlen, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(itdm_tree, hf_itdm_chksum, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(itdm_tree, hf_itdm_uid, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; proto_tree_add_item(itdm_tree, hf_itdm_ack, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(itdm_tree, hf_itdm_act, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(itdm_tree, hf_itdm_chcmd, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(itdm_tree, hf_itdm_chid, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; if (chcmd == ITDM_CMD_PACKET_RATE) { proto_tree_add_item(itdm_tree, hf_itdm_pktrate, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } else { proto_tree_add_item(itdm_tree, hf_itdm_chloc1, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if (chcmd == ITDM_CMD_CYCLIC_REAF || chcmd == ITDM_CMD_NEW_CHAN || chcmd == ITDM_CMD_CLOSE_CHAN) { proto_tree_add_item(itdm_tree, hf_itdm_cxnsize, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } else { proto_tree_add_item(itdm_tree, hf_itdm_chloc2, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } } } next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, tree); }
static void dissect_cups(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *cups_tree = NULL; proto_tree *ptype_subtree = NULL; proto_item *ti = NULL; gint offset = 0; gint next_offset; guint len; const guint8 *str; cups_ptype_t ptype; unsigned int state; col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_CUPS); col_clear(pinfo->cinfo, COL_INFO); ti = proto_tree_add_item(tree, proto_cups, tvb, offset, -1, ENC_NA); cups_tree = proto_item_add_subtree(ti, ett_cups); /* Format (1450 bytes max.): */ /* type state uri ["location" ["info" ["make-and-model"]]]\n */ ptype = get_hex_uint(tvb, offset, &next_offset); len = next_offset - offset; if (len != 0) { ti = proto_tree_add_uint(cups_tree, hf_cups_ptype, tvb, offset, len, ptype); ptype_subtree = proto_item_add_subtree(ti, ett_cups_ptype); proto_tree_add_item(ptype_subtree, hf_cups_ptype_default, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_implicit, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_variable, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_large, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_medium, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_small, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_sort, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_bind, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_cover, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_punch, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_collate, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_copies, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_staple, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_duplex, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_color, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_bw, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_remote, tvb, offset, len, ENC_BIG_ENDIAN); proto_tree_add_item(ptype_subtree, hf_cups_ptype_class, tvb, offset, len, ENC_BIG_ENDIAN); } offset = next_offset; if (!skip_space(tvb, offset, &next_offset)) return; /* end of packet */ offset = next_offset; state = get_hex_uint(tvb, offset, &next_offset); len = next_offset - offset; if (len != 0) { proto_tree_add_uint(cups_tree, hf_cups_state, tvb, offset, len, state); } offset = next_offset; if (!skip_space(tvb, offset, &next_offset)) return; /* end of packet */ offset = next_offset; str = get_unquoted_string(tvb, offset, &next_offset, &len); if (str == NULL) return; /* separator/terminator not found */ proto_tree_add_string(cups_tree, hf_cups_uri, tvb, offset, len, str); col_add_fstr(pinfo->cinfo, COL_INFO, "%.*s (%s)", (guint16) len, str, val_to_str(state, cups_state_values, "0x%x")); offset = next_offset; if (!cups_tree) return; if (!skip_space(tvb, offset, &next_offset)) return; /* end of packet */ offset = next_offset; str = get_quoted_string(tvb, offset, &next_offset, &len); if (str == NULL) return; /* separator/terminator not found */ proto_tree_add_string(cups_tree, hf_cups_location, tvb, offset+1, len, str); offset = next_offset; if (!skip_space(tvb, offset, &next_offset)) return; /* end of packet */ offset = next_offset; str = get_quoted_string(tvb, offset, &next_offset, &len); if (str == NULL) return; /* separator/terminator not found */ proto_tree_add_string(cups_tree, hf_cups_information, tvb, offset+1, len, str); offset = next_offset; if (!skip_space(tvb, offset, &next_offset)) return; /* end of packet */ offset = next_offset; str = get_quoted_string(tvb, offset, &next_offset, &len); if (str == NULL) return; /* separator/terminator not found */ proto_tree_add_string(cups_tree, hf_cups_make_model, tvb, offset+1, len, str); }
static void dissect_forces(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti, *tlv_item; proto_tree *forces_tree, *forces_flags_tree; proto_tree *forces_main_header_tree, *forces_tlv_tree, *tlv_tree; gint length_count; guint8 message_type; guint16 tlv_type; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ForCES"); col_clear(pinfo->cinfo, COL_INFO); ti = proto_tree_add_item(tree, proto_forces, tvb, 0, -1, ENC_NA); forces_tree = proto_item_add_subtree(ti, ett_forces); ti = proto_tree_add_text(forces_tree, tvb, 0, ForCES_HEADER_LENGTH, "Common Header"); forces_main_header_tree = proto_item_add_subtree(ti, ett_forces_main_header); proto_tree_add_item(forces_main_header_tree, hf_forces_version, tvb, 0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(forces_main_header_tree, hf_forces_rsvd, tvb, 0, 1, ENC_BIG_ENDIAN); message_type = tvb_get_guint8(tvb, offset+1); proto_tree_add_item( forces_main_header_tree, hf_forces_messagetype, tvb, offset+1, 1, ENC_BIG_ENDIAN); length_count = tvb_get_ntohs(tvb, offset+2) * 4; /*multiply 4 DWORD*/ ti = proto_tree_add_uint_format( forces_main_header_tree, hf_forces_length, tvb, offset+2, 2, length_count, "Length: %u Bytes", length_count); if (length_count != tvb_reported_length_remaining(tvb, offset)) expert_add_info_format(pinfo, ti, &ei_forces_length, "Bogus: ForCES Header length (%u bytes) is wrong),should be (%u bytes)", length_count, tvb_reported_length_remaining(tvb, offset)); if (length_count < 24) expert_add_info_format(pinfo, ti, &ei_forces_length, "Bogus: ForCES Header length (%u bytes) is less than 24bytes)", length_count); col_add_fstr(pinfo->cinfo, COL_INFO, "Message Type: %s, Total Length: %u Bytes", val_to_str(message_type, message_type_vals, "Unknown messagetype 0x%x"), length_count); proto_tree_add_item( forces_main_header_tree, hf_forces_sid, tvb, offset+4, 4, ENC_BIG_ENDIAN); proto_tree_add_item( forces_main_header_tree, hf_forces_did, tvb, offset+8, 4, ENC_BIG_ENDIAN); proto_tree_add_item( forces_main_header_tree, hf_forces_correlator, tvb, offset+12, 8, ENC_BIG_ENDIAN); /*Add flags tree*/ ti = proto_tree_add_item(forces_main_header_tree, hf_forces_flags, tvb, offset+20, 4, ENC_BIG_ENDIAN); forces_flags_tree = proto_item_add_subtree(ti, ett_forces_flags); proto_tree_add_item(forces_flags_tree, hf_forces_flags_ack, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_at, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_em, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_pri, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_reserved, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_rsrvd, tvb, offset+20, 4, ENC_BIG_ENDIAN); proto_tree_add_item(forces_flags_tree, hf_forces_flags_tp, tvb, offset+20, 4, ENC_BIG_ENDIAN); offset += 24; while (tvb_reported_length_remaining(tvb, offset) >= TLV_TL_LENGTH) { ti = proto_tree_add_text(forces_tree, tvb, offset, TLV_TL_LENGTH, "TLV"); forces_tlv_tree = proto_item_add_subtree(ti, ett_forces_tlv); tlv_type = tvb_get_ntohs(tvb, offset); tlv_item = proto_tree_add_item(forces_tlv_tree, hf_forces_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN); length_count = tvb_get_ntohs(tvb, offset+2) * 4; proto_item_set_len(ti, length_count); ti = proto_tree_add_uint_format_value(forces_tlv_tree, hf_forces_tlv_length, tvb, offset+2, 2, length_count, "%u Bytes", length_count); if (tvb_reported_length_remaining(tvb, offset) < length_count) expert_add_info_format(pinfo, ti, &ei_forces_tlv_length, "Bogus: Main TLV length (%u bytes) is wrong", length_count); if (length_count < TLV_TL_LENGTH) { expert_add_info_format(pinfo, ti, &ei_forces_tlv_length, "Bogus TLV length: %u", length_count); break; } offset += TLV_TL_LENGTH; length_count -= TLV_TL_LENGTH; switch(tlv_type) { case LFBselect_TLV: ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "LFB select TLV"); tlv_tree = proto_item_add_subtree(ti, ett_forces_lfbselect_tlv_type); dissect_lfbselecttlv(tvb, pinfo, tlv_tree, offset, length_count); break; case REDIRECT_TLV: ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "Redirect TLV"); tlv_tree = proto_item_add_subtree(ti, ett_forces_redirect_tlv_type); dissect_redirecttlv(tvb, pinfo, tlv_tree, offset); break; case ASResult_TLV: ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "ASResult TLV"); tlv_tree = proto_item_add_subtree(ti, ett_forces_asresult_tlv); proto_tree_add_item(tlv_tree, hf_forces_asresult_association_setup_result, tvb, offset, 4, ENC_BIG_ENDIAN); break; case ASTreason_TLV: ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "ASTreason TLV"); tlv_tree = proto_item_add_subtree(ti, ett_forces_astreason_tlv); proto_tree_add_item(tlv_tree, hf_forces_astreason_tlv_teardown_reason, tvb, offset, 4, ENC_BIG_ENDIAN); break; default: expert_add_info(pinfo, tlv_item, &ei_forces_tlv_type); ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "Unknown TLV"); tlv_tree = proto_item_add_subtree(ti, ett_forces_unknown_tlv); proto_tree_add_item(tlv_tree, hf_forces_unknown_tlv, tvb, offset, length_count, ENC_NA); break; } offset += length_count; } }
/* * Name: dissect_esis() * * Description: * Main entry area for esis de-mangling. This will build the * main esis tree data and call the sub-protocols as needed. * * Input: * tvbuff * : tvbuff referring to packet data * packet_info * : info for current packet * proto_tree * : tree of display data. May be NULL. * * Output: * void, but we will add to the proto_tree if it is not NULL. */ static void dissect_esis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { const char *pdu_type_string = NULL; const char *pdu_type_format_string = "PDU Type : %s (R:%s%s%s)"; esis_hdr_t ehdr; proto_item *ti; proto_tree *esis_tree = NULL; guint8 variable_len; guint tmp_uint = 0; const char *cksum_status; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ESIS"); col_clear(pinfo->cinfo, COL_INFO); tvb_memcpy(tvb, (guint8 *)&ehdr, 0, sizeof ehdr); if (tree) { ti = proto_tree_add_item(tree, proto_esis, tvb, 0, -1, ENC_NA); esis_tree = proto_item_add_subtree(ti, ett_esis); if (ehdr.esis_version != ESIS_REQUIRED_VERSION){ esis_dissect_unknown(tvb, esis_tree, "Unknown ESIS version (%u vs %u)", ehdr.esis_version, ESIS_REQUIRED_VERSION ); return; } if (ehdr.esis_length < ESIS_HDR_FIXED_LENGTH) { esis_dissect_unknown(tvb, esis_tree, "Bogus ESIS length (%u, must be >= %u)", ehdr.esis_length, ESIS_HDR_FIXED_LENGTH ); return; } proto_tree_add_uint( esis_tree, hf_esis_nlpi, tvb, 0, 1, ehdr.esis_nlpi ); proto_tree_add_uint( esis_tree, hf_esis_length, tvb, 1, 1, ehdr.esis_length ); proto_tree_add_uint( esis_tree, hf_esis_version, tvb, 2, 1, ehdr.esis_version ); proto_tree_add_uint( esis_tree, hf_esis_reserved, tvb, 3, 1, ehdr.esis_reserved ); pdu_type_string = val_to_str(ehdr.esis_type&OSI_PDU_TYPE_MASK, esis_vals, "Unknown (0x%x)"); proto_tree_add_uint_format( esis_tree, hf_esis_type, tvb, 4, 1, ehdr.esis_type, pdu_type_format_string, pdu_type_string, (ehdr.esis_type&BIT_8) ? "1" : "0", (ehdr.esis_type&BIT_7) ? "1" : "0", (ehdr.esis_type&BIT_6) ? "1" : "0"); tmp_uint = pntohs( ehdr.esis_holdtime ); proto_tree_add_uint_format(esis_tree, hf_esis_holdtime, tvb, 5, 2, tmp_uint, "Holding Time : %u seconds", tmp_uint ); tmp_uint = pntohs( ehdr.esis_checksum ); switch (calc_checksum( tvb, 0, ehdr.esis_length, tmp_uint )) { case NO_CKSUM: cksum_status = "Not Used"; break; case DATA_MISSING: cksum_status = "Not checkable - not all of packet was captured"; break; case CKSUM_OK: cksum_status = "Is good"; break; case CKSUM_NOT_OK: cksum_status = "Is wrong"; break; default: cksum_status = NULL; DISSECTOR_ASSERT_NOT_REACHED(); } proto_tree_add_uint_format( esis_tree, hf_esis_checksum, tvb, 7, 2, tmp_uint, "Checksum : 0x%x ( %s )", tmp_uint, cksum_status ); } /* * Let us make sure we use the same names for all our decodes * here. First, dump the name into info column, and THEN * dispatch the sub-type. */ col_add_str(pinfo->cinfo, COL_INFO, val_to_str( ehdr.esis_type&OSI_PDU_TYPE_MASK, esis_vals, "Unknown (0x%x)" ) ); variable_len = ehdr.esis_length - ESIS_HDR_FIXED_LENGTH; switch (ehdr.esis_type & OSI_PDU_TYPE_MASK) { case ESIS_ESH_PDU: esis_dissect_esh_pdu( variable_len, tvb, esis_tree); break; case ESIS_ISH_PDU: esis_dissect_ish_pdu( variable_len, tvb, esis_tree); break; case ESIS_RD_PDU: esis_dissect_redirect_pdu( variable_len, tvb, esis_tree); break; default: esis_dissect_unknown(tvb, esis_tree, "Unknown ESIS packet type 0x%x", ehdr.esis_type & OSI_PDU_TYPE_MASK ); } } /* dissect_esis */
dissect_q932_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { gint offset; proto_item *ti; proto_tree *ie_tree; guint8 ie_type, ie_len; offset = 0; ti = proto_tree_add_item(tree, proto_q932, tvb, offset, -1, ENC_NA); proto_item_set_hidden(ti); ie_type = tvb_get_guint8(tvb, offset); ie_len = tvb_get_guint8(tvb, offset + 1); ie_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_q932_ie, NULL, val_to_str(ie_type, VALS(q932_str_ie_type), "unknown (0x%02X)")); proto_tree_add_item(ie_tree, hf_q932_ie_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(ie_tree, hf_q932_ie_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); offset += 2; if (tvb_reported_length_remaining(tvb, offset) <= 0) return offset; switch (ie_type) { case Q932_IE_FACILITY : dissect_q932_facility_ie(tvb, offset, pinfo, ie_tree, ie_len); break; case Q932_IE_NOTIFICATION_INDICATOR : dissect_q932_ni_ie(tvb, offset, pinfo, ie_tree, ie_len); break; default: if (ie_len > 0) {
static int dissect_openvpn_msg_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *openvpn_tree, proto_tree *parent_tree, gint offset) { gboolean tls_auth; guint openvpn_keyid; guint openvpn_opcode; guint32 msg_mpid = -1; guint32 msg_sessionid = -1; guint8 openvpn_predict_tlsauth_arraylength; proto_item *ti2; proto_tree *packetarray_tree, *type_tree; guint32 msg_length_remaining; gboolean msg_lastframe; fragment_head *frag_msg; tvbuff_t *new_tvb; gboolean save_fragmented; /* Clear out stuff in the info column */ col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME); col_clear(pinfo->cinfo,COL_INFO); /* read opcode and write to info column */ openvpn_opcode = tvb_get_bits8(tvb, offset*8, 5); col_append_fstr(pinfo->cinfo, COL_INFO, "MessageType: %s", val_to_str_const(openvpn_opcode, openvpn_message_types, "Unknown Messagetype")); openvpn_keyid = tvb_get_bits8(tvb, offset*8 + 5, 3); proto_item_append_text(parent_tree, ", Opcode: %s, Key ID: %d", val_to_str(openvpn_opcode, openvpn_message_types, "Unknown (0x%02x)"), openvpn_keyid); ti2 = proto_tree_add_item(openvpn_tree, hf_openvpn_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(ti2, " [opcode/key_id]"); type_tree = proto_item_add_subtree(ti2, ett_openvpn_type); proto_tree_add_item(type_tree, hf_openvpn_opcode, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_openvpn_keyid, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (openvpn_opcode == P_DATA_V2) { proto_tree_add_item(openvpn_tree, hf_openvpn_peerid, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; } else if (openvpn_opcode != P_DATA_V1) { /* if we have a P_CONTROL or P_ACK packet */ /* read sessionid */ msg_sessionid = tvb_get_bits32(tvb, offset*8+32, 32, ENC_BIG_ENDIAN); proto_tree_add_item(openvpn_tree, hf_openvpn_sessionid, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* tls-auth detection (this can be overridden by preferences */ openvpn_predict_tlsauth_arraylength = tvb_get_guint8(tvb, offset); /* if the first 4 bytes that would, if tls-auth is used, contain part of the hmac, lack entropy, we asume no tls-auth is used */ if (pref_tls_auth_override == FALSE) { if ((openvpn_opcode != P_DATA_V1) && (openvpn_predict_tlsauth_arraylength > 0) && check_for_valid_hmac(tvb_get_ntohl(tvb, offset))) { tls_auth = TRUE; } else { tls_auth = FALSE; } } else { tls_auth = pref_tls_auth; } if (tls_auth == TRUE) { proto_tree_add_item(openvpn_tree, hf_openvpn_hmac, tvb, offset, tls_auth_hmac_size, ENC_NA); offset += tls_auth_hmac_size; if (tvb_reported_length_remaining(tvb, offset) >= 8) { proto_tree_add_item(openvpn_tree, hf_openvpn_pid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; if (pref_long_format) { proto_tree_add_item(openvpn_tree, hf_openvpn_net_time, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } } } if (tvb_reported_length_remaining(tvb, offset) >= 1) { /* read P_ACK packet-id array length */ gint pid_arraylength = tvb_get_guint8(tvb, offset); gint i; proto_tree_add_item(openvpn_tree, hf_openvpn_mpid_arraylength, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (pid_arraylength > 0) { packetarray_tree = proto_tree_add_subtree(openvpn_tree, tvb, offset, 0, ett_openvpn_packetarray, NULL, "Packet-ID Array"); for (i = 0; i < pid_arraylength; i++) { proto_tree_add_item(packetarray_tree, hf_openvpn_mpid_arrayelement, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } if (tvb_reported_length_remaining(tvb, offset) >= 8) { proto_tree_add_item(openvpn_tree, hf_openvpn_rsessionid, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; } } } /* if we have a P_CONTROL packet */ if (openvpn_opcode != P_ACK_V1) { /* read Message Packet-ID */ if (tvb_reported_length_remaining(tvb, offset) >= 4) { msg_mpid = tvb_get_bits32(tvb, offset*8, 32, ENC_BIG_ENDIAN); proto_tree_add_item(openvpn_tree, hf_openvpn_mpid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } } } /* if we have more data left, determine what to do */ msg_length_remaining = tvb_reported_length_remaining(tvb, offset); if (msg_length_remaining == 0) { return tvb_captured_length(tvb); } if (openvpn_opcode != P_CONTROL_V1) { proto_tree *data_tree; data_tree = proto_tree_add_subtree_format(openvpn_tree, tvb, offset, -1, ett_openvpn_data, NULL, "Data (%d bytes)", tvb_captured_length_remaining(tvb, offset)); proto_tree_add_item(data_tree, hf_openvpn_data, tvb, offset, -1, ENC_NA); return tvb_captured_length(tvb); } /* Try to reassemble */ /* an ordinary openvpn control packet contains 100 bytes only if it is part of a fragmented message and is not the last fragment of the current transmission. Note that the tvb contains exactly one openvpn PDU: UDP: by definition; TCP: because of the use of tcp_dissect_pdus(). */ if (msg_length_remaining == 100) { msg_lastframe = FALSE; } else { msg_lastframe = TRUE; } save_fragmented = pinfo->fragmented; pinfo->fragmented = TRUE; frag_msg = fragment_add_seq_next( &msg_reassembly_table, tvb, offset, pinfo, msg_sessionid, /* ID for fragments belonging together */ NULL, msg_length_remaining, /* fragment length - to the end */ !(msg_lastframe)); /* More fragments ? */ /* show "data" fragment on tree unless "reassembled" message has just one part. */ /* i.e., show if ("not reassembled") or ("reassembled" and "has multiple fragments") */ if ((frag_msg == NULL) || (frag_msg->next != NULL)) { proto_tree *data_tree; data_tree = proto_tree_add_subtree_format(openvpn_tree, tvb, offset, -1, ett_openvpn_data, NULL, "Message fragment (%d bytes)", tvb_captured_length_remaining(tvb, offset)); proto_tree_add_item(data_tree, hf_openvpn_fragment_bytes, tvb, offset, -1, ENC_NA); } new_tvb = NULL; if (frag_msg) { if (msg_lastframe) { /* Reassembled */ new_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled Message", frag_msg, &openvpn_frag_items, NULL, openvpn_tree); if (frag_msg->next != NULL) { /* multiple frags ? */ col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled "); /* overwritten by next dissector */ } } else { /* Not last packet of reassembled Short Message */ col_append_fstr(pinfo->cinfo, COL_INFO, " (Message fragment %d) ", msg_mpid); if (pinfo->num != frag_msg->reassembled_in) { /* Add a "Reassembled in" link if not reassembled in this frame */ proto_tree_add_uint(openvpn_tree, hf_openvpn_reassembled_in, tvb, 0, 0, frag_msg->reassembled_in); } } } /* if (frag_msg) */ pinfo->fragmented = save_fragmented; /* Now see if we need to call subdissector. new_tvb is non-null if we "reassembled* a message (even just one fragment) */ if (new_tvb) { /* call SSL/TLS dissector if we just processed the last fragment */ call_dissector(ssl_handle, new_tvb, pinfo, parent_tree); } return tvb_captured_length(tvb); }