/* packet-gryphon.c * Routines for Gryphon protocol packet disassembly * By Steve Limkemann * Copyright 1998 Steve Limkemann * * $Id: packet-gryphon.c,v 1.25 2001/12/03 04:00:24 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs * Copyright 1998 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "plugins/plugin_api.h" #include "moduleinfo.h" #ifdef HAVE_SYS_TYPES_H #include #endif #include #include #include #include #ifdef HAVE_NETINET_IN_H # include #endif #include "packet.h" #include "packet-gryphon.h" #include "plugins/plugin_api_defs.h" #ifndef __ETHEREAL_STATIC__ G_MODULE_EXPORT const gchar version[] = VERSION; #endif #ifndef G_HAVE_GINT64 #error "Sorry, this won't compile without 64-bit integer support" #endif /* * See * * http://www.dgtech.com/gryphon/docs/html/ */ static int proto_gryphon = -1; static int hf_gryph_src = -1; static int hf_gryph_srcchan = -1; static int hf_gryph_dest = -1; static int hf_gryph_destchan= -1; static int hf_gryph_type = -1; static int hf_gryph_cmd = -1; static gint ett_gryphon = -1; static gint ett_gryphon_header = -1; static gint ett_gryphon_body = -1; static gint ett_gryphon_command_data = -1; static gint ett_gryphon_response_data = -1; static gint ett_gryphon_data_header = -1; static gint ett_gryphon_flags = -1; static gint ett_gryphon_data_body = -1; static gint ett_gryphon_cmd_filter_block = -1; static gint ett_gryphon_cmd_events_data = -1; static gint ett_gryphon_cmd_config_device = -1; static gint ett_gryphon_cmd_sched_data = -1; static gint ett_gryphon_cmd_sched_cmd = -1; static gint ett_gryphon_cmd_response_block = -1; static gint ett_gryphon_pgm_list = -1; static gint ett_gryphon_pgm_status = -1; static gint ett_gryphon_pgm_options = -1; static int dissect_gryphon_message(tvbuff_t *tvb, int offset, proto_tree *tree, gboolean is_msgresp_add); static int decode_command(tvbuff_t*, int, int, int, proto_tree*); static int decode_response(tvbuff_t*, int, int, int, proto_tree*); static int decode_data(tvbuff_t*, int, int, int, proto_tree*); static int decode_event(tvbuff_t*, int, int, int, proto_tree*); static int cmd_init(tvbuff_t*, int, int, int, proto_tree*); static int resp_time(tvbuff_t*, int, int, int, proto_tree*); static int cmd_setfilt(tvbuff_t*, int, int, int, proto_tree*); static int cmd_ioctl(tvbuff_t*, int, int, int, proto_tree*); static int cmd_addfilt(tvbuff_t*, int, int, int, proto_tree*); static int resp_addfilt(tvbuff_t*, int, int, int, proto_tree*); static int cmd_modfilt(tvbuff_t*, int, int, int, proto_tree*); static int resp_filthan(tvbuff_t*, int, int, int, proto_tree*); static int dfiltmode(tvbuff_t*, int, int, int, proto_tree*); static int filtmode(tvbuff_t*, int, int, int, proto_tree*); static int resp_events(tvbuff_t*, int, int, int, proto_tree*); static int cmd_register(tvbuff_t*, int, int, int, proto_tree*); static int resp_register(tvbuff_t*, int, int, int, proto_tree*); static int resp_getspeeds(tvbuff_t*, int, int, int, proto_tree*); static int cmd_sort(tvbuff_t*, int, int, int, proto_tree*); static int cmd_optimize(tvbuff_t*, int, int, int, proto_tree*); static int resp_config(tvbuff_t*, int, int, int, proto_tree*); static int cmd_sched(tvbuff_t*, int, int, int, proto_tree*); static int resp_blm_data(tvbuff_t*, int, int, int, proto_tree*); static int resp_blm_stat(tvbuff_t*, int, int, int, proto_tree*); static int cmd_addresp(tvbuff_t*, int, int, int, proto_tree*); static int resp_addresp(tvbuff_t*, int, int, int, proto_tree*); static int cmd_modresp(tvbuff_t*, int, int, int, proto_tree*); static int resp_resphan(tvbuff_t*, int, int, int, proto_tree*); static int resp_sched(tvbuff_t*, int, int, int, proto_tree*); static int cmd_desc(tvbuff_t*, int, int, int, proto_tree*); static int resp_desc(tvbuff_t*, int, int, int, proto_tree*); static int cmd_upload(tvbuff_t*, int, int, int, proto_tree*); static int cmd_delete(tvbuff_t*, int, int, int, proto_tree*); static int cmd_list(tvbuff_t*, int, int, int, proto_tree*); static int resp_list(tvbuff_t*, int, int, int, proto_tree*); static int cmd_start(tvbuff_t*, int, int, int, proto_tree*); static int resp_start(tvbuff_t*, int, int, int, proto_tree*); static int resp_status(tvbuff_t*, int, int, int, proto_tree*); static int cmd_options(tvbuff_t*, int, int, int, proto_tree*); static int cmd_files(tvbuff_t*, int, int, int, proto_tree*); static int resp_files(tvbuff_t*, int, int, int, proto_tree*); static int eventnum(tvbuff_t*, int, int, int, proto_tree*); static int speed(tvbuff_t*, int, int, int, proto_tree*); static int filter_block(tvbuff_t*, int, int, int, proto_tree*); static int blm_mode(tvbuff_t*, int, int, int, proto_tree*); static int cmd_usdt(tvbuff_t*, int, int, int, proto_tree*); static char *frame_type[] = { "", "Command request", "Command response", "Network (vehicle) data", "Event", "Miscellaneous", "Text string" }; static void dissect_gryphon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset; proto_item *ti; proto_tree *gryphon_tree; guint8 frmtyp; if (check_col(pinfo->fd, COL_PROTOCOL)) col_set_str(pinfo->fd, COL_PROTOCOL, "Gryphon"); if (check_col(pinfo->fd, COL_INFO)) col_clear(pinfo->fd, COL_INFO); ti = proto_tree_add_item(tree, proto_gryphon, tvb, 0, tvb_length(tvb), FALSE); gryphon_tree = proto_item_add_subtree(ti, ett_gryphon); if (check_col(pinfo->fd, COL_INFO)) { /* * Indicate what kind of message the first message is. */ frmtyp = tvb_get_guint8(tvb, 6) & ~RESPONSE_FLAGS; if (frmtyp >= SIZEOF (frame_type)) col_set_str(pinfo->fd, COL_INFO, "- Invalid -"); else col_set_str(pinfo->fd, COL_INFO, frame_type[frmtyp]); } if (tree) { offset = 0; while (tvb_reported_length_remaining(tvb, offset) > 0) offset = dissect_gryphon_message(tvb, offset, gryphon_tree, FALSE); } } static int dissect_gryphon_message(tvbuff_t *tvb, int offset, proto_tree *tree, gboolean is_msgresp_add) { proto_tree *header_tree, *body_tree, *localTree; proto_item *header_item, *body_item, *localItem; int start_offset, msgend; int msglen, msgpad; unsigned int src, dest, i, frmtyp; guint8 flags; static const value_string src_dest[] = { {SD_CARD, "Card"}, {SD_SERVER, "Server"}, {SD_CLIENT, "Client"}, {SD_SCHED, "Scheduler"}, {SD_SCRIPT, "Script Processor"}, {SD_PGM, "Program Loader"}, {SD_USDT, "USDT Server"}, {SD_BLM, "Bus Load Monitoring"}, {SD_FLIGHT, "Flight Recorder"}, {SD_RESP, "Message Responder"}, {-1, "- unknown -"}, }; src = tvb_get_guint8(tvb, offset + 0); dest = tvb_get_guint8(tvb, offset + 2); msglen = tvb_get_ntohs(tvb, offset + 4); flags = tvb_get_guint8(tvb, offset + 6); frmtyp = flags & ~RESPONSE_FLAGS; if (frmtyp >= SIZEOF (frame_type)) { /* * Unknown message type. */ proto_tree_add_text(tree, tvb, offset, msglen, "Data"); offset += msglen; return offset; } header_item = proto_tree_add_text(tree, tvb, offset, MSG_HDR_SZ, "Header"); header_tree = proto_item_add_subtree(header_item, ett_gryphon_header); for (i = 0; i < SIZEOF(src_dest); i++) { if (src_dest[i].value == src) break; } if (i >= SIZEOF(src_dest)) i = SIZEOF(src_dest) - 1; proto_tree_add_text(header_tree, tvb, offset, 2, "Source: %s, channel %u", src_dest[i].strptr, tvb_get_guint8(tvb, offset + 1)); proto_tree_add_uint_hidden(header_tree, hf_gryph_src, tvb, offset, 1, src); proto_tree_add_uint_hidden(header_tree, hf_gryph_srcchan, tvb, offset+1, 1, tvb_get_guint8(tvb, offset + 1)); for (i = 0; i < SIZEOF(src_dest); i++) { if (src_dest[i].value == dest) break; } if (i >= SIZEOF(src_dest)) i = SIZEOF(src_dest) - 1; proto_tree_add_text(header_tree, tvb, offset+2, 2, "Destination: %s, channel %u", src_dest[i].strptr, tvb_get_guint8(tvb, offset + 3)); proto_tree_add_uint_hidden(header_tree, hf_gryph_dest, tvb, offset+2, 1, dest); proto_tree_add_uint_hidden(header_tree, hf_gryph_destchan, tvb, offset+3, 1, tvb_get_guint8(tvb, offset + 3)); proto_tree_add_text(header_tree, tvb, offset+4, 2, "Data length: %u bytes", msglen); proto_tree_add_text(header_tree, tvb, offset+6, 1, "Frame type: %s", frame_type[frmtyp]); if (is_msgresp_add) { localItem = proto_tree_add_text(header_tree, tvb, offset+6, 1, "Flags"); localTree = proto_item_add_subtree (localItem, ett_gryphon_flags); if (flags & DONT_WAIT_FOR_RESP) { proto_tree_add_text(localTree, tvb, offset+6, 1, "1... .... = Don't wait for response"); } else { proto_tree_add_text(localTree, tvb, offset+6, 1, "0... .... = Wait for response"); } if (flags & WAIT_FOR_PREV_RESP) { proto_tree_add_text(localTree, tvb, offset+6, 1, ".1.. .... = Wait for previous responses"); } else { proto_tree_add_text(localTree, tvb, offset+6, 1, ".0.. .... = Don't wait for previous responses"); } } proto_tree_add_text(header_tree, tvb, offset+7, 1, "reserved"); proto_tree_add_uint_hidden(header_tree, hf_gryph_type, tvb, offset+6, 1, frmtyp); msgpad = 3 - (msglen + 3) % 4; msgend = offset + msglen + msgpad + MSG_HDR_SZ; body_item = proto_tree_add_text(tree, tvb, offset + MSG_HDR_SZ, msglen + msgpad, "Body"); body_tree = proto_item_add_subtree(body_item, ett_gryphon_body); start_offset = offset; offset += MSG_HDR_SZ; switch (frmtyp) { case GY_FT_CMD: offset = decode_command(tvb, offset, dest, msglen, body_tree); break; case GY_FT_RESP: offset = decode_response(tvb, offset, src, msglen, body_tree); break; case GY_FT_DATA: offset = decode_data(tvb, offset, src, msglen, body_tree); break; case GY_FT_EVENT: offset = decode_event(tvb, offset, src, msglen, body_tree); break; case GY_FT_MISC: break; case GY_FT_TEXT: break; default: break; } if (offset < msgend - msgpad) { i = msgend - msgpad - offset; proto_tree_add_text(tree, tvb, offset, i, "Data"); offset += i; } if (offset < msgend) { i = msgend - offset; proto_tree_add_text(tree, tvb, offset, i, "padding"); offset += i; } return offset; } static const val_str_dsp cmds[] = { {CMD_INIT, "Initialize", cmd_init, NULL}, {CMD_GET_STAT, "Get status", NULL, NULL}, {CMD_GET_CONFIG, "Get configuration", NULL, resp_config}, {CMD_EVENT_ENABLE, "Enable event", eventnum, NULL}, {CMD_EVENT_DISABLE, "Disable event", eventnum, NULL}, {CMD_GET_TIME, "Get time", NULL, resp_time}, {CMD_GET_RXDROP, "Get number of dropped RX messages", NULL, NULL}, {CMD_RESET_RXDROP, "Clear number of dropped RX messages", NULL, NULL}, {CMD_BCAST_ON, "Set broadcasts on", NULL, NULL}, {CMD_BCAST_OFF, "Set broadcasts off", NULL, NULL}, {CMD_CARD_SET_SPEED, "Set channel baud rate", speed, NULL}, {CMD_CARD_GET_SPEED, "Get channel baud rate", NULL, speed}, {CMD_CARD_SET_FILTER, "Set filter (deprecated)", cmd_setfilt, NULL}, {CMD_CARD_GET_FILTER, "Get filter", resp_addfilt, cmd_addfilt}, {CMD_CARD_TX, "Transmit message", decode_data, NULL}, {CMD_CARD_TX_LOOP_ON, "Set transmit loopback on", NULL, NULL}, {CMD_CARD_TX_LOOP_OFF, "Set transmit loopback off", NULL, NULL}, {CMD_CARD_IOCTL, "IOCTL pass-through", cmd_ioctl, NULL}, {CMD_CARD_ADD_FILTER, "Add a filter", cmd_addfilt, resp_addfilt}, {CMD_CARD_MODIFY_FILTER, "Modify a filter", cmd_modfilt, NULL}, {CMD_CARD_GET_FILTER_HANDLES, "Get filter handles", NULL, resp_filthan}, {CMD_CARD_SET_DEFAULT_FILTER, "Set default filter", dfiltmode, NULL}, {CMD_CARD_GET_DEFAULT_FILTER, "Get default filter mode", NULL, dfiltmode}, {CMD_CARD_SET_FILTER_MODE, "Set filter mode", filtmode, NULL}, {CMD_CARD_GET_FILTER_MODE, "Get filter mode", NULL, filtmode}, {CMD_CARD_GET_EVNAMES, "Get event names", NULL, resp_events}, {CMD_CARD_GET_SPEEDS, "Get defined speeds", NULL, resp_getspeeds}, {CMD_SERVER_REG, "Register with server", cmd_register, resp_register}, {CMD_SERVER_SET_SORT, "Set the sorting behavior", cmd_sort, NULL}, {CMD_SERVER_SET_OPT, "Set the type of optimization", cmd_optimize, NULL}, {CMD_BLM_SET_MODE, "Set Bus Load Monitoring mode", blm_mode, NULL}, {CMD_BLM_GET_MODE, "Get Bus Load Monitoring mode", NULL, blm_mode}, {CMD_BLM_GET_DATA, "Get Bus Load data", NULL, resp_blm_data}, {CMD_BLM_GET_STATS, "Get Bus Load statistics", NULL, resp_blm_stat}, {CMD_FLIGHT_GET_CONFIG, "Get flight recorder channel info", NULL, NULL}, {CMD_FLIGHT_START_MON, "Start flight recorder monitoring", NULL, NULL}, {CMD_FLIGHT_STOP_MON, "Stop flight recorder monitoring", NULL, NULL}, {CMD_MSGRESP_ADD, "Add response message", cmd_addresp, resp_addresp}, {CMD_MSGRESP_GET, "Get response message", resp_addresp, cmd_addresp}, {CMD_MSGRESP_MODIFY, "Modify response message state", cmd_modresp, NULL}, {CMD_MSGRESP_GET_HANDLES, "Get response message handles", NULL, resp_resphan}, {CMD_PGM_DESC, "Describe program to to uploaded", cmd_desc, resp_desc}, {CMD_PGM_UPLOAD, "Upload a program to the Gryphon", cmd_upload, NULL}, {CMD_PGM_DELETE, "Delete an uploaded program", cmd_delete, NULL}, {CMD_PGM_LIST, "Get a list of uploaded programs", cmd_list, resp_list}, {CMD_PGM_START, "Start an uploaded program", cmd_start, resp_start}, {CMD_PGM_STOP, "Stop an uploaded program", resp_start, NULL}, {CMD_PGM_STATUS, "Get status of an uploaded program", cmd_delete, resp_status}, {CMD_PGM_OPTIONS, "Set program upload options", cmd_options, resp_status}, {CMD_PGM_FILES, "Get a list of files & directories", cmd_files, resp_files}, {CMD_SCHED_TX, "Schedule transmission of messages", cmd_sched, resp_sched}, {CMD_SCHED_KILL_TX, "Stop and destroy a message transmission", NULL, NULL}, {CMD_SCHED_STOP_TX, "Kill a message transmission (deprecated)", NULL, NULL}, {CMD_USDT_IOCTL, "Register/Unregister with USDT server", cmd_usdt, NULL}, {-1, "- unknown -", NULL, NULL}, }; static const value_string responses[] = { {RESP_OK, "OK - no error"}, {RESP_UNKNOWN_ERR, "Unknown error"}, {RESP_UNKNOWN_CMD, "Unrecognised command"}, {RESP_UNSUPPORTED, "Unsupported command"}, {RESP_INVAL_CHAN, "Invalid channel specified"}, {RESP_INVAL_DST, "Invalid destination"}, {RESP_INVAL_PARAM, "Invalid parameter(s)"}, {RESP_INVAL_MSG, "Invalid message"}, {RESP_INVAL_LEN, "Invalid length field"}, {RESP_TX_FAIL, "Transmit failed"}, {RESP_RX_FAIL, "Receive failed"}, {RESP_AUTH_FAIL, "Authorization failed"}, {RESP_MEM_ALLOC_ERR, "Memory allocation error"}, {RESP_TIMEOUT, "Command timed out"}, {RESP_UNAVAILABLE, "Unavailable"}, {RESP_BUF_FULL, "Buffer full"}, {RESP_NO_SUCH_JOB, "No such job"}, {-1, "- unknown -"}, }; static const value_string filter_data_types[] = { {FILTER_DATA_TYPE_HEADER_FRAME, "frame header"}, {FILTER_DATA_TYPE_HEADER, "data message header"}, {FILTER_DATA_TYPE_DATA, "data message data"}, {FILTER_DATA_TYPE_EXTRA_DATA, "data message extra data"}, {FILTER_EVENT_TYPE_HEADER, "event message header"}, {FILTER_EVENT_TYPE_DATA, "event message"}, {-1, "- unknown -"}, }; static const value_string operators[] = { {BIT_FIELD_CHECK, "Bit field check"}, {SVALUE_GT, "Greater than (signed)"}, {SVALUE_GE, "Greater than or equal to (signed)"}, {SVALUE_LT, "Less than (signed)"}, {SVALUE_LE, "Less than or equal to (signed)"}, {VALUE_EQ, "Equal to"}, {VALUE_NE, "Not equal to"}, {UVALUE_GT, "Greater than (unsigned)"}, {UVALUE_GE, "Greater than or equal to (unsigned)"}, {UVALUE_LT, "Less than (unsigned)"}, {UVALUE_LE, "Less than or equal to (unsigned)"}, {DIG_LOW_TO_HIGH, "Digital, low to high transistion"}, {DIG_HIGH_TO_LOW, "Digital, high to low transistion"}, {DIG_TRANSITION, "Digital, change of state"}, {-1, "- unknown -"}, }; static const value_string modes[] = { {FILTER_OFF_PASS_ALL, "Filter off, pass all messages"}, {FILTER_OFF_BLOCK_ALL, "Filter off, block all messages"}, {FILTER_ON, "Filter on"}, {-1, "- unknown -"}, }; static const value_string dmodes[] = { {DEFAULT_FILTER_BLOCK, "Block"}, {DEFAULT_FILTER_PASS, "Pass"}, {-1, "- unknown -"}, }; static const value_string filtacts[] = { {DELETE_FILTER, "Delete"}, {ACTIVATE_FILTER, "Activate"}, {DEACTIVATE_FILTER, "Deactivate"}, {-1, "- unknown -"}, }; static const value_string ioctls[] = { {GINIT, "GINIT: Initialize"}, {GLOOPON, "GLOOPON: Loop on"}, {GLOOPOFF, "GLOOPOFF: Loop off"}, {GGETHWTYPE, "GGETHWTYPE: Get hardware type"}, {GGETREG, "GGETREG: Get register"}, {GSETREG, "GSETREG: Set register"}, {GGETRXCOUNT, "GGETRXCOUNT: Get the receive message counter"}, {GSETRXCOUNT, "GSETRXCOUNT: Set the receive message counter"}, {GGETTXCOUNT, "GGETTXCOUNT: Get the transmit message counter"}, {GSETTXCOUNT, "GSETTXCOUNT: Set the transmit message counter"}, {GGETRXDROP, "GGETRXDROP: Get the number of dropped receive messages"}, {GSETRXDROP, "GSETRXDROP: Set the number of dropped receive messages"}, {GGETTXDROP, "GGETTXDROP: Get the number of dropped transmit messages"}, {GSETTXDROP, "GSETTXDROP: Set the number of dropped transmit messages"}, {GGETRXBAD, "GGETRXBAD: Get the number of bad receive messages"}, {GGETTXBAD, "GGETTXBAD: Get the number of bad transmit messages"}, {GGETCOUNTS, "GGETCOUNTS: Get total message counter"}, {GGETBLMON, "GGETBLMON: Get bus load monitoring status"}, {GSETBLMON, "GSETBLMON: Set bus load monitoring status (turn on/off)"}, {GGETERRLEV, "GGETERRLEV: Get error level"}, {GSETERRLEV, "GSETERRLEV: Set error level"}, {GGETBITRATE, "GGETBITRATE: Get bit rate"}, {GGETRAM, "GGETRAM: Read value from RAM"}, {GSETRAM, "GSETRAM: Write value to RAM"}, {GCANGETBTRS, "GCANGETBTRS: Read CAN bit timing registers"}, {GCANSETBTRS, "GCANSETBTRS: Write CAN bit timing registers"}, {GCANGETBC, "GCANGETBC: Read CAN byte count"}, {GCANSETBC, "GCANSETBC: Write CAN byte count"}, {GCANGETMODE, "GCANGETMODE"}, {GCANSETMODE, "GCANSETMODE"}, {GCANGETTRANS, "GCANGETTRANS"}, {GCANSETTRANS, "GCANSETTRANS"}, {GCANSENDERR, "GCANSENDERR"}, {GCANRGETOBJ, "GCANRGETOBJ"}, {GCANRSETSTDID, "GCANRSETSTDID"}, {GCANRSETEXTID, "GCANRSETEXTID"}, {GCANRSETDATA, "GCANRSETDATA"}, {GCANRENABLE, "GCANRENABLE"}, {GCANRDISABLE, "GCANRDISABLE"}, {GCANRGETMASKS, "GCANRGETMASKS"}, {GCANRSETMASKS, "GCANRSETMASKS"}, {GCANSWGETMODE, "GCANSWGETMODE"}, {GCANSWSETMODE, "GCANSWSETMODE"}, {GDLCGETFOURX, "GDLCGETFOURX"}, {GDLCSETFOURX, "GDLCSETFOURX"}, {GDLCGETLOAD, "GDLCGETLOAD"}, {GDLCSETLOAD, "GDLCSETLOAD"}, {GDLCSENDBREAK, "GDLCSENDBREAK"}, {GDLCABORTTX, "GDLCABORTTX"}, {GDLCGETHDRMODE, "DLCGETHDRMODE"}, {GDLCSETHDRMODE, "GDLCSETHDRMODE"}, {GHONSLEEP, "GHONSLEEP"}, {GHONSILENCE, "GHONSILENCE"}, {GKWPSETPTIMES, "GKWPSETPTIMES"}, {GKWPSETWTIMES, "GKWPSETWTIMES"}, {GKWPDOWAKEUP, "GKWPDOWAKEUP"}, {GKWPGETBITTIME, "GKWPGETBITTIME"}, {GKWPSETBITTIME, "GKWPSETBITTIME"}, {GKWPSETNODEADDR, "GKWPSETNODEADDR"}, {GKWPGETNODETYPE, "GKWPGETNODETYPE"}, {GKWPSETNODETYPE, "GKWPSETNODETYPE"}, {GKWPSETWAKETYPE, "GKWPSETWAKETYPE"}, {GKWPSETTARGADDR, "GKWPSETTARGADDR"}, {GKWPSETKEYBYTES, "GKWPSETKEYBYTES"}, {GKWPSETSTARTREQ, "GKWPSETSTARTREQ"}, {GKWPSETSTARTRESP, "GKWPSETSTARTRESP"}, {GKWPSETPROTOCOL, "GKWPSETPROTOCOL"}, {GKWPGETLASTKEYBYTES, "GKWPGETLASTKEYBYTES"}, {GKWPSETLASTKEYBYTES, "GKWPSETLASTKEYBYTES"}, {GSCPGETBBR, "GSCPGETBBR"}, {GSCPSETBBR, "GSCPSETBBR"}, {GSCPGETID, "GSCPGETID"}, {GSCPSETID, "GSCPSETID"}, {GSCPADDFUNCID, "GSCPADDFUNCID"}, {GSCPCLRFUNCID, "GSCPCLRFUNCID"}, {GUBPGETBITRATE, "GUBPGETBITRATE"}, {GUBPSETBITRATE, "GUBPSETBITRATE"}, {GUBPGETINTERBYTE, "GUBPGETINTERBYTE"}, {GUBPSETINTERBYTE, "GUBPSETINTERBYTE"}, {GUBPGETNACKMODE, "GUBPGETNACKMODE"}, {GUBPSETNACKMODE, "GUBPSETNACKMODE"}, {-1, "- unknown -"}, }; static int decode_command(tvbuff_t *tvb, int offset, int dst, int msglen, proto_tree *pt) { int cmd, padding; unsigned int i; proto_tree *ft; proto_item *ti; cmd = tvb_get_guint8(tvb, offset); proto_tree_add_uint_hidden(pt, hf_gryph_cmd, tvb, offset, 1, cmd); if (cmd > 0x3F) cmd += dst * 256; for (i = 0; i < SIZEOF(cmds); i++) { if (cmds[i].value == cmd) break; } if (i >= SIZEOF(cmds) && dst >= SD_KNOWN) { cmd = (cmd & 0xFF) + SD_CARD * 256; for (i = 0; i < SIZEOF(cmds); i++) { if (cmds[i].value == cmd) break; } } if (i >= SIZEOF(cmds)) i = SIZEOF(cmds) - 1; proto_tree_add_text (pt, tvb, offset, 4, "Command: %s", cmds[i].strptr); offset += 4; msglen -= 4; if (cmds[i].cmd_fnct && msglen > 0) { padding = 3 - (msglen + 3) % 4; ti = proto_tree_add_text(pt, tvb, offset, msglen, "Data: (%d bytes)", msglen); ft = proto_item_add_subtree(ti, ett_gryphon_command_data); offset = (*(cmds[i].cmd_fnct)) (tvb, offset, dst, msglen, ft); } return offset; } static int decode_response(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { int cmd; unsigned int i, j, resp; proto_tree *ft; proto_item *ti; cmd = tvb_get_guint8(tvb, offset); if (cmd > 0x3F) cmd += src * 256; for (i = 0; i < SIZEOF(cmds); i++) { if (cmds[i].value == cmd) break; } if (i >= SIZEOF(cmds) && src >= SD_KNOWN) { cmd = (cmd & 0xFF) + SD_CARD * 256; for (i = 0; i < SIZEOF(cmds); i++) { if (cmds[i].value == cmd) break; } } if (i >= SIZEOF(cmds)) i = SIZEOF(cmds) - 1; proto_tree_add_text (pt, tvb, offset, 4, "Command: %s", cmds[i].strptr); offset += 4; msglen -= 4; resp = tvb_get_ntohl (tvb, offset); for (j = 0; j < SIZEOF(responses); j++) { if (responses[j].value == resp) break; } if (j >= SIZEOF(responses)) j = SIZEOF(responses) - 1; proto_tree_add_text (pt, tvb, offset, 4, "Status: %s", responses[j].strptr); offset += 4; msglen -= 4; if (cmds[i].rsp_fnct && msglen > 0) { ti = proto_tree_add_text(pt, tvb, offset, msglen, "Data: (%d bytes)", msglen); ft = proto_item_add_subtree(ti, ett_gryphon_response_data); offset = (*(cmds[i].rsp_fnct)) (tvb, offset, src, msglen, ft); } return offset; } static int decode_data(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_item *item, *item1; proto_tree *tree, *tree1; int hdrsize, datasize, extrasize, hdrbits, msgsize, padding, mode; int hours, minutes, seconds, fraction; unsigned long timestamp; hdrsize = tvb_get_guint8(tvb, offset+0); hdrbits = tvb_get_guint8(tvb, offset+1); datasize = tvb_get_ntohs(tvb, offset+2); extrasize = tvb_get_guint8(tvb, offset+4); padding = 3 - (hdrsize + datasize + extrasize + 3) % 4; msgsize = hdrsize + datasize + extrasize + padding + 16; item = proto_tree_add_text(pt, tvb, offset, 16, "Message header"); tree = proto_item_add_subtree (item, ett_gryphon_data_header); proto_tree_add_text(tree, tvb, offset, 2, "Header length: %d bytes, %d bits", hdrsize, hdrbits); proto_tree_add_text(tree, tvb, offset+2, 2, "Data length: %d bytes", datasize); proto_tree_add_text(tree, tvb, offset+4, 1, "Extra data length: %d bytes", extrasize); mode = tvb_get_guint8(tvb, offset+5); item1 = proto_tree_add_text(tree, tvb, offset+5, 1, "Mode: %d", mode); if (mode) { tree1 = proto_item_add_subtree (item1, ett_gryphon_flags); if (mode & 0x80) proto_tree_add_text(tree1, tvb, offset+5, 1, "1... .... = Transmitted message"); if (mode & 0x40) proto_tree_add_text(tree1, tvb, offset+5, 1, ".1.. .... = Received message"); if (mode & 0x20) proto_tree_add_text(tree1, tvb, offset+5, 1, "..1. .... = Local message"); if (mode & 0x10) proto_tree_add_text(tree1, tvb, offset+5, 1, "...1 .... = Remote message"); if (mode & 0x01) proto_tree_add_text(tree1, tvb, offset+5, 1, ".... ...1 = Internal message"); } proto_tree_add_text(tree, tvb, offset+6, 1, "Priority: %u", tvb_get_guint8(tvb, offset+6)); proto_tree_add_text(tree, tvb, offset+7, 1, "Error status: %u", tvb_get_guint8(tvb, offset+7)); timestamp = tvb_get_ntohl(tvb, offset+8); hours = timestamp /(100000 * 60 *60); minutes = (timestamp / (100000 * 60)) % 60; seconds = (timestamp / 100000) % 60; fraction = timestamp % 100000; proto_tree_add_text(tree, tvb, offset+8, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction); proto_tree_add_text(tree, tvb, offset+12, 1, "Context: %u", tvb_get_guint8(tvb, offset+12)); proto_tree_add_text(tree, tvb, offset+13, 3, "reserved:"); offset += 16; item = proto_tree_add_text(pt, tvb, offset, msgsize-16-padding, "Message Body"); tree = proto_item_add_subtree (item, ett_gryphon_data_body); if (hdrsize) { proto_tree_add_text(tree, tvb, offset, hdrsize, "Header"); offset += hdrsize; } if (datasize) { proto_tree_add_text(tree, tvb, offset, datasize, "Data"); offset += datasize; } if (extrasize) { proto_tree_add_text(tree, tvb, offset, extrasize, "Extra data"); offset += extrasize; } if (padding) { proto_tree_add_text(pt, tvb, offset, padding, "padding"); offset += padding; } return offset; } static int decode_event(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { int hours, minutes, seconds, fraction, padding, length; unsigned long timestamp; int msgend; padding = 3 - (msglen + 3) % 4; msgend = offset + msglen; proto_tree_add_text(pt, tvb, offset, 1, "Event ID: %u", tvb_get_guint8(tvb, offset)); proto_tree_add_text(pt, tvb, offset+1, 1, "Event context: %u", tvb_get_guint8(tvb, offset+1)); proto_tree_add_text(pt, tvb, offset+2, 2, "reserved"); offset += 4; timestamp = tvb_get_ntohl(tvb, offset); hours = timestamp /(100000 * 60 *60); minutes = (timestamp / (100000 * 60)) % 60; seconds = (timestamp / 100000) % 60; fraction = timestamp % 100000; proto_tree_add_text(pt, tvb, offset, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction); offset += 4; if (offset < msgend) { length = msgend - offset; proto_tree_add_text (pt, tvb, offset, length, "Data (%d bytes)", length); offset += length; } if (padding) { proto_tree_add_text(pt, tvb, offset, padding, "padding"); offset += padding; } return offset; } static int cmd_init(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { char *ptr; if (tvb_get_guint8(tvb, offset) == 0) ptr = "Always initialize"; else ptr = "Initialize if not previously initialized"; proto_tree_add_text(pt, tvb, offset, 1, "Mode: %s", ptr); proto_tree_add_text(pt, tvb, offset+1, 3, "reserved"); offset += 4; return offset; } static int eventnum(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { guint8 event = tvb_get_guint8(tvb, offset); if (event) proto_tree_add_text(pt, tvb, offset, 1, "Event number: %u", event); else proto_tree_add_text(pt, tvb, offset, 1, "Event numbers: All"); proto_tree_add_text(pt, tvb, offset+1, 3, "padding"); offset += 4; return offset; } static int resp_time(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { int hours, minutes, seconds, fraction; union { unsigned int lng[2]; guint64 lnglng; } ts; unsigned int timestamp; unsigned char date[45]; ts.lng[1] = tvb_get_ntohl(tvb, offset); ts.lng[0] = tvb_get_ntohl(tvb, offset + 4); timestamp = ts.lnglng / 100000L; strncpy (date, ctime((time_t*)×tamp), sizeof(date)); date[strlen(date)-1] = 0x00; proto_tree_add_text(pt, tvb, offset, 8, "Date/Time: %s", date); timestamp = ts.lng[0]; hours = timestamp /(100000 * 60 *60); minutes = (timestamp / (100000 * 60)) % 60; seconds = (timestamp / 100000) % 60; fraction = timestamp % 100000; proto_tree_add_text(pt, tvb, offset+4, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction); offset += 8; return offset; } static int cmd_setfilt(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { int flag = tvb_get_ntohl(tvb, offset); int length, padding; unsigned char mode[30]; length = tvb_get_guint8(tvb, offset+4) + tvb_get_guint8(tvb, offset+5) + tvb_get_ntohs(tvb, offset+6); if (flag) strcpy (mode, "Pass"); else strcpy (mode, "Block"); if (length == 0) strcat (mode, " all"); proto_tree_add_text(pt, tvb, offset, 4, "Pass/Block flag: %s", mode); proto_tree_add_text(pt, tvb, offset+4, 4, "Length of Pattern & Mask: %d", length); offset += 8; if (length) { proto_tree_add_text(pt, tvb, offset, length * 2, "discarded data"); offset += length * 2; } padding = 3 - (length * 2 + 3) % 4; if (padding) { proto_tree_add_text(pt, tvb, offset+1, 3, "padding"); offset += padding; } return offset; } static int cmd_ioctl(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { unsigned int ioctl, i; ioctl = tvb_get_ntohl(tvb, offset); for (i = 0; i < SIZEOF(ioctls); i++) { if (ioctls[i].value == ioctl) break; } if (i >= SIZEOF(ioctls)) i = SIZEOF(ioctls) - 1; proto_tree_add_text(pt, tvb, offset, 4, "IOCTL: %s", ioctls[i].strptr); offset += 4; msglen -= 4; if (msglen > 0) { proto_tree_add_text(pt, tvb, offset, msglen, "Data"); offset += msglen; } return offset; } static int cmd_addfilt(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_item *item; proto_tree *tree; guint8 flags; int blocks, i, length; char *ptr; char pass[] = ".... ...1 = Conforming messages are passed"; char block[] = ".... ...0 = Conforming messages are blocked"; char active[] = ".... ..1. = The filter is active"; char inactive[] = ".... ..0. = The filter is inactive"; item = proto_tree_add_text(pt, tvb, offset, 1, "Flags"); tree = proto_item_add_subtree (item, ett_gryphon_flags); flags = tvb_get_guint8(tvb, offset); if (flags & FILTER_PASS_FLAG) ptr = pass; else ptr = block; proto_tree_add_text(tree, tvb, offset, 1, ptr); if (flags & FILTER_ACTIVE_FLAG) ptr = active; else ptr = inactive; proto_tree_add_text(tree, tvb, offset, 1, ptr); offset += 1; msglen -= 1; blocks = tvb_get_guint8(tvb, offset); proto_tree_add_text(pt, tvb, offset, 1, "Number of filter blocks = %d", blocks); proto_tree_add_text(pt, tvb, offset+1, 6, "reserved"); offset += 7; msglen -= 7; for (i = 1; i <= blocks; i++) { length = tvb_get_ntohs(tvb, offset+2) * 2 + 8; length += 3 - (length + 3) % 4; item = proto_tree_add_text(pt, tvb, offset, length, "Filter block %d", i); tree = proto_item_add_subtree (item, ett_gryphon_cmd_filter_block); offset = filter_block(tvb, offset, src, msglen, tree); } return offset; } static int resp_addfilt(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_tree_add_text(pt, tvb, offset, 1, "Filter handle: %u", tvb_get_guint8(tvb, offset)); proto_tree_add_text(pt, tvb, offset+1, 3, "reserved"); offset += 4; return offset; } static int cmd_modfilt(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { guint8 filter_handle; unsigned char action, i; filter_handle = tvb_get_guint8(tvb, offset); if (filter_handle) proto_tree_add_text(pt, tvb, offset, 1, "Filter handle: %u", filter_handle); else proto_tree_add_text(pt, tvb, offset, 1, "Filter handles: all"); action = tvb_get_guint8(tvb, offset + 1); for (i = 0; i < SIZEOF(filtacts); i++) { if (filtacts[i].value == action) break; } if (i >= SIZEOF(filtacts)) i = SIZEOF(filtacts) - 1; proto_tree_add_text(pt, tvb, offset+1, 1, "Action: %s filter", filtacts[i].strptr); proto_tree_add_text(pt, tvb, offset+2, 2, "reserved"); offset += 4; return offset; } static int resp_filthan(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { int handles = tvb_get_guint8(tvb, offset); int i, padding; proto_tree_add_text(pt, tvb, offset, 1, "Number of filter handles: %d", handles); for (i = 1; i <= handles; i++){ proto_tree_add_text(pt, tvb, offset+i, 1, "Handle %d: %u", i, tvb_get_guint8(tvb, offset+i)); } padding = 3 - (handles + 1 + 3) % 4; if (padding) proto_tree_add_text(pt, tvb, offset+1+handles, padding, "padding"); offset += 1+handles+padding; return offset; } static int dfiltmode(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { unsigned int i; unsigned char mode; mode = tvb_get_guint8(tvb, offset); for (i = 0; i < SIZEOF(modes); i++) { if (dmodes[i].value == mode) break; } if (i >= SIZEOF(dmodes)) i = SIZEOF(dmodes) - 1; proto_tree_add_text(pt, tvb, offset, 1, "Filter mode: %s", dmodes[i].strptr); proto_tree_add_text(pt, tvb, offset+1, 3, "reserved"); offset += 4; return offset; } static int filtmode(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { unsigned int i; unsigned char mode; mode = tvb_get_guint8(tvb, offset); for (i = 0; i < SIZEOF(modes); i++) { if (modes[i].value == mode) break; } if (i >= SIZEOF(modes)) i = SIZEOF(modes) - 1; proto_tree_add_text(pt, tvb, offset, 1, "Filter mode: %s", modes[i].strptr); proto_tree_add_text(pt, tvb, offset+1, 3, "reserved"); offset += 4; return offset; } static int resp_events(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { unsigned int i; proto_tree *tree; proto_item *item; i = 1; while (msglen != 0) { item = proto_tree_add_text(pt, tvb, offset, 20, "Event %d:", i); tree = proto_item_add_subtree (item, ett_gryphon_cmd_events_data); proto_tree_add_text(tree, tvb, offset, 1, "Event ID: %u", tvb_get_guint8(tvb, offset)); proto_tree_add_text(tree, tvb, offset+1, 19, "Event name: %.19s", tvb_get_ptr(tvb, offset+1, 19)); offset += 20; msglen -= 20; i++; } return offset; } static int cmd_register(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_tree_add_text(pt, tvb, offset, 16, "Username: %.16s", tvb_get_ptr(tvb, offset, 16)); offset += 16; proto_tree_add_text(pt, tvb, offset, 32, "Password: %.32s", tvb_get_ptr(tvb, offset, 32)); offset += 32; return offset; } static int resp_register(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_tree_add_text(pt, tvb, offset, 1, "Client ID: %u", tvb_get_guint8(tvb, offset)); proto_tree_add_text(pt, tvb, offset+1, 1, "Privileges: %u", tvb_get_guint8(tvb, offset+1)); proto_tree_add_text(pt, tvb, offset+2, 2, "reserved"); offset += 4; return offset; } static int resp_getspeeds(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { int size; int number; int index; proto_tree_add_text(pt, tvb, offset, 4, "Set Speed IOCTL"); proto_tree_add_text(pt, tvb, offset+4, 4, "Get Speed IOCTL"); size = tvb_get_guint8(tvb, offset+8); proto_tree_add_text(pt, tvb, offset+8, 1, "Speed data size is %d bytes", size); number = tvb_get_guint8(tvb, offset+9); proto_tree_add_text(pt, tvb, offset+9, 1, "There are %d preset speeds", number); offset += 10; for (index = 0; index < number; index++) { proto_tree_add_text(pt, tvb, offset, size, "Data for preset %d", index+1); offset += size; } return offset; } static int cmd_sort(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { char *which; which = tvb_get_guint8(tvb, offset) ? "Sort into blocks of up to 16 messages" : "Do not sort messages"; proto_tree_add_text(pt, tvb, offset, 1, "Set sorting: %s", which); offset += 1; return offset; } static int cmd_optimize(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { char *which; which = tvb_get_guint8(tvb, offset) ? "Optimize for latency (Nagle algorithm disabled)" : "Optimize for throughput (Nagle algorithm enabled)"; proto_tree_add_text(pt, tvb, offset, 1, "Set optimization: %s", which); offset += 1; return offset; } static int resp_config(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_item *ti; proto_tree *ft; int devices; int i; unsigned int j, x; static const value_string protocol_types[] = { {GDUMMY * 256 + GDGDMARKONE, "Dummy device driver"}, {GCAN * 256 + G82527, "CAN, 82527 subtype"}, {GCAN * 256 + GSJA1000, "CAN, SJA1000 subtype"}, {GCAN * 256 + G82527SW, "CAN, 82527 single wire subtype"}, {GJ1850 * 256 + GHBCCPAIR, "J1850, HBCC subtype"}, {GJ1850 * 256 + GDLC, "J1850, GM DLC subtype"}, {GJ1850 * 256 + GCHRYSLER, "J1850, Chrysler subtype"}, {GJ1850 * 256 + GDEHC12, "J1850, DE HC12 KWP/BDLC subtype"}, {GKWP2000 * 256 + GDEHC12KWP, "Keyword protocol 2000"}, {GHONDA * 256 + GDGHC08, "Honda UART, DG HC08 subtype"}, {GFORDUBP * 256 + GDGUBP08, "Ford UBP, DG HC08 subtype"}, {-1, "- unknown -"}, }; proto_tree_add_text(pt, tvb, offset, 20, "Device name: %.20s", tvb_get_ptr(tvb, offset, 20)); offset += 20; proto_tree_add_text(pt, tvb, offset, 8, "Device version: %.8s", tvb_get_ptr(tvb, offset, 8)); offset += 8; proto_tree_add_text(pt, tvb, offset, 20, "Device serial number: %.20s", tvb_get_ptr(tvb, offset, 20)); offset += 20; devices = tvb_get_guint8(tvb, offset); proto_tree_add_text(pt, tvb, offset, 1, "Number of channels: %d", devices); proto_tree_add_text(pt, tvb, offset+1, 15, "reserved"); offset += 16; for (i = 1; i <= devices; i++) { ti = proto_tree_add_text(pt, tvb, offset, 80, "Channel %d:", i); ft = proto_item_add_subtree(ti, ett_gryphon_cmd_config_device); proto_tree_add_text(ft, tvb, offset, 20, "Driver name: %.20s", tvb_get_ptr(tvb, offset, 20)); offset += 20; proto_tree_add_text(ft, tvb, offset, 8, "Driver version: %.8s", tvb_get_ptr(tvb, offset, 8)); offset += 8; proto_tree_add_text(ft, tvb, offset, 24, "Device security string: %.24s", tvb_get_ptr(tvb, offset, 24)); offset += 24; proto_tree_add_text(ft, tvb, offset, 20, "Hardware serial number: %.20s", tvb_get_ptr(tvb, offset, 20)); offset += 20; x = tvb_get_ntohs(tvb, offset); for (j = 0; j < SIZEOF(protocol_types); j++) { if (protocol_types[j].value == x) break; } if (j >= SIZEOF(protocol_types)) j = SIZEOF(protocol_types) -1; proto_tree_add_text(ft, tvb, offset, 2, "Protocol type & subtype: %s", protocol_types[j].strptr); offset += 2; proto_tree_add_text(ft, tvb, offset, 1, "Channel ID: %u", tvb_get_guint8(tvb, offset)); proto_tree_add_text(ft, tvb, offset+1, 5, "reserved"); offset += 6; } return offset; } static int cmd_sched(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_item *item, *item1; proto_tree *tree, *tree1; int save_offset; unsigned int i, x, length; unsigned char def_chan = tvb_get_guint8(tvb, offset-9); char *ptr; char crit[] = ".... ...1 = Critical scheduler"; char norm[] = ".... ...0 = Normal scheduler"; x = tvb_get_ntohl(tvb, offset); if (x == 0xFFFFFFFF) proto_tree_add_text(pt, tvb, offset, 4, "Number of iterations: infinite"); else proto_tree_add_text(pt, tvb, offset, 4, "Number of iterations: %d", x); offset += 4; msglen -= 4; x = tvb_get_ntohl(tvb, offset); item = proto_tree_add_text(pt, tvb, offset, 4, "Flags"); tree = proto_item_add_subtree (item, ett_gryphon_flags); ptr = x & 1 ? crit : norm; proto_tree_add_text(tree, tvb, offset, 4, ptr, NULL); offset += 4; msglen -= 4; i = 1; while (msglen > 0) { length = 16 + tvb_get_guint8(tvb, offset+16) + tvb_get_ntohs(tvb, offset+18) + tvb_get_guint8(tvb, offset+20) + 16; length += 3 - (length + 3) % 4; item = proto_tree_add_text(pt, tvb, offset, length, "Message %d", i); tree = proto_item_add_subtree (item, ett_gryphon_cmd_sched_data); x = tvb_get_ntohl(tvb, offset); proto_tree_add_text(tree, tvb, offset, 4, "Sleep: %d milliseconds", x); offset += 4; msglen -= 4; x = tvb_get_ntohl(tvb, offset); proto_tree_add_text(tree, tvb, offset, 4, "Transmit count: %d", x); offset += 4; msglen -= 4; x = tvb_get_ntohl(tvb, offset); proto_tree_add_text(tree, tvb, offset, 4, "Transmit period: %d milliseconds", x); offset += 4; msglen -= 4; proto_tree_add_text(tree, tvb, offset, 2, "reserved flags"); x = tvb_get_guint8(tvb, offset+2); if (x == 0) x = def_chan; proto_tree_add_text(tree, tvb, offset+2, 1, "Channel: %d", x); proto_tree_add_text(tree, tvb, offset+3, 1, "reserved"); offset += 4; msglen -= 4; item1 = proto_tree_add_text(tree, tvb, offset, length, "Message"); tree1 = proto_item_add_subtree (item1, ett_gryphon_cmd_sched_cmd); save_offset = offset; offset = decode_data(tvb, offset, msglen, src, tree1); msglen -= offset - save_offset; i++; } return offset; } static int resp_blm_data(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { unsigned int i; int hours, minutes, seconds, fraction, x, fract; unsigned long timestamp; char *fields[] = { "Bus load average: %d.%02d%%", "Current bus load: %d.%02d%%", "Peak bus load: %d.%02d%%", "Historic peak bus load: %d.%02d%%" }; timestamp = tvb_get_ntohl(tvb, offset); hours = timestamp /(100000 * 60 *60); minutes = (timestamp / (100000 * 60)) % 60; seconds = (timestamp / 100000) % 60; fraction = timestamp % 100000; proto_tree_add_text(pt, tvb, offset, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction); offset += 4; for (i = 0; i < SIZEOF(fields); i++){ x = tvb_get_ntohs(tvb, offset); fract = x % 100; x /= 100; proto_tree_add_text(pt, tvb, offset, 2, fields[i], x, fract); offset += 2; } return offset; } static int resp_blm_stat(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { unsigned int x, i; char *fields[] = { "Receive frame count: %d", "Transmit frame count: %d", "Receive dropped frame count: %d", "Transmit dropped frame count: %d", "Receive error count: %d", "Transmit error count: %d", }; offset = resp_blm_data(tvb, offset, src, msglen, pt); for (i = 0; i < SIZEOF(fields); i++){ x = tvb_get_ntohl(tvb, offset); proto_tree_add_text(pt, tvb, offset, 4, fields[i], x); offset += 4; } return offset; } static int cmd_addresp(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_item *item; proto_tree *tree; int blocks, responses, old_handle, i, length; int action, actionType, actionValue; char *ptr; char active[] = ".... ..1. = The response is active"; char inactive[] = ".... ..0. = The response is inactive"; actionType = 0; item = proto_tree_add_text(pt, tvb, offset, 1, "Flags"); tree = proto_item_add_subtree (item, ett_gryphon_flags); if (tvb_get_guint8(tvb, offset) & FILTER_ACTIVE_FLAG) ptr = active; else ptr = inactive; proto_tree_add_text(tree, tvb, offset, 1, ptr, NULL); offset += 1; blocks = tvb_get_guint8(tvb, offset); proto_tree_add_text(pt, tvb, offset, 1, "Number of filter blocks = %d", blocks); offset += 1; responses = tvb_get_guint8(tvb, offset); proto_tree_add_text(pt, tvb, offset, 1, "Number of response blocks = %d", responses); offset += 1; old_handle = tvb_get_guint8(tvb, offset); proto_tree_add_text(pt, tvb, offset, 1, "Old handle = %d", old_handle); offset += 1; action = tvb_get_guint8(tvb, offset); switch (action & 7) { case FR_RESP_AFTER_EVENT: ptr = "Send response(s) for each conforming message"; break; case FR_RESP_AFTER_PERIOD: ptr = "Send response(s) after the specified period expires following a conforming message"; break; case FR_IGNORE_DURING_PER: ptr = "Send response(s) for a conforming message and ignore\nfurther messages until the specified period expires"; break; default: ptr = "- unknown -"; } item = proto_tree_add_text(pt, tvb, offset, 1, "Action = %s", ptr); tree = proto_item_add_subtree (item, ett_gryphon_flags); if (action & FR_DEACT_AFTER_PER && !(action & FR_DELETE)){ proto_tree_add_text(tree, tvb, offset, 1, "1.0. .... Deactivate this response after the specified period following a conforming message"); } if (action & FR_DEACT_ON_EVENT && !(action & FR_DELETE)){ proto_tree_add_text(tree, tvb, offset, 1, ".10. .... Deactivate this response for a conforming message"); } if (action & FR_DEACT_AFTER_PER && action & FR_DELETE){ proto_tree_add_text(tree, tvb, offset, 1, "1.1. .... Delete this response after the specified period following a conforming message"); } if (action & FR_DEACT_ON_EVENT && action & FR_DELETE){ proto_tree_add_text(tree, tvb, offset, 1, ".11. .... Delete this response for a conforming message"); } actionValue = tvb_get_ntohs(tvb, offset+2); if (actionValue) { if (action & FR_PERIOD_MSGS){ ptr = "...1 .... The period is in frames"; actionType = 1; } else { ptr = "...0 .... The period is in 0.01 seconds"; actionType = 0; } proto_tree_add_text(tree, tvb, offset, 1, ptr, NULL); } offset += 1; proto_tree_add_text(pt, tvb, offset, 1, "reserved"); offset += 1; if (actionValue) { if (actionType == 1) { proto_tree_add_text(tree, tvb, offset, 2, "Period: %d messages", actionValue); } else { proto_tree_add_text(tree, tvb, offset, 2, "Period: %d.%02d seconds", actionValue/100, actionValue%100); } } offset += 2; for (i = 1; i <= blocks; i++) { length = tvb_get_ntohs(tvb, offset+2) * 2 + 8; length += 3 - (length + 3) % 4; item = proto_tree_add_text(pt, tvb, offset, length, "Filter block %d", i); tree = proto_item_add_subtree (item, ett_gryphon_cmd_filter_block); offset = filter_block(tvb, offset, src, msglen, tree); } for (i = 1; i <= responses; i++) { length = tvb_get_ntohs(tvb, offset+4) + 8; length += 3 - (length + 3) % 4; item = proto_tree_add_text(pt, tvb, offset, length, "Response block %d", i); tree = proto_item_add_subtree (item, ett_gryphon_cmd_response_block); dissect_gryphon_message(tvb, offset, tree, TRUE); offset += length; } return offset; } static int resp_addresp(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_tree_add_text(pt, tvb, offset, 1, "Response handle: %u", tvb_get_guint8(tvb, offset)); proto_tree_add_text(pt, tvb, offset+1, 3, "reserved"); offset += 4; return offset; } static int cmd_modresp(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { unsigned char action; unsigned char dest = tvb_get_guint8(tvb, offset-5); guint8 resp_handle; unsigned int i; resp_handle = tvb_get_guint8(tvb, offset); if (resp_handle) proto_tree_add_text(pt, tvb, offset, 1, "Response handle: %u", resp_handle); else if (dest) proto_tree_add_text(pt, tvb, offset, 1, "Response handles: all on channel %hd", dest); else proto_tree_add_text(pt, tvb, offset, 1, "Response handles: all"); action = tvb_get_guint8(tvb, offset+1); for (i = 0; i < SIZEOF(filtacts); i++) { if (filtacts[i].value == action) break; } if (i >= SIZEOF(filtacts)) i = SIZEOF(filtacts) - 1; proto_tree_add_text(pt, tvb, offset+1, 1, "Action: %s response", filtacts[i].strptr); proto_tree_add_text(pt, tvb, offset+2, 2, "reserved"); offset += 4; return offset; } static int resp_resphan(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { int handles = tvb_get_guint8(tvb, offset); int i, padding; proto_tree_add_text(pt, tvb, offset, 1, "Number of response handles: %d", handles); for (i = 1; i <= handles; i++){ proto_tree_add_text(pt, tvb, offset+i, 1, "Handle %d: %u", i, tvb_get_guint8(tvb, offset+i)); } padding = 3 - (handles + 1 + 3) % 4; if (padding) proto_tree_add_text(pt, tvb, offset+1+handles, padding, "padding"); offset += 1+handles+padding; return offset; } static int resp_sched(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { unsigned int id = tvb_get_ntohl(tvb, offset); proto_tree_add_text(pt, tvb, offset, 4, "Transmit schedule ID: %u", id); offset += 4; return offset; } static int cmd_desc(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_tree_add_text(pt, tvb, offset, 4, "Program size: %u bytes", tvb_get_ntohl(tvb, offset)); offset += 4; proto_tree_add_text(pt, tvb, offset, 32, "Program name: %.32s", tvb_get_ptr(tvb, offset, 32)); offset += 32; proto_tree_add_text(pt, tvb, offset, 80, "Program description: %.80s", tvb_get_ptr(tvb, offset, 80)); offset += 80; return offset; } static int resp_desc(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_item *item; proto_tree *tree; char *ptr; char missing[] = ".... ...0 = The program is not present"; char present[] = ".... ...1 = The program is already present"; item = proto_tree_add_text(pt, tvb, offset, 1, "Flags"); tree = proto_item_add_subtree (item, ett_gryphon_flags); if (tvb_get_guint8(tvb, offset) & 1) ptr = present; else ptr = missing; proto_tree_add_text(tree, tvb, offset, 1, ptr); proto_tree_add_text(pt, tvb, offset+1, 1, "Handle: %u", tvb_get_guint8(tvb, offset+1)); proto_tree_add_text(pt, tvb, offset+2, 2, "reserved"); offset += 4; return offset; } static int cmd_upload(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { unsigned int length; proto_tree_add_text(pt, tvb, offset, 2, "Block number: %u", tvb_get_ntohs(tvb, offset)); offset += 4; msglen -= 4; proto_tree_add_text(pt, tvb, offset+2, 1, "Handle: %u", tvb_get_guint8(tvb, offset+2)); offset += 3; msglen -= 3; length = msglen; proto_tree_add_text(pt, tvb, offset, length, "Data (%d bytes)", length); offset += length; length = 3 - (length + 3) % 4; if (length) { proto_tree_add_text(pt, tvb, offset, length, "padding"); offset += length; } return offset; } static int cmd_delete(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_tree_add_text(pt, tvb, offset, 32, "Program name: %.32s", tvb_get_ptr(tvb, offset, 32)); offset += 32; return offset; } static int cmd_list(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_tree_add_text(pt, tvb, offset, 1, "Block number: %u", tvb_get_guint8(tvb, offset)); proto_tree_add_text(pt, tvb, offset+1, 3, "reserved"); offset += 4; return offset; } static int resp_list(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_item *item; proto_tree *tree; unsigned int i, count; count = tvb_get_guint8(tvb, offset); proto_tree_add_text(pt, tvb, offset, 1, "Number of programs in this response: %d", count); proto_tree_add_text(pt, tvb, offset+1, 1, "reserved"); offset += 2; proto_tree_add_text(pt, tvb, offset, 2, "Number of remaining programs: %u", tvb_get_ntohs(tvb, offset)); offset += 2; for (i = 1; i <= count; i++) { item = proto_tree_add_text(pt, tvb, offset, 112, "Program %d", i); tree = proto_item_add_subtree (item, ett_gryphon_pgm_list); proto_tree_add_text(tree, tvb, offset, 32, "Name: %.32s", tvb_get_ptr(tvb, offset, 32)); offset += 32; proto_tree_add_text(tree, tvb, offset, 80, "Description: %.80s", tvb_get_ptr(tvb, offset, 80)); offset += 80; } return offset; } static int cmd_start(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { char string[120]; gint length; offset = cmd_delete(tvb, offset, src, msglen, pt); length = tvb_get_nstringz0(tvb, offset, 120, string) + 1; proto_tree_add_text(pt, tvb, offset, length, "Arguments: %s", string); offset += length; length = 3 - (length + 3) % 4; if (length) { proto_tree_add_text(pt, tvb, offset, length, "padding"); offset += length; } return offset; } static int resp_start(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_tree_add_text(pt, tvb, offset, 1, "Channel (Client) number: %u", tvb_get_guint8(tvb, offset)); proto_tree_add_text(pt, tvb, offset+1, 3, "reserved"); offset += 4; return offset; } static int resp_status(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_item *item; proto_tree *tree; unsigned int i, copies, length; copies = tvb_get_guint8(tvb, offset); item = proto_tree_add_text(pt, tvb, offset, 1, "Number of running copies: %d", copies); tree = proto_item_add_subtree (item, ett_gryphon_pgm_status); offset += 1; if (copies) { for (i = 1; i <= copies; i++) { proto_tree_add_text(tree, tvb, offset, 1, "Program %d channel (client) number %u", i, tvb_get_guint8(tvb, offset)); offset += 1; } } length = 3 - (copies + 1 + 3) % 4; if (length) { proto_tree_add_text(pt, tvb, offset, length, "padding"); offset += length; } return offset; } static int cmd_options(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_item *item; proto_tree *tree; unsigned int i, size, padding, option, option_length, option_value; unsigned char *string, *string1; item = proto_tree_add_text(pt, tvb, offset, 1, "Handle: %u", tvb_get_guint8(tvb, offset)); item = proto_tree_add_text(pt, tvb, offset+1, 3, "reserved"); offset += 4; msglen -= 4; for (i = 1; msglen > 0; i++) { option_length = tvb_get_guint8(tvb, offset+1); size = option_length + 2; padding = 3 - ((size + 3) %4); item = proto_tree_add_text(pt, tvb, offset, size + padding, "Option number %d", i); tree = proto_item_add_subtree (item, ett_gryphon_pgm_options); option = tvb_get_guint8(tvb, offset); switch (option_length) { case 1: option_value = tvb_get_guint8(tvb, offset+2); break; case 2: option_value = tvb_get_ntohs(tvb, offset+2); break; case 4: option_value = tvb_get_ntohl(tvb, offset+2); break; default: option_value = 0; } string = "unknown option"; string1 = "unknown option data"; switch (option) { case PGM_CONV: string = "Type of data in the file"; switch (option_value) { case PGM_BIN: string1 = "Binary - Don't modify"; break; case PGM_ASCII: string1 = "ASCII - Remove CR's"; break; } break; case PGM_TYPE: string = "Type of file"; switch (option_value) { case PGM_PGM: string1 = "Executable"; break; case PGM_DATA: string1 = "Data"; break; } break; } proto_tree_add_text(tree, tvb, offset, 1, "%s", string); proto_tree_add_text(tree, tvb, offset+2, option_length, "%s", string1); if (padding) proto_tree_add_text(tree, tvb, offset+option_length+2, padding, "padding"); offset += size + padding; msglen -= size + padding; } return offset; } static int cmd_files(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { u_char *which; if (tvb_get_guint8(tvb, offset) == 0) which = "First group of names"; else which = "Subsequent group of names"; proto_tree_add_text(pt, tvb, offset, 1, "%s", which); proto_tree_add_text(pt, tvb, offset+1, msglen-1, "Directory: %.*s", msglen-1, tvb_get_ptr(tvb, offset+1, msglen-1)); offset += msglen; return offset; } static int resp_files(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { u_char *flag; flag = tvb_get_guint8(tvb, offset) ? "Yes": "No"; proto_tree_add_text(pt, tvb, offset, 1, "More filenames to return: %s", flag); proto_tree_add_text(pt, tvb, offset+1, msglen-1, "File and directory names"); offset += msglen; return offset; } static int cmd_usdt(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { u_char *desc; guint8 assemble_flag; if (tvb_get_guint8(tvb, offset)) desc = "Register with gusdt"; else desc = "Unregister with gusdt"; proto_tree_add_text(pt, tvb, offset, 1, "%s", desc); if (tvb_get_guint8(tvb, offset+1)) desc = "Echo long transmit messages back to the client"; else desc = "Do not echo long transmit messages back to the client"; proto_tree_add_text(pt, tvb, offset+1, 1, "%s", desc); assemble_flag = tvb_get_guint8(tvb, offset+2); if (assemble_flag == 2) desc = "Assemble long received messages but do not send them to the client"; else if (assemble_flag) desc = "Assemble long received messages and send them to the client"; else desc = "Do not assemble long received messages on behalf of the client"; proto_tree_add_text(pt, tvb, offset+2, 1, "%s", desc); offset += 4; return offset; } static int speed(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { proto_tree_add_text(pt, tvb, offset, 1, "Baud rate index: %u", tvb_get_guint8(tvb, offset)); proto_tree_add_text(pt, tvb, offset+1, 3, "reserved"); offset += 4; return offset; } static int filter_block(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { unsigned int type, operator, i; int length, padding; proto_tree_add_text(pt, tvb, offset, 2, "Filter field starts at byte %d", tvb_get_ntohs(tvb, offset)); length = tvb_get_ntohs(tvb, offset+2); proto_tree_add_text(pt, tvb, offset+2, 2, "Filter field is %d bytes long", length); type = tvb_get_guint8(tvb, offset+4); for (i = 0; i < SIZEOF(filter_data_types); i++) { if (filter_data_types[i].value == type) break; } if (i >= SIZEOF(filter_data_types)) i = SIZEOF(filter_data_types) - 1; proto_tree_add_text(pt, tvb, offset+4, 1, "Filtering on %s", filter_data_types[i].strptr); operator = tvb_get_guint8(tvb, offset+5); for (i = 0; i < SIZEOF(operators); i++) { if (operators[i].value == operator) break; } if (i >= SIZEOF(operators)) i = SIZEOF(operators) - 1; proto_tree_add_text(pt, tvb, offset+5, 1, "Type of comparison: %s", operators[i].strptr); proto_tree_add_text(pt, tvb, offset+6, 2, "reserved"); offset += 8; if (operator == BIT_FIELD_CHECK) { proto_tree_add_text(pt, tvb, offset, length, "Pattern"); proto_tree_add_text(pt, tvb, offset+length, length, "Mask"); } else { switch (length) { case 1: proto_tree_add_text(pt, tvb, offset, 1, "Value: %u", tvb_get_guint8(tvb, offset)); break; case 2: proto_tree_add_text(pt, tvb, offset, 2, "Value: %u", tvb_get_ntohs(tvb, offset)); break; case 4: proto_tree_add_text(pt, tvb, offset, 4, "Value: %u", tvb_get_ntohl(tvb, offset)); break; default: proto_tree_add_text(pt, tvb, offset, length, "Value"); } } offset += length * 2; padding = 3 - (length * 2 + 3) % 4; if (padding) { proto_tree_add_text(pt, tvb, offset, padding, "padding"); offset += padding; } return offset; } static int blm_mode(tvbuff_t *tvb, int offset, int src, int msglen, proto_tree *pt) { char *mode, line[50]; int x, y, seconds; x = tvb_get_ntohl(tvb, offset); y = tvb_get_ntohl(tvb, offset+4); switch (x) { case 0: mode = "Off"; sprintf (line, "reserved"); break; case 1: mode = "Average over time"; seconds = y / 1000; y = y % 1000; sprintf (line, "Averaging period: %d.%03d seconds", seconds, y); break; case 2: mode = "Average over frame count"; sprintf (line, "Averaging period: %d frames", y); break; default: mode = "- unknown -"; sprintf (line, "reserved"); } proto_tree_add_text(pt, tvb, offset, 4, "Mode: %s", mode); offset += 4; proto_tree_add_text(pt, tvb, offset, 4, line, NULL); offset += 4; return offset; } void proto_register_gryphon(void) { static hf_register_info hf[] = { { &hf_gryph_src, { "Source", "gryph.src", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_gryph_srcchan, { "Source channel", "gryph.srcchan", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_gryph_dest, { "Destination", "gryph.dest", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_gryph_destchan, { "Destination channel", "gryph.dstchan", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_gryph_type, { "Frame type", "gryph.type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_gryph_cmd, { "Command", "gryph.cmd.cmd", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, }; static gint *ett[] = { &ett_gryphon, &ett_gryphon_header, &ett_gryphon_body, &ett_gryphon_command_data, &ett_gryphon_response_data, &ett_gryphon_data_header, &ett_gryphon_flags, &ett_gryphon_data_body, &ett_gryphon_cmd_filter_block, &ett_gryphon_cmd_events_data, &ett_gryphon_cmd_config_device, &ett_gryphon_cmd_sched_data, &ett_gryphon_cmd_sched_cmd, &ett_gryphon_cmd_response_block, &ett_gryphon_pgm_list, &ett_gryphon_pgm_status, &ett_gryphon_pgm_options, }; proto_gryphon = proto_register_protocol("DG Gryphon Protocol", "Gryphon", "gryphon"); proto_register_field_array(proto_gryphon, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } void proto_reg_handoff_gryphon(void) { dissector_handle_t gryphon_handle; gryphon_handle = create_dissector_handle(dissect_gryphon, proto_gryphon); dissector_add("tcp.port", 7000, gryphon_handle); } /* Start the functions we need for the plugin stuff */ G_MODULE_EXPORT void plugin_reg_handoff(void){ proto_reg_handoff_gryphon(); } G_MODULE_EXPORT void plugin_init(plugin_address_table_t *pat){ /* initialise the table of pointers needed in Win32 DLLs */ plugin_address_table_init(pat); /* register the new protocol, protocol fields, and subtrees */ if (proto_gryphon == -1) { /* execute protocol initialization only once */ proto_register_gryphon(); } } /* End the functions we need for plugin stuff */