guint16 is_asciitpkt(tvbuff_t *tvb) { guint16 count; /* * If TPKT is disabled, don't dissect it, just return -1, meaning * "this isn't TPKT". */ if (!proto_is_protocol_enabled(proto_tpkt_ptr)) return -1; /* There should at least be 8 bytes left in the frame */ if (!tvb_bytes_exist(tvb, 0, 8)) return -1; /* there aren't */ /* * The first four octets should be ASCII */ for (count = 0; count <=7 ; count ++) { if(!isalnum(tvb_get_guint8(tvb,count))) { return 0; } } return 1; }
/* This function is only called from the IGMP dissector */ int dissect_dvmrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { proto_tree *tree; proto_item *item; if (!proto_is_protocol_enabled(find_protocol_by_id(proto_dvmrp))) { /* 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); } item = proto_tree_add_item(parent_tree, proto_dvmrp, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_dvmrp); col_set_str(pinfo->cinfo, COL_PROTOCOL, "DVMRP"); col_clear(pinfo->cinfo, COL_INFO); if ((tvb_length_remaining(tvb, offset)>=8) && (((tvb_get_guint8(tvb, 6)==0xff) && (tvb_get_guint8(tvb, 7)==0x03)) || !strict_v3)) { offset = dissect_dvmrp_v3(tvb, pinfo, tree, offset); } else { offset = dissect_dvmrp_v1(tvb, pinfo, tree, offset); } proto_item_set_len(item, offset); return offset; }
static gboolean proto_hier_tree_iter_next(GtkTreeModel *tree_model, GtkTreeIter *iter) { ProtoHierTreeModel *model; g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), FALSE); model = (ProtoHierTreeModel *) tree_model; g_return_val_if_fail(iter->stamp == model->stamp, FALSE); /* protocol */ if (iter->user_data2 == NULL) { void *cookie = iter->user_data; int proto_id; proto_id = proto_get_next_protocol(&cookie); /* get next enabled protocol */ while (proto_id != -1) { protocol_t *p = find_protocol_by_id(proto_id); if (proto_is_protocol_enabled(p)) break; proto_id = proto_get_next_protocol(&cookie); } if (proto_id == -1) return FALSE; iter->user_data = cookie; iter->user_data3 = proto_registrar_get_nth(proto_id); return TRUE; } /* field */ { void *cookie2 = iter->user_data2; header_field_info *hfinfo; hfinfo = proto_get_next_protocol_field(&cookie2); /* get next field */ while (hfinfo) { if (hfinfo->same_name_prev_id == -1) break; hfinfo = proto_get_next_protocol_field(&cookie2); } /* not found? */ if (!hfinfo) return FALSE; iter->user_data2 = cookie2; iter->user_data3 = hfinfo; return TRUE; } }
// ui/gtk/filter_autocomplete.c:build_autocompletion_list void FieldFilterEdit::buildCompletionList(const QString &field_word) { // Push a hint about the current field. if (syntaxState() == Valid) { emit popFilterSyntaxStatus(); header_field_info *hfinfo = proto_registrar_get_byname(field_word.toUtf8().constData()); if (hfinfo) { QString cursor_field_msg = QString("%1: %2") .arg(hfinfo->name) .arg(ftype_pretty_name(hfinfo->type)); emit pushFilterSyntaxStatus(cursor_field_msg); } } if (field_word.length() < 1) { completion_model_->setStringList(QStringList()); return; } void *proto_cookie; QStringList field_list; int field_dots = field_word.count('.'); // Some protocol names (_ws.expert) contain periods. for (int proto_id = proto_get_first_protocol(&proto_cookie); proto_id != -1; proto_id = proto_get_next_protocol(&proto_cookie)) { protocol_t *protocol = find_protocol_by_id(proto_id); if (!proto_is_protocol_enabled(protocol)) continue; // Don't complete the current word. const QString pfname = proto_get_protocol_filter_name(proto_id); if (field_word.compare(pfname)) field_list << pfname; // Add fields only if we're past the protocol name and only for the // current protocol. if (field_dots > pfname.count('.')) { void *field_cookie; const QByteArray fw_ba = field_word.toUtf8(); // or toLatin1 or toStdString? const char *fw_utf8 = fw_ba.constData(); gsize fw_len = (gsize) strlen(fw_utf8); for (header_field_info *hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo; hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie)) { if (hfinfo->same_name_prev_id != -1) continue; // Ignore duplicate names. if (!g_ascii_strncasecmp(fw_utf8, hfinfo->abbrev, fw_len)) { if ((gsize) strlen(hfinfo->abbrev) != fw_len) field_list << hfinfo->abbrev; } } } } field_list.sort(); completion_model_->setStringList(field_list); completer()->setCompletionPrefix(field_word); }
static GtkTreePath * proto_hier_tree_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter) { ProtoHierTreeModel *model; GtkTreePath *path; int pos; int p_id; void *cookie; g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), NULL); model = (ProtoHierTreeModel *) tree_model; g_return_val_if_fail(iter != NULL, NULL); g_return_val_if_fail(iter->stamp == model->stamp, FALSE); p_id = proto_get_data_protocol(iter->user_data); path = gtk_tree_path_new(); /* protocol */ { int id; /* XXX, assuming that protocols can't be disabled! */ pos = 0; for (id = proto_get_first_protocol(&cookie); id != p_id && id != -1; id = proto_get_next_protocol(&cookie)) { protocol_t *p = find_protocol_by_id(id); if (!proto_is_protocol_enabled(p)) continue; pos++; } gtk_tree_path_append_index(path, pos); } /* field */ if (iter->user_data2 != NULL) { header_field_info *hfinfo; pos = 0; for (hfinfo = proto_get_first_protocol_field(p_id, &cookie); hfinfo && hfinfo != iter->user_data3; hfinfo = proto_get_next_protocol_field(&cookie)) { if (hfinfo->same_name_prev_id != -1) continue; pos++; } gtk_tree_path_append_index(path, pos); } return path; }
/* This function is only called from the IGMP dissector */ int dissect_msnip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { proto_tree *tree; proto_item *item; guint8 type; if (!proto_is_protocol_enabled(find_protocol_by_id(proto_msnip))) { /* 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); } item = proto_tree_add_item(parent_tree, proto_msnip, tvb, offset, -1, FALSE); tree = proto_item_add_subtree(item, ett_msnip); col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSNIP"); col_clear(pinfo->cinfo, COL_INFO); type = tvb_get_guint8(tvb, offset); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, msnip_types, "Unknown Type:0x%02x")); } /* type of command */ proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type); offset += 1; switch (type) { case MSNIP_GM: offset = dissect_msnip_gm(tvb, pinfo, tree, offset); break; case MSNIP_IS: offset = dissect_msnip_is(tvb, pinfo, tree, offset); break; case MSNIP_RMR: offset = dissect_msnip_rmr(tvb, pinfo, tree, offset); break; } if (item) { proto_item_set_len(item, offset); } return offset; }
// Nearly identical to SupportedProtocolsDialog::fillTree. void DisplayFilterExpressionDialog::fillTree() { void *proto_cookie; QList <QTreeWidgetItem *> proto_list; for (int proto_id = proto_get_first_protocol(&proto_cookie); proto_id != -1; proto_id = proto_get_next_protocol(&proto_cookie)) { protocol_t *protocol = find_protocol_by_id(proto_id); if (!proto_is_protocol_enabled(protocol)) continue; QTreeWidgetItem *proto_ti = new QTreeWidgetItem(proto_type_); QString label = QString("%1 " UTF8_MIDDLE_DOT " %3") .arg(proto_get_protocol_short_name(protocol)) .arg(proto_get_protocol_long_name(protocol)); proto_ti->setText(0, label); proto_ti->setData(0, Qt::UserRole, QVariant::fromValue(proto_id)); proto_list << proto_ti; } wsApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers, 1); ui->fieldTreeWidget->invisibleRootItem()->addChildren(proto_list); ui->fieldTreeWidget->sortByColumn(0, Qt::AscendingOrder); int field_count = 0; foreach (QTreeWidgetItem *proto_ti, proto_list) { void *field_cookie; int proto_id = proto_ti->data(0, Qt::UserRole).toInt(); QList <QTreeWidgetItem *> field_list; for (header_field_info *hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo != NULL; hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie)) { if (hfinfo->same_name_prev_id != -1) continue; // Ignore duplicate names. QTreeWidgetItem *field_ti = new QTreeWidgetItem(field_type_); QString label = QString("%1 " UTF8_MIDDLE_DOT " %3").arg(hfinfo->abbrev).arg(hfinfo->name); field_ti->setText(0, label); field_ti->setData(0, Qt::UserRole, VariantPointer<header_field_info>::asQVariant(hfinfo)); field_list << field_ti; field_count++; if (field_count % 10000 == 0) { wsApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers, 1); } } std::sort(field_list.begin(), field_list.end()); proto_ti->addChildren(field_list); }
void proto_disable_proto_by_name(const char *name) { protocol_t *protocol; int proto_id; proto_id = proto_get_id_by_filter_name(name); if (proto_id >= 0 ) { protocol = find_protocol_by_id(proto_id); if (proto_is_protocol_enabled(protocol) == TRUE) { if (proto_can_toggle_protocol(proto_id) == TRUE) { proto_set_decoding(proto_id, FALSE); } } } }
/* This function is only called from the IGMP dissector */ int dissect_mrdisc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { proto_tree *tree; proto_item *item; guint8 type; if (!proto_is_protocol_enabled(find_protocol_by_id(proto_mrdisc))) { /* 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); } item = proto_tree_add_item(parent_tree, proto_mrdisc, tvb, offset, 0, ENC_NA); tree = proto_item_add_subtree(item, ett_mrdisc); col_set_str(pinfo->cinfo, COL_PROTOCOL, "MRDISC"); col_clear(pinfo->cinfo, COL_INFO); type = tvb_get_guint8(tvb, offset); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, mrdisc_types, "Unknown Type:0x%02x")); } /* type of command */ proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type); offset += 1; switch (type) { case MRDISC_MRA: offset = dissect_mrdisc_mra(tvb, pinfo, tree, offset); break; case MRDISC_MRS: case MRDISC_MRT: /* MRS and MRT packets looks the same */ offset = dissect_mrdisc_mrst(tvb, pinfo, tree, offset); break; } return offset; }
static gint proto_hier_tree_iter_n_children(GtkTreeModel *tree_model, GtkTreeIter *iter) { ProtoHierTreeModel *model; gint count = 0; int p_id; void *cookie; g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), 0); model = (ProtoHierTreeModel *) tree_model; g_return_val_if_fail(iter == NULL || iter->user_data != NULL, 0); if (iter) { header_field_info *hfinfo; g_return_val_if_fail(iter->stamp == model->stamp, 0); /* field has no child */ if (iter->user_data2 != NULL) return 0; p_id = proto_get_data_protocol(iter->user_data); /* count not-duplicated fields */ for (hfinfo = proto_get_first_protocol_field(p_id, &cookie); hfinfo; hfinfo = proto_get_next_protocol_field(&cookie)) { if (hfinfo->same_name_prev_id != -1) continue; count++; } } else { /* count enabled protocols */ for (p_id = proto_get_first_protocol(&cookie); p_id != -1; p_id = proto_get_next_protocol(&cookie)) { protocol_t *p = find_protocol_by_id(p_id); if (!proto_is_protocol_enabled(p)) continue; count++; } } return count; }
static void decode_proto_add_to_list (const gchar *table_name, gpointer value, gpointer user_data) { struct decode_as_default_populate* populate = (struct decode_as_default_populate*)user_data; const gchar *proto_name; gint i; dissector_handle_t handle; handle = (dissector_handle_t)value; proto_name = dissector_handle_get_short_name(handle); i = dissector_handle_get_protocol_index(handle); if (i >= 0 && !proto_is_protocol_enabled(find_protocol_by_id(i))) return; populate->add_to_list(table_name, proto_name, value, populate->ui_element); }
/* This function is only called from the IGMP dissector */ int dissect_rgmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { proto_tree *tree; proto_item *item; guint8 type; if (!proto_is_protocol_enabled(find_protocol_by_id(proto_rgmp))) { /* 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); } item = proto_tree_add_item(parent_tree, proto_rgmp, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_rgmp); col_set_str(pinfo->cinfo, COL_PROTOCOL, "RGMP"); col_clear(pinfo->cinfo, COL_INFO); type = tvb_get_guint8(tvb, offset); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, rgmp_types, "Unknown Type: 0x%02x")); } proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type); offset += 1; /* reserved */ offset += 1; igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; return offset; }
/* * Check whether this could be a TPKT-encapsulated PDU. * Returns -1 if it's not, and the PDU length from the TPKT header * if it is. * * "min_len" is the minimum length of the PDU; the length field in the * TPKT header must be at least "4+min_len" in order for this to be a * valid TPKT PDU for the protocol in question. */ int is_tpkt(tvbuff_t *tvb, int min_len) { guint16 pkt_len; /* * If TPKT is disabled, don't dissect it, just return -1, meaning * "this isn't TPKT". */ if (!proto_is_protocol_enabled(proto_tpkt_ptr)) return -1; /* There should at least be 4 bytes left in the frame */ if (tvb_captured_length(tvb) < 4) return -1; /* there aren't */ /* * The first octet should be 3 and the second one should be 0 * The H.323 implementers guide suggests that this might not * always be the case.... */ if (!(tvb_get_guint8(tvb, 0) == 3 && tvb_get_guint8(tvb, 1) == 0)) return -1; /* they're not */ /* * Get the length from the TPKT header. Make sure it's large * enough. */ pkt_len = tvb_get_ntohs(tvb, 2); if (pkt_len < 4 + min_len) return -1; /* it's not */ /* * Return the length from the header. */ return pkt_len; }
/* * Write out a list of disabled protocols. * * On success, "*pref_path_return" is set to NULL. * On error, "*pref_path_return" is set to point to the pathname of * the file we tried to read - it should be freed by our caller - * and "*errno_return" is set to the error. */ void save_disabled_protos_list(char **pref_path_return, int *errno_return) { gchar *ff_path, *ff_path_new; FILE *ff; gint i; protocol_t *protocol; void *cookie; *pref_path_return = NULL; /* assume no error */ ff_path = get_persconffile_path(PROTOCOLS_FILE_NAME, TRUE, TRUE); /* Write to "XXX.new", and rename if that succeeds. That means we don't trash the file if we fail to write it out completely. */ ff_path_new = g_strdup_printf("%s.new", ff_path); if ((ff = ws_fopen(ff_path_new, "w")) == NULL) { *pref_path_return = ff_path; *errno_return = errno; g_free(ff_path_new); return; } /* Iterate over all the protocols */ for (i = proto_get_first_protocol(&cookie); i != -1; i = proto_get_next_protocol(&cookie)) { if (!proto_can_toggle_protocol(i)) { continue; } protocol = find_protocol_by_id(i); if (proto_is_protocol_enabled(protocol)) { continue; } /* Write out the protocol name. */ fprintf(ff, "%s\n", proto_get_protocol_filter_name(i)); } if (fclose(ff) == EOF) { *pref_path_return = ff_path; *errno_return = errno; ws_unlink(ff_path_new); g_free(ff_path_new); return; } #ifdef _WIN32 /* ANSI C doesn't say whether "rename()" removes the target if it exists; the Win32 call to rename files doesn't do so, which I infer is the reason why the MSVC++ "rename()" doesn't do so. We must therefore remove the target file first, on Windows. XXX - ws_rename() should be ws_stdio_rename() on Windows, and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING, so it should remove the target if it exists, so this stuff shouldn't be necessary. Perhaps it dates back to when we were calling rename(), with that being a wrapper around Microsoft's _rename(), which didn't remove the target. */ if (ws_remove(ff_path) < 0 && errno != ENOENT) { /* It failed for some reason other than "it's not there"; if it's not there, we don't need to remove it, so we just drive on. */ *pref_path_return = ff_path; *errno_return = errno; ws_unlink(ff_path_new); g_free(ff_path_new); return; } #endif if (ws_rename(ff_path_new, ff_path) < 0) { *pref_path_return = ff_path; *errno_return = errno; ws_unlink(ff_path_new); g_free(ff_path_new); return; } g_free(ff_path_new); g_free(ff_path); }
static gboolean proto_hier_tree_iter_nth_child(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n) { ProtoHierTreeModel *model; gint proto_id; void *cookie; g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), FALSE); model = (ProtoHierTreeModel *) tree_model; if (parent) { header_field_info *hfinfo; g_return_val_if_fail(parent->stamp == model->stamp, FALSE); /* no child of field */ if (parent->user_data2 != NULL) return FALSE; proto_id = proto_get_data_protocol(parent->user_data); /* get n-th field of protocol */ hfinfo = proto_get_first_protocol_field(proto_id, &cookie); while (hfinfo) { if (hfinfo->same_name_prev_id == -1) { if (!n) break; n--; } hfinfo = proto_get_next_protocol_field(&cookie); } /* not found? */ if (!hfinfo) return FALSE; iter->stamp = model->stamp; iter->user_data = parent->user_data; iter->user_data2 = cookie; iter->user_data3 = hfinfo; return TRUE; } /* get n-th enabled protocol */ proto_id = proto_get_first_protocol(&cookie); while (proto_id != -1) { protocol_t *p = find_protocol_by_id(proto_id); if (proto_is_protocol_enabled(p)) { if (!n) break; n--; } proto_id = proto_get_next_protocol(&cookie); } /* not found? */ if (proto_id == -1) return FALSE; iter->stamp = model->stamp; iter->user_data = cookie; iter->user_data2 = NULL; iter->user_data3 = proto_registrar_get_nth(proto_id); return TRUE; }
gboolean dissect_mailslot_smb(tvbuff_t *mshdr_tvb, tvbuff_t *setup_tvb, tvbuff_t *tvb, const char *mailslot, packet_info *pinfo, proto_tree *parent_tree) { smb_info_t *smb_info; smb_transact_info_t *tri; int trans_subcmd; proto_tree *tree = NULL; proto_item *item = NULL; guint16 opcode; int offset = 0; int len; if (!proto_is_protocol_enabled(find_protocol_by_id(proto_smb_msp))) { return FALSE; } pinfo->current_proto = "SMB Mailslot"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMB Mailslot"); if ((tvb==NULL) || (tvb_reported_length(tvb)==0)) { /* Interim reply */ col_set_str(pinfo->cinfo, COL_INFO, "Interim reply"); return TRUE; } col_clear(pinfo->cinfo, COL_INFO); smb_info = pinfo->private_data; if (smb_info->sip != NULL && smb_info->sip->extra_info_type == SMB_EI_TRI) tri = smb_info->sip->extra_info; else tri = NULL; /* check which mailslot this is about */ trans_subcmd=MAILSLOT_UNKNOWN; if(smb_info->request){ if(strncmp(mailslot,"BROWSE",6) == 0){ trans_subcmd=MAILSLOT_BROWSE; } else if(strncmp(mailslot,"LANMAN",6) == 0){ trans_subcmd=MAILSLOT_LANMAN; } else if(strncmp(mailslot,"NET",3) == 0){ trans_subcmd=MAILSLOT_NET; } else if(strncmp(mailslot,"TEMP\\NETLOGON",13) == 0){ trans_subcmd=MAILSLOT_TEMP_NETLOGON; } else if(strncmp(mailslot,"MSSP",4) == 0){ trans_subcmd=MAILSLOT_MSSP; } if (!pinfo->fd->flags.visited) { if (tri != NULL) tri->trans_subcmd = trans_subcmd; } } else { if(!tri){ return FALSE; } else { trans_subcmd = tri->trans_subcmd; } } /* Only do these ones if we have them. For fragmented SMB Transactions we may only have the setup area for the first fragment */ if(mshdr_tvb && setup_tvb){ if (parent_tree) { item = proto_tree_add_item(parent_tree, proto_smb_msp, mshdr_tvb, 0, -1, FALSE); tree = proto_item_add_subtree(item, ett_smb_msp); } /* do the opcode field */ opcode = tvb_get_letohs(setup_tvb, offset); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, opcode_vals, "Unknown opcode: 0x%04x")); } /* These are in the setup words; use "setup_tvb". */ /* opcode */ proto_tree_add_uint(tree, hf_opcode, setup_tvb, offset, 2, opcode); offset += 2; /* priority */ proto_tree_add_item(tree, hf_priority, setup_tvb, offset, 2, TRUE); offset += 2; /* class */ proto_tree_add_item(tree, hf_class, setup_tvb, offset, 2, TRUE); offset += 2; /* These are in the rest of the data; use "mshdr_tvb", which starts at the same place "setup_tvb" does. */ /* size */ /* this is actually bytecount in the SMB Transaction command */ proto_tree_add_item(tree, hf_size, mshdr_tvb, offset, 2, TRUE); offset += 2; /* mailslot name */ len = tvb_strsize(mshdr_tvb, offset); proto_tree_add_item(tree, hf_name, mshdr_tvb, offset, len, TRUE); offset += len; proto_item_set_len(item, offset); } switch(trans_subcmd){ case MAILSLOT_BROWSE: call_dissector(mailslot_browse_handle, tvb, pinfo, parent_tree); break; case MAILSLOT_LANMAN: call_dissector(mailslot_lanman_handle, tvb, pinfo, parent_tree); break; case MAILSLOT_NET: case MAILSLOT_TEMP_NETLOGON: case MAILSLOT_MSSP: call_dissector(netlogon_handle, tvb, pinfo, parent_tree); break; default: /* * We dissected the mailslot header, but we don't know * how to dissect the message; dissect the latter as data, * but indicate that we successfully dissected the mailslot * stuff. */ call_dissector(data_handle ,tvb, pinfo, parent_tree); break; } return TRUE; }
ProtocolTreeWidgetItem(QTreeWidgetItem *parent, const protocol_t *protocol) : EnableProtocolTreeWidgetItem (parent, proto_get_protocol_long_name(protocol), proto_get_protocol_short_name(protocol), proto_is_protocol_enabled(protocol), protocol_type_), protocol_(protocol) { }
static int dissect_gssapi_work(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_verifier) { proto_item *volatile item; proto_tree *volatile subtree; volatile int return_offset = 0; gssapi_conv_info_t *volatile gss_info; gssapi_oid_value *oidvalue; dissector_handle_t handle; conversation_t *conversation; tvbuff_t *oid_tvb; int len, start_offset, oid_start_offset; volatile int offset; gint8 appclass; gboolean pc, ind_field; gint32 tag; guint32 len1; const char *oid; fragment_data *fd_head=NULL; gssapi_frag_info_t *fi; tvbuff_t *volatile gss_tvb=NULL; asn1_ctx_t asn1_ctx; void *pd_save; start_offset=0; offset=0; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); /* * We don't know whether the data is encrypted, so say it's * not, for now. The subdissector must set gssapi_data_encrypted * if it is. */ pinfo->gssapi_data_encrypted = FALSE; /* * We need a conversation for later */ conversation = find_or_create_conversation(pinfo); gss_info = (gssapi_conv_info_t *)conversation_get_proto_data(conversation, proto_gssapi); if (!gss_info) { gss_info = se_new(gssapi_conv_info_t); gss_info->oid=NULL; gss_info->do_reassembly=FALSE; gss_info->frags=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "gssapi_frags"); conversation_add_proto_data(conversation, proto_gssapi, gss_info); } item = proto_tree_add_item( tree, proto_gssapi, tvb, offset, -1, ENC_NA); subtree = proto_item_add_subtree(item, ett_gssapi); /* * Catch the ReportedBoundsError exception; the stuff we've been * handed doesn't necessarily run to the end of the packet, it's * an item inside a packet, so if it happens to be malformed (or * we, or a dissector we call, has a bug), so that an exception * is thrown, we want to report the error, but return and let * our caller dissect the rest of the packet. * * If it gets a BoundsError, we can stop, as there's nothing more * in the packet after our blob to see, so we just re-throw the * exception. */ pd_save = pinfo->private_data; TRY { gss_tvb=tvb; /* First of all, if it's the first time we see this packet * then check whether we are in the middle of reassembly or not */ if( (!pinfo->fd->flags.visited) && (gss_info->do_reassembly) && (gssapi_reassembly) ){ fi=(gssapi_frag_info_t *)se_tree_lookup32(gss_info->frags, gss_info->first_frame); if(!fi){ goto done; } se_tree_insert32(gss_info->frags, pinfo->fd->num, fi); fd_head=fragment_add(&gssapi_reassembly_table, tvb, 0, pinfo, fi->first_frame, NULL, gss_info->frag_offset, tvb_length(tvb), TRUE); gss_info->frag_offset+=tvb_length(tvb); /* we need more fragments */ if(!fd_head){ goto done; } /* this blob is now fully reassembled */ gss_info->do_reassembly=FALSE; fi->reassembled_in=pinfo->fd->num; gss_tvb=tvb_new_child_real_data(tvb, fd_head->data, fd_head->datalen, fd_head->datalen); add_new_data_source(pinfo, gss_tvb, "Reassembled GSSAPI"); } /* We have seen this packet before. * Is this blob part of reassembly or a normal blob ? */ if( (pinfo->fd->flags.visited) && (gssapi_reassembly) ){ fi=(gssapi_frag_info_t *)se_tree_lookup32(gss_info->frags, pinfo->fd->num); if(fi){ fd_head=fragment_get(&gssapi_reassembly_table, pinfo, fi->first_frame, NULL); if(fd_head && (fd_head->flags&FD_DEFRAGMENTED)){ if(pinfo->fd->num==fi->reassembled_in){ proto_item *frag_tree_item; gss_tvb=tvb_new_child_real_data(tvb, fd_head->data, fd_head->datalen, fd_head->datalen); add_new_data_source(pinfo, gss_tvb, "Reassembled GSSAPI"); show_fragment_tree(fd_head, &gssapi_frag_items, tree, pinfo, tvb, &frag_tree_item); } else { proto_item *it; it=proto_tree_add_uint(tree, hf_gssapi_reassembled_in, tvb, 0, 0, fi->reassembled_in); PROTO_ITEM_SET_GENERATED(it); goto done; } } } } /* Read header */ offset = get_ber_identifier(gss_tvb, offset, &appclass, &pc, &tag); offset = get_ber_length(gss_tvb, offset, &len1, &ind_field); if (!(appclass == BER_CLASS_APP && pc && tag == 0)) { /* It could be NTLMSSP, with no OID. This can happen for anything that microsoft calls 'Negotiate' or GSS-SPNEGO */ if ((tvb_length_remaining(gss_tvb, start_offset)>7) && (tvb_strneql(gss_tvb, start_offset, "NTLMSSP", 7) == 0)) { return_offset = call_dissector(ntlmssp_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree); goto done; } /* Maybe it's new NTLMSSP payload */ if ((tvb_length_remaining(gss_tvb, start_offset)>16) && ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) { return_offset = call_dissector(ntlmssp_payload_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree); pinfo->gssapi_data_encrypted = TRUE; goto done; } if ((tvb_length_remaining(gss_tvb, start_offset)==16) && ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) { if( is_verifier ) { return_offset = call_dissector(ntlmssp_verf_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree); } else if( pinfo->gssapi_encrypted_tvb ) { return_offset = call_dissector(ntlmssp_data_only_handle, tvb_new_subset_remaining(pinfo->gssapi_encrypted_tvb, 0), pinfo, subtree); pinfo->gssapi_data_encrypted = TRUE; } goto done; } /* Maybe it's new GSSKRB5 CFX Wrapping */ if ((tvb_length_remaining(gss_tvb, start_offset)>2) && ((tvb_memeql(gss_tvb, start_offset, "\04\x04", 2) == 0) || (tvb_memeql(gss_tvb, start_offset, "\05\x04", 2) == 0))) { return_offset = call_dissector(spnego_krb5_wrap_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree); goto done; } /* * If we do not recognise an Application class, * then we are probably dealing with an inner context * token or a wrap token, and we should retrieve the * gssapi_oid_value pointer from the per-frame data or, * if there is no per-frame data (as would be the case * the first time we dissect this frame), from the * conversation that exists or that we created from * pinfo (and then make it per-frame data). * We need to make it per-frame data as there can be * more than one GSS-API negotiation in a conversation. * * Note! We "cheat". Since we only need the pointer, * we store that as the data. (That's not really * "cheating" - the per-frame data and per-conversation * data code doesn't care what you supply as a data * pointer; it just treats it as an opaque pointer, it * doesn't dereference it or free what it points to.) */ oidvalue = (gssapi_oid_value *)p_get_proto_data(pinfo->fd, proto_gssapi, 0); if (!oidvalue && !pinfo->fd->flags.visited) { /* No handle attached to this frame, but it's the first */ /* pass, so it'd be attached to the conversation. */ oidvalue = gss_info->oid; if (gss_info->oid) p_add_proto_data(pinfo->fd, proto_gssapi, 0, gss_info->oid); } if (!oidvalue) { proto_tree_add_text(subtree, gss_tvb, start_offset, 0, "Unknown header (class=%d, pc=%d, tag=%d)", appclass, pc, tag); return_offset = tvb_length(gss_tvb); goto done; } else { tvbuff_t *oid_tvb_local; oid_tvb_local = tvb_new_subset_remaining(gss_tvb, start_offset); if (is_verifier) handle = oidvalue->wrap_handle; else handle = oidvalue->handle; len = call_dissector(handle, oid_tvb_local, pinfo, subtree); if (len == 0) return_offset = tvb_length(gss_tvb); else return_offset = start_offset + len; goto done; /* We are finished here */ } } /* Read oid */ oid_start_offset=offset; offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, subtree, gss_tvb, offset, hf_gssapi_oid, &oid); oidvalue = gssapi_lookup_oid_str(oid); /* Check if we need reassembly of this blob. * Only try reassembly for OIDs we recognize * and when we have the entire tvb * * SMB will sometimes split one large GSSAPI blob * across multiple SMB/SessionSetup commands. * While we should look at the uid returned in the response * to the first SessionSetup and use that as a key * instead for simplicity we assume there will not be several * such authentication at once on a single tcp session */ if( (!pinfo->fd->flags.visited) && (oidvalue) && (tvb_length(gss_tvb)==tvb_reported_length(gss_tvb)) && (len1>(guint32)tvb_length_remaining(gss_tvb, oid_start_offset)) && (gssapi_reassembly) ){ fi=se_new(gssapi_frag_info_t); fi->first_frame=pinfo->fd->num; fi->reassembled_in=0; se_tree_insert32(gss_info->frags, pinfo->fd->num, fi); fragment_add(&gssapi_reassembly_table, gss_tvb, 0, pinfo, pinfo->fd->num, NULL, 0, tvb_length(gss_tvb), TRUE); fragment_set_tot_len(&gssapi_reassembly_table, pinfo, pinfo->fd->num, NULL, len1+oid_start_offset); gss_info->do_reassembly=TRUE; gss_info->first_frame=pinfo->fd->num; gss_info->frag_offset=tvb_length(gss_tvb); goto done; } /* * Hand off to subdissector. */ if ((oidvalue == NULL) || !proto_is_protocol_enabled(oidvalue->proto)) { /* No dissector for this oid */ proto_tree_add_text(subtree, gss_tvb, oid_start_offset, -1, "Token object"); return_offset = tvb_length(gss_tvb); goto done; } /* Save a pointer to the data for the OID for the * GSSAPI protocol for this conversation. */ /* * Now add the proto data ... * but only if it is not already there. */ if(!gss_info->oid){ gss_info->oid=oidvalue; } if (is_verifier) { handle = oidvalue->wrap_handle; if (handle != NULL) { oid_tvb = tvb_new_subset_remaining(gss_tvb, offset); len = call_dissector(handle, oid_tvb, pinfo, subtree); if (len == 0) return_offset = tvb_length(gss_tvb); else return_offset = offset + len; } else { proto_tree_add_text(subtree, gss_tvb, offset, -1, "Authentication verifier"); return_offset = tvb_length(gss_tvb); } } else { handle = oidvalue->handle; if (handle != NULL) { oid_tvb = tvb_new_subset_remaining(gss_tvb, offset); len = call_dissector(handle, oid_tvb, pinfo, subtree); if (len == 0) return_offset = tvb_length(gss_tvb); else return_offset = offset + len; } else { proto_tree_add_text(subtree, gss_tvb, offset, -1, "Authentication credentials"); return_offset = tvb_length(gss_tvb); } } done: ; } CATCH_NONFATAL_ERRORS { /* * Somebody threw an exception that means that there * was a problem dissecting the payload; that means * that a dissector was found, so we don't need to * dissect the payload as data or update the protocol * or info columns. * * Just show the exception and then drive on to show * the trailer, after noting that a dissector was found * and restoring the protocol value that was in effect * before we called the subdissector. * * Restore the private_data structure in case one of the * called dissectors modified it (and, due to the exception, * was unable to restore it). */ pinfo->private_data = pd_save; show_exception(gss_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; proto_item_set_len(item, return_offset); return return_offset; }
/* 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, ENC_NA); 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, ENC_BIG_ENDIAN); 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, ENC_BIG_ENDIAN); 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, ENC_BIG_ENDIAN); 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, ENC_BIG_ENDIAN); 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, ENC_BIG_ENDIAN); 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, ENC_BIG_ENDIAN); 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, ENC_BIG_ENDIAN); 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, ENC_BIG_ENDIAN); offset += 4; break; } default: break; } done:; return offset+tvb_length_remaining(tvb, offset); }
static void dissect_xmpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { xml_frame_t *xml_frame; gboolean out_packet; conversation_t *conversation; xmpp_conv_info_t *xmpp_info; proto_tree *xmpp_tree = NULL; proto_item *xmpp_item = NULL; xmpp_element_t *packet = NULL; /*check if desegment * now it checks that last char is '>', * TODO checks that first element in packet is closed*/ int indx; gchar last_char; if (xmpp_desegment) { indx = tvb_reported_length(tvb) - 1; if (indx >= 0) { last_char = tvb_get_guint8(tvb, indx); while ((last_char <= ' ') && (indx - 1 >= 0)) { indx--; last_char = tvb_get_guint8(tvb, indx); } if ((indx >= 0) && (last_char != '>')) { pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; return; } } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "XMPP"); col_clear(pinfo->cinfo, COL_INFO); conversation = find_or_create_conversation(pinfo); xmpp_info = (xmpp_conv_info_t *)conversation_get_proto_data(conversation, proto_xmpp); if (xmpp_info && xmpp_info->ssl_proceed && xmpp_info->ssl_proceed < pinfo->fd->num) { call_dissector(ssl_handle, tvb, pinfo, tree); return; } /*if tree == NULL then xmpp_item and xmpp_tree will also NULL*/ xmpp_item = proto_tree_add_item(tree, proto_xmpp, tvb, 0, -1, ENC_NA); xmpp_tree = proto_item_add_subtree(xmpp_item, ett_xmpp); call_dissector(xml_handle, tvb, pinfo, xmpp_tree); /* If XML dissector is disabled, we can't do much */ if (!proto_is_protocol_enabled(find_protocol_by_id(dissector_handle_get_protocol_index(xml_handle)))) { col_append_str(pinfo->cinfo, COL_INFO, "(XML dissector disabled, can't dissect XMPP)"); expert_add_info_format(pinfo, xmpp_item, PI_UNDECODED, PI_WARN, "XML dissector disabled, can't dissect XMPP"); return; } /*if stream end occurs then return*/ if(xmpp_stream_close(xmpp_tree,tvb, pinfo)) { if(xmpp_tree) xmpp_proto_tree_hide_first_child(xmpp_tree); return; } if(!pinfo->private_data) return; /*data from XML dissector*/ xml_frame = ((xml_frame_t*)pinfo->private_data)->first_child; if(!xml_frame) return; if (!xmpp_info) { xmpp_info = se_new(xmpp_conv_info_t); xmpp_info->req_resp = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_req_resp"); xmpp_info->jingle_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_jingle_sessions"); xmpp_info->ibb_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_ibb_sessions"); xmpp_info->gtalk_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_gtalk_sessions"); xmpp_info->ssl_start = 0; xmpp_info->ssl_proceed = 0; conversation_add_proto_data(conversation, proto_xmpp, (void *) xmpp_info); } if (pinfo->match_uint == pinfo->destport) out_packet = TRUE; else out_packet = FALSE; while(xml_frame) { packet = xmpp_xml_frame_to_element_t(xml_frame, NULL, tvb); DISSECTOR_ASSERT(packet); if (strcmp(packet->name, "iq") == 0) { xmpp_iq_reqresp_track(pinfo, packet, xmpp_info); xmpp_jingle_session_track(pinfo, packet, xmpp_info); xmpp_gtalk_session_track(pinfo, packet, xmpp_info); } if (strcmp(packet->name, "iq") == 0 || strcmp(packet->name, "message") == 0) { xmpp_ibb_session_track(pinfo, packet, xmpp_info); } if (tree) { /* we are being asked for details */ proto_item *outin_item; if (out_packet) outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_out, tvb, 0, 0, TRUE); else outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_in, tvb, 0, 0, TRUE); PROTO_ITEM_SET_HIDDEN(outin_item); /*it hides tree generated by XML dissector*/ xmpp_proto_tree_hide_first_child(xmpp_tree); if (strcmp(packet->name, "iq") == 0) { xmpp_iq(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "presence") == 0) { xmpp_presence(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "message") == 0) { xmpp_message(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "auth") == 0) { xmpp_auth(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "challenge") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_challenge, ett_xmpp_challenge, "CHALLENGE"); } else if (strcmp(packet->name, "response") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_response, ett_xmpp_response, "RESPONSE"); } else if (strcmp(packet->name, "success") == 0) { xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_success, ett_xmpp_success, "SUCCESS"); } else if (strcmp(packet->name, "failure") == 0) { xmpp_failure(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "xml") == 0) { xmpp_xml_header(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "stream") == 0) { xmpp_stream(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "features") == 0) { xmpp_features(xmpp_tree, tvb, pinfo, packet); } else if (strcmp(packet->name, "starttls") == 0) { xmpp_starttls(xmpp_tree, tvb, pinfo, packet, xmpp_info); }else if (strcmp(packet->name, "proceed") == 0) { xmpp_proceed(xmpp_tree, tvb, pinfo, packet, xmpp_info); }else { xmpp_proto_tree_show_first_child(xmpp_tree); expert_add_info_format(pinfo, xmpp_tree, PI_UNDECODED, PI_NOTE, "Unknown packet: %s", packet->name); col_clear(pinfo->cinfo, COL_INFO); col_append_fstr(pinfo->cinfo, COL_INFO, "UNKNOWN PACKET "); } /*appends to COL_INFO information about src or dst*/ if (pinfo->match_uint == pinfo->destport) { xmpp_attr_t *to = xmpp_get_attr(packet, "to"); if (to) col_append_fstr(pinfo->cinfo, COL_INFO, "> %s ", to->value); } else { xmpp_attr_t *from = xmpp_get_attr(packet, "from"); if (from) col_append_fstr(pinfo->cinfo, COL_INFO, "< %s ", from->value); } } xmpp_element_t_tree_free(packet); xml_frame = xml_frame->next_sibling; } }
/* This function is only called from the IGMP dissector */ int dissect_igap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { proto_tree *tree; proto_item *item; guint8 type, tsecs, subtype, asize, msize; guchar account[ACCOUNT_SIZE+1], message[MESSAGE_SIZE+1]; if (!proto_is_protocol_enabled(find_protocol_by_id(proto_igap))) { /* 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); } item = proto_tree_add_item(parent_tree, proto_igap, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_igap); col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGAP"); col_clear(pinfo->cinfo, COL_INFO); type = tvb_get_guint8(tvb, offset); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, igap_types, "Unknown Type: 0x%02x")); proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type); offset += 1; tsecs = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(tree, hf_max_resp, tvb, offset, 1, tsecs, "%.1f sec (0x%02x)", tsecs * 0.1, tsecs); offset += 1; igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_uint(tree, hf_version, tvb, offset, 1, tvb_get_guint8(tvb, offset)); offset += 1; subtype = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_subtype, tvb, offset, 1, subtype); offset += 2; proto_tree_add_uint(tree, hf_challengeid, tvb, offset, 1, tvb_get_guint8(tvb, offset)); offset += 1; asize = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_asize, tvb, offset, 1, asize); offset += 1; msize = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_msize, tvb, offset, 1, msize); offset += 3; if (asize > 0) { if (asize > ACCOUNT_SIZE) { /* Bogus account size. XXX - flag this? */ asize = ACCOUNT_SIZE; } tvb_memcpy(tvb, account, offset, asize); account[asize] = '\0'; proto_tree_add_string(tree, hf_account, tvb, offset, asize, account); } offset += ACCOUNT_SIZE; if (msize > 0) { if (msize > MESSAGE_SIZE) { /* Bogus message size. XXX - flag this? */ msize = MESSAGE_SIZE; } tvb_memcpy(tvb, message, offset, msize); switch (subtype) { case IGAP_SUBTYPE_PASSWORD_JOIN: case IGAP_SUBTYPE_PASSWORD_LEAVE: /* Challenge field is user's password */ message[msize] = '\0'; proto_tree_add_string(tree, hf_igap_user_password, tvb, offset, msize, message); break; case IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN: case IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE: /* Challenge field is the results of MD5 calculation */ proto_tree_add_item(tree, hf_igap_result_of_md5_calculation, tvb, offset, msize, ENC_NA); break; case IGAP_SUBTYPE_CHALLENGE: /* Challenge field is the challenge value */ proto_tree_add_item(tree, hf_igap_challenge, tvb, offset, msize, ENC_NA); break; case IGAP_SUBTYPE_AUTH_MESSAGE: /* Challenge field indicates the result of the authenticaion */ proto_tree_add_uint(tree, hf_igap_authentication_result, tvb, offset, msize, message[0]); break; case IGAP_SUBTYPE_ACCOUNTING_MESSAGE: /* Challenge field indicates the accounting status */ proto_tree_add_uint(tree, hf_igap_accounting_status, tvb, offset, msize, message[0]); break; default: proto_tree_add_item(tree, hf_igap_unknown_message, tvb, offset, msize, ENC_NA); } } offset += MESSAGE_SIZE; if (item) proto_item_set_len(item, offset); return offset; }