HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-elcom.c
blobe0abe27635766da0e95c749728a5365b9a05432e
1 /* packet-elcom.c
2 * Routines for elcom packet dissection
3 * Copyright 2008, 2011 juha.takala@iki.fi (Juha Takala)
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-imap.c
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * I found the protocol specification at
28 * http://www.sintef.no/upload/Energiforskning/Energisystemer/ELCOM%2090.pdf
31 #include "config.h"
33 #include <epan/packet.h>
35 #define TCP_PORT_ELCOM 5997
37 /* Application level: */
38 #define A_CONRQ 0x04
39 #define A_CONRS 0x05
41 /* Presentation level: */
42 #define P_CONRQ 0x00
43 #define P_CONRS 0x10
44 #define P_RELRQ 0x20
45 #define P_RELRS 0x30
46 #define P_DATRQ 0x80
48 #define TC_REQ 0x40
49 #define TC_RSP 0x41
51 #define LOWADR_LEN 17
52 #define SUFFIX_LEN 2
53 #define TOTAL_LEN (LOWADR_LEN + SUFFIX_LEN + 2)
55 #define ELCOM_UNKNOWN_ENDIAN 0
56 #define ELCOM_LITTLE_ENDIAN 1
57 #define ELCOM_BIG_ENDIAN 2
59 void proto_register_elcom(void);
60 void proto_reg_handoff_elcom(void);
62 static int proto_elcom = -1;
63 static int hf_elcom_response = -1;
64 static int hf_elcom_request = -1;
66 static int hf_elcom_length = -1;
67 static int hf_elcom_type = -1;
69 static int hf_elcom_initiator = -1;
70 static int hf_elcom_initiator_endian = -1;
71 static int hf_elcom_initiator_ip = -1;
72 static int hf_elcom_initiator_port = -1;
73 static int hf_elcom_initiator_suff = -1;
75 static int hf_elcom_responder = -1;
76 static int hf_elcom_responder_endian = -1;
77 static int hf_elcom_responder_ip = -1;
78 static int hf_elcom_responder_port = -1;
79 static int hf_elcom_responder_suff = -1;
81 static int hf_elcom_userdata = -1;
82 static int hf_elcom_userdata_length = -1;
83 static int hf_elcom_userdata_pduid = -1;
84 static int hf_elcom_userdata_version = -1;
85 static int hf_elcom_userdata_result = -1;
86 static int hf_elcom_userdata_restmark = -1;
87 static int hf_elcom_userdata_cf = -1;
89 static int hf_elcom_datarequest = -1;
90 static int hf_elcom_datarequest_grouptype = -1;
91 static int hf_elcom_datarequest_result = -1;
92 static int hf_elcom_datarequest_groupnumber = -1;
93 static int hf_elcom_datarequest_grouppriority = -1;
94 static int hf_elcom_datarequest_groupsize = -1;
95 static int hf_elcom_datarequest_groupindex1 = -1;
96 static int hf_elcom_datarequest_groupindex2 = -1;
97 static int hf_elcom_datarequest_oid = -1;
99 static int hf_elcom_release_reason = -1;
100 static int hf_elcom_release_result = -1;
102 static int hf_elcom_strangeleftover = -1;
104 static gint ett_elcom = -1;
105 static gint ett_elcom_initiator = -1;
106 static gint ett_elcom_responder = -1;
107 static gint ett_elcom_userdata = -1;
108 static gint ett_elcom_datarequest = -1;
110 static gboolean elcom_show_hex = TRUE;
112 static const value_string endian_vals[] = {
113 {0x0002, "Big"},
114 {0x0200, "Little"},
115 {0, NULL }
118 static const value_string suffix_vals[] = {
119 {'A', "Control"},
120 {'B', "Unsolicited"},
121 {'C', "Periodic"},
122 {'D', "Requested, scheduling"},
123 {'E', "Requested, present/archived"},
124 {'G', "Supervisory"},
125 {'F', "Test"},
126 {0, NULL }
129 static const value_string userdata_pduid_vals[] = {
130 {0x04, "Connect Request"},
131 {0x05, "Connect Response"},
132 {0, NULL }
135 static const value_string userdata_version_vals[] = {
136 {0x00, "Class 0, v0"},
137 {0x01, "Class 1, v0"},
138 {0x02, "Class 2, v0"},
139 {0x12, "Class 2, v1"},
140 {0x13, "Class 3, v1"},
141 {0, NULL }
144 static const value_string userdata_result_vals[] = {
145 {0x00, "OK"},
146 {0, NULL }
149 static const value_string datarequest_grouptype_vals[] = {
150 {TC_REQ, "Test Connection Request"},
151 {TC_RSP, "Test Connection Response"},
152 {0, NULL }
155 static const value_string datarequest_result_vals[] = {
156 {0x00, "OK"},
157 {0, NULL }
160 static const value_string type_vals[] = {
161 {P_CONRQ, "Connect Request"},
162 {P_CONRS, "Connect Response"},
163 {P_RELRQ, "Release Request"},
164 {P_RELRS, "Release Response"},
165 {P_DATRQ, "Data Request"},
166 {0, NULL }
169 static gint
170 dissect_lower_address(proto_item *ti_arg, gint ett_arg,
171 tvbuff_t *tvb, gint arg_offset,
172 int hf_endian, int hf_ip, int hf_port, int hf_suff)
174 gint offset = arg_offset;
175 guint8 len1, len2;
176 guint8 *suffix;
177 proto_tree *tree;
178 proto_item *ti;
180 tree = proto_item_add_subtree(ti_arg, ett_arg);
183 * Coding of address:
184 * ELCOM-90 TRA3825.02 User Element conventions, p. 5-2 and Appendix G
186 len1 = tvb_get_guint8(tvb, offset);
187 if (tvb_length_remaining(tvb, offset+len1+1) <= 0)
188 return offset;
189 len2 = tvb_get_guint8(tvb, offset+len1+1);
190 if (tvb_length_remaining(tvb, offset+len1+len2+2) <= 0)
191 return offset;
192 if ((len1 != LOWADR_LEN) || (len2 != SUFFIX_LEN)) {
193 proto_item_append_text(tree, " Invalid structure");
194 return offset;
198 /* Show pre stuff */
199 if (0x82 != tvb_get_guint8(tvb, offset+1)) {
200 proto_item_append_text(tree, " Not IPV4 address");
201 return offset;
203 offset += 2;
206 /* endian */
207 proto_tree_add_item(tree, hf_endian, tvb, offset, 2, ENC_BIG_ENDIAN);
208 offset += 2;
210 /* port */
211 proto_tree_add_item(tree, hf_port, tvb, offset, 2, ENC_BIG_ENDIAN);
212 offset += 2;
214 /* ip-addr */
215 proto_tree_add_item(tree, hf_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
216 offset += 4;
218 offset += 8; /* skip the zero bytes */
220 /* SUFFIX */
221 suffix = tvb_get_string(wmem_packet_scope(), tvb, offset+1, len2);
222 ti = proto_tree_add_item(tree, hf_suff, tvb, offset, 1, ENC_ASCII|ENC_LITTLE_ENDIAN);
223 offset += len2+1;
225 if (!(suffix[0] == 'A' || suffix[0] == 'B')) {
226 proto_item_append_text(ti, " (invalid)");
227 return offset;
230 proto_item_append_text(ti, " (%s)", val_to_str_const(suffix[1], suffix_vals, "<<-- WHAT?") );
231 return offset;
234 static gint
235 dissect_userdata(proto_item *ti_arg, gint ett_arg, tvbuff_t *tvb, gint arg_offset)
237 gint offset = arg_offset;
238 guint8 flen, lenbytes;
239 guint8 year, month, day, hour, min, sec;
240 guint16 msec;
241 proto_tree *tree;
242 proto_item *ti;
244 tree = proto_item_add_subtree(ti_arg, ett_arg);
246 /* length of User Data, should be 1 byte field ... */
247 flen = tvb_get_guint8(tvb, offset);
248 lenbytes = 1;
250 /* ... but sometimes it seems to be 2 bytes; try to be clever */
251 if (flen == 0) {
252 flen = tvb_get_guint8(tvb, offset+1);
253 lenbytes = 2;
255 if (flen == 0 || flen > 79) /* invalid */
256 return offset;
258 ti = proto_tree_add_item(tree, hf_elcom_userdata_length, tvb, offset, lenbytes, ENC_BIG_ENDIAN);
259 offset += lenbytes;
260 if (lenbytes == 2) {
261 proto_item_append_text(ti, " (2 bytes, should be 1 byte)");
264 if (tvb_length_remaining(tvb, offset) <= 0)
265 return offset;
267 proto_tree_add_item(tree, hf_elcom_userdata_pduid, tvb, offset, 1, ENC_BIG_ENDIAN);
268 offset++;
270 if (tvb_length_remaining(tvb, offset) <= 0)
271 return offset;
273 proto_tree_add_item(tree, hf_elcom_userdata_version, tvb, offset, 1, ENC_BIG_ENDIAN);
274 offset++;
277 if (tvb_length_remaining(tvb, offset) <= 0)
278 return offset;
280 proto_tree_add_item(tree, hf_elcom_userdata_result, tvb, offset, 1, ENC_BIG_ENDIAN);
281 offset++;
283 /* show the rest */
284 /* tree2 = proto_tree_add_text(tree, tvb, offset, -1, "User Data"); */
286 if (tvb_length_remaining(tvb, offset) <= 0)
287 return offset;
288 ti = proto_tree_add_item(tree, hf_elcom_userdata_restmark, tvb, offset, 1, ENC_BIG_ENDIAN);
289 proto_item_append_text(ti, " <-- '0' = no restart etc.");
290 offset +=1;
292 if (tvb_length_remaining(tvb, offset+8) <= 0)
293 return offset;
294 year = tvb_get_guint8(tvb, offset);
295 month = tvb_get_guint8(tvb, offset+1);
296 day = tvb_get_guint8(tvb, offset+2);
297 hour = tvb_get_guint8(tvb, offset+3);
298 min = tvb_get_guint8(tvb, offset+4);
299 sec = tvb_get_guint8(tvb, offset+5);
300 msec = tvb_get_ntohs(tvb, offset+6);
302 proto_tree_add_none_format(tree, hf_elcom_userdata_cf, tvb, offset, 8,
303 "Control Field: %4d-%02d-%02d %02d:%02d:%02d.%d",
304 year+1900, month, day, hour, min, sec, msec);
306 offset += 12;
307 if (tvb_length_remaining(tvb, offset+12) > 0) {
308 proto_item_append_text(ti, " Security info: ");
310 /* security info field, if present */
311 while (tvb_length_remaining(tvb, offset) > 0) {
312 proto_item_append_text(ti, elcom_show_hex ? " %02x" : " %03o",
313 tvb_get_guint8(tvb, offset));
314 offset++;
317 return offset;
320 static gint
321 dissect_datarequest(proto_item *ti_arg, gint ett_arg, tvbuff_t *tvb, gint arg_offset)
323 gint offset = arg_offset;
324 guint8 gtype, oidlen;
325 proto_tree *tree, *tree2;
326 proto_item *ti;
328 tree = proto_item_add_subtree(ti_arg, ett_arg);
329 if (tvb_length_remaining(tvb, offset) <= 0)
330 return offset;
332 gtype = tvb_get_guint8(tvb, offset);
333 ti = proto_tree_add_item(tree, hf_elcom_datarequest_grouptype,
334 tvb, offset, 1, ENC_BIG_ENDIAN);
335 offset += 1;
337 switch (gtype) {
339 case TC_REQ:
340 /* No more data for this type, suppress the error message */
341 break;
343 case TC_RSP:
345 proto_tree_add_item(tree, hf_elcom_datarequest_result,
346 tvb, offset, 1, ENC_BIG_ENDIAN);
347 offset++;
349 break;
351 default:
352 proto_item_append_text(ti, " <<--- meaning WHAT?");
353 return offset;
355 if (tvb_length_remaining(tvb, offset) <= 0)
356 return offset;
358 proto_tree_add_item(tree, hf_elcom_datarequest_groupnumber, tvb, offset, 1, ENC_BIG_ENDIAN);
359 offset += 1;
360 if (tvb_length_remaining(tvb, offset) <= 0)
361 return offset;
363 proto_tree_add_item(tree, hf_elcom_datarequest_grouppriority, tvb, offset, 1, ENC_BIG_ENDIAN);
364 offset += 1;
365 if (tvb_length_remaining(tvb, offset) <= 0)
366 return offset;
368 proto_tree_add_item(tree, hf_elcom_datarequest_groupsize, tvb, offset, 1, ENC_BIG_ENDIAN);
369 offset += 1;
370 if (tvb_length_remaining(tvb, offset) <= 0)
371 return offset;
373 proto_tree_add_item(tree, hf_elcom_datarequest_groupindex1, tvb, offset, 2, ENC_BIG_ENDIAN);
374 offset += 2;
375 if (tvb_length_remaining(tvb, offset) <= 0)
376 return offset;
378 proto_tree_add_item(tree, hf_elcom_datarequest_groupindex2, tvb, offset, 2, ENC_BIG_ENDIAN);
379 offset += 2;
380 if (tvb_length_remaining(tvb, offset) <= 0)
381 return offset;
383 while (1) {
384 oidlen = tvb_get_guint8(tvb, offset);
385 if (oidlen == 0) /* normal termination */
386 break;
387 if (tvb_length_remaining(tvb, offset+oidlen+1) <= 0)
388 return offset;
389 proto_tree_add_item(tree, hf_elcom_datarequest_oid, tvb, offset, 1, ENC_ASCII|ENC_NA);
390 offset += oidlen+1;
392 offset += 1; /* the loop exited at the 0 length byte */
393 if (tvb_length_remaining(tvb, offset) <= 0)
394 return offset;
396 /* show the rest */
397 tree2 = proto_tree_add_text(tree, tvb, offset, -1, "leftover =");
398 while (tvb_length_remaining(tvb, offset) > 0) {
399 proto_item_append_text(tree2, elcom_show_hex ? " %02x" : " %03o",
400 tvb_get_guint8(tvb, offset));
401 offset++;
404 return offset;
407 /* XXX: Are all the tests against tvb_length() really the right way to handle invalid fields ?
408 * It seems to me that invalid fields should just add an expert item
409 * or cause a "Malformed" exception.
411 static void
412 dissect_elcom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
414 gboolean is_request, length_ok;
415 proto_tree *elcom_tree;
416 proto_item *ti, *hidden_item;
417 gint offset = 0;
418 guint elcom_len;
419 guint8 elcom_msg_type;
420 guint8 *suffix;
422 /* Check that there's enough data */
423 if (tvb_length(tvb) < 3)
424 return;
426 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ELCOM");
427 col_clear(pinfo->cinfo, COL_INFO);
429 is_request = (pinfo->match_uint == pinfo->destport);
430 elcom_len = tvb_get_ntohs(tvb, 0);
431 length_ok = (tvb_reported_length(tvb) == (elcom_len+2));
433 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Len=%d%s",
434 is_request ? "Request" : "Response",
435 elcom_len,
436 length_ok ? "" : " (incorrect)");
438 elcom_msg_type = tvb_get_guint8(tvb, 2);
439 switch (elcom_msg_type) {
440 case P_CONRQ:
441 case P_CONRS:
443 /* starting after elcom_len and elcom_msg_type,
444 initiator + responder + userdata fields must be there */
445 if (tvb_length_remaining(tvb, 3+TOTAL_LEN+TOTAL_LEN+3) < 0) return;
446 /* check also that those field lengths are valid */
447 if (tvb_get_guint8(tvb, 3) != LOWADR_LEN) return;
448 if (tvb_get_guint8(tvb, 3+1+LOWADR_LEN) != SUFFIX_LEN) return;
449 if (tvb_get_guint8(tvb, 3+TOTAL_LEN) != LOWADR_LEN) return;
450 if (tvb_get_guint8(tvb, 3+1+TOTAL_LEN+LOWADR_LEN) != SUFFIX_LEN) return;
452 /* finally believe that there is valid suffix */
453 suffix = tvb_get_string(wmem_packet_scope(), tvb, 3+2+LOWADR_LEN, 2);
454 col_append_fstr(pinfo->cinfo, COL_INFO, " %s Connect", suffix);
455 break;
457 case P_RELRQ:
458 case P_RELRS:
459 col_append_str(pinfo->cinfo, COL_INFO, " Release");
460 break;
462 case P_DATRQ:
463 col_append_str(pinfo->cinfo, COL_INFO, " Data");
464 break;
467 switch (elcom_msg_type) {
468 case P_CONRQ:
469 case P_RELRQ:
470 col_append_str(pinfo->cinfo, COL_INFO, " Request");
471 break;
473 case P_CONRS:
474 case P_RELRS:
475 col_append_str(pinfo->cinfo, COL_INFO, " Response");
476 break;
479 if (!tree)
480 return;
482 ti = proto_tree_add_item(tree, proto_elcom, tvb, offset, -1, ENC_NA);
483 elcom_tree = proto_item_add_subtree(ti, ett_elcom);
485 hidden_item = proto_tree_add_boolean(elcom_tree,
486 is_request ? hf_elcom_request : hf_elcom_response,
487 tvb, 0, 0, TRUE);
488 PROTO_ITEM_SET_HIDDEN(hidden_item);
490 /* 2 first bytes are the frame length */
491 offset = 0;
492 ti = proto_tree_add_item(elcom_tree, hf_elcom_length, tvb, offset, 2, ENC_BIG_ENDIAN);
493 offset = +2;
494 if (! length_ok) {
495 proto_item_append_text(ti, " (incorrect)");
498 elcom_msg_type = tvb_get_guint8(tvb, offset);
499 ti = proto_tree_add_item(elcom_tree, hf_elcom_type, tvb, offset, 1, ENC_BIG_ENDIAN);
500 proto_item_append_text(elcom_tree, " ( %s)", val_to_str(elcom_msg_type, type_vals, "Unknown %d"));
502 offset++;
503 if (tvb_length_remaining(tvb, offset) <= 0)
504 return;
506 switch (elcom_msg_type) {
507 case P_CONRQ:
508 case P_CONRS:
510 * Connection request/release assiciated PDU's,
511 * /ELCOM-90 P Protocol spec/ p. 85...
514 /* We need the length here, hardcode the LOWADR_LEN = 21 */
515 ti = proto_tree_add_item(elcom_tree, hf_elcom_initiator, tvb, offset, TOTAL_LEN, ENC_BIG_ENDIAN);
516 offset = dissect_lower_address(ti, ett_elcom_initiator, tvb, offset,
517 hf_elcom_initiator_endian,
518 hf_elcom_initiator_ip,
519 hf_elcom_initiator_port,
520 hf_elcom_initiator_suff);
521 if (tvb_length_remaining(tvb, offset) <= 0)
522 return;
524 ti = proto_tree_add_item(elcom_tree, hf_elcom_responder, tvb, offset, TOTAL_LEN, ENC_BIG_ENDIAN);
525 offset = dissect_lower_address(ti, ett_elcom_responder, tvb, offset,
526 hf_elcom_responder_endian,
527 hf_elcom_responder_ip,
528 hf_elcom_responder_port,
529 hf_elcom_responder_suff);
530 if (tvb_length_remaining(tvb, offset) <= 0)
531 return;
533 /* Rest of the payload is USER-DATA, 0..82 bytes */
534 ti = proto_tree_add_item(elcom_tree, hf_elcom_userdata, tvb, offset, -1, ENC_NA);
535 offset = dissect_userdata(ti, ett_elcom_userdata, tvb, offset);
537 break;
539 case P_RELRQ:
541 proto_tree_add_item(elcom_tree, hf_elcom_release_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
542 offset += 1;
544 break;
545 case P_RELRS:
547 proto_tree_add_item(elcom_tree, hf_elcom_release_result, tvb, offset, 1, ENC_BIG_ENDIAN);
549 offset += 1;
551 break;
553 case P_DATRQ:
554 ti = proto_tree_add_item(elcom_tree, hf_elcom_datarequest, tvb, offset, -1, ENC_NA);
555 offset = dissect_datarequest(ti, ett_elcom_datarequest, tvb, offset);
556 break;
558 default:
559 proto_item_append_text(ti, " <<--- meaning WHAT??");
560 break;
564 if (tvb_length_remaining(tvb, offset) <= 0)
565 return;
567 /* We should not get here, but if we do, show what is left over: */
568 ti = proto_tree_add_item(elcom_tree, hf_elcom_strangeleftover, tvb, offset, -1, ENC_NA);
569 while (tvb_length_remaining(tvb, offset) > 0) {
570 proto_item_append_text(ti, elcom_show_hex ? " %02x" : " %03o",
571 tvb_get_guint8(tvb, offset));
572 offset++;
576 void
577 proto_register_elcom(void)
579 /* Setup list of header fields See Section 1.6.1 for details*/
580 static hf_register_info hf[] = {
581 { &hf_elcom_response,
582 { "Response", "elcom.response",
583 FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }
586 { &hf_elcom_request,
587 { "Request", "elcom.request",
588 FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }
591 { &hf_elcom_length,
592 { "Length", "elcom.length",
593 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
596 { &hf_elcom_type,
597 { "Type", "elcom.type",
598 FT_UINT8, BASE_HEX, VALS(type_vals), 0, NULL, HFILL }
601 { &hf_elcom_initiator,
602 { "Initiator", "elcom.initiator",
603 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
606 { &hf_elcom_initiator_endian,
607 { "Endian", "elcom.initiator.endian",
608 FT_UINT16, BASE_HEX, VALS(endian_vals), 0, NULL, HFILL }
611 { &hf_elcom_initiator_ip,
612 { "IP", "elcom.initiator.ip",
613 FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }
616 { &hf_elcom_initiator_port,
617 { "Port", "elcom.initiator.port",
618 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
621 { &hf_elcom_initiator_suff,
622 { "Suffix", "elcom.initiator.suffix",
623 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
626 { &hf_elcom_responder,
627 { "Responder", "elcom.responder",
628 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
631 { &hf_elcom_responder_endian,
632 { "Endian", "elcom.responder.endian",
633 FT_UINT16, BASE_HEX, VALS(endian_vals), 0, NULL, HFILL }
636 { &hf_elcom_responder_ip,
637 { "IP", "elcom.responder.ip",
638 FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }
641 { &hf_elcom_responder_port,
642 { "Port", "elcom.responder.port",
643 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
646 { &hf_elcom_responder_suff,
647 { "Suffix", "elcom.responder.suffix",
648 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
651 { &hf_elcom_userdata,
652 { "User Data", "elcom.userdata",
653 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
656 { &hf_elcom_userdata_length,
657 { "Length", "elcom.userdata.length",
658 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
661 { &hf_elcom_userdata_pduid,
662 { "PDU-ID", "elcom.userdata.pduid",
663 FT_UINT8, BASE_DEC, VALS(userdata_pduid_vals), 0, NULL, HFILL }
666 { &hf_elcom_userdata_version,
667 { "Version", "elcom.userdata.version",
668 FT_UINT8, BASE_DEC, VALS(userdata_version_vals), 0, NULL, HFILL }
671 { &hf_elcom_userdata_result,
672 { "Result", "elcom.userdata.result",
673 FT_UINT8, BASE_DEC, VALS(userdata_result_vals), 0, NULL, HFILL }
676 { &hf_elcom_userdata_restmark,
677 { "Restart marking", "elcom.userdata.response.restartcode",
678 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
681 { &hf_elcom_userdata_cf,
682 { "Control Field", "elcom.userdata.response.controlfield",
683 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
686 { &hf_elcom_release_reason,
687 { "Reason", "elcom.release.reason",
688 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
691 { &hf_elcom_release_result,
692 { "Result", "elcom.release.result",
693 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
696 { &hf_elcom_datarequest,
697 { "Data Request", "elcom.datarequest",
698 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
701 { &hf_elcom_datarequest_grouptype,
702 { "Group Type", "elcom.datarequest.grouptype",
703 FT_UINT8, BASE_DEC, VALS(datarequest_grouptype_vals), 0, NULL, HFILL }
706 { &hf_elcom_datarequest_result,
707 { "Result", "elcom.datarequest.result",
708 FT_UINT8, BASE_DEC, VALS(datarequest_result_vals), 0, NULL, HFILL }
711 { &hf_elcom_datarequest_groupnumber,
712 { "Group Number", "elcom.datarequest.groupnumber",
713 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
716 { &hf_elcom_datarequest_grouppriority,
717 { "Group Priority", "elcom.datarequest.grouppriority",
718 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
721 { &hf_elcom_datarequest_groupsize,
722 { "Group Size", "elcom.datarequest.groupsize",
723 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
726 { &hf_elcom_datarequest_groupindex1,
727 { "Group Index1", "elcom.datarequest.groupindex1",
728 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
731 { &hf_elcom_datarequest_groupindex2,
732 { "Group Index2", "elcom.datarequest.groupindex2",
733 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
736 { &hf_elcom_datarequest_oid,
737 { "Obkect Name", "elcom.datarequest.oid",
738 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
740 { &hf_elcom_strangeleftover,
741 { "Strange Leftover", "elcom.leftover",
742 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
746 /* Setup protocol subtree array */
747 static gint *ett[] = {
748 &ett_elcom,
749 &ett_elcom_initiator,
750 &ett_elcom_responder,
751 &ett_elcom_userdata,
752 &ett_elcom_datarequest
755 /* Register the protocol name and description */
756 proto_elcom = proto_register_protocol (
757 "ELCOM Communication Protocol",
758 "ELCOM",
759 "elcom"
762 /* Required function calls to register the header fields and subtrees used */
763 proto_register_field_array(proto_elcom, hf, array_length(hf));
764 proto_register_subtree_array(ett, array_length(ett));
768 void
769 proto_reg_handoff_elcom(void)
771 dissector_handle_t elcom_handle;
773 elcom_handle = create_dissector_handle(dissect_elcom, proto_elcom);
774 dissector_add_uint("tcp.port", TCP_PORT_ELCOM, elcom_handle);
778 * Editor modelines
780 * Local Variables:
781 * c-basic-offset: 8
782 * tab-width: 8
783 * indent-tabs-mode: nil
784 * End:
786 * ex: set shiftwidth=8 tabstop=8 expandtab:
787 * :indentSize=8:tabSize=8:noTabs=true: