Change "unsigned gint64" to "guint64", and add GPL header to plugin_api.[ch]
[obnox/wireshark/wip.git] / plugins / gryphon / packet-gryphon.c
1 /* packet-gryphon.c
2  * Routines for Gryphon protocol packet disassembly
3  *
4  * $Id: packet-gryphon.c,v 1.6 2000/02/07 17:23:53 gram Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Steve Limkemann <stevelim@dgtech.com>
8  * Copyright 1998 Steve Limkemann
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  *
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "plugins/plugin_api.h"
33
34 #include "moduleinfo.h"
35
36 #ifdef HAVE_SYS_TYPES_H
37 #include <sys/types.h>
38 #endif
39
40 #include <string.h>
41 #include <ctype.h>
42 #include <time.h>
43
44 #include <glib.h>
45 #ifdef HAVE_NETINET_IN_H
46 # include <netinet/in.h>
47 #endif
48 #include "packet.h"
49 #include "dfilter.h"
50 #include "packet-gryphon.h"
51
52 DLLEXPORT const gchar version[] = VERSION;
53 DLLEXPORT const gchar desc[] = "DG Gryphon Protocol";
54 DLLEXPORT const gchar protocol[] = "tcp";
55 DLLEXPORT const gchar filter_string[] = "tcp.port == 7000";
56
57 #ifndef G_HAVE_GINT64
58 #error "Sorry, this won't compile without 64-bit integer support"
59 #endif                                                                  
60
61 static int proto_gryphon = -1;
62
63 static int hf_gryph_src = -1;
64 static int hf_gryph_srcchan = -1;
65 static int hf_gryph_dest = -1;
66 static int hf_gryph_destchan= -1;
67 static int hf_gryph_type = -1;
68 static int hf_gryph_cmd = -1;
69
70 static gint ett_gryphon = -1;
71 static gint ett_gryphon_header = -1;
72 static gint ett_gryphon_body = -1;
73 static gint ett_gryphon_command_data = -1;
74 static gint ett_gryphon_response_data = -1;
75 static gint ett_gryphon_data_header = -1;
76 static gint ett_gryphon_flags = -1;
77 static gint ett_gryphon_data_body = -1;
78 static gint ett_gryphon_cmd_filter_block = -1;
79 static gint ett_gryphon_cmd_events_data = -1;
80 static gint ett_gryphon_cmd_config_device = -1;
81 static gint ett_gryphon_cmd_sched_data = -1;
82 static gint ett_gryphon_cmd_sched_cmd = -1;
83 static gint ett_gryphon_cmd_response_block = -1;
84 static gint ett_gryphon_pgm_list = -1;
85 static gint ett_gryphon_pgm_status = -1;
86 static gint ett_gryphon_pgm_options = -1;
87
88
89
90 DLLEXPORT void
91 dissector(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
92 {
93
94     proto_tree      *gryphon_tree, *header_tree, *body_tree;
95     proto_item      *ti, *header_item, *body_item;
96     const u_char    *data, *dataend, *msgend;
97     int             src, msglen, msgpad, dest, frmtyp, i, end_of_frame;
98     static const u_char *frame_type[] = {"",
99                                          "Command request",
100                                          "Command response",
101                                          "Network (vehicle) data",
102                                          "Event",
103                                          "Miscelaneous",
104                                          "Text string"};
105     static const value_string src_dest[] = {
106             {SD_CARD,           "Card"},
107             {SD_SERVER,         "Server"},
108             {SD_CLIENT,         "Client"},
109             {SD_SCHED,          "Scheduler"},
110             {SD_SCRIPT,         "Script Processor"},
111             {SD_PGM,            "Program Loader"},
112             {SD_USDT,           "USDT Server"},
113             {SD_BLM,            "Bus Load Monitoring"},
114             {SD_FLIGHT,         "Flight Recorder"},
115             {SD_RESP,           "Message Responder"},
116             {-1,                "- unknown -"},
117             };                                 
118
119     data = &pd[offset];
120     if (fd) {
121         end_of_frame = END_OF_FRAME;
122     }
123     else {
124         end_of_frame = pntohs (data + 4) + 8;
125         end_of_frame += 3 - (end_of_frame + 3 ) % 4;
126     }
127     dataend = data + end_of_frame;
128
129     if (fd && check_col(fd, COL_PROTOCOL))
130         col_add_str(fd, COL_PROTOCOL, "Gryphon");
131
132     if (END_OF_FRAME < 8)
133         return;
134
135     if (fd && check_col(fd, COL_INFO)) {
136         /*
137          * Indicate what kind of message this is.
138          */
139         col_add_str (fd, COL_INFO, frame_type[data[6]]);
140     }
141     if (tree) {
142         if (fd) {
143             ti = proto_tree_add_item(tree, proto_gryphon, offset,
144                     end_of_frame, NULL);
145             gryphon_tree = proto_item_add_subtree(ti, ett_gryphon);
146         } else
147             gryphon_tree = tree;
148
149         while (data < dataend) {
150             src = data[0];
151             dest = data[2];
152             frmtyp = data[6];
153             msglen = pntohs ((unsigned short *)&data[4]);
154
155             header_item = proto_tree_add_text(gryphon_tree, offset,
156                     MSG_HDR_SZ, "Header", NULL);
157             header_tree = proto_item_add_subtree(header_item,
158                     ett_gryphon_header);
159             for (i = 0; i < SIZEOF(src_dest); i++) {
160                 if (src_dest[i].value == src)
161                     break;
162             }
163             if (i >= SIZEOF(src_dest))
164                 i = SIZEOF(src_dest) - 1;
165             proto_tree_add_text(header_tree, offset, 2,
166                     "Source: %s, channel %hd", src_dest[i].strptr, data[1]);
167             proto_tree_add_item_hidden(header_tree, hf_gryph_src, offset, 1, src);
168             proto_tree_add_item_hidden(header_tree, hf_gryph_srcchan, offset+1, 1, data[1]);
169
170             for (i = 0; i < SIZEOF(src_dest); i++) {
171                 if (src_dest[i].value == dest)
172                     break;
173             }
174             if (i >= SIZEOF(src_dest))
175                 i = SIZEOF(src_dest) - 1;
176             proto_tree_add_text(header_tree, offset+2, 2,
177                     "Destination: %s, channel %hd", src_dest[i].strptr, data[3]);
178             proto_tree_add_item_hidden(header_tree, hf_gryph_dest, offset+2, 1, dest);
179             proto_tree_add_item_hidden(header_tree, hf_gryph_destchan, offset+3, 1, data[3]);
180
181             proto_tree_add_text(header_tree, offset+4, 2,
182                     "Data length: %d bytes", msglen);
183             proto_tree_add_text(header_tree, offset+6, 1,
184                     "Frame type: %s", frame_type[frmtyp]);
185             proto_tree_add_text(header_tree, offset+7, 1, "reserved", NULL);
186
187             proto_tree_add_item_hidden(header_tree, hf_gryph_type, offset+6, 1, frmtyp);
188             msgpad = 3 - (msglen + 3) % 4;
189             msgend = data + msglen + msgpad + MSG_HDR_SZ;
190
191             body_item = proto_tree_add_text(gryphon_tree, offset + MSG_HDR_SZ,
192                     msglen + msgpad, "Body", NULL);
193             body_tree = proto_item_add_subtree(body_item, ett_gryphon_body);
194
195             offset += MSG_HDR_SZ;
196             data += MSG_HDR_SZ;
197             switch (frmtyp) {
198             case GY_FT_CMD:
199                 decode_command (dest, &data, dataend, &offset, msglen, body_tree);
200                 break;
201             case GY_FT_RESP:
202                 decode_response (src, &data, dataend, &offset, msglen, body_tree);
203                 break;
204             case GY_FT_DATA:
205                 decode_data (src, &data, dataend, &offset, msglen, body_tree);
206                 break;
207             case GY_FT_EVENT:
208                 decode_event (src, &data, dataend, &offset, msglen, body_tree);
209                 break;
210             case GY_FT_MISC:
211                 break;
212             case GY_FT_TEXT:
213                 break;
214             default:
215                 break;
216             }
217             if (data < msgend - msgpad) {
218                 i = msgend - msgpad - data;
219                 proto_tree_add_text(gryphon_tree, offset, i, "Data", NULL);
220                 BUMP (offset, data, i);
221             }
222             if (data < msgend) {
223                 i = msgend - data;
224                 proto_tree_add_text(gryphon_tree, offset, i, "padding", NULL);
225                 BUMP (offset, data, i);
226             }
227 /*          data = dataend;*/
228         }
229
230    }
231 }
232
233
234 static const val_str_dsp cmds[] = {
235         {CMD_INIT,              "Initialize", cmd_init, NULL},
236         {CMD_GET_STAT,          "Get status", NULL, NULL},
237         {CMD_GET_CONFIG,        "Get configuration", NULL, resp_config},
238         {CMD_EVENT_ENABLE,      "Enable event", eventnum, NULL},
239         {CMD_EVENT_DISABLE,     "Disable event", eventnum, NULL},
240         {CMD_GET_TIME,          "Get time", NULL, resp_time},
241         {CMD_GET_RXDROP,        "Get number of dropped RX messages", NULL, NULL},
242         {CMD_RESET_RXDROP,      "Clear number of dropped RX messages", NULL, NULL},
243         {CMD_BCAST_ON,          "Set broadcasts on", NULL, NULL},
244         {CMD_BCAST_OFF,         "Set broadcasts off", NULL, NULL},
245         {CMD_CARD_SET_SPEED,    "Set channel baud rate", speed, NULL},
246         {CMD_CARD_GET_SPEED,    "Get channel baud rate", NULL, speed},
247         {CMD_CARD_SET_FILTER,   "Set filter (deprecated)", cmd_setfilt, NULL},
248         {CMD_CARD_GET_FILTER,   "Get filter", resp_addfilt, cmd_addfilt},
249         {CMD_CARD_TX,           "Transmit message", decode_data, NULL},
250         {CMD_CARD_TX_LOOP_ON,   "Set transmit loopback on", NULL, NULL},
251         {CMD_CARD_TX_LOOP_OFF,  "Set transmit loopback off", NULL, NULL},
252         {CMD_CARD_IOCTL,        "IOCTL pass-through", cmd_ioctl, NULL},
253         {CMD_CARD_ADD_FILTER,   "Add a filter", cmd_addfilt, resp_addfilt},
254         {CMD_CARD_MODIFY_FILTER, "Modify a filter", cmd_modfilt, NULL},
255         {CMD_CARD_GET_FILTER_HANDLES, "Get filter handles", NULL, resp_filthan},
256         {CMD_CARD_SET_DEFAULT_FILTER, "Set default filter", dfiltmode, NULL},
257         {CMD_CARD_GET_DEFAULT_FILTER, "Get default filter mode", NULL, dfiltmode},
258         {CMD_CARD_SET_FILTER_MODE, "Set filter mode", filtmode, NULL},
259         {CMD_CARD_GET_FILTER_MODE, "Get filter mode", NULL, filtmode},
260         {CMD_CARD_GET_EVNAMES,  "Get event names", NULL, resp_events},
261         {CMD_CARD_GET_SPEEDS,   "Get defined speeds", NULL, NULL},
262         {CMD_SERVER_REG,        "Register with server", cmd_register, resp_register},
263         {CMD_BLM_SET_MODE,      "Set Bus Load Monitoring mode", blm_mode, NULL},
264         {CMD_BLM_GET_MODE,      "Get Bus Load Monitoring mode", NULL, blm_mode},
265         {CMD_BLM_GET_DATA,      "Get Bus Load data", NULL, resp_blm_data},
266         {CMD_BLM_GET_STATS,     "Get Bus Load statistics", NULL, resp_blm_stat},
267         {CMD_FLIGHT_GET_CONFIG, "Get flight recorder channel info", NULL, NULL},
268         {CMD_FLIGHT_START_MON,  "Start flight recorder monitoring", NULL, NULL},
269         {CMD_FLIGHT_STOP_MON,   "Stop flight recorder monitoring", NULL, NULL},
270         {CMD_MSGRESP_ADD,       "Add response message", cmd_addresp, resp_addresp},
271         {CMD_MSGRESP_GET,       "Get response message", resp_addresp, cmd_addresp},
272         {CMD_MSGRESP_MODIFY,    "Modify response message state", cmd_modresp, NULL},
273         {CMD_MSGRESP_GET_HANDLES, "Get response message handles", NULL, resp_resphan},
274         {CMD_PGM_DESC,          "Describe program to to uploaded", cmd_desc, resp_desc},
275         {CMD_PGM_UPLOAD,        "Upload a program to the Gryphon", cmd_upload, NULL},
276         {CMD_PGM_DELETE,        "Delete an uploaded program", cmd_delete, NULL},
277         {CMD_PGM_LIST,          "Get a list of uploaded programs", cmd_list, resp_list},
278         {CMD_PGM_START,         "Start an uploaded program", cmd_start, resp_start},
279         {CMD_PGM_STOP,          "Stop an uploaded program", resp_start, NULL},
280         {CMD_PGM_STATUS,        "Get status of an uploaded program", cmd_delete, resp_status},
281         {CMD_PGM_OPTIONS,       "Set program upload options", cmd_options, resp_status},
282         {CMD_SCHED_TX,          "Schedule transmission of messages", cmd_sched, resp_sched},
283         {CMD_SCHED_KILL_TX,     "Stop and destroy a message transmission", NULL, NULL},
284         {CMD_SCHED_STOP_TX,     "Kill a message transmission (deprecated)", NULL, NULL},
285         {-1,                    "- unknown -", NULL, NULL},
286         };
287
288 static const value_string responses[] = {
289         {RESP_OK,               "OK - no error"},
290         {RESP_UNKNOWN_ERR,      "Unknown error"},
291         {RESP_UNKNOWN_CMD,      "Unrecognised command"},
292         {RESP_UNSUPPORTED,      "Unsupported command"},
293         {RESP_INVAL_CHAN,       "Invalid channel specified"},
294         {RESP_INVAL_DST,        "Invalid destination"},
295         {RESP_INVAL_PARAM,      "Invalid parameter(s)"},
296         {RESP_INVAL_MSG,        "Invalid message"},
297         {RESP_INVAL_LEN,        "Invalid length field"},
298         {RESP_TX_FAIL,          "Transmit failed"},
299         {RESP_RX_FAIL,          "Receive failed"},
300         {RESP_AUTH_FAIL,        "Authorization failed"},
301         {RESP_MEM_ALLOC_ERR,    "Memory allocation error"},
302         {RESP_TIMEOUT,          "Command timed out"},
303         {RESP_UNAVAILABLE,      "Unavailable"},
304         {RESP_BUF_FULL,         "Buffer full"},
305         {RESP_NO_SUCH_JOB,      "No such job"},
306         {-1,                    "- unknown -"},
307         };
308         
309 static const value_string filter_data_types[] = {
310         {FILTER_DATA_TYPE_HEADER_FRAME, "frame header"},
311         {FILTER_DATA_TYPE_HEADER,       "data message header"},
312         {FILTER_DATA_TYPE_DATA,         "data message data"},
313         {FILTER_DATA_TYPE_EXTRA_DATA,   "data message extra data"},
314         {-1,                            "- unknown -"},
315         };
316
317 static const value_string operators[] = {
318         {BIT_FIELD_CHECK,       "Bit field check"},
319         {SVALUE_GT,             "Greater than (signed)"},
320         {SVALUE_GE,             "Greater than or equal to (signed)"},
321         {SVALUE_LT,             "Less than (signed)"},
322         {SVALUE_LE,             "Less than or equal to (signed)"},
323         {VALUE_EQ,              "Equal to"},
324         {VALUE_NE,              "Not equal to"},
325         {UVALUE_GT,             "Greater than (unsigned)"},
326         {UVALUE_GE,             "Greater than or equal to (unsigned)"},
327         {UVALUE_LT,             "Less than (unsigned)"},
328         {UVALUE_LE,             "Less than or equal to (unsigned)"},
329         {DIG_LOW_TO_HIGH,       "Digital, low to high transistion"},
330         {DIG_HIGH_TO_LOW,       "Digital, high to low transistion"},
331         {DIG_TRANSITION,        "Digital, change of state"},
332         {-1,                    "- unknown -"},
333         };
334
335 static const value_string modes[] = {
336         {FILTER_OFF_PASS_ALL,   "Filter off, pass all messages"},
337         {FILTER_OFF_BLOCK_ALL,  "Filter off, block all messages"},
338         {FILTER_ON,             "Filter on"},
339         {-1,                    "- unknown -"},
340         };
341
342 static const value_string dmodes[] = {
343         {DEFAULT_FILTER_BLOCK,  "Block"},
344         {DEFAULT_FILTER_PASS,   "Pass"},
345         {-1,                    "- unknown -"},
346         };
347
348 static const value_string filtacts[] = {
349         {DELETE_FILTER,         "Delete"},
350         {ACTIVATE_FILTER,       "Activate"},
351         {DEACTIVATE_FILTER,     "Deactivate"},
352         {-1,                    "- unknown -"},
353         };
354
355 static const value_string ioctls[] = {
356         {GINIT,                 "GINIT: Initialize"},
357         {GLOOPON,               "GLOOPON: Loop on"},
358         {GLOOPOFF,              "GLOOPOFF: Loop off"},
359         {GGETHWTYPE,            "GGETHWTYPE: Get hardware type"},
360         {GGETREG,               "GGETREG: Get register"},
361         {GSETREG,               "GSETREG: Set register"},
362         {GGETRXCOUNT,           "GGETRXCOUNT: Get the receive message counter"},
363         {GSETRXCOUNT,           "GSETRXCOUNT: Set the receive message counter"},
364         {GGETTXCOUNT,           "GGETTXCOUNT: Get the transmit message counter"},
365         {GSETTXCOUNT,           "GSETTXCOUNT: Set the transmit message counter"},
366         {GGETRXDROP,            "GGETRXDROP: Get the number of dropped receive messages"},
367         {GSETRXDROP,            "GSETRXDROP: Set the number of dropped receive messages"},
368         {GGETTXDROP,            "GGETTXDROP: Get the number of dropped transmit messages"},
369         {GSETTXDROP,            "GSETTXDROP: Set the number of dropped transmit messages"},
370         {GGETRXBAD,             "GGETRXBAD: Get the number of bad receive messages"},
371         {GGETTXBAD,             "GGETTXBAD: Get the number of bad transmit messages"},
372         {GGETCOUNTS,            "GGETCOUNTS: Get total message counter"},
373         {GGETBLMON,             "GGETBLMON: Get bus load monitoring status"},
374         {GSETBLMON,             "GSETBLMON: Set bus load monitoring status (turn on/off)"},
375         {GGETERRLEV,            "GGETERRLEV: Get error level"},
376         {GSETERRLEV,            "GSETERRLEV: Set error level"},
377         {GGETBITRATE,           "GGETBITRATE: Get bit rate"},
378         {GGETRAM,               "GGETRAM: Read value from RAM"},
379         {GSETRAM,               "GSETRAM: Write value to RAM"},
380         {GCANGETBTRS,           "GCANGETBTRS: Read CAN bit timing registers"},
381         {GCANSETBTRS,           "GCANSETBTRS: Write CAN bit timing registers"},
382         {GCANGETBC,             "GCANGETBC: Read CAN byte count"},
383         {GCANSETBC,             "GCANSETBC: Write CAN byte count"},
384         {GCANGETMODE,           "GCANGETMODE"},
385         {GCANSETMODE,           "GCANSETMODE"},
386         {GCANGETTRANS,          "GCANGETTRANS"},
387         {GCANSETTRANS,          "GCANSETTRANS"},
388         {GCANSENDERR,           "GCANSENDERR"},
389         {GCANRGETOBJ,           "GCANRGETOBJ"},
390         {GCANRSETSTDID,         "GCANRSETSTDID"},
391         {GCANRSETEXTID,         "GCANRSETEXTID"},
392         {GCANRSETDATA,          "GCANRSETDATA"},
393         {GCANRENABLE,           "GCANRENABLE"},
394         {GCANRDISABLE,          "GCANRDISABLE"},
395         {GCANRGETMASKS,         "GCANRGETMASKS"},
396         {GCANRSETMASKS,         "GCANRSETMASKS"},
397         {GCANSWGETMODE,         "GCANSWGETMODE"},
398         {GCANSWSETMODE,         "GCANSWSETMODE"},
399         {GDLCGETFOURX,          "GDLCGETFOURX"},
400         {GDLCSETFOURX,          "GDLCSETFOURX"},
401         {GDLCGETLOAD,           "GDLCGETLOAD"},
402         {GDLCSETLOAD,           "GDLCSETLOAD"},
403         {GDLCSENDBREAK,         "GDLCSENDBREAK"},
404         {GDLCABORTTX,           "GDLCABORTTX"},
405         {GDLCGETHDRMODE,        "DLCGETHDRMODE"},
406         {GDLCSETHDRMODE,        "GDLCSETHDRMODE"},
407         {GHONSLEEP,             "GHONSLEEP"},
408         {GHONSILENCE,           "GHONSILENCE"},
409         {GKWPSETPTIMES,         "GKWPSETPTIMES"},
410         {GKWPSETWTIMES,         "GKWPSETWTIMES"},
411         {GKWPDOWAKEUP,          "GKWPDOWAKEUP"},
412         {GKWPGETBITTIME,        "GKWPGETBITTIME"},
413         {GKWPSETBITTIME,        "GKWPSETBITTIME"},
414         {GKWPSETNODEADDR,       "GKWPSETNODEADDR"},
415         {GKWPGETNODETYPE,       "GKWPGETNODETYPE"},
416         {GKWPSETNODETYPE,       "GKWPSETNODETYPE"},
417         {GKWPSETWAKETYPE,       "GKWPSETWAKETYPE"},
418         {GKWPSETTARGADDR,       "GKWPSETTARGADDR"},
419         {GKWPSETKEYBYTES,       "GKWPSETKEYBYTES"},
420         {GKWPSETSTARTREQ,       "GKWPSETSTARTREQ"},
421         {GKWPSETSTARTRESP,      "GKWPSETSTARTRESP"},
422         {GKWPSETPROTOCOL,       "GKWPSETPROTOCOL"},
423         {GKWPGETLASTKEYBYTES,   "GKWPGETLASTKEYBYTES"},
424         {GKWPSETLASTKEYBYTES,   "GKWPSETLASTKEYBYTES"},
425         {GSCPGETBBR,            "GSCPGETBBR"},
426         {GSCPSETBBR,            "GSCPSETBBR"},
427         {GSCPGETID,             "GSCPGETID"},
428         {GSCPSETID,             "GSCPSETID"},
429         {GSCPADDFUNCID,         "GSCPADDFUNCID"},
430         {GSCPCLRFUNCID,         "GSCPCLRFUNCID"},
431         {GUBPGETBITRATE,        "GUBPGETBITRATE"},
432         {GUBPSETBITRATE,        "GUBPSETBITRATE"},
433         {GUBPGETINTERBYTE,      "GUBPGETINTERBYTE"},
434         {GUBPSETINTERBYTE,      "GUBPSETINTERBYTE"},
435         {GUBPGETNACKMODE,       "GUBPGETNACKMODE"},
436         {GUBPSETNACKMODE,       "GUBPSETNACKMODE"},
437         {-1,                    "- unknown -"},
438         };
439
440
441 void
442 decode_command (int dst, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
443 {
444     int             cmd, i;
445     proto_tree      *ft;
446     proto_item      *pi;
447
448     cmd = (*data)[0];
449     proto_tree_add_item_hidden(pt, hf_gryph_cmd, *offset, 1, cmd);
450     if (cmd > 0x3F)
451         cmd += dst * 256;
452
453     for (i = 0; i < SIZEOF(cmds); i++) {
454         if (cmds[i].value == cmd)
455             break;
456     }
457     if (i >= SIZEOF(cmds) && dst >= SD_KNOWN) {
458         cmd = (cmd & 0xFF) + SD_CARD * 256;
459         for (i = 0; i < SIZEOF(cmds); i++) {
460             if (cmds[i].value == cmd)
461                 break;
462         }
463     }
464     if (i >= SIZEOF(cmds))
465         i = SIZEOF(cmds) - 1;
466
467     proto_tree_add_text (pt, *offset, 4, "Command: %s", cmds[i].strptr);
468     BUMP (*offset, *data, 4);
469
470     if (cmds[i].cmd_fnct && dataend - *data) {
471         pi = proto_tree_add_text(pt, *offset, dataend - *data, "Data: (%d bytes)", dataend - *data);
472         ft = proto_item_add_subtree(pi, ett_gryphon_command_data);
473         (*(cmds[i].cmd_fnct)) (dst, data, dataend, offset, msglen, ft);
474     }
475 }
476
477 void
478 decode_response (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
479 {
480     int             cmd, i, j, resp;
481     proto_tree      *ft;
482     proto_item      *pi;
483
484     cmd = (*data)[0];
485     if (cmd > 0x3F)
486         cmd += src * 256;
487
488     for (i = 0; i < SIZEOF(cmds); i++) {
489         if (cmds[i].value == cmd)
490             break;
491     }
492     if (i >= SIZEOF(cmds) && src >= SD_KNOWN) {
493         cmd = (cmd & 0xFF) + SD_CARD * 256;
494         for (i = 0; i < SIZEOF(cmds); i++) {
495             if (cmds[i].value == cmd)
496                 break;
497         }
498     }
499     if (i >= SIZEOF(cmds))
500         i = SIZEOF(cmds) - 1;
501     proto_tree_add_text (pt, *offset, 4, "Command: %s", cmds[i].strptr);
502     BUMP (*offset, *data, 4);
503     
504     resp = pntohl ((unsigned long *)data[0]);
505     for (j = 0; j < SIZEOF(responses); j++) {
506         if (responses[j].value == resp)
507             break;
508     }
509     if (j >= SIZEOF(responses))
510         j = SIZEOF(responses) - 1;
511     proto_tree_add_text (pt, *offset, 4, "Status: %s", responses[j].strptr);
512     BUMP (*offset, *data, 4);
513
514     if (cmds[i].rsp_fnct) {
515     pi = proto_tree_add_text(pt, *offset, dataend - *data, "Data: (%d bytes)", dataend - *data);
516     ft = proto_item_add_subtree(pi, ett_gryphon_response_data);
517         (*(cmds[i].rsp_fnct)) (src, data, dataend, offset, msglen, ft);
518     }
519 }
520
521 void
522 decode_data (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
523 {
524     proto_item  *item, *item1;
525     proto_tree  *tree, *tree1;
526     int     hdrsize, datasize, extrasize, hdrbits, msgsize, padding, mode;
527     int     hours, minutes, seconds, fraction;
528     unsigned long   timestamp;
529
530         hdrsize = (*data)[0];
531         hdrbits = (*data)[1];
532         datasize = pntohs ((unsigned short *)((*data)+2));
533         extrasize = (*data)[4];
534         padding = 3 - (hdrsize + datasize + extrasize + 3) % 4;
535         msgsize = hdrsize + datasize + extrasize + padding + 16;
536
537         item = proto_tree_add_text(pt, *offset, 16, "Message header", NULL);
538         tree = proto_item_add_subtree (item, ett_gryphon_data_header);
539         proto_tree_add_text(tree, *offset, 2, "Header length: %d bytes, %d bits", hdrsize, hdrbits);
540         proto_tree_add_text(tree, *offset+2, 2, "Data length: %d bytes", datasize);
541         proto_tree_add_text(tree, *offset+4, 1, "Extra data length: %d bytes", extrasize);
542         mode = (*data)[5];
543         item1 = proto_tree_add_text(tree, *offset+5, 1, "Mode: %hd", mode);
544         if (mode) {
545             tree1 = proto_item_add_subtree (item1, ett_gryphon_flags);
546             if (mode & 0x80)
547                 proto_tree_add_text(tree1, *offset+5, 1, "1... .... = Transmitted message", NULL);
548             if (mode & 0x40)
549                 proto_tree_add_text(tree1, *offset+5, 1, ".1.. .... = Received message", NULL);
550             if (mode & 0x20)
551                 proto_tree_add_text(tree1, *offset+5, 1, "..1. .... = Local message", NULL);
552             if (mode & 0x10)
553                 proto_tree_add_text(tree1, *offset+5, 1, "...1 .... = Remote message", NULL);
554             if (mode & 0x01)
555                 proto_tree_add_text(tree1, *offset+5, 1, ".... ...1 = Internal message", NULL);
556         }
557         proto_tree_add_text(tree, *offset+6, 1, "Priority: %d", (*data)[6]);
558         proto_tree_add_text(tree, *offset+7, 1, "Error status: %hd", (*data)[7]);
559         timestamp = pntohl ((unsigned long *)((*data)+8));
560         hours = timestamp /(100000 * 60 *60);
561         minutes = (timestamp / (100000 * 60)) % 60;
562         seconds = (timestamp / 100000) % 60;
563         fraction = timestamp % 100000;
564         proto_tree_add_text(tree, *offset+8, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction);
565         proto_tree_add_text(tree, *offset+12, 1, "Context: %hd", (*data)[12]);
566         proto_tree_add_text(tree, *offset+13, 3, "reserved:", NULL);
567         BUMP (*offset, *data, 16);
568         item = proto_tree_add_text(pt, *offset, msgsize-16-padding, "Message Body", NULL);
569         tree = proto_item_add_subtree (item, ett_gryphon_data_body);
570         if (hdrsize) {
571             proto_tree_add_text(tree, *offset, hdrsize, "Header", NULL);
572             BUMP (*offset, *data, hdrsize);
573         }
574         if (datasize) {
575             proto_tree_add_text(tree, *offset, datasize, "Data", NULL);
576             BUMP (*offset, *data, datasize);
577         }
578         if (extrasize) {
579             proto_tree_add_text(tree, *offset, extrasize, "Extra data", NULL);
580             BUMP (*offset, *data, extrasize);
581         }
582         if (padding) {
583             proto_tree_add_text(pt, *offset, padding, "padding", NULL);
584             BUMP (*offset, *data, padding);
585         }
586 }
587
588 void
589 decode_event (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
590 {
591     int             hours, minutes, seconds, fraction, padding, length;
592     unsigned long   timestamp;
593     const u_char    *msgend;
594
595     padding = 3 - (msglen + 3) % 4;
596     msgend = *data + msglen;
597     proto_tree_add_text(pt, *offset, 1, "Event ID: %hd", **data);
598     proto_tree_add_text(pt, *offset+1, 1, "Event context: %hd", *((*data)+1));
599     proto_tree_add_text(pt, *offset+2, 2, "reserved", NULL);
600     BUMP (*offset, *data, 4);
601     timestamp = pntohl ((unsigned long *)(*data));
602     hours = timestamp /(100000 * 60 *60);
603     minutes = (timestamp / (100000 * 60)) % 60;
604     seconds = (timestamp / 100000) % 60;
605     fraction = timestamp % 100000;
606     proto_tree_add_text(pt, *offset, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction);
607     BUMP (*offset, *data, 4);
608     if (*data < msgend) {
609         length = msgend - *data;
610         proto_tree_add_text (pt, *offset, length, "Data (%d bytes)", length);
611         BUMP (*offset, *data, length);
612     }
613     if (padding) {
614         proto_tree_add_text (pt, *offset, padding, "padding", NULL);
615         BUMP (*offset, *data, padding);
616     }
617 }
618
619 void
620 cmd_init (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
621 {
622     char        *ptr;
623     
624     if (*data >= dataend)
625         return;
626     if (**data == 0)
627         ptr = "Always initialize";
628     else
629         ptr = "Initialize if not previously initialized";
630     proto_tree_add_text(pt, *offset, 1, "Mode: %s", ptr);
631     proto_tree_add_text(pt, *offset+1, 3, "reserved", NULL);
632     BUMP (*offset, *data, 4);
633 }
634
635 void
636 eventnum (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
637 {
638     unsigned char   event = **data;
639     
640     if (event)
641         proto_tree_add_text(pt, *offset, 1, "Event number: %hd", event);
642     else
643         proto_tree_add_text(pt, *offset, 1, "Event numbers: All", NULL);
644     proto_tree_add_text(pt, *offset+1, 3, "padding", NULL);
645     BUMP (*offset, *data, 4);
646 }
647
648 void
649 resp_time (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
650 {
651     int     hours, minutes, seconds, fraction;
652     union {
653         unsigned int            lng[2];
654         guint64                 lnglng;
655     } ts;
656     unsigned int    timestamp;
657     unsigned char   date[45];
658    
659     ts.lng[1] = pntohl ((unsigned int *)(*data));
660     ts.lng[0] = pntohl ((unsigned int *)((*data)+4));
661     timestamp = ts.lnglng / 100000L;
662     strncpy (date, ctime((time_t*)&timestamp), sizeof(date));
663     date[strlen(date)-1] = 0x00;
664     proto_tree_add_text(pt, *offset, 8, "Date/Time: %s", date);
665     timestamp = ts.lng[0];
666     hours = timestamp /(100000 * 60 *60);
667     minutes = (timestamp / (100000 * 60)) % 60;
668     seconds = (timestamp / 100000) % 60;
669     fraction = timestamp % 100000;
670     proto_tree_add_text(pt, *offset+4, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction);
671     BUMP (*offset, *data, 8);
672 }
673
674 void
675 cmd_setfilt (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
676 {
677     int             flag = pntohl ((unsigned int *)((*data)+4));
678     int             length, padding;
679     unsigned char   mode[30];
680     
681     length =  *((*data)+4) + *((*data)+5) + pntohs ((unsigned short *)((*data)+6));
682     if (flag)
683         strcpy (mode, "Pass");
684     else
685         strcpy (mode, "Block");
686     if (length == 0)
687         strcat (mode, " all");
688     proto_tree_add_text(pt, *offset, 4, "Pass/Block flag: %s", mode);
689     proto_tree_add_text(pt, *offset+4, 4, "Length of Pattern & Mask: %d", length);
690     BUMP (*offset, *data, 8);
691     if (length) {
692         proto_tree_add_text(pt, *offset, length * 2, "discarded data", NULL);
693         BUMP (*offset, *data, length * 2);
694     }
695     padding = 3 - (length * 2 + 3) % 4;
696     if (padding) {
697         proto_tree_add_text(pt, *offset+1, 3, "padding", NULL);
698         BUMP (*offset, *data, padding);
699     }
700 }
701
702 void
703 cmd_ioctl (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
704 {
705     unsigned int    ioctl;
706     int             i;
707
708     ioctl = pntohl ((unsigned int *)(*data));
709     for (i = 0; i < SIZEOF(ioctls); i++) {
710         if (ioctls[i].value == ioctl)
711             break;
712     }
713     if (i >= SIZEOF(ioctls))
714         i = SIZEOF(ioctls) - 1;
715     proto_tree_add_text(pt, *offset, 4, "IOCTL: %s", ioctls[i].strptr);
716     BUMP (*offset, *data, 4);
717     proto_tree_add_text(pt, *offset, dataend - *data, "Data", NULL);
718     BUMP (*offset, *data, dataend - *data);
719 }
720
721 void
722 cmd_addfilt (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
723 {
724     proto_item  *item;
725     proto_tree  *tree;
726     int         blocks, i, length;
727     char        *ptr;
728     char        pass[] = ".... ...1 = Conforming messages are passed";
729     char        block[] = ".... ...0 = Conforming messages are blocked";
730     char        active[] = ".... ..1. = The filter is active";
731     char        inactive[] = ".... ..0. = The filter is inactive";
732
733     item = proto_tree_add_text(pt, *offset, 1, "Flags", NULL);
734     tree = proto_item_add_subtree (item, ett_gryphon_flags);
735     if (**data & FILTER_PASS_FLAG)
736         ptr = pass;
737     else
738         ptr = block;
739     proto_tree_add_text(tree, *offset, 1, ptr, NULL);
740     if (**data & FILTER_ACTIVE_FLAG)
741         ptr = active;
742     else
743         ptr = inactive;
744     proto_tree_add_text(tree, *offset, 1, ptr, NULL);
745     BUMP (*offset, *data, 1);
746     blocks = **data;
747     proto_tree_add_text(pt, *offset, 1, "Number of filter blocks = %d", blocks);
748     proto_tree_add_text(pt, *offset+1, 6, "reserved", NULL);
749     BUMP (*offset, *data, 7);
750     for (i = 1; i <= blocks; i++) {
751         length = pntohs ((unsigned short *)((*data)+2)) * 2 + 8;
752         length += 3 - (length + 3) % 4;
753         item = proto_tree_add_text(pt, *offset, length, "Filter block %d", i);
754         tree = proto_item_add_subtree (item, ett_gryphon_cmd_filter_block);
755         filter_block (src, data, dataend, offset, msglen, tree);
756     }
757 }
758
759 void
760 resp_addfilt (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
761 {
762     proto_tree_add_text(pt, *offset, 1, "Filter handle: %hd", **data);
763     proto_tree_add_text(pt, *offset+1, 3, "reserved", NULL);
764     BUMP (*offset, *data, 4);
765 }
766
767 void
768 cmd_modfilt (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
769 {
770     unsigned char   action;
771     int             i;
772
773     if (**data)
774         proto_tree_add_text(pt, *offset, 1, "Filter handle: %hd", **data);
775     else
776         proto_tree_add_text(pt, *offset, 1, "Filter handles: all", NULL);
777     action = *((*data) + 1);
778     for (i = 0; i < SIZEOF(filtacts); i++) {
779         if (filtacts[i].value == action)
780             break;
781     }
782     if (i >= SIZEOF(filtacts))
783         i = SIZEOF(filtacts) - 1;
784     proto_tree_add_text(pt, *offset+1, 1, "Action: %s filter", filtacts[i].strptr);
785     proto_tree_add_text(pt, *offset+2, 2, "reserved", NULL);
786     BUMP (*offset, *data, 4);
787 }
788
789 void
790 resp_filthan (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
791 {
792     int         handles = **data;
793     int         i, padding;
794     
795     proto_tree_add_text(pt, *offset, 1, "Number of filter handles: %d", handles);
796     for (i = 1; i <= handles; i++){
797         proto_tree_add_text(pt, *offset+i, 1, "Handle %d: %hd", i, *(*data+i));
798     }
799     padding = 3 - (handles + 1 + 3) % 4;
800     if (padding)
801         proto_tree_add_text(pt, *offset+1+handles, padding, "padding", NULL);
802     BUMP (*offset, *data, 1+handles+padding);
803 }
804
805 void
806 dfiltmode (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
807     int             i;
808     unsigned char   mode;
809     
810     mode = **data;
811     for (i = 0; i < SIZEOF(modes); i++) {
812         if (dmodes[i].value == mode)
813             break;
814     }
815     if (i >= SIZEOF(dmodes))
816         i = SIZEOF(dmodes) - 1;
817     proto_tree_add_text(pt, *offset, 1, "Filter mode: %s", dmodes[i].strptr);
818     proto_tree_add_text(pt, *offset+1, 3, "reserved", NULL);
819     BUMP (*offset, *data, 4);
820 }
821
822 void
823 filtmode (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
824     int             i;
825     unsigned char   mode;
826     
827     mode = **data;
828     for (i = 0; i < SIZEOF(modes); i++) {
829         if (modes[i].value == mode)
830             break;
831     }
832     if (i >= SIZEOF(modes))
833         i = SIZEOF(modes) - 1;
834     proto_tree_add_text(pt, *offset, 1, "Filter mode: %s", modes[i].strptr);
835     proto_tree_add_text(pt, *offset+1, 3, "reserved", NULL);
836     BUMP (*offset, *data, 4);
837 }
838
839 void
840 resp_events (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
841     int             i;
842     proto_tree      *tree;
843     proto_item      *item;
844     
845     i = 1;
846     while (*data < dataend) {
847         item = proto_tree_add_text(pt, *offset, 20, "Event %d:", i);
848         tree = proto_item_add_subtree (item, ett_gryphon_cmd_events_data);
849         proto_tree_add_text(tree, *offset, 1, "Event ID: %hd", **data);
850         proto_tree_add_text(tree, *offset+1, 19, "Event name: %s", (*data)+1);
851         BUMP (*offset, *data, 20);
852         i++;
853     }
854 }
855
856 void
857 cmd_register (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
858 {
859     char        string[33];
860     
861     MEMCPY (string, *data, 16);
862     proto_tree_add_text(pt, *offset, 16, "Username: %s", string);
863     BUMP (*offset, *data, 16);
864     MEMCPY (string, *data, 32);
865     proto_tree_add_text(pt, *offset, 32, "Password: %s", string);
866     BUMP (*offset, *data, 32);
867 }
868
869 void
870 resp_register (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
871     
872     proto_tree_add_text(pt, *offset, 1, "Client ID: %hd", (*data)[0]);
873     proto_tree_add_text(pt, *offset+1, 1, "Privileges: %hd", (*data)[1]);
874     proto_tree_add_text(pt, *offset+2, 2, "reserved", NULL);
875     BUMP (*offset, *data, 4);
876 }
877
878 void
879 resp_config (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
880     proto_item  *pi;
881     proto_tree  *ft;
882     char        string[33];
883     int         devices;
884     int         i, j, x;
885     
886     static const value_string protocol_types[] = {
887         {GDUMMY * 256 + GDGDMARKONE,    "Dummy device driver"},
888         {GCAN * 256 + G82527,           "CAN, 82527 subtype"},
889         {GCAN * 256 + GSJA1000,         "CAN, SJA1000 subtype"},
890         {GCAN * 256 + G82527SW,         "CAN, 82527 single wire subtype"},
891         {GJ1850 * 256 + GHBCCPAIR,      "J1850, HBCC subtype"},
892         {GJ1850 * 256 + GDLC,           "J1850, GM DLC subtype"},
893         {GJ1850 * 256 + GCHRYSLER,      "J1850, Chrysler subtype"},
894         {GJ1850 * 256 + GDEHC12,        "J1850, DE HC12 KWP/BDLC subtype"},
895         {GKWP2000,                      "Keyword protocol 2000"},
896         {GHONDA * 256 + GDGHC08,        "Honda UART, DG HC08 subtype"},
897         {GFORDUBP * 256 + GDGUBP08,     "Ford UBP, DG HC08 subtype"},
898         {-1,                            "- unknown -"},
899     };
900
901
902
903
904    MEMCPY (string, *data, 20);
905     proto_tree_add_text(pt, *offset, 20, "Device name: %s", string);
906     BUMP (*offset, *data, 20);
907
908     MEMCPY (string, *data, 8);
909     proto_tree_add_text(pt, *offset, 8, "Device version: %s", string);
910     BUMP (*offset, *data, 8);
911
912     MEMCPY (string, *data, 20);
913     proto_tree_add_text(pt, *offset, 20, "Device serial number: %s", string);
914     BUMP (*offset, *data, 20);
915
916     devices = **data;
917     proto_tree_add_text(pt, *offset, 1, "Number of channels: %d", devices);
918     proto_tree_add_text(pt, *offset+1, 15, "reserved", NULL);
919     BUMP (*offset, *data, 16);
920     for (i = 1; i <= devices; i++) {
921         pi = proto_tree_add_text(pt, *offset, 80, "Channel %d:", i);
922         ft = proto_item_add_subtree(pi, ett_gryphon_cmd_config_device);
923         MEMCPY (string, *data, 20);
924         proto_tree_add_text(ft, *offset, 20, "Driver name: %s", string);
925         BUMP (*offset, *data, 20);
926
927         MEMCPY (string, *data, 8);
928         proto_tree_add_text(ft, *offset, 8, "Driver version: %s", string);
929         BUMP (*offset, *data, 8);
930
931         MEMCPY (string, *data, 24);
932         proto_tree_add_text(ft, *offset, 24, "device security string: %s", string);
933         BUMP (*offset, *data, 24);
934
935         MEMCPY (string, *data, 20);
936         proto_tree_add_text(ft, *offset, 20, "Hardware serial number: %s", string);
937         BUMP (*offset, *data, 20);
938
939         x = pntohs ((unsigned short *)*data);
940         for (j = 0; j < SIZEOF(protocol_types); j++) {
941             if (protocol_types[j].value == x)
942                 break;
943         }
944         if (j >= SIZEOF(protocol_types))
945             j = SIZEOF(protocol_types) -1;
946         proto_tree_add_text(ft, *offset, 2, "Protocol type & subtype: %s", protocol_types[j].strptr);
947         BUMP (*offset, *data, 2);
948
949         proto_tree_add_text(ft, *offset, 1, "Channel ID: %hd", **data);
950         proto_tree_add_text(ft, *offset+1, 5, "reserved", NULL);
951         BUMP (*offset, *data, 6);
952     }
953 }
954
955 void
956 cmd_sched (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
957 {
958     proto_item      *item, *item1;
959     proto_tree      *tree, *tree1;
960     unsigned int    i, x, length;
961     unsigned char   def_chan = *((*data)-9);
962     char            *ptr;
963     char            crit[] = ".... ...1 = Critical scheduler";
964     char            norm[] = ".... ...0 = Normal scheduler";
965     
966     x = pntohl ((unsigned int *)*data);
967     if (x == 0xFFFFFFFF)
968         proto_tree_add_text(pt, *offset, 4, "Number of iterations: infinite", NULL);
969     else
970         proto_tree_add_text(pt, *offset, 4, "Number of iterations: %d", x);
971     BUMP (*offset, *data, 4);
972     x = pntohl ((unsigned int *)*data);
973     item = proto_tree_add_text(pt, *offset, 4, "Flags", NULL);
974     tree = proto_item_add_subtree (item, ett_gryphon_flags);
975     ptr = x & 1 ? crit : norm;
976     proto_tree_add_text(tree, *offset, 4, ptr, NULL);
977     BUMP (*offset, *data, 4);
978     i = 1;
979     while (*data < dataend) {
980         length = 16 + (*data)[16] + pntohs ((unsigned short *)((*data)+18)) + (*data)[20] + 16;
981         length += 3 - (length + 3) % 4;
982         item = proto_tree_add_text(pt, *offset, length, "Message %d", i);
983         tree = proto_item_add_subtree (item, ett_gryphon_cmd_sched_data);
984         x = pntohl ((unsigned int *)*data);
985         proto_tree_add_text(tree, *offset, 4, "Sleep: %d milliseconds", x);
986         BUMP (*offset, *data, 4);
987         x = pntohl ((unsigned int *)*data);
988         proto_tree_add_text(tree, *offset, 4, "Transmit count: %d", x);
989         BUMP (*offset, *data, 4);
990         x = pntohl ((unsigned int *)*data);
991         proto_tree_add_text(tree, *offset, 4, "Transmit period: %d milliseconds", x);
992         BUMP (*offset, *data, 4);
993         proto_tree_add_text(tree, *offset, 2, "reserved flags", NULL);
994         x = *((*data)+2);
995         if (x == 0)
996             x = def_chan;
997         proto_tree_add_text(tree, *offset+2, 1, "Channel: %d", x);
998         proto_tree_add_text(tree, *offset+3, 1, "reserved", NULL);
999         BUMP (*offset, *data, 4);
1000         item1 = proto_tree_add_text(tree, *offset, length, "Message", NULL);
1001         tree1 = proto_item_add_subtree (item1, ett_gryphon_cmd_sched_cmd);
1002         decode_data (src, data, dataend, offset, msglen, tree1);
1003         i++;
1004     }
1005 }
1006
1007 void
1008 resp_blm_data (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
1009 {
1010     int     hours, minutes, seconds, fraction, i, x, fract;
1011     unsigned long   timestamp;
1012     char    *fields[] = {
1013         "Bus load average: %d.%02d%%",
1014         "Current bus load: %d.%02d%%",
1015         "Peak bus load: %d.%02d%%",
1016         "Historic peak bus load: %d.%02d%%"
1017     };
1018
1019     timestamp = pntohl ((unsigned long *)(*data));
1020     hours = timestamp /(100000 * 60 *60);
1021     minutes = (timestamp / (100000 * 60)) % 60;
1022     seconds = (timestamp / 100000) % 60;
1023     fraction = timestamp % 100000;
1024     proto_tree_add_text(pt, *offset, 4, "Timestamp: %d:%02d:%02d.%05d", hours, minutes, seconds, fraction);
1025     BUMP (*offset, *data, 4);
1026     for (i = 0; i < SIZEOF(fields); i++){
1027         x = pntohs ((unsigned short *)(*data));
1028         fract = x % 100;
1029         x /= 100;
1030         proto_tree_add_text(pt, *offset, 2, fields[i], x, fract);
1031         BUMP (*offset, *data, 2);
1032     }
1033 }
1034
1035 void
1036 resp_blm_stat (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
1037 {
1038     unsigned int    x, i;
1039     char            *fields[] = {
1040         "Receive frame count: %d",
1041         "Transmit frame count: %d",
1042         "Receive dropped frame count: %d",
1043         "Transmit dropped frame count: %d",
1044         "Receive error count: %d",
1045         "Transmit error count: %d",
1046     };
1047
1048     resp_blm_data (src, data, dataend, offset, msglen, pt);
1049     for (i = 0; i < SIZEOF(fields); i++){
1050         x = pntohl ((unsigned int *)(*data));
1051         proto_tree_add_text(pt, *offset, 4, fields[i], x);
1052         BUMP (*offset, *data, 4);
1053     }
1054 }
1055
1056 void
1057 cmd_addresp (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
1058 {
1059     proto_item  *item;
1060     proto_tree  *tree;
1061     int         blocks, responses, old_handle, i, length;
1062     int         action, actionType, actionValue;
1063     char        *ptr;
1064     char        active[] = ".... ..1. = The response is active";
1065     char        inactive[] = ".... ..0. = The response is inactive";
1066
1067     actionType = 0;
1068     item = proto_tree_add_text(pt, *offset, 1, "Flags", NULL);
1069     tree = proto_item_add_subtree (item, ett_gryphon_flags);
1070     if (**data & FILTER_ACTIVE_FLAG)
1071         ptr = active;
1072     else
1073         ptr = inactive;
1074     proto_tree_add_text(tree, *offset, 1, ptr, NULL);
1075     BUMP (*offset, *data, 1);
1076     blocks = **data;
1077     proto_tree_add_text(pt, *offset, 1, "Number of filter blocks = %d", blocks);
1078     BUMP (*offset, *data, 1);
1079     responses = **data;
1080     proto_tree_add_text(pt, *offset, 1, "Number of response blocks = %d", responses);
1081     BUMP (*offset, *data, 1);
1082     old_handle = **data;
1083     proto_tree_add_text(pt, *offset, 1, "Old handle = %d", old_handle);
1084     BUMP (*offset, *data, 1);
1085     action = **data;
1086     switch (action & 7) {
1087     case FR_RESP_AFTER_EVENT:
1088         ptr = "Send response(s) for each conforming message";
1089         break;
1090     case FR_RESP_AFTER_PERIOD:
1091         ptr = "Send response(s) after the specified period expires following a conforming message";
1092         break;
1093     case FR_IGNORE_DURING_PER:
1094         ptr = "Send response(s) for a conforming message and ignore\nfurther messages until the specified period expires";
1095         break;
1096     default:
1097         ptr = "- unknown -";
1098     }
1099     item = proto_tree_add_text(pt, *offset, 1, "Action = %s", ptr);
1100     tree = proto_item_add_subtree (item, ett_gryphon_flags);
1101     if (action & FR_DEACT_AFTER_PER && !(action & FR_DELETE)){
1102         proto_tree_add_text(tree, *offset, 1,
1103                 "1.0. .... Deactivate this response after the specified period following a conforming message", NULL);
1104     }
1105     if (action & FR_DEACT_ON_EVENT && !(action & FR_DELETE)){
1106         proto_tree_add_text(tree, *offset, 1,
1107                 ".10. .... Deactivate this response for a conforming message", NULL);
1108     }
1109     if (action & FR_DEACT_AFTER_PER && action & FR_DELETE){
1110         proto_tree_add_text(tree, *offset, 1,
1111                 "1.1. .... Delete this response after the specified period following a conforming message", NULL);
1112     }
1113     if (action & FR_DEACT_ON_EVENT && action & FR_DELETE){
1114         proto_tree_add_text(tree, *offset, 1,
1115                 ".11. .... Delete this response for a conforming message", NULL);
1116     }
1117     actionValue = pntohs ((unsigned short *)((*data)+2));
1118     if (actionValue) {
1119         if (action & FR_PERIOD_MSGS){
1120             ptr = "...1 .... The period is in frames";
1121             actionType = 1;
1122         } else {
1123             ptr = "...0 .... The period is in 0.01 seconds";
1124             actionType = 0;
1125         }
1126         proto_tree_add_text(tree, *offset, 1, ptr, NULL);
1127     }
1128     BUMP (*offset, *data, 1);
1129     proto_tree_add_text(pt, *offset, 1, "reserved", NULL);
1130     BUMP (*offset, *data, 1);
1131     if (actionValue) {
1132         if (actionType == 1) {
1133             proto_tree_add_text(tree, *offset, 2, "Period: %d messages", actionValue);
1134         } else {
1135             proto_tree_add_text(tree, *offset, 2, "Period: %d.%02d seconds", actionValue/100, actionValue%100);
1136         }
1137     }
1138     BUMP (*offset, *data, 2);
1139     for (i = 1; i <= blocks; i++) {
1140         length = pntohs ((unsigned short *)((*data)+2)) * 2 + 8;
1141         length += 3 - (length + 3) % 4;
1142         item = proto_tree_add_text(pt, *offset, length, "Filter block %d", i);
1143         tree = proto_item_add_subtree (item, ett_gryphon_cmd_filter_block);
1144         filter_block (src, data, dataend, offset, msglen, tree);
1145     }
1146     for (i = 1; i <= responses; i++) {
1147         length = pntohs ((unsigned short *)((*data)+4)) + 8;
1148         length += 3 - (length + 3) % 4;
1149         item = proto_tree_add_text(pt, *offset, length, "Response block %d", i);
1150         tree = proto_item_add_subtree (item, ett_gryphon_cmd_response_block);
1151         dissector((*data)-*offset, *offset, NULL, tree);
1152         BUMP (*offset, *data, length);
1153     }
1154 }
1155
1156 void
1157 resp_addresp (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
1158 {
1159     if (*data < dataend) {
1160         proto_tree_add_text(pt, *offset, 1, "Response handle: %hd", **data);
1161         proto_tree_add_text(pt, *offset+1, 3, "reserved", NULL);
1162         BUMP (*offset, *data, 4);
1163     }
1164 }
1165
1166 void
1167 cmd_modresp (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
1168 {
1169     unsigned char   action;
1170     unsigned char   dest = *((*data)-5);
1171     int             i;
1172
1173     if (**data)
1174         proto_tree_add_text(pt, *offset, 1, "Response handle: %hd", **data);
1175     else if (dest)
1176         proto_tree_add_text(pt, *offset, 1, "Response handles: all on channel %hd", dest);
1177     else
1178         proto_tree_add_text(pt, *offset, 1, "Response handles: all", NULL);
1179     action = *((*data) + 1);
1180     for (i = 0; i < SIZEOF(filtacts); i++) {
1181         if (filtacts[i].value == action)
1182             break;
1183     }
1184     if (i >= SIZEOF(filtacts))
1185         i = SIZEOF(filtacts) - 1;
1186     proto_tree_add_text(pt, *offset+1, 1, "Action: %s response", filtacts[i].strptr);
1187     proto_tree_add_text(pt, *offset+2, 2, "reserved", NULL);
1188     BUMP (*offset, *data, 4);
1189 }
1190
1191 void
1192 resp_resphan (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
1193 {
1194     int         handles = **data;
1195     int         i, padding;
1196     
1197     proto_tree_add_text(pt, *offset, 1, "Number of response handles: %d", handles);
1198     for (i = 1; i <= handles; i++){
1199         proto_tree_add_text(pt, *offset+i, 1, "Handle %d: %hd", i, *(*data+i));
1200     }
1201     padding = 3 - (handles + 1 + 3) % 4;
1202     if (padding)
1203         proto_tree_add_text(pt, *offset+1+handles, padding, "padding", NULL);
1204     BUMP (*offset, *data, 1+handles+padding);
1205 }
1206
1207 void
1208 resp_sched (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
1209 {
1210     unsigned int    id = pntohl ((unsigned int *)(*data));
1211     proto_tree_add_text(pt, *offset, 4, "Transmit schedule ID: %d", id);
1212     BUMP (*offset, *data, 4);
1213 }
1214
1215 void
1216 cmd_desc (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
1217 {
1218     u_char  string[81];
1219     
1220     proto_tree_add_text(pt, *offset, 4, "Program size: %d bytes", pntohl ((unsigned int *)(*data)));
1221     BUMP (*offset, *data, 4);
1222     strncpy (string, *data, 32);
1223     string[32] = 0;
1224     proto_tree_add_text(pt, *offset, 32, "Program name: %s", string);
1225     BUMP (*offset, *data, 32);
1226     strncpy (string, *data, 80);
1227     string[80] = 0;
1228     proto_tree_add_text(pt, *offset, 80, "Program description: %s", string);
1229     BUMP (*offset, *data, 80);
1230 }
1231
1232 void
1233 resp_desc (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt)
1234 {
1235     proto_item  *item;
1236     proto_tree  *tree;
1237     char        *ptr;
1238     char        missing[] = ".... ...0 = The program is not present";
1239     char        present[] = ".... ...1 = The program is already present";
1240     
1241     item = proto_tree_add_text(pt, *offset, 1, "Flags", NULL);
1242     tree = proto_item_add_subtree (item, ett_gryphon_flags);
1243     if (**data & 1)
1244         ptr = present;
1245     else
1246         ptr = missing;
1247     proto_tree_add_text(tree, *offset, 1, ptr, NULL);
1248     proto_tree_add_text(pt, *offset+1, 1, "Handle: %hd", (*data)[1]);
1249     proto_tree_add_text(pt, *offset+2, 2, "reserved", NULL);
1250     BUMP (*offset, *data, 4);
1251 }
1252
1253 void
1254 cmd_upload (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
1255     unsigned int    length;
1256     
1257     proto_tree_add_text(pt, *offset, 2, "Block number: %d", pntohs ((unsigned short *)(*data)));
1258     BUMP (*offset, *data, 4);
1259     proto_tree_add_text(pt, *offset+2, 1, "Handle: %hd", (*data)[2]);
1260     BUMP (*offset, *data, 3);
1261     length = *data - dataend;
1262     proto_tree_add_text(pt, *offset, length, "Data (%d bytes)", length);
1263     BUMP (*offset, *data, length);
1264     length = 3 - (length + 3) % 4;
1265     if (length) {
1266         proto_tree_add_text(pt, *offset, length, "padding", NULL);
1267         BUMP (*offset, *data, length);
1268     }
1269 }
1270
1271 void
1272 cmd_delete (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
1273     u_char  string[33];
1274     
1275     strncpy (string, *data, 32);
1276     string[32] = 0;
1277     proto_tree_add_text(pt, *offset, 32, "Program name: %s", string);
1278     BUMP (*offset, *data, 32);
1279 }
1280
1281 void
1282 cmd_list (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
1283     
1284     proto_tree_add_text(pt, *offset, 1, "Block number: %hd", (*data)[0]);
1285     proto_tree_add_text(pt, *offset+1, 3, "reserved", NULL);
1286     BUMP (*offset, *data, 4);
1287 }
1288
1289 void
1290 resp_list (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
1291     proto_item  *item;
1292     proto_tree  *tree;
1293     u_char  string[81];
1294     unsigned int    i, count;
1295     
1296     count = (*data)[0];
1297     proto_tree_add_text(pt, *offset, 1, "Number of programs in this response: %d", count);
1298     proto_tree_add_text(pt, *offset+1, 1, "reserved", NULL);
1299     BUMP (*offset, *data, 2);
1300     proto_tree_add_text(pt, *offset, 2, "Number of remaining programs: %d", pntohs ((unsigned short *)(*data)));
1301     BUMP (*offset, *data, 2);
1302     for (i = 1; i <= count; i++) {
1303         item = proto_tree_add_text(pt, *offset, 112, "Program %d", i);
1304         tree = proto_item_add_subtree (item, ett_gryphon_pgm_list);
1305         strncpy (string, *data, 32);
1306         string[32] = 0;
1307         proto_tree_add_text(tree, *offset, 32, "Name: %s", string);
1308         BUMP (*offset, *data, 32);
1309         strncpy (string, *data, 80);
1310         string[80] = 0;
1311         proto_tree_add_text(tree, *offset, 80, "Description: %s", string);
1312         BUMP (*offset, *data, 80);
1313     }
1314 }
1315
1316 void
1317 cmd_start (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
1318     u_char          string[120];
1319     unsigned int    length;
1320     
1321     cmd_delete (src, data, dataend, offset, msglen, pt);
1322     strncpy (string, *data, 119);
1323     string[119] = 0;
1324     length = strlen (string) + 1;
1325     proto_tree_add_text(pt, *offset, length, "Arguments: %s", string);
1326     BUMP (*offset, *data, length);
1327     length = 3 - (length + 3) % 4;
1328     if (length) {
1329         proto_tree_add_text(pt, *offset, length, "padding", NULL);
1330         BUMP (*offset, *data, length);
1331     }
1332 }
1333
1334 void
1335 resp_start (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
1336     
1337     proto_tree_add_text(pt, *offset, 1, "Channel (Client) number: %hd", (*data)[0]);
1338     proto_tree_add_text(pt, *offset+1, 3, "reserved", NULL);
1339     BUMP (*offset, *data, 4);
1340 }
1341
1342 void
1343 resp_status (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
1344     proto_item  *item;
1345     proto_tree  *tree;
1346     unsigned int    i, copies, length;
1347     
1348     copies = (*data)[0];
1349     item = proto_tree_add_text(pt, *offset, 1, "Number of running copies: %d", copies);
1350     tree = proto_item_add_subtree (item, ett_gryphon_pgm_status);
1351     BUMP (*offset, *data, 1);
1352     if (copies) {
1353         for (i = 1; i <= copies; i++) {
1354             proto_tree_add_text(tree, *offset, 1, "Program %d channel (client) number %hd", i, (*data)[0]);
1355             BUMP (*offset, *data, 1);
1356         }
1357     }
1358     length = 3 - (copies + 1 + 3) % 4;
1359     if (length) {
1360         proto_tree_add_text(pt, *offset, length, "padding", NULL);
1361         BUMP (*offset, *data, length);
1362     }
1363 }
1364
1365 void
1366 cmd_options (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
1367     proto_item  *item;
1368     proto_tree  *tree;
1369     unsigned int    i, size, padding, option, option_length, option_value;
1370     unsigned char   *string, *string1;
1371     
1372     item = proto_tree_add_text(pt, *offset, 1, "Handle: %hd", **data);
1373     item = proto_tree_add_text(pt, *offset+1, 3, "reserved", NULL);
1374     BUMP (*offset, *data, 4);
1375     for (i = 1; *data <= dataend; i++) {
1376         size = (*data)[1] + 2;
1377         padding = 3 - ((size + 3) %4);
1378         item = proto_tree_add_text(pt, *offset, size + padding, "Option number %d", i);
1379         tree = proto_item_add_subtree (item, ett_gryphon_pgm_options);
1380         option = **data;
1381         option_length = (*data)[1];
1382         switch (option_length) {
1383         case 1:
1384             option_value = (*data)[2];
1385             break;
1386         case 2:
1387             option_value = pntohs ((unsigned short *)((*data)+2));
1388             break;
1389         case 4:
1390             option_value = pntohl ((unsigned int *)((*data)+2));
1391             break;
1392         default:
1393             option_value = 0;
1394         }
1395         string = "unknown option";
1396         string1 = "unknown option data";
1397         switch (option) {
1398         case PGM_CONV:
1399             string = "Type of data in the file";
1400             switch (option_value) {
1401             case PGM_BIN:
1402                 string1 = "Binary - Don't modify";
1403                 break;
1404             case PGM_ASCII:
1405                 string1 = "ASCII - Remove CR's";
1406                 break;
1407             }
1408             break;
1409         case PGM_TYPE:
1410             string = "Type of file";
1411             switch (option_value) {
1412             case PGM_PGM:
1413                 string1 = "Executable";
1414                 break;
1415             case PGM_DATA:
1416                 string1 = "Data";
1417                 break;
1418             }
1419             break;
1420         }
1421         proto_tree_add_text(tree, *offset, 1, "%s", string);
1422         proto_tree_add_text(tree, *offset+2, option_length, "%s", string1);
1423         if (padding)
1424             proto_tree_add_text(tree, *offset+option_length+2, padding, "padding", NULL);
1425         BUMP (*offset, *data, size + padding);
1426     }
1427 }
1428
1429 void
1430 speed (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
1431     
1432     proto_tree_add_text(pt, *offset, 1, "Baud rate index: %hd", (*data)[0]);
1433     proto_tree_add_text(pt, *offset+1, 3, "reserved", NULL);
1434     BUMP (*offset, *data, 4);
1435 }
1436
1437 void
1438 filter_block (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
1439     int     length, type, i, operator, padding;
1440     
1441     proto_tree_add_text(pt, *offset, 2, "Filter field starts at byte %d", pntohs ((unsigned short *)(*data)));
1442     length = pntohs ((unsigned short *)((*data)+2));
1443     proto_tree_add_text(pt, *offset+2, 2, "Filter field is %d bytes long", length);
1444     type = *((*data)+4);
1445     for (i = 0; i < SIZEOF(filter_data_types); i++) {
1446         if (filter_data_types[i].value == type)
1447             break;
1448     }
1449     if (i >= SIZEOF(filter_data_types))
1450         i = SIZEOF(filter_data_types) - 1;
1451     proto_tree_add_text(pt, *offset+4, 1, "Filtering on %s", filter_data_types[i].strptr);
1452
1453     operator = *((*data)+5);
1454     for (i = 0; i < SIZEOF(operators); i++) {
1455         if (operators[i].value == operator)
1456             break;
1457     }
1458     if (i >= SIZEOF(operators))
1459         i = SIZEOF(operators) - 1;
1460     proto_tree_add_text(pt, *offset+5, 1, "Type of comparison: %s", operators[i].strptr);
1461     proto_tree_add_text(pt, *offset+6, 2, "reserved" ,NULL);
1462     BUMP (*offset, *data, 8);
1463     
1464     if (operator == BIT_FIELD_CHECK) {
1465         proto_tree_add_text(pt, *offset, length, "Pattern" ,NULL);
1466         proto_tree_add_text(pt, *offset+length, length, "Mask" ,NULL);
1467     } else {
1468         switch (length) {
1469         case 1:
1470             proto_tree_add_text(pt, *offset, 1, "Value: %hd", **data);
1471             break;
1472         case 2:
1473             proto_tree_add_text(pt, *offset, 2, "Value: %d", pntohs ((unsigned short *)(*data)));
1474             break;
1475         case 4:
1476             proto_tree_add_text(pt, *offset, 4, "Value: %dl", pntohl ((unsigned long *)(*data)));
1477             break;
1478         default:
1479             proto_tree_add_text(pt, *offset, length, "Value", NULL);
1480         }
1481     }
1482     BUMP (*offset, *data, length * 2);
1483     padding = 3 - (length * 2 + 3) % 4;
1484     if (padding) {
1485         proto_tree_add_text(pt, *offset, padding, "padding", NULL);
1486         BUMP (*offset, *data, padding);
1487     }
1488 }
1489
1490 void
1491 blm_mode (int src, const u_char **data, const u_char *dataend, int *offset, int msglen, proto_tree *pt) {
1492     
1493     char    *mode, line[50];
1494     int     x, y, seconds;
1495     
1496     x = pntohl ((unsigned long *)(*data));
1497     y = pntohl ((unsigned long *)((*data)+4));
1498     switch (x) {
1499     case 0:
1500         mode = "Off";
1501         sprintf (line, "reserved");
1502         break;
1503     case 1:
1504         mode = "Average over time";
1505         seconds = y / 1000;
1506         y = y % 1000;
1507         sprintf (line, "Averaging period: %d.%03d seconds", seconds, y);
1508         break;
1509     case 2:
1510         mode = "Average over frame count";
1511         sprintf (line, "Averaging period: %d frames", y);
1512         break;
1513     default:
1514         mode = "- unknown -";
1515         sprintf (line, "reserved");
1516     }
1517     proto_tree_add_text(pt, *offset, 4, "Mode: %s", mode);
1518     BUMP (*offset, *data, 4);
1519     proto_tree_add_text(pt, *offset, 4, line, NULL);
1520     BUMP (*offset, *data, 4);
1521 }
1522
1523 DLLEXPORT void
1524 plugin_init(plugin_address_table_t *pat)
1525 {
1526     static hf_register_info hf[] = {
1527         { &hf_gryph_src,
1528         { "Source",           "gryph.src", FT_UINT8, BASE_DEC, NULL, 0x0,
1529                 "" }},
1530         { &hf_gryph_srcchan,
1531         { "Source channel",   "gryph.srcchan", FT_UINT8, BASE_DEC, NULL, 0x0,
1532                 "" }},
1533         { &hf_gryph_dest,
1534         { "Destination",      "gryph.dest", FT_UINT8, BASE_DEC, NULL, 0x0,
1535                 "" }},
1536         { &hf_gryph_destchan,
1537         { "Destination channel", "gryph.dstchan", FT_UINT8, BASE_DEC, NULL, 0x0,
1538                 "" }},
1539         { &hf_gryph_type,
1540         { "Frame type",       "gryph.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1541                 "" }},
1542         { &hf_gryph_cmd,
1543         { "Command",          "gryph.cmd.cmd", FT_UINT8, BASE_DEC, NULL, 0x0,
1544                 "" }},
1545     };
1546
1547     static gint *ett[] = {
1548         &ett_gryphon,
1549         &ett_gryphon_header,
1550         &ett_gryphon_body,
1551         &ett_gryphon_command_data,
1552         &ett_gryphon_response_data,
1553         &ett_gryphon_data_header,
1554         &ett_gryphon_flags,
1555         &ett_gryphon_data_body,
1556         &ett_gryphon_cmd_filter_block,
1557         &ett_gryphon_cmd_events_data,
1558         &ett_gryphon_cmd_config_device,
1559         &ett_gryphon_cmd_sched_data,
1560         &ett_gryphon_cmd_sched_cmd,
1561         &ett_gryphon_cmd_response_block,
1562         &ett_gryphon_pgm_list,
1563         &ett_gryphon_pgm_status,
1564         &ett_gryphon_pgm_options,
1565     };
1566     plugin_address_table_init(pat);
1567     dfilter_cleanup();
1568     proto_gryphon = proto_register_protocol("DG Gryphon Protocol", "gryphon");
1569     proto_register_field_array(proto_gryphon, hf, array_length(hf));
1570     proto_register_subtree_array(ett, array_length(ett));
1571     dfilter_init();
1572 }