From Chad Singer:

UNISTIM Tap interface plus call grapher.

svn path=/trunk/; revision=22834
This commit is contained in:
Jaap Keuter 2007-09-10 07:21:27 +00:00
parent 070cf8b006
commit e1541263e4
5 changed files with 678 additions and 126 deletions

View File

@ -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 =
@ -3072,6 +3074,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 **********************************/
/****************************************************************************/

View File

@ -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.

View File

@ -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.*/

View File

@ -30,14 +30,129 @@
#include <glib.h>
#include <epan/packet.h>
#include <epan/tap.h>
#include <epan/emem.h>
#include <string.h>
#include "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 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 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"
static int global_unistim_port = 0;
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;
proto_tree_add_item(rudpm_tree,hf_unistim_seq_nu,tvb,offset,4,FALSE);
/* 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*/

View File

@ -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