aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaap Keuter <jaap.keuter@xs4all.nl>2007-09-10 07:21:27 +0000
committerJaap Keuter <jaap.keuter@xs4all.nl>2007-09-10 07:21:27 +0000
commite1541263e4d7a337fbcadfbfc480cc7fbcdbc9d9 (patch)
tree2df2f760d637ae9a2b5b1c99c6f69828974641be
parent070cf8b006eb507c26d71e1a31e64165ec6f498e (diff)
From Chad Singer:
UNISTIM Tap interface plus call grapher. svn path=/trunk/; revision=22834
-rw-r--r--gtk/voip_calls.c430
-rw-r--r--gtk/voip_calls.h6
-rw-r--r--gtk/voip_calls_dlg.c8
-rw-r--r--plugins/unistim/packet-unistim.c225
-rw-r--r--plugins/unistim/packet-unistim.h131
5 files changed, 676 insertions, 124 deletions
diff --git a/gtk/voip_calls.c b/gtk/voip_calls.c
index 7e2b7f2336..5e677b8174 100644
--- a/gtk/voip_calls.c
+++ b/gtk/voip_calls.c
@@ -62,6 +62,7 @@
#include <epan/dissectors/packet-t30.h>
#include <epan/dissectors/packet-h248.h>
#include <epan/dissectors/packet-sccp.h>
+#include <plugins/unistim/packet-unistim.h>
#include <epan/conversation.h>
#include <epan/rtp_pt.h>
#include <epan/ws_strsplit.h>
@@ -98,7 +99,8 @@ const char *voip_protocol_name[]={
"H.248",
"SCCP",
"BSSMAP",
- "RANAP"
+ "RANAP",
+ "UNISTIM"
};
typedef struct {
@@ -119,7 +121,7 @@ static h245_labels_t h245_labels;
/****************************************************************************/
/* the one and only global voip_calls_tapinfo_t structure */
static voip_calls_tapinfo_t the_tapinfo_struct =
- {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
/* the one and only global voip_rtp_tapinfo_t structure */
static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
@@ -3073,6 +3075,430 @@ remove_tap_listener_sccp_calls(void)
/****************************************************************************/
+/****************************TAP for UNISTIM ********************************/
+/****************************************************************************/
+
+static int
+unistim_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *unistim_info)
+{
+ voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
+ voip_calls_info_t *tmp_listinfo;
+ voip_calls_info_t *strinfo = NULL;
+ unistim_info_t *tmp_unistim_info = NULL;
+ GList *list = NULL;
+ GString *g_tmp = NULL;
+ gchar *frame_label = NULL;
+ gchar *comment = NULL;
+
+ /* Fetch specific packet infos */
+ const unistim_info_t *pi = unistim_info;
+
+ /* Init gstring */
+ g_tmp = g_string_new(NULL);
+
+ /* Check to see if this is a dup */
+ list = g_list_first(tapinfo->strinfo_list);
+
+ while(list)
+ {
+ tmp_listinfo = list->data;
+
+ if(tmp_listinfo->protocol == VOIP_UNISTIM){
+
+ tmp_unistim_info = tmp_listinfo->prot_info;
+
+ /* Search by termid if possible, otherwise use ni/it ip + port.. */
+ if(pi->termid != 0){
+ if(tmp_unistim_info->termid == pi->termid){
+ /* If the call has ended, then we can reuse it.. */
+ if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
+ /* Do nothing */
+ } else {
+ strinfo = (voip_calls_info_t*)(list->data);
+ break;
+ }
+ }
+ } else {
+ /* If no term id use ips / port to find entry */
+ if(ADDRESSES_EQUAL(&tmp_unistim_info->it_ip, &pinfo->dst) && ADDRESSES_EQUAL(&tmp_unistim_info->ni_ip,&pinfo->src) && (tmp_unistim_info->it_port == pinfo->destport)){
+ if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
+ /* Do nothing previous call */
+ } else {
+ strinfo = (voip_calls_info_t*)(list->data);
+ break;
+ }
+ }
+ else if(ADDRESSES_EQUAL(&tmp_unistim_info->it_ip, &pinfo->src) && ADDRESSES_EQUAL(&tmp_unistim_info->ni_ip,&pinfo->dst) && (tmp_unistim_info->it_port == pinfo->srcport)) {
+ if(tmp_listinfo->call_state == VOIP_COMPLETED || tmp_listinfo->call_state == VOIP_UNKNOWN){
+ /* Do nothing, it ain't our call.. */
+ } else {
+ strinfo = (voip_calls_info_t*)(list->data);
+ break;
+ }
+ }
+ }
+ }
+
+ /* Otherwise, go to the next one.. */
+ list = g_list_next(list);
+ }
+
+ if(pi->payload_type == 2 || pi->payload_type == 1){
+
+ if(pi->key_state == 1 || pi->hook_state == 1){
+
+ /* If the user hits a button,
+ Session will be SETUP */
+
+ /* If new add to list */
+ if (strinfo==NULL){
+
+ strinfo = g_malloc(sizeof(voip_calls_info_t));
+ strinfo->call_active_state = VOIP_ACTIVE;
+ strinfo->call_state = VOIP_CALL_SETUP;
+ strinfo->from_identity=g_strdup_printf("%x",pi->termid);
+ strinfo->to_identity=g_strdup_printf("UNKNOWN");
+ COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
+ strinfo->first_frame_num=pinfo->fd->num;
+ strinfo->selected=FALSE;
+
+ /* Set this on init of struct so in case the call doesn't complete, we'll have a ref. */
+ /* Otherwise if the call is completed we'll have the open/close streams to ref actual call duration */
+ strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
+ strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
+
+ strinfo->protocol=VOIP_UNISTIM;
+ strinfo->prot_info=g_malloc(sizeof(unistim_info_t));
+
+ tmp_unistim_info = strinfo->prot_info;
+
+ /* Clear tap struct */
+ tmp_unistim_info->rudp_type = 0;
+ tmp_unistim_info->payload_type = 0;
+ tmp_unistim_info->sequence = pi->sequence;
+ tmp_unistim_info->termid = pi->termid;
+ tmp_unistim_info->key_val = -1;
+ tmp_unistim_info->key_state = -1;
+ tmp_unistim_info->hook_state = -1;
+ tmp_unistim_info->stream_connect = -1;
+ tmp_unistim_info->trans_connect = -1;
+ tmp_unistim_info->set_termid = -1;
+ tmp_unistim_info->string_data = NULL;
+ tmp_unistim_info->key_buffer = NULL;
+
+ COPY_ADDRESS(&(tmp_unistim_info->it_ip),&(pi->it_ip));
+ COPY_ADDRESS(&(tmp_unistim_info->ni_ip),&(pi->ni_ip));
+ tmp_unistim_info->it_port = pi->it_port;
+
+ strinfo->free_prot_info = g_free;
+ strinfo->npackets = 0;
+ strinfo->call_num = tapinfo->ncalls++;
+ tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
+
+ } else {
+
+ /* Set up call wide info struct */
+ tmp_unistim_info = strinfo->prot_info;
+ tmp_unistim_info->sequence = pi->sequence;
+ }
+
+ /* Each packet COULD BE OUR LAST!!!! */
+ strinfo->stop_sec=(gint32)(pinfo->fd->rel_ts.secs);
+ strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
+ strinfo->last_frame_num=pinfo->fd->num;
+
+ /* This is a valid packet so increment counter */
+ ++(strinfo->npackets);
+
+ /* increment the packets counter of all calls */
+ ++(tapinfo->npackets);
+
+ /* Key was depressed.. update key buffer.. */
+ if(pi->key_val >= 0 && pi->key_val <= 11){
+
+ if(tmp_unistim_info->key_buffer != NULL){
+
+ /* assign to temp variable */
+ g_string_assign(g_tmp,tmp_unistim_info->key_buffer);
+
+ /* Manipulate the data */
+ if(pi->key_val == 10) {
+ tmp_unistim_info->key_buffer = g_strdup_printf("%s*",g_tmp->str);
+ } else if(pi->key_val == 11) {
+ tmp_unistim_info->key_buffer = g_strdup_printf("%s#",g_tmp->str);
+ } else {
+ tmp_unistim_info->key_buffer = g_strdup_printf("%s%d",g_tmp->str,pi->key_val);
+ }
+
+ } else {
+
+ /* Create new string */
+ if(pi->key_val == 10) {
+ tmp_unistim_info->key_buffer = g_strdup_printf("*");
+ } else if(pi->key_val == 11) {
+ tmp_unistim_info->key_buffer = g_strdup_printf("#");
+ } else {
+ tmp_unistim_info->key_buffer = g_strdup_printf("%d",pi->key_val);
+ }
+
+ }
+
+ /* Select for non-digit characters */
+ if(pi->key_val == 10) {
+ comment = g_strdup_printf("Key Input Sent: * (%d)", pi->sequence);
+ } else if(pi->key_val == 11) {
+ comment = g_strdup_printf("Key Input Sent: # (%d)", pi->sequence);
+ } else {
+ comment = g_strdup_printf("Key Input Sent: %d (%d)",pi->key_val, pi->sequence);
+ }
+ } else if(pi->key_val == 12) {
+ /* Set label and comment for graph */
+ comment = g_strdup_printf("Key Input Sent: UP (%d)", pi->sequence);
+ } else if(pi->key_val == 13) {
+ /* Set label and comment for graph */
+ comment = g_strdup_printf("Key Input Sent: DOWN (%d)", pi->sequence);
+ } else if(pi->key_val == 14) {
+ /* Set label and comment for graph */
+ comment = g_strdup_printf("Key Input Sent: RIGHT (%d)", pi->sequence);
+ } else if(pi->key_val == 15) {
+ if(pi->key_buffer != NULL){
+ /* Get data */
+ g_string_assign(g_tmp,pi->key_buffer);
+
+ /* Manipulate the data */
+ g_string_truncate(g_tmp,g_tmp->len-1);
+
+ /* Insert new data */
+ tmp_unistim_info->key_buffer = g_strdup_printf("%s",g_tmp->str);
+ }
+
+ /* Set label and comment for graph */
+ comment = g_strdup_printf("Key Input Sent: LEFT (%d)", pi->sequence);
+ } else if(pi->key_val == 20) {
+ /* User pressed the soft key 0 probably dial */
+ comment = g_strdup_printf("Key Input Sent: S0 (%d)", pi->sequence);
+ } else if(pi->key_val == 21) {
+ /* User pressed the soft key 1 */
+ comment = g_strdup_printf("Key Input Sent: S1 (%d)", pi->sequence);
+ } else if(pi->key_val == 22) {
+ /* User pressed the soft key 2 */
+ /* On cs2k phones, soft key 2 is backspace. */
+ if(pi->key_buffer != NULL) {
+
+ /* Get data */
+ g_string_assign(g_tmp,pi->key_buffer);
+
+ /* Manipulate the data */
+ g_string_truncate(g_tmp,g_tmp->len-1);
+
+ /* Insert new data */
+ tmp_unistim_info->key_buffer = g_strdup_printf("%s",g_tmp->str);
+ }
+
+ /* add label and comment */
+ comment = g_strdup_printf("Key Input Sent: S2 (%d)", pi->sequence);
+ } else if(pi->key_val == 28) {
+ /* User pressed something */
+ comment = g_strdup_printf("Key Input Sent: Release (%d)", pi->sequence);
+ } else if(pi->key_val == 23) {
+ /* User pressed the soft key 3 */
+ /* Cancel on cs2k so clear buffer */
+ /* On mcs its config which will clear the buffer too */
+ tmp_unistim_info->key_buffer = g_strdup_printf("\n");
+
+ /* User pressed something, set labels*/
+ comment = g_strdup_printf("Key Input Sent: S3 (%d)", pi->sequence);
+ } else if(pi->key_val == 27) {
+ /* User pressed something */
+ comment = g_strdup_printf("Key Input Sent: Hold (%d)", pi->sequence);
+ } else if(pi->key_val == 29) {
+ /* User pressed something */
+ comment = g_strdup_printf("Key Input Sent: Mute (%d)", pi->sequence);
+ } else if(pi->key_val == 30) {
+ /* User pressed something */
+ comment = g_strdup_printf("Key Input Sent: Headset (%d)", pi->sequence);
+ } else if(pi->key_val == 31) {
+ /* Handsfree button */
+ comment = g_strdup_printf("Key Input Sent: Handsfree (%d)", pi->sequence);
+ } else if(pi->key_val >= 32 && pi->key_val <= 56) {
+ /* Prog. Key X */
+ comment = g_strdup_printf("Key Input Sent: Prog%d (%d)", (pi->key_val & 31), pi->sequence);
+ }
+
+ if(pi->key_val != -1) {
+
+ frame_label = g_strdup_printf("KEY INPUT");
+
+ if (comment == NULL)
+ /* Ouch! What do you do!? */
+ /* User pressed something */
+ comment = g_strdup_printf("Key Input Sent: UNKNOWN - %d (%d)", pi->key_val, pi->sequence);
+
+ /* add to the graph */
+ add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
+
+ }
+
+ if(pi->hook_state == 1) {
+
+ /* Phone is off hook */
+ frame_label = g_strdup_printf("OFF HOOK");
+ comment = g_strdup_printf("Off Hook (%d)", pi->sequence);
+
+ /* add to the graph */
+ add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
+ } else if(pi->hook_state == 0) {
+
+ /* Phone is on hook */
+ frame_label = g_strdup_printf("ON HOOK");
+ comment = g_strdup_printf("On Hook (%d)", pi->sequence);
+
+ /* add to the graph */
+ add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
+ }
+
+ }
+
+ /* Open stream was sent from server */
+ if(pi->stream_connect == 1 && strinfo != NULL) {
+
+ /* Open stream */
+ /* Signifies the start of the call so set start_sec & start_usec */
+ strinfo->start_sec=(gint32) (pinfo->fd->rel_ts.secs);
+ strinfo->start_usec=pinfo->fd->rel_ts.nsecs/1000;
+
+ /* Local packets too */
+ ++(strinfo->npackets);
+
+ /* increment the packets counter of all calls */
+ ++(tapinfo->npackets);
+
+ /* ?? means we're not quite sure if this is accurate. Since Unistim isn't a true
+ Call control protocol, we can only guess at the destination by messing with
+ key buffers. */
+ if(tmp_unistim_info->key_buffer != NULL){
+ strinfo->to_identity = g_strdup_printf("?? %s",tmp_unistim_info->key_buffer);
+ }
+
+ /* change sequence number for ACK detection */
+ tmp_unistim_info->sequence = pi->sequence;
+
+ /* State changes too */
+ strinfo->call_active_state = VOIP_ACTIVE;
+ strinfo->call_state = VOIP_IN_CALL;
+
+ /* Add graph data */
+ frame_label = g_strdup_printf("STREAM OPENED");
+ comment = g_strdup_printf("Stream Opened (%d)",pi->sequence);
+
+ /* add to the graph */
+ add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
+
+ /* Redraw the scree */
+ tapinfo->redraw = TRUE;
+ return 1;
+
+ } else if(pi->stream_connect == 0 && strinfo != NULL) {
+ /* Close Stream */
+
+ /* Set stop seconds + usec */
+ strinfo->stop_sec=(gint32) (pinfo->fd->rel_ts.secs);
+ strinfo->stop_usec=pinfo->fd->rel_ts.nsecs/1000;
+ strinfo->last_frame_num=pinfo->fd->num;
+
+ tmp_unistim_info->sequence = pi->sequence;
+
+ if(strinfo->call_state == VOIP_IN_CALL){
+ strinfo->call_active_state = VOIP_INACTIVE;
+ strinfo->call_state = VOIP_COMPLETED;
+ } else {
+ strinfo->call_state = VOIP_UNKNOWN;
+ strinfo->call_active_state = VOIP_INACTIVE;
+ }
+
+ frame_label = g_strdup_printf("STREAM CLOSED");
+ comment = g_strdup_printf("Stream Closed (%d)",pi->sequence);
+
+ /* add to the graph */
+ add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
+
+ }
+
+ } else if(pi->rudp_type == 1 && strinfo != NULL) {
+ /* ACK */
+ /* Only show acks for processed seq #s */
+ if(tmp_unistim_info->sequence == pi->sequence) {
+
+ frame_label = g_strdup_printf("ACK");
+ comment = g_strdup_printf("ACK for sequence %d",pi->sequence);
+
+ /* add to the graph */
+ add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
+
+ }
+
+ } else if(pi->rudp_type == 0 && strinfo != NULL) {
+
+ /* NAK */
+ frame_label = g_strdup_printf("NAK");
+ comment = g_strdup_printf("NAK for sequence %d",pi->sequence);
+
+ /* add to the graph */
+ add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst), 1);
+
+ }
+
+ /* free dataz */
+ g_free(frame_label);
+ g_free(comment);
+
+ tapinfo->redraw = TRUE;
+
+ return 1;
+}
+
+/****************************************************************************/
+/* TAP INTERFACE */
+/****************************************************************************/
+static gboolean have_unistim_tap_listener=FALSE;
+/****************************************************************************/
+void
+unistim_calls_init_tap(void){
+
+ GString *error_string;
+
+ if(have_unistim_tap_listener==FALSE) {
+
+ error_string = register_tap_listener("unistim", &(the_tapinfo_struct.unistim_dummy),
+ NULL,
+ voip_calls_dlg_reset,
+ unistim_calls_packet,
+ voip_calls_dlg_draw
+ );
+
+ if (error_string != NULL) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ error_string->str);
+ g_string_free(error_string, TRUE);
+ exit(1);
+ }
+
+ have_unistim_tap_listener=TRUE;
+ }
+}
+
+/****************************************************************************/
+void
+remove_tap_listener_unistim_calls(void)
+{
+ protect_thread_critical_region();
+ remove_tap_listener(&(the_tapinfo_struct.unistim_dummy));
+ unprotect_thread_critical_region();
+
+ have_unistim_tap_listener=FALSE;
+}
+
+/****************************************************************************/
/* ***************************TAP for OTHER PROTOCOL **********************************/
/****************************************************************************/
diff --git a/gtk/voip_calls.h b/gtk/voip_calls.h
index 4d98382020..8fe6a90a96 100644
--- a/gtk/voip_calls.h
+++ b/gtk/voip_calls.h
@@ -72,7 +72,8 @@ typedef enum _voip_protocol {
TEL_H248,
TEL_SCCP,
TEL_BSSMAP,
- TEL_RANAP
+ TEL_RANAP,
+ VOIP_UNISTIM
} voip_protocol;
extern const char *voip_protocol_name[];
@@ -188,6 +189,7 @@ typedef struct _voip_calls_tapinfo {
int sccp_dummy;
int sua_dummy;
int megaco_dummy;
+ int unistim_dummy;
} voip_calls_tapinfo_t;
@@ -246,6 +248,7 @@ void actrace_calls_init_tap(void);
void t38_init_tap(void);
void h248_calls_init_tap(void);
void sccp_calls_init_tap(void);
+void unistim_calls_init_tap(void);
/*
* Removes the voip_calls tap listener (if not already done)
@@ -265,6 +268,7 @@ void remove_tap_listener_actrace_calls(void);
void remove_tap_listener_t38(void);
void remove_tap_listener_h248_calls(void);
void remove_tap_listener_sccp_calls(void);
+void remove_tap_listener_unistim_calls(void);
/*
* Retrieves a constant reference to the unique info structure of the voip_calls tap listener.
diff --git a/gtk/voip_calls_dlg.c b/gtk/voip_calls_dlg.c
index 1d577a6f8d..ee6d880285 100644
--- a/gtk/voip_calls_dlg.c
+++ b/gtk/voip_calls_dlg.c
@@ -212,6 +212,9 @@ static void voip_calls_remove_tap_listener(void)
remove_tap_listener_sccp_calls();
remove_tap_listener_sdp_calls();
remove_tap_listener_rtp();
+ if (find_tap_id("unistim")) {
+ remove_tap_listener_unistim_calls();
+ }
remove_tap_listener_rtp_event();
if (find_tap_id("mgcp")) {
remove_tap_listener_mgcp_calls();
@@ -371,6 +374,7 @@ voip_calls_on_filter (GtkButton *button _U_,
case MEDIA_T38:
case TEL_BSSMAP:
case TEL_RANAP:
+ case VOIP_UNISTIM:
/* XXX - not supported */
break;
}
@@ -835,6 +839,10 @@ voip_calls_init_tap(const char *dummy _U_, void* userdata _U_)
h248_calls_init_tap();
sccp_calls_init_tap();
sdp_calls_init_tap();
+ /* We don't register this tap, if we don't have the unistim plugin loaded.*/
+ if (find_tap_id("unistim")) {
+ unistim_calls_init_tap();
+ }
rtp_init_tap();
rtp_event_init_tap();
/* We don't register this tap, if we don't have the mgcp plugin loaded.*/
diff --git a/plugins/unistim/packet-unistim.c b/plugins/unistim/packet-unistim.c
index 1a7d6e6484..c455627ec7 100644
--- a/plugins/unistim/packet-unistim.c
+++ b/plugins/unistim/packet-unistim.c
@@ -30,13 +30,128 @@
#include <glib.h>
#include <epan/packet.h>
+#include <epan/tap.h>
#include <epan/emem.h>
#include <string.h>
#include "packet-unistim.h"
-#include "header_field.h"
+#include "defines.h"
+#include "audio.h"
+#include "basic.h"
+#include "display.h"
+#include "network.h"
+#include "key.h"
+#include "broadcast.h"
+
+static int global_unistim_port = 5000;
+
+static unistim_info_t *uinfo;
+static int unistim_tap = -1;
+
+static void dissect_payload(proto_tree *unistim_tree,tvbuff_t *tvb,gint offset, packet_info *pinfo);
+static void dissect_unistim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static dissector_handle_t unistim_handle;
+
+static void dissect_broadcast_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_audio_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_display_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_key_indicator_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_basic_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_network_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_broadcast_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_audio_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_display_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_key_indicator_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_basic_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_network_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
+ tvbuff_t *tvb,gint offset,guint msg_len);
+static void dissect_message(proto_tree *unistim_tree, tvbuff_t *tvb,gint offset);
+static void set_ascii_item(proto_tree *unistim_tree, tvbuff_t *tvb,
+ gint offset,guint msg_len);
+static void set_ascii_null_term_item(proto_tree *msg_tree,tvbuff_t *tvb,
+ gint offset,guint msg_len, char *label);
+
+
+static int proto_unistim = -1;
+static int hf_unistim_seq_nu = -1;
+static int hf_unistim_packet_type = -1;
+static int hf_unistim_payload = -1;
+static int hf_unistim_cmd_add = -1;
+static int hf_unistim_len =-1;
+static int hf_terminal_id=-1;
+static int hf_basic_bit_field=-1;
+static const true_false_string basic_bit_yn={
+ "For Following Byte",
+ "For Following Byte"
+};
+
+static int hf_basic_switch_cmd=-1;
+static int hf_basic_phone_cmd=-1;
+static int hf_broadcast_switch_cmd=-1;
+static int hf_broadcast_phone_cmd=-1;
+static int hf_audio_switch_cmd=-1;
+static int hf_audio_phone_cmd=-1;
+static int hf_display_switch_cmd=-1;
+static int hf_display_phone_cmd=-1;
+static int hf_key_switch_cmd=-1;
+static int hf_key_phone_cmd=-1;
+static int hf_network_switch_cmd=-1;
+static int hf_network_phone_cmd=-1;
+
+
+static int hf_generic_data=-1;
+static int hf_generic_string=-1;
+static gint ett_unistim = -1;
-static int global_unistim_port = 0;
+static const value_string packet_names[]={
+ {0,"NAK"},
+ {1,"ACK"},
+ {2,"Payload"},
+ {0,NULL}
+};
+
+static const value_string payload_names[]={
+ {0x00,"NULL Protocol"},
+ {0x01,"Aggregate Unistim"},
+ {0x02,"Aggregate Unistim with Terminal ID"},
+ {0xff,"Free Form Protocol"},
+ {0,NULL}
+};
+
+static const range_string sequence_numbers[]={
+ {0x00,0xFFFFFFFE,"Normal Sequence Number"},
+ {0xFFFFFFFF,0xFFFFFFFF, "RESET Sequence Number"},
+ {0,0,NULL}
+};
+
+static const value_string command_address[]={
+ {0x11,"Broadcast Manager Switch"},
+ {0x16,"Audio Manager Switch"},
+ {0x17,"Display Manager Switch"},
+ {0x19,"Key/Indicator Manager Switch"},
+ {0x1a,"Basic Manager Switch"},
+ {0x1e,"Network Manager Switch"},
+ {0x91,"Broadcast Manager Phone"},
+ {0x96,"Audio Manager Phone"},
+ {0x97,"Display Manager Phone"},
+ {0x99,"Key/Indicator Manager Phone"},
+ {0x9a,"Basic Manager Phone"},
+ {0x9e,"Network Manager Phone"},
+ {0,NULL}
+};
+
+#include "header_field.h"
void
proto_register_unistim(void){
@@ -56,6 +171,8 @@ proto_register_unistim(void){
proto_register_subtree_array(ett,array_length(ett));
proto_register_field_array(proto_unistim,hf,array_length(hf));
+
+ unistim_tap = register_tap("unistim");
}
void
@@ -86,10 +203,33 @@ dissect_unistim(tvbuff_t *tvb,packet_info *pinfo,proto_tree *tree){
overall_unistim_tree = proto_item_add_subtree(ti,ett_unistim);
ti1=proto_tree_add_text(overall_unistim_tree,tvb,offset,5,"Reliable UDP");
rudpm_tree=proto_item_add_subtree(ti1,ett_unistim);
+
proto_tree_add_item(rudpm_tree,hf_unistim_seq_nu,tvb,offset,4,FALSE);
- offset+=4;
+ /* Allocate new mem for queueing */
+ uinfo = se_alloc(sizeof(unistim_info_t));
+
+ /* Clear tap struct */
+ uinfo->rudp_type = 0;
+ uinfo->payload_type = 0;
+ uinfo->sequence = tvb_get_ntohl(tvb,offset);
+ uinfo->termid = 0;
+ uinfo->key_val = -1;
+ uinfo->key_state = -1;
+ uinfo->hook_state = -1;
+ uinfo->stream_connect = -1;
+ uinfo->trans_connect = -1;
+ uinfo->set_termid = -1;
+ uinfo->string_data = NULL;
+ uinfo->key_buffer = NULL;
+ SET_ADDRESS(&uinfo->it_ip, AT_NONE, 0, NULL);
+ SET_ADDRESS(&uinfo->ni_ip, AT_NONE, 0, NULL);
+ uinfo->it_port = 0;
+
+ offset+=4;
proto_tree_add_item(rudpm_tree,hf_unistim_packet_type,tvb,offset,1,FALSE);
+ uinfo->rudp_type = tvb_get_guint8(tvb,offset);
+
switch(tvb_get_guint8(tvb,offset)) {
case 0x00:
/*NAK*/
@@ -107,10 +247,8 @@ dissect_unistim(tvbuff_t *tvb,packet_info *pinfo,proto_tree *tree){
if (check_col(pinfo->cinfo, COL_INFO))
col_add_fstr(pinfo->cinfo, COL_INFO, "Payload seq - 0x%X",
tvb_get_ntohl(tvb, offset-4));
- if(tree){ /*we are being asked for details*/
- offset+=1;
- dissect_payload(overall_unistim_tree,tvb,offset);
- }
+ offset+=1;
+ dissect_payload(overall_unistim_tree,tvb,offset,pinfo);
break;
default:
if (check_col(pinfo->cinfo, COL_INFO))
@@ -118,26 +256,45 @@ dissect_unistim(tvbuff_t *tvb,packet_info *pinfo,proto_tree *tree){
tvb_get_ntohl(tvb, offset-4));
break;
}
+
+ /* Queue packet for tap */
+ tap_queue_packet(unistim_tap, pinfo, uinfo);
}
static void
-dissect_payload(proto_tree *overall_unistim_tree,tvbuff_t *tvb, gint offset){
+dissect_payload(proto_tree *overall_unistim_tree,tvbuff_t *tvb, gint offset, packet_info *pinfo){
proto_item *ti;
proto_tree *unistim_tree;
guint payload_proto=tvb_get_guint8(tvb,offset);
+
+ /* Payload type for tap */
+ uinfo->payload_type = payload_proto;
+
ti=proto_tree_add_item(overall_unistim_tree,hf_unistim_payload,
tvb,offset,1,FALSE);
offset+=1;
unistim_tree=proto_item_add_subtree(ti,ett_unistim);
+
switch(payload_proto){
case 0x00:
/*NULL PROTO - NOTHING LEFT TO DO*/
return;
case 0x01:
/*UNISTIM only so no term id but further payload work*/
+ /* Collect info for tap */
+ /* If no term id then packet sourced from NI */
+ COPY_ADDRESS(&(uinfo->ni_ip), &(pinfo->src));
+ COPY_ADDRESS(&(uinfo->it_ip), &(pinfo->dst));
+ uinfo->it_port = pinfo->destport;
break;
case 0x02:
/*UNISTIM with term id*/
+ /* Termid packs are always sourced from the it, so collect relevant infos */
+ COPY_ADDRESS(&(uinfo->ni_ip),&(pinfo->dst));
+ COPY_ADDRESS(&(uinfo->it_ip),&(pinfo->src));
+ uinfo->it_port = pinfo->srcport;
+ uinfo->termid = tvb_get_ntohl(tvb,offset);
+
proto_tree_add_item(unistim_tree,hf_terminal_id,tvb,offset,4,FALSE);
offset+=4;
break;
@@ -146,6 +303,7 @@ dissect_payload(proto_tree *overall_unistim_tree,tvbuff_t *tvb, gint offset){
break;
}
+
dissect_message(unistim_tree,tvb,offset);
}
@@ -158,13 +316,19 @@ dissect_message(proto_tree *unistim_tree,tvbuff_t *tvb,gint offset){
proto_tree *msg_tree;
ti = proto_tree_add_text(unistim_tree,tvb,offset,-1,"Unistim CMD");
+
msg_tree = proto_item_add_subtree(ti,ett_unistim);
+
address=tvb_get_guint8(tvb,offset);
+
proto_tree_add_item(msg_tree,hf_unistim_cmd_add,tvb,offset,1,FALSE);
+
offset+=1;
msg_len=tvb_get_guint8(tvb,offset);
+
proto_item_set_len(ti, msg_len);
proto_tree_add_item(msg_tree,hf_unistim_len,tvb,offset,1,FALSE);
+
offset+=1;
/*from switch*/
switch(address){
@@ -222,6 +386,7 @@ dissect_message(proto_tree *unistim_tree,tvbuff_t *tvb,gint offset){
default:
/*See some undocumented messages. Don't want to miss the ones we understand*/
proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len-2,FALSE);
+
offset+=(msg_len-2);
if (tvb_length_remaining(tvb,offset) > 0){
next_byte=tvb_get_guint8(tvb,offset);
@@ -241,7 +406,9 @@ dissect_basic_phone(proto_tree *msg_tree, proto_tree *unistim_tree,
proto_item *ti;
basic_cmd=tvb_get_guint8(tvb,offset);
+
ti=proto_tree_add_item(msg_tree,hf_basic_phone_cmd,tvb,offset,1,FALSE);
+
offset+=1;msg_len-=1;
switch(basic_cmd){
@@ -366,6 +533,9 @@ dissect_basic_switch(proto_tree *msg_tree, proto_tree *unistim_tree,
break;
case 0x07:
/*Assign Terminal ID*/
+ /* Set tap info */
+ uinfo->set_termid = 1;
+
proto_tree_add_item(msg_tree,hf_basic_switch_terminal_id,
tvb,offset,msg_len,FALSE);
offset+=msg_len;
@@ -766,8 +936,12 @@ dissect_display_switch(proto_tree *msg_tree, proto_tree *unistim_tree,
tvb,offset,1,FALSE);
offset+=1;msg_len-=1;
}
- if(msg_len>0)
+ if(msg_len>0){
+ /* I'm guessing this will work flakily at best */
+ uinfo->string_data = tvb_get_string(tvb,offset,msg_len);
set_ascii_item(msg_tree,tvb,offset,msg_len);
+ }
+
offset+=msg_len;
break;
case 0x1a:
@@ -1342,6 +1516,12 @@ dissect_key_indicator_phone(proto_tree *msg_tree, proto_tree *unistim_tree,
case 0x00:
/*Key Event*/
+ /* Set the tap info */
+ uinfo->key_state = tvb_get_guint8(tvb,offset);
+ uinfo->key_state >>= 6;
+ /* Extract the key code */
+ uinfo->key_val = (tvb_get_guint8(tvb,offset) & 0x3F);
+
proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,FALSE);
proto_tree_add_item(msg_tree,hf_key_code,tvb,offset,1,FALSE);
proto_tree_add_item(msg_tree,hf_key_command,tvb,offset,1,FALSE);
@@ -1354,9 +1534,15 @@ dissect_key_indicator_phone(proto_tree *msg_tree, proto_tree *unistim_tree,
break;
case 0x03:
/*On Hook length = 3*/
+ /* Set tap info.. */
+ uinfo->hook_state = 0;
+
break;
case 0x04:
/*Off Hook length = 3*/
+ /* Set tap info.. */
+ uinfo->hook_state = 1;
+
break;
case 0x05:
/*User Activity Timer Expired length = 3*/
@@ -1895,6 +2081,9 @@ dissect_audio_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
break;
case 0x30:
/*Open Audio Stream*/
+ /* Set the tap info */
+ uinfo->stream_connect = 1;
+
proto_tree_add_item(msg_tree,hf_audio_rx_stream_id,tvb,offset,1,FALSE);
offset+=1;msg_len-=1;
proto_tree_add_item(msg_tree,hf_audio_tx_stream_id,tvb,offset,1,FALSE);
@@ -1934,6 +2123,9 @@ dissect_audio_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
break;
case 0x31:
/*Close Audio Stream*/
+ /* Set the tap info */
+ uinfo->stream_connect = 0;
+
proto_tree_add_item(msg_tree,hf_audio_rx_stream_id,tvb,offset,1,FALSE);
offset+=1;msg_len-=1;
proto_tree_add_item(msg_tree,hf_audio_tx_stream_id,tvb,offset,1,FALSE);
@@ -1941,6 +2133,9 @@ dissect_audio_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
break;
case 0x32:
/*Connect Transducer*/
+ /* Tap info again */
+ uinfo->trans_connect = 1;
+
proto_tree_add_item(msg_tree,hf_basic_bit_field, tvb,offset,1,FALSE);
proto_tree_add_item(msg_tree,hf_audio_transducer_pair,tvb,offset,1,FALSE);
proto_tree_add_item(msg_tree,hf_audio_rx_enable,tvb,offset,1,FALSE);
@@ -2084,21 +2279,33 @@ dissect_audio_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
switch(audio_cmd){
case 0x00:
/*Handset Connected length =3*/
+ /* Set the tap info */
+ uinfo->hook_state = 1;
break;
case 0x01:
/*Handset Disconnected length =3*/
+ /* Set the tap info */
+ uinfo->hook_state = 0;
break;
case 0x02:
/*Headset Connected length =3*/
+ /* Set the tap info */
+ uinfo->hook_state = 1;
break;
case 0x03:
/*Headset Disconnected length =3*/
+ /* Set the tap info */
+ uinfo->hook_state = 0;
break;
case 0x04:
/*Supervisor Headset Connected length =3*/
+ /* Set the tap info */
+ uinfo->hook_state = 1;
break;
case 0x05:
/*Supervisor Headset Disconnected length =3*/
+ /* Set the tap info */
+ uinfo->hook_state = 0;
break;
case 0x07:
/*Audio Manager Attributes Info*/
diff --git a/plugins/unistim/packet-unistim.h b/plugins/unistim/packet-unistim.h
index 7922b82d52..8dedf0d050 100644
--- a/plugins/unistim/packet-unistim.h
+++ b/plugins/unistim/packet-unistim.h
@@ -27,118 +27,25 @@
#ifndef PACKET_UNISTIM_H
#define PACKET_UNISTIM_H
-#include "defines.h"
-#include "audio.h"
-#include "basic.h"
-#include "display.h"
-#include "network.h"
-#include "key.h"
-#include "broadcast.h"
-
-
-static void dissect_payload(proto_tree *unistim_tree,tvbuff_t *tvb,gint offset);
-static void dissect_unistim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
-static dissector_handle_t unistim_handle;
-
-static void dissect_broadcast_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_audio_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_display_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_key_indicator_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_basic_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_network_switch(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_broadcast_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_audio_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_display_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_key_indicator_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_basic_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_network_phone(proto_tree *msg_tree,proto_tree *unistim_tree,
- tvbuff_t *tvb,gint offset,guint msg_len);
-static void dissect_message(proto_tree *unistim_tree, tvbuff_t *tvb,gint offset);
-static void set_ascii_item(proto_tree *unistim_tree, tvbuff_t *tvb,
- gint offset,guint msg_len);
-static void set_ascii_null_term_item(proto_tree *msg_tree,tvbuff_t *tvb,
- gint offset,guint msg_len, char *label);
-
-
-static int proto_unistim = -1;
-static int hf_unistim_seq_nu = -1;
-static int hf_unistim_packet_type = -1;
-static int hf_unistim_payload = -1;
-static int hf_unistim_cmd_add = -1;
-static int hf_unistim_len =-1;
-static int hf_terminal_id=-1;
-static int hf_basic_bit_field=-1;
-static const true_false_string basic_bit_yn={
- "For Following Byte",
- "For Following Byte"
-};
-
-static int hf_basic_switch_cmd=-1;
-static int hf_basic_phone_cmd=-1;
-static int hf_broadcast_switch_cmd=-1;
-static int hf_broadcast_phone_cmd=-1;
-static int hf_audio_switch_cmd=-1;
-static int hf_audio_phone_cmd=-1;
-static int hf_display_switch_cmd=-1;
-static int hf_display_phone_cmd=-1;
-static int hf_key_switch_cmd=-1;
-static int hf_key_phone_cmd=-1;
-static int hf_network_switch_cmd=-1;
-static int hf_network_phone_cmd=-1;
-
-
-static int hf_generic_data=-1;
-static int hf_generic_string=-1;
-
-static gint ett_unistim = -1;
-
-static const value_string packet_names[]={
- {0,"NAK"},
- {1,"ACK"},
- {2,"Payload"},
- {0,NULL}
-};
-
-static const value_string payload_names[]={
- {0x00,"NULL Protocol"},
- {0x01,"Aggregate Unistim"},
- {0x02,"Aggregate Unistim with Terminal ID"},
- {0xff,"Free Form Protocol"},
- {0,NULL}
-};
-
-static const range_string sequence_numbers[]={
- {0x00,0xFFFFFFFE,"Normal Sequence Number"},
- {0xFFFFFFFF,0xFFFFFFFF, "RESET Sequence Number"},
- {0,0,NULL}
-};
-
-static const value_string command_address[]={
- {0x11,"Broadcast Manager Switch"},
- {0x16,"Audio Manager Switch"},
- {0x17,"Display Manager Switch"},
- {0x19,"Key/Indicator Manager Switch"},
- {0x1a,"Basic Manager Switch"},
- {0x1e,"Network Manager Switch"},
- {0x91,"Broadcast Manager Phone"},
- {0x96,"Audio Manager Phone"},
- {0x97,"Display Manager Phone"},
- {0x99,"Key/Indicator Manager Phone"},
- {0x9a,"Basic Manager Phone"},
- {0x9e,"Network Manager Phone"},
- {0,NULL}
-};
+typedef struct _unistim_info_t
+{
+ guint8 rudp_type; /* NAK, ACK, Payload */
+ guint8 payload_type; /* unistim payload type (aggregate, non-aggregate, encapsulated) */
+ guint32 sequence; /* rudp sequence number */
+ guint32 termid; /* termid if available */
+ address it_ip; /* IP addr of it, determined by who is sending termids */
+ guint32 it_port; /* port of it (phone) */
+ address ni_ip; /* IP addr of ni (server) as determined by who's sending termids */
+ gint key_val; /* actual key pressed (-1 if not used) */
+ gint key_state; /* Key state 1=down 0=up */
+ gint hook_state; /* Hook state 1=offhook 0=onhook */
+ gint stream_connect; /* Audio stream connect 1=connect 0=disconnect */
+ gint trans_connect; /* Transducer connect? 1=connect 0=disconnect */
+ gint set_termid; /* Set the termid 1=set termid */
+ guint8 *string_data; /* Any time a string is written to the display, this has the string */
+ gint call_state; /* Not used? */
+ guchar *key_buffer; /* Used in voip-calls.c tap, holds call keys pressed */
+} unistim_info_t;
#endif