diff options
-rw-r--r-- | gtk/voip_calls.c | 430 | ||||
-rw-r--r-- | gtk/voip_calls.h | 6 | ||||
-rw-r--r-- | gtk/voip_calls_dlg.c | 8 | ||||
-rw-r--r-- | plugins/unistim/packet-unistim.c | 225 | ||||
-rw-r--r-- | plugins/unistim/packet-unistim.h | 131 |
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 |