HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-xtp.c
blobee7b00ba19dbe3bf87b89c8f060ac513119aee79
1 /* packet-xtp.c
2 * Routines for Xpress Transport Protocol dissection
3 * Copyright 2008, Shigeo Nakamura <naka_shigeo@yahoo.co.jp>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 * Ref: http://www.packeteer.com/resources/prod-sol/XTP.pdf
28 #include "config.h"
30 #include <glib.h>
32 #include <epan/packet.h>
33 #include <epan/exceptions.h>
34 #include <epan/expert.h>
35 #include <epan/ipproto.h>
36 #include <epan/in_cksum.h>
37 #include <epan/wmem/wmem.h>
40 #define XTP_VERSION_4 0x001
42 /* XTP type of Service */
43 #define XTP_TOS_UNSPEC 0
44 #define XTP_TOS_UNACKED_DGRAM 1
45 #define XTP_TOS_ACKED_DGRAM 2
46 #define XTP_TOS_TRANS 3
47 #define XTP_TOS_UNICAST_STREAM 4
48 #define XTP_TOS_UNACKED_MULTICAST_STREAM 5
49 #define XTP_TOS_MULTICAST_STREAM 6
51 /* Address Format */
52 #define XTP_ADDR_NULL 0
53 #define XTP_ADDR_IP 1
54 #define XTP_ADDR_ISO 2
55 #define XTP_ADDR_XEROX 3
56 #define XTP_ADDR_IPX 4
57 #define XTP_ADDR_LOCAL 5
58 #define XTP_ADDR_IP6 6
60 /* packet type */
61 #define XTP_DATA_PKT 0
62 #define XTP_CNTL_PKT 1
63 #define XTP_FIRST_PKT 2
64 #define XTP_ECNTL_PKT 3
65 #define XTP_TCNTL_PKT 5
66 #define XTP_JOIN_PKT 6
67 #define XTP_JCNTL_PKT 7
68 #define XTP_DIAG_PKT 8
70 /* cmd options mask */
71 #define XTP_CMD_OPTIONS_NOCHECK 0x400000
72 #define XTP_CMD_OPTIONS_EDGE 0x200000
73 #define XTP_CMD_OPTIONS_NOERR 0x100000
74 #define XTP_CMD_OPTIONS_MULTI 0x080000
75 #define XTP_CMD_OPTIONS_RES 0x040000
76 #define XTP_CMD_OPTIONS_SORT 0x020000
77 #define XTP_CMD_OPTIONS_NOFLOW 0x010000
78 #define XTP_CMD_OPTIONS_FASTNAK 0x008000
79 #define XTP_CMD_OPTIONS_SREQ 0x004000
80 #define XTP_CMD_OPTIONS_DREQ 0x002000
81 #define XTP_CMD_OPTIONS_RCLOSE 0x001000
82 #define XTP_CMD_OPTIONS_WCLOSE 0x000800
83 #define XTP_CMD_OPTIONS_EOM 0x000400
84 #define XTP_CMD_OPTIONS_END 0x000200
85 #define XTP_CMD_OPTIONS_BTAG 0x000100
87 #define XTP_KEY_RTN ((guint64)1<<63)
89 /** packet structures definition **/
90 struct xtp_cntl {
91 guint64 rseq;
92 guint64 alloc;
93 guint32 echo;
95 #define XTP_CNTL_PKT_LEN 20
97 struct xtp_ecntl {
98 guint64 rseq;
99 guint64 alloc;
100 guint32 echo;
101 guint32 nspan;
103 #define MIN_XTP_ECNTL_PKT_LEN 24
105 struct xtp_traffic_cntl {
106 guint64 rseq;
107 guint64 alloc;
108 guint32 echo;
109 guint32 rsvd;
110 guint64 xkey;
112 #define XTP_TRAFFIC_CNTL_LEN 32
114 /* tformat = 0x00 */
115 struct xtp_traffic_spec0 {
116 guint16 tlen;
117 guint8 service;
118 guint8 tformat;
119 guint32 none;
121 #define XTP_TRAFFIC_SPEC0_LEN 8
123 /* tformat = 0x01 */
124 struct xtp_traffic_spec1 {
125 guint16 tlen;
126 guint8 service;
127 guint8 tformat;
128 guint32 maxdata;
129 guint32 inrate;
130 guint32 inburst;
131 guint32 outrate;
132 guint32 outburst;
134 #define XTP_TRAFFIC_SPEC1_LEN 24
136 struct xtp_ip_addr_seg {
137 guint16 alen;
138 guint8 adomain;
139 guint8 aformat;
140 guint32 dsthost;
141 guint32 srchost;
142 guint16 dstport;
143 guint16 srcport;
145 #define XTP_IP_ADDR_SEG_LEN 16
146 #define XTP_NULL_ADDR_SEG_LEN 8
148 struct xtp_diag {
149 guint32 code;
150 guint32 val;
151 gchar *msg;
153 #define XTP_DIAG_PKT_HEADER_LEN 8
155 struct xtphdr {
156 guint64 key;
157 guint32 cmd;
158 guint32 cmd_options; /* 24 bits */
159 guint8 cmd_ptype;
160 guint8 cmd_ptype_ver; /* 3 bits */
161 guint8 cmd_ptype_pformat; /* 5 bits */
162 guint32 dlen;
163 guint16 check;
164 guint16 sort;
165 guint32 sync;
166 guint64 seq;
168 #define XTP_HEADER_LEN 32
171 static const value_string version_vals[] = {
172 { XTP_VERSION_4, "XTP version 4.0" },
173 { 0, NULL }
176 static const value_string service_vals[] = {
177 { XTP_TOS_UNSPEC, "Unspecified" },
178 { XTP_TOS_UNACKED_DGRAM, "Traditional Unacknowledged Datagram Service" },
179 { XTP_TOS_ACKED_DGRAM, "Acknowledged Datagram Service" },
180 { XTP_TOS_TRANS, "Transaction Service" },
181 { XTP_TOS_UNICAST_STREAM, "Traditional Reliable Unicast Stream Service" },
182 { XTP_TOS_UNACKED_MULTICAST_STREAM, "Unacknowledged Multicast Stream Service" },
183 { XTP_TOS_MULTICAST_STREAM, "Reliable Multicast Stream Service" },
184 { 0, NULL }
187 static const value_string aformat_vals[] = {
188 { XTP_ADDR_NULL, "Null Address" },
189 { XTP_ADDR_IP, "Internet Protocol Address" },
190 { XTP_ADDR_ISO, "ISO Connectionless Network Layer Protocol Address" },
191 { XTP_ADDR_XEROX, "Xerox Network System Address" },
192 { XTP_ADDR_IPX, "IPX Address" },
193 { XTP_ADDR_LOCAL, "Local Address" },
194 { XTP_ADDR_IP6, "Internet Protocol Version 6 Address" },
195 { 0, NULL }
198 static const value_string pformat_vals[] = {
199 { XTP_DATA_PKT, "DATA" },
200 { XTP_CNTL_PKT, "CNTL" },
201 { XTP_FIRST_PKT, "FIRST" },
202 { XTP_ECNTL_PKT, "ECNTL" },
203 { XTP_TCNTL_PKT, "TCNTL" },
204 { XTP_JOIN_PKT, "JOIN<obsolete>" },
205 { XTP_JCNTL_PKT, "JCNTL" },
206 { XTP_DIAG_PKT, "DIAG" },
207 { 0, NULL }
210 static const value_string diag_code_vals[] = {
211 { 1, "Context Refused" },
212 { 2, "Context Abandoned" },
213 { 3, "Invalid Context" },
214 { 4, "Request Refused" },
215 { 5, "Join Refused" },
216 { 6, "Protocol Error" },
217 { 7, "Maximum Packet Size Error" },
218 { 0, NULL }
221 static const value_string diag_val_vals[] = {
222 { 0, "Unspecified" },
223 { 1, "No listener" },
224 { 2, "Options refused" },
225 { 3, "Address format not supported" },
226 { 4, "Malformed address format" },
227 { 5, "Traffic format not supported" },
228 { 6, "Traffic specification refused" },
229 { 7, "Malformed traffic format" },
230 { 8, "No provider for service" },
231 { 9, "No resource" },
232 { 10, "Host going down" },
233 { 11, "Invalid retransmission request" },
234 { 12, "Context in improper state" },
235 { 13, "Join request denied" },
236 { 0, NULL }
239 /* Initialize the protocol and registered fields */
240 static int proto_xtp = -1;
241 /* common header */
242 static int hf_xtp_key = -1;
243 static int hf_xtp_cmd = -1;
244 static int hf_xtp_cmd_options = -1;
245 static int hf_xtp_cmd_options_nocheck = -1;
246 static int hf_xtp_cmd_options_edge = -1;
247 static int hf_xtp_cmd_options_noerr = -1;
248 static int hf_xtp_cmd_options_multi = -1;
249 static int hf_xtp_cmd_options_res = -1;
250 static int hf_xtp_cmd_options_sort = -1;
251 static int hf_xtp_cmd_options_noflow = -1;
252 static int hf_xtp_cmd_options_fastnak = -1;
253 static int hf_xtp_cmd_options_sreq = -1;
254 static int hf_xtp_cmd_options_dreq = -1;
255 static int hf_xtp_cmd_options_rclose = -1;
256 static int hf_xtp_cmd_options_wclose = -1;
257 static int hf_xtp_cmd_options_eom = -1;
258 static int hf_xtp_cmd_options_end = -1;
259 static int hf_xtp_cmd_options_btag = -1;
260 static int hf_xtp_cmd_ptype = -1;
261 static int hf_xtp_cmd_ptype_ver = -1;
262 static int hf_xtp_cmd_ptype_pformat = -1;
263 static int hf_xtp_dlen = -1;
264 static int hf_xtp_sort = -1;
265 static int hf_xtp_sync = -1;
266 static int hf_xtp_seq = -1;
267 /* control segment */
268 static int hf_xtp_cntl_rseq = -1;
269 static int hf_xtp_cntl_alloc = -1;
270 static int hf_xtp_cntl_echo = -1;
271 static int hf_xtp_ecntl_rseq = -1;
272 static int hf_xtp_ecntl_alloc = -1;
273 static int hf_xtp_ecntl_echo = -1;
274 static int hf_xtp_ecntl_nspan = -1;
275 static int hf_xtp_ecntl_span_left = -1;
276 static int hf_xtp_ecntl_span_right = -1;
277 static int hf_xtp_tcntl_rseq = -1;
278 static int hf_xtp_tcntl_alloc = -1;
279 static int hf_xtp_tcntl_echo = -1;
280 static int hf_xtp_tcntl_rsvd = -1;
281 static int hf_xtp_tcntl_xkey = -1;
282 /* traffic specifier */
283 static int hf_xtp_tspec_tlen = -1;
284 static int hf_xtp_tspec_service = -1;
285 static int hf_xtp_tspec_tformat = -1;
286 static int hf_xtp_tspec_traffic = -1;
287 static int hf_xtp_tspec_maxdata = -1;
288 static int hf_xtp_tspec_inrate = -1;
289 static int hf_xtp_tspec_outrate = -1;
290 static int hf_xtp_tspec_inburst = -1;
291 static int hf_xtp_tspec_outburst = -1;
292 /* address segment */
293 static int hf_xtp_aseg_alen = -1;
294 static int hf_xtp_aseg_adomain = -1;
295 static int hf_xtp_aseg_aformat = -1;
296 static int hf_xtp_aseg_address = -1;
297 static int hf_xtp_aseg_dsthost = -1;
298 static int hf_xtp_aseg_srchost = -1;
299 static int hf_xtp_aseg_dstport = -1;
300 static int hf_xtp_aseg_srcport = -1;
301 /* others */
302 static int hf_xtp_btag = -1;
303 static int hf_xtp_diag_code = -1;
304 static int hf_xtp_diag_val = -1;
305 static int hf_xtp_diag_msg = -1;
307 /* Initialize the subtree pointers */
308 static gint ett_xtp = -1;
309 static gint ett_xtp_cmd = -1;
310 static gint ett_xtp_cmd_options = -1;
311 static gint ett_xtp_cmd_ptype = -1;
312 static gint ett_xtp_cntl = -1;
313 static gint ett_xtp_ecntl = -1;
314 static gint ett_xtp_tcntl = -1;
315 static gint ett_xtp_tspec = -1;
316 static gint ett_xtp_jcntl = -1;
317 static gint ett_xtp_first = -1;
318 static gint ett_xtp_aseg = -1;
319 static gint ett_xtp_data = -1;
320 static gint ett_xtp_diag = -1;
322 static expert_field ei_xtp_spans_bad = EI_INIT;
324 /* dissector of each payload */
325 static int
326 dissect_xtp_aseg(tvbuff_t *tvb, proto_tree *tree, guint32 offset) {
327 guint32 len = tvb_length_remaining(tvb, offset);
328 guint32 start = offset;
329 proto_item *ti, *ti2, *top_ti;
330 proto_tree *xtp_subtree;
331 struct xtp_ip_addr_seg aseg[1];
332 int error = 0;
334 top_ti = proto_tree_add_text(tree, tvb, offset, len, "Address Segment");
335 xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_aseg);
337 if (len < XTP_NULL_ADDR_SEG_LEN) {
338 proto_item_append_text(top_ti, ", bogus length(%u, must be at least %u)",
339 len, XTP_NULL_ADDR_SEG_LEN);
340 return 0;
343 /** parse common fields **/
344 /* alen(2) */
345 aseg->alen = tvb_get_ntohs(tvb, offset);
346 offset += 2;
347 /* adomain(1) */
348 aseg->adomain = tvb_get_guint8(tvb, offset);
349 offset++;
350 /* aformat(1) */
351 aseg->aformat = tvb_get_guint8(tvb, offset);
353 /** display common fields **/
354 offset = start;
355 /* alen(2) */
356 ti = proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_alen,
357 tvb, offset, 2, aseg->alen);
358 offset += 2;
359 if (aseg->alen > len) {
360 proto_item_append_text(ti, ", bogus length(%u, must be at most %u)",
361 aseg->alen, len);
362 error = 1;
364 /* adomain(1) */
365 proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_adomain,
366 tvb, offset, 1, aseg->adomain);
367 offset++;
368 /* aformat(1) */
369 ti2 = proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_aformat,
370 tvb, offset, 1, aseg->aformat);
371 offset++;
372 switch (aseg->aformat) {
373 case 0:
374 if (aseg->alen != XTP_NULL_ADDR_SEG_LEN) {
375 proto_item_append_text(ti, ", bogus length(%u, must be %u)",
376 aseg->alen, XTP_NULL_ADDR_SEG_LEN);
377 error = 1;
379 break;
380 case 1:
381 if (aseg->alen != XTP_IP_ADDR_SEG_LEN) {
382 proto_item_append_text(ti, ", bogus length(%u, must be %u)",
383 aseg->alen, XTP_IP_ADDR_SEG_LEN);
384 error = 1;
386 break;
387 default:
388 if (aseg->aformat < 128) {
389 proto_item_append_text(ti2,
390 ", Unsupported aformat(%u)", aseg->aformat);
391 error = 1;
393 break;
396 if (error)
397 return (offset - start);
399 /** parse and display each address fileds */
400 switch (aseg->aformat) {
401 case 0:
402 /* address(4) */
403 aseg->dsthost = tvb_get_ntohl(tvb, offset);
404 proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_address,
405 tvb, offset, 4, aseg->dsthost);
406 offset += 4;
407 break;
408 case 1:
409 /* dsthost(4) */
410 aseg->dsthost = tvb_get_ipv4(tvb, offset);
411 proto_tree_add_ipv4(xtp_subtree, hf_xtp_aseg_dsthost,
412 tvb, offset, 4, aseg->dsthost);
413 offset += 4;
414 /* srchost(4) */
415 aseg->srchost = tvb_get_ipv4(tvb, offset);
416 proto_tree_add_ipv4(xtp_subtree, hf_xtp_aseg_srchost,
417 tvb, offset, 4, aseg->srchost);
418 offset += 4;
419 /* dstport(2) */
420 aseg->dstport = tvb_get_ntohs(tvb, offset);
421 proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_dstport,
422 tvb, offset, 2, aseg->dstport);
423 offset += 2;
424 /* srcport(2) */
425 aseg->srcport = tvb_get_ntohs(tvb, offset);
426 proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_srcport,
427 tvb, offset, 2, aseg->srcport);
428 offset += 2;
430 /** add summary **/
431 proto_item_append_text(top_ti, ", Dst Port: %u", aseg->dstport);
432 proto_item_append_text(top_ti, ", Src Port: %u", aseg->srcport);
433 break;
434 default:
435 break;
438 return (offset - start);
441 static int
442 dissect_xtp_traffic_cntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
443 guint32 offset) {
444 guint32 len = tvb_length_remaining(tvb, offset);
445 guint32 start = offset;
446 proto_item *top_ti;
447 proto_tree *xtp_subtree;
448 struct xtp_traffic_cntl tcntl[1];
450 top_ti = proto_tree_add_text(tree, tvb, offset, len,
451 "Traffic Control Segment");
452 xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_tcntl);
454 if (len < XTP_TRAFFIC_CNTL_LEN) {
455 proto_item_append_text(top_ti,
456 ", bogus length(%u, must be at least %u)",
457 len, XTP_TRAFFIC_CNTL_LEN);
458 return 0;
461 /** parse **/
462 /* rseq(8) */
463 tcntl->rseq = tvb_get_ntohl(tvb, offset);
464 tcntl->rseq <<= 32;
465 tcntl->rseq += tvb_get_ntohl(tvb, offset+4);
466 offset += 8;
467 /* alloc(8) */
468 tcntl->alloc = tvb_get_ntohl(tvb, offset);
469 tcntl->alloc <<= 32;
470 tcntl->alloc += tvb_get_ntohl(tvb, offset+4);
471 offset += 8;
472 /* echo(4) */
473 tcntl->echo = tvb_get_ntohl(tvb, offset);
474 offset += 4;
475 /* rsvd(4) */
476 tcntl->rsvd = tvb_get_ntohl(tvb, offset);
477 offset += 4;
478 /* xkey(8) */
479 tcntl->xkey = tvb_get_ntohl(tvb, offset);
480 tcntl->xkey <<= 32;
481 tcntl->xkey += tvb_get_ntohl(tvb, offset+4);
483 /** add summary **/
484 col_append_fstr(pinfo->cinfo, COL_INFO,
485 " Recv-Seq=%" G_GINT64_MODIFIER "u", tcntl->rseq);
486 col_append_fstr(pinfo->cinfo, COL_INFO,
487 " Alloc=%" G_GINT64_MODIFIER "u", tcntl->alloc);
489 proto_item_append_text(top_ti,
490 ", Recv-Seq: %" G_GINT64_MODIFIER "u", tcntl->rseq);
492 /** display **/
493 offset = start;
494 /* rseq(8) */
495 proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_rseq,
496 tvb, offset, 8, tcntl->rseq);
497 offset += 8;
498 /* alloc(8) */
499 proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_alloc,
500 tvb, offset, 8, tcntl->alloc);
501 offset += 4;
502 /* echo(4) */
503 proto_tree_add_uint(xtp_subtree, hf_xtp_tcntl_echo,
504 tvb, offset, 4, tcntl->echo);
505 offset += 4;
506 /* rsvd(4) */
507 proto_tree_add_uint(xtp_subtree, hf_xtp_tcntl_rsvd,
508 tvb, offset, 4, tcntl->rsvd);
509 offset += 4;
510 /* xkey(8) */
511 proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_xkey,
512 tvb, offset, 8, tcntl->xkey);
513 offset += 8;
515 return (offset - start);
518 static int
519 dissect_xtp_tspec(tvbuff_t *tvb, proto_tree *tree, guint32 offset) {
520 guint32 len = tvb_length_remaining(tvb, offset);
521 guint32 start = offset;
522 proto_item *ti, *ti2;
523 proto_tree *xtp_subtree;
524 struct xtp_traffic_spec1 tspec[1];
525 int error = 0;
527 ti = proto_tree_add_text(tree, tvb, offset, len, "Traffic Specifier");
528 xtp_subtree = proto_item_add_subtree(ti, ett_xtp_tspec);
530 if (len < XTP_TRAFFIC_SPEC0_LEN) {
531 proto_item_append_text(ti,
532 ", bogus length(%u, must be at least %u)",
533 len, XTP_TRAFFIC_SPEC0_LEN);
534 return 0;
537 /** parse common fields **/
538 /* tlen(2) */
539 tspec->tlen = tvb_get_ntohs(tvb, offset);
540 offset += 2;
541 /* service(1) */
542 tspec->service = tvb_get_guint8(tvb, offset);
543 offset++;
544 /* tformat(1) */
545 tspec->tformat = tvb_get_guint8(tvb, offset);
547 /** display common fields */
548 offset = start;
549 /* tlen(2) */
550 ti = proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_tlen,
551 tvb, offset, 2, tspec->tlen);
552 offset += 2;
553 if (tspec->tlen > len) {
554 proto_item_append_text(ti, ", bogus length(%u, must be at most %u)",
555 tspec->tlen, len);
556 error = 1;
558 /* service(1) */
559 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_service,
560 tvb, offset, 1, tspec->service);
561 offset++;
562 /* tformat(1) */
563 ti2 = proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_tformat,
564 tvb, offset, 1, tspec->tformat);
565 offset++;
566 switch (tspec->tformat) {
567 case 0:
568 if (tspec->tlen != XTP_TRAFFIC_SPEC0_LEN) {
569 proto_item_append_text(ti, ", bogus length(%u, must be %u)",
570 tspec->tlen, XTP_TRAFFIC_SPEC0_LEN);
571 error = 1;
573 break;
574 case 1:
575 if (tspec->tlen != XTP_TRAFFIC_SPEC1_LEN) {
576 proto_item_append_text(ti, ", bogus length(%u, must be %u)",
577 tspec->tlen, XTP_TRAFFIC_SPEC1_LEN);
578 error = 1;
580 break;
581 default:
582 proto_item_append_text(ti2, ", Unsupported tformat(%u)",
583 tspec->tformat);
584 error = 1;
585 break;
588 if (error)
589 return (offset - start);
591 /** parse and display each traffic fields **/
592 switch (tspec->tformat) {
593 case 0:
594 /* traffic(4) */
595 tspec->maxdata = tvb_get_ntohl(tvb, offset);
596 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_traffic,
597 tvb, offset, 4, tspec->maxdata);
598 offset += 4;
599 break;
600 case 1:
601 /* maxdata(4) */
602 tspec->maxdata = tvb_get_ntohl(tvb, offset);
603 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_maxdata,
604 tvb, offset, 4, tspec->maxdata);
605 offset += 4;
606 /* inrate(4) */
607 tspec->inrate = tvb_get_ntohl(tvb, offset);
608 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_inrate,
609 tvb, offset, 4, tspec->inrate);
610 offset += 4;
611 /* inburst(4) */
612 tspec->inburst = tvb_get_ntohl(tvb, offset);
613 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_inburst,
614 tvb, offset, 4, tspec->inburst);
615 offset += 4;
616 /* outrate(4) */
617 tspec->outrate = tvb_get_ntohl(tvb, offset);
618 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_outrate,
619 tvb, offset, 4, tspec->outrate);
620 offset += 4;
621 /* outburst(4) */
622 tspec->outburst = tvb_get_ntohl(tvb, offset);
623 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_outburst,
624 tvb, offset, 4, tspec->outburst);
625 offset += 4;
626 break;
627 default:
628 break;
631 return (offset - start);
634 static void
635 dissect_xtp_data(tvbuff_t *tvb, proto_tree *tree, guint32 offset, gboolean have_btag) {
636 guint32 len = tvb_length_remaining(tvb, offset);
637 proto_item *ti;
638 proto_tree *xtp_subtree;
639 guint64 btag;
641 ti = proto_tree_add_text(tree, tvb, offset, len, "Data Segment");
642 xtp_subtree = proto_item_add_subtree(ti, ett_xtp_data);
644 if (have_btag) {
645 btag = tvb_get_ntohl(tvb, offset);
646 btag <<= 32;
647 btag += tvb_get_ntohl(tvb, offset+4);
648 proto_tree_add_uint64(xtp_subtree, hf_xtp_btag, tvb, offset, 8, btag);
649 offset += 8;
650 len -= 8;
653 proto_tree_add_text(xtp_subtree, tvb, offset, len,
654 "Data (%u byte%s)", len,
655 plurality(len, "", "s"));
657 return;
660 static void
661 dissect_xtp_cntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
662 guint32 offset) {
663 guint32 len = tvb_length_remaining(tvb, offset);
664 guint32 start = offset;
665 proto_item *top_ti;
666 proto_tree *xtp_subtree;
667 struct xtp_cntl cntl[1];
669 top_ti = proto_tree_add_text(tree, tvb, offset, len,
670 "Common Control Segment");
671 xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_cntl);
673 if (len != XTP_CNTL_PKT_LEN) {
674 proto_item_append_text(top_ti, ", bogus length(%u, must be %u)",
675 len, XTP_CNTL_PKT_LEN);
676 return;
679 /** parse **/
680 /* rseq(8) */
681 cntl->rseq = tvb_get_ntohl(tvb, offset);
682 cntl->rseq <<= 32;
683 cntl->rseq += tvb_get_ntohl(tvb, offset+4);
684 offset += 8;
685 /* alloc(8) */
686 cntl->alloc = tvb_get_ntohl(tvb, offset);
687 cntl->alloc <<= 32;
688 cntl->alloc += tvb_get_ntohl(tvb, offset+4);
689 offset += 8;
690 /* echo(4) */
691 cntl->echo = tvb_get_ntohl(tvb, offset);
693 /** add summary **/
694 col_append_fstr(pinfo->cinfo, COL_INFO,
695 " Recv-Seq=%" G_GINT64_MODIFIER "u", cntl->rseq);
696 col_append_fstr(pinfo->cinfo, COL_INFO,
697 " Alloc=%" G_GINT64_MODIFIER "u", cntl->alloc);
699 proto_item_append_text(top_ti,
700 ", Recv-Seq: %" G_GINT64_MODIFIER "u", cntl->rseq);
702 /** display **/
703 offset = start;
704 /* rseq(8) */
705 proto_tree_add_uint64(xtp_subtree, hf_xtp_cntl_rseq,
706 tvb, offset, 8, cntl->rseq);
707 offset += 8;
708 /* alloc(8) */
709 proto_tree_add_uint64(xtp_subtree, hf_xtp_cntl_alloc,
710 tvb, offset, 8, cntl->alloc);
711 offset += 4;
712 /* echo(4) */
713 proto_tree_add_uint(xtp_subtree, hf_xtp_cntl_echo,
714 tvb, offset, 4, cntl->echo);
716 return;
719 static void
720 dissect_xtp_first(tvbuff_t *tvb, proto_tree *tree, guint32 offset) {
722 if (!dissect_xtp_aseg(tvb, tree, offset))
723 return;
725 offset += XTP_IP_ADDR_SEG_LEN;
726 dissect_xtp_tspec(tvb, tree, offset);
728 return;
731 #define XTP_MAX_NSPANS 10000 /* Arbitrary. (Documentation link is dead.) */
732 static void
733 dissect_xtp_ecntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
734 guint32 offset) {
735 guint32 len = tvb_length_remaining(tvb, offset);
736 guint32 start = offset;
737 proto_item *top_ti;
738 proto_tree *xtp_subtree;
739 struct xtp_ecntl ecntl[1];
740 guint spans_len;
741 guint i;
743 top_ti = proto_tree_add_text(tree, tvb, offset, len,
744 "Error Control Segment");
745 xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_ecntl);
747 if (len < MIN_XTP_ECNTL_PKT_LEN) {
748 proto_item_append_text(top_ti,
749 ", bogus length (%u, must be at least %u)",
750 len, MIN_XTP_ECNTL_PKT_LEN);
751 return;
754 /** parse **/
755 /* rseq(8) */
756 ecntl->rseq = tvb_get_ntohl(tvb, offset);
757 ecntl->rseq <<= 32;
758 ecntl->rseq += tvb_get_ntohl(tvb, offset+4);
759 offset += 8;
760 /* alloc(8) */
761 ecntl->alloc = tvb_get_ntohl(tvb, offset);
762 ecntl->alloc <<= 32;
763 ecntl->alloc += tvb_get_ntohl(tvb, offset+4);
764 offset += 8;
765 /* echo(4) */
766 ecntl->echo = tvb_get_ntohl(tvb, offset);
767 offset += 4;
768 /* nspan(4) */
769 ecntl->nspan = tvb_get_ntohl(tvb, offset);
770 offset += 4;
771 len = len + XTP_HEADER_LEN - offset;
772 spans_len = 16 * ecntl->nspan;
774 if (len != spans_len) {
775 expert_add_info_format(pinfo, top_ti, &ei_xtp_spans_bad, "Number of spans (%u) incorrect. Should be %u.", ecntl->nspan, len);
776 THROW(ReportedBoundsError);
779 if (ecntl->nspan > XTP_MAX_NSPANS) {
780 expert_add_info_format(pinfo, top_ti, &ei_xtp_spans_bad, "Too many spans: %u", ecntl->nspan);
781 THROW(ReportedBoundsError);
784 /** add summary **/
785 col_append_fstr(pinfo->cinfo, COL_INFO,
786 " Recv-Seq=%" G_GINT64_MODIFIER "u", ecntl->rseq);
787 col_append_fstr(pinfo->cinfo, COL_INFO,
788 " Alloc=%" G_GINT64_MODIFIER "u", ecntl->alloc);
790 proto_item_append_text(top_ti,
791 ", Recv-Seq: %" G_GINT64_MODIFIER "u", ecntl->rseq);
793 /** display **/
794 offset = start;
795 /* rseq(8) */
796 proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_rseq,
797 tvb, offset, 8, ecntl->rseq);
798 offset += 8;
799 /* alloc(8) */
800 proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_alloc,
801 tvb, offset, 8, ecntl->alloc);
802 offset += 8;
803 /* echo(4) */
804 proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_echo,
805 tvb, offset, 4, ecntl->echo);
806 offset += 4;
807 /* nspan(4) */
808 proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_nspan,
809 tvb, offset, 4, ecntl->nspan);
810 offset += 4;
811 /* spans(16n) */
812 for (i = 0; i < ecntl->nspan; i++) {
813 proto_tree_add_item(xtp_subtree, hf_xtp_ecntl_span_left,
814 tvb, offset, 8, ENC_LITTLE_ENDIAN);
815 offset += 8;
816 proto_tree_add_item(xtp_subtree, hf_xtp_ecntl_span_right,
817 tvb, offset, 8, ENC_LITTLE_ENDIAN);
818 offset += 8;
821 return;
824 static void
825 dissect_xtp_tcntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
826 guint32 offset) {
828 if (!dissect_xtp_traffic_cntl(tvb, pinfo, tree, offset))
829 return;
831 offset += XTP_TRAFFIC_CNTL_LEN;
832 dissect_xtp_tspec(tvb, tree, offset);
834 return;
837 static void
838 dissect_xtp_jcntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
839 guint32 offset) {
841 if (!dissect_xtp_traffic_cntl(tvb, pinfo, tree, offset))
842 return;
844 offset += XTP_TRAFFIC_CNTL_LEN;
845 if (!dissect_xtp_aseg(tvb, tree, offset))
846 return;
848 offset += XTP_IP_ADDR_SEG_LEN;
849 dissect_xtp_tspec(tvb, tree, offset);
851 return;
854 static void
855 dissect_xtp_diag(tvbuff_t *tvb, proto_tree *tree, guint32 offset) {
856 guint32 len = tvb_length_remaining(tvb, offset);
857 guint32 start = offset;
858 proto_item *ti;
859 proto_tree *xtp_subtree;
860 struct xtp_diag diag[1];
861 guint32 msg_len;
863 ti = proto_tree_add_text(tree, tvb, offset, len, "Diagnostic Segment");
864 xtp_subtree = proto_item_add_subtree(ti, ett_xtp_diag);
866 if (len < XTP_DIAG_PKT_HEADER_LEN) {
867 proto_item_append_text(ti,
868 ", bogus length (%u, must be at least %u)",
869 len, XTP_DIAG_PKT_HEADER_LEN);
870 return;
873 /** parse **/
874 /* code(4) */
875 diag->code = tvb_get_ntohl(tvb, offset);
876 offset += 4;
877 /* val(4) */
878 diag->val = tvb_get_ntohl(tvb, offset);
879 offset += 4;
880 /* message(n) */
881 msg_len = tvb_length_remaining(tvb, offset);
882 diag->msg = tvb_get_string(NULL, tvb, offset, msg_len);
884 /** display **/
885 offset = start;
886 /* code(4) */
887 proto_tree_add_uint(xtp_subtree, hf_xtp_diag_code,
888 tvb, offset, 4, diag->code);
889 offset += 4;
890 /* val(4) */
891 proto_tree_add_uint(xtp_subtree, hf_xtp_diag_val,
892 tvb, offset, 4, diag->val);
893 offset += 4;
894 /* message(4) */
895 proto_tree_add_string(xtp_subtree, hf_xtp_diag_msg,
896 tvb, offset, msg_len, diag->msg);
897 g_free(diag->msg);
899 return;
902 /* main dissector */
903 static int
904 dissect_xtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
905 guint32 offset, len;
906 proto_item *ti;
907 proto_tree *xtp_tree, *xtp_cmd_tree, *xtp_subtree;
908 struct xtphdr xtph[1];
909 int error = 0;
910 gchar *options;
911 static const char *fstr[] = { "<None>", "NOCHECK", "EDGE", "NOERR", "MULTI", "RES",
912 "SORT", "NOFLOW", "FASTNAK", "SREQ", "DREQ",
913 "RCLOSE", "WCLOSE", "EOM", "END", "BTAG" };
914 gint fpos = 0, returned_length;
915 guint i, bpos;
916 guint cmd_options;
917 vec_t cksum_vec[1];
918 guint16 computed_cksum;
919 gboolean have_btag;
921 if ((len = tvb_length(tvb)) < XTP_HEADER_LEN)
922 return 0;
924 col_set_str(pinfo->cinfo, COL_PROTOCOL, "XTP");
925 col_clear(pinfo->cinfo, COL_INFO);
927 /** parse header **/
928 offset = 0;
929 /* key(8) */
930 xtph->key = tvb_get_ntohl(tvb, offset);
931 xtph->key <<= 32;
932 xtph->key += tvb_get_ntohl(tvb, offset+4);
933 offset += 8;
934 /* cmd(4) */
935 xtph->cmd = tvb_get_ntohl(tvb, offset);
936 xtph->cmd_options = xtph->cmd >> 8;
937 xtph->cmd_ptype = xtph->cmd & 0xff;
938 xtph->cmd_ptype_ver = (xtph->cmd_ptype & 0xe0) >> 5;
939 xtph->cmd_ptype_pformat = xtph->cmd_ptype & 0x1f;
940 offset += 4;
941 /* dlen(4) */
942 xtph->dlen = tvb_get_ntohl(tvb, offset);
943 offset += 4;
944 /* check(2) */
945 xtph->check = tvb_get_ntohs(tvb, offset);
946 offset += 2;
947 /* sort(2) */
948 xtph->sort = tvb_get_ntohs(tvb, offset);
949 offset += 2;
950 /* sync(4) */
951 xtph->sync = tvb_get_ntohl(tvb, offset);
952 offset += 4;
953 /* seq(8) */
954 xtph->seq = tvb_get_ntohl(tvb, offset);
955 xtph->seq <<= 32;
956 xtph->seq += tvb_get_ntohl(tvb, offset+4);
958 #define MAX_OPTIONS_LEN 128
959 options=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_OPTIONS_LEN);
960 options[0]=0;
961 cmd_options = xtph->cmd_options >> 8;
962 for (i = 0; i < 16; i++) {
963 bpos = 1 << (15 - i);
964 if (cmd_options & bpos) {
965 returned_length = g_snprintf(&options[fpos],
966 MAX_OPTIONS_LEN-fpos, "%s%s",
967 fpos?", ":"",
968 fstr[i]);
969 fpos += MIN(returned_length, MAX_OPTIONS_LEN-fpos);
973 col_add_str(pinfo->cinfo, COL_INFO,
974 val_to_str(xtph->cmd_ptype_pformat,
975 pformat_vals, "Unknown pformat (%u)"));
976 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", options);
977 col_append_fstr(pinfo->cinfo, COL_INFO,
978 " Seq=%" G_GINT64_MODIFIER "u", xtph->seq);
979 col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", xtph->dlen);
981 if (tree) {
982 ti = proto_tree_add_item(tree, proto_xtp, tvb, 0, -1, ENC_NA);
983 /** add summary **/
984 proto_item_append_text(ti,
985 ", Key: 0x%016" G_GINT64_MODIFIER "X", xtph->key);
986 proto_item_append_text(ti,
987 ", Seq: %" G_GINT64_MODIFIER "u", xtph->seq);
988 proto_item_append_text(ti, ", Len: %u", xtph->dlen);
990 xtp_tree = proto_item_add_subtree(ti, ett_xtp);
991 /* key(8) */
992 offset = 0;
993 proto_tree_add_uint64(xtp_tree, hf_xtp_key,
994 tvb, offset, 8, xtph->key);
995 offset += 8;
996 /* cmd(4) */
997 ti = proto_tree_add_uint(xtp_tree, hf_xtp_cmd,
998 tvb, offset, 4, xtph->cmd);
999 xtp_cmd_tree = proto_item_add_subtree(ti, ett_xtp_cmd);
1000 ti = proto_tree_add_uint(xtp_cmd_tree, hf_xtp_cmd_options,
1001 tvb, offset, 3, xtph->cmd_options);
1002 /** add summary **/
1003 proto_item_append_text(ti, " [%s]", options);
1005 xtp_subtree = proto_item_add_subtree(ti, ett_xtp_cmd_options);
1006 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_nocheck,
1007 tvb, offset, 3, xtph->cmd_options);
1008 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_edge,
1009 tvb, offset, 3, xtph->cmd_options);
1010 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_noerr,
1011 tvb, offset, 3, xtph->cmd_options);
1012 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_multi,
1013 tvb, offset, 3, xtph->cmd_options);
1014 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_res,
1015 tvb, offset, 3, xtph->cmd_options);
1016 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_sort,
1017 tvb, offset, 3, xtph->cmd_options);
1018 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_noflow,
1019 tvb, offset, 3, xtph->cmd_options);
1020 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_fastnak,
1021 tvb, offset, 3, xtph->cmd_options);
1022 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_sreq,
1023 tvb, offset, 3, xtph->cmd_options);
1024 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_dreq,
1025 tvb, offset, 3, xtph->cmd_options);
1026 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_rclose,
1027 tvb, offset, 3, xtph->cmd_options);
1028 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_wclose,
1029 tvb, offset, 3, xtph->cmd_options);
1030 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_eom,
1031 tvb, offset, 3, xtph->cmd_options);
1032 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_end,
1033 tvb, offset, 3, xtph->cmd_options);
1034 proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_btag,
1035 tvb, offset, 3, xtph->cmd_options);
1036 offset += 3;
1037 ti = proto_tree_add_uint(xtp_cmd_tree, hf_xtp_cmd_ptype,
1038 tvb, offset, 1, xtph->cmd_ptype);
1039 xtp_subtree = proto_item_add_subtree(ti, ett_xtp_cmd_ptype);
1040 proto_tree_add_uint(xtp_subtree, hf_xtp_cmd_ptype_ver,
1041 tvb, offset, 1, xtph->cmd_ptype_ver);
1042 if (xtph->cmd_ptype_ver != XTP_VERSION_4) {
1043 proto_item_append_text(ti,
1044 ", Unknown XTP version (%03X)", xtph->cmd_ptype_ver);
1045 error = 1;
1047 proto_tree_add_uint(xtp_subtree, hf_xtp_cmd_ptype_pformat,
1048 tvb, offset, 1, xtph->cmd_ptype_pformat);
1049 offset++;
1050 /* dlen(4) */
1051 ti = proto_tree_add_uint(xtp_tree, hf_xtp_dlen,
1052 tvb, offset, 4, xtph->dlen);
1053 if (xtph->dlen != len - XTP_HEADER_LEN) {
1054 proto_item_append_text(ti, ", bogus length (%u, must be %u)",
1055 xtph->dlen, len - XTP_HEADER_LEN);
1056 error = 1;
1058 offset += 4;
1059 /* check(2) */
1060 if (!pinfo->fragmented) {
1061 guint32 check_len = XTP_HEADER_LEN;
1062 if (!(xtph->cmd_options & XTP_CMD_OPTIONS_NOCHECK))
1063 check_len += xtph->dlen;
1064 cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, check_len);
1065 cksum_vec[0].len = check_len;
1066 computed_cksum = in_cksum(cksum_vec, 1);
1067 if (computed_cksum == 0) {
1068 proto_tree_add_text(xtp_tree, tvb, offset, 2,
1069 "Checksum: 0x%04x [correct]", xtph->check);
1070 } else {
1071 proto_tree_add_text(xtp_tree, tvb, offset, 2,
1072 "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1073 xtph->check,
1074 in_cksum_shouldbe(xtph->check, computed_cksum));
1077 else {
1078 proto_tree_add_text(xtp_tree, tvb, offset, 2,
1079 "Checksum: 0x%04x", xtph->check);
1081 offset += 2;
1082 /* sort(2) */
1083 proto_tree_add_uint(xtp_tree, hf_xtp_sort, tvb, offset, 2, xtph->sort);
1084 offset += 2;
1085 /* sync(4) */
1086 proto_tree_add_uint(xtp_tree, hf_xtp_sync, tvb, offset, 4, xtph->sync);
1087 offset += 4;
1088 /* seq(8) */
1089 proto_tree_add_uint64(xtp_tree, hf_xtp_seq, tvb, offset, 8, xtph->seq);
1090 offset += 8;
1092 if (!error) {
1093 switch (xtph->cmd_ptype_pformat) {
1094 case XTP_DATA_PKT:
1095 have_btag = !!(xtph->cmd_options & XTP_CMD_OPTIONS_BTAG);
1096 dissect_xtp_data(tvb, xtp_tree, offset, have_btag);
1097 break;
1098 case XTP_CNTL_PKT:
1099 dissect_xtp_cntl(tvb, pinfo, xtp_tree, offset);
1100 break;
1101 case XTP_FIRST_PKT:
1102 dissect_xtp_first(tvb, xtp_tree, offset);
1103 break;
1104 case XTP_ECNTL_PKT:
1105 dissect_xtp_ecntl(tvb, pinfo, xtp_tree, offset);
1106 break;
1107 case XTP_TCNTL_PKT:
1108 dissect_xtp_tcntl(tvb, pinfo, xtp_tree, offset);
1109 break;
1110 case XTP_JOIN_PKT:
1111 /* obsolete */
1112 break;
1113 case XTP_JCNTL_PKT:
1114 dissect_xtp_jcntl(tvb, pinfo, xtp_tree, offset);
1115 break;
1116 case XTP_DIAG_PKT:
1117 dissect_xtp_diag(tvb, xtp_tree, offset);
1118 break;
1119 default:
1120 /* error */
1121 break;
1126 return tvb_length(tvb);
1129 void
1130 proto_register_xtp(void)
1132 static hf_register_info hf[] = {
1133 /* command header */
1134 { &hf_xtp_key,
1135 { "Key", "xtp.key",
1136 FT_UINT64, BASE_HEX, NULL, 0x0,
1137 NULL, HFILL }
1139 { &hf_xtp_cmd,
1140 { "Command", "xtp.cmd",
1141 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }
1143 { &hf_xtp_cmd_options,
1144 { "Options", "xtp.cmd.options",
1145 FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL }
1147 { &hf_xtp_cmd_options_nocheck,
1148 { "NOCHECK", "xtp.cmd.options.nocheck",
1149 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1150 XTP_CMD_OPTIONS_NOCHECK, NULL, HFILL }
1152 { &hf_xtp_cmd_options_edge,
1153 { "EDGE", "xtp.cmd.options.edge",
1154 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1155 XTP_CMD_OPTIONS_EDGE, NULL, HFILL }
1157 { &hf_xtp_cmd_options_noerr,
1158 { "NOERR", "xtp.cmd.options.noerr",
1159 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1160 XTP_CMD_OPTIONS_NOERR, NULL, HFILL }
1162 { &hf_xtp_cmd_options_multi,
1163 { "MULTI", "xtp.cmd.options.multi",
1164 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1165 XTP_CMD_OPTIONS_MULTI, NULL, HFILL }
1167 { &hf_xtp_cmd_options_res,
1168 { "RES", "xtp.cmd.options.res",
1169 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1170 XTP_CMD_OPTIONS_RES, NULL, HFILL }
1172 { &hf_xtp_cmd_options_sort,
1173 { "SORT", "xtp.cmd.options.sort",
1174 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1175 XTP_CMD_OPTIONS_SORT, NULL, HFILL }
1177 { &hf_xtp_cmd_options_noflow,
1178 { "NOFLOW", "xtp.cmd.options.noflow",
1179 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1180 XTP_CMD_OPTIONS_NOFLOW, NULL, HFILL }
1182 { &hf_xtp_cmd_options_fastnak,
1183 { "FASTNAK", "xtp.cmd.options.fastnak",
1184 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1185 XTP_CMD_OPTIONS_FASTNAK, NULL, HFILL }
1187 { &hf_xtp_cmd_options_sreq,
1188 { "SREQ", "xtp.cmd.options.sreq",
1189 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1190 XTP_CMD_OPTIONS_SREQ, NULL, HFILL }
1192 { &hf_xtp_cmd_options_dreq,
1193 { "DREQ", "xtp.cmd.options.dreq",
1194 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1195 XTP_CMD_OPTIONS_DREQ, NULL, HFILL }
1197 { &hf_xtp_cmd_options_rclose,
1198 { "RCLOSE", "xtp.cmd.options.rclose",
1199 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1200 XTP_CMD_OPTIONS_RCLOSE, NULL, HFILL }
1202 { &hf_xtp_cmd_options_wclose,
1203 { "WCLOSE", "xtp.cmd.options.wclose",
1204 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1205 XTP_CMD_OPTIONS_WCLOSE, NULL, HFILL }
1207 { &hf_xtp_cmd_options_eom,
1208 { "EOM", "xtp.cmd.options.eom",
1209 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1210 XTP_CMD_OPTIONS_EOM, NULL, HFILL }
1212 { &hf_xtp_cmd_options_end,
1213 { "END", "xtp.cmd.options.end",
1214 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1215 XTP_CMD_OPTIONS_END, NULL, HFILL }
1217 { &hf_xtp_cmd_options_btag,
1218 { "BTAG", "xtp.cmd.options.btag",
1219 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1220 XTP_CMD_OPTIONS_BTAG, NULL, HFILL }
1222 { &hf_xtp_cmd_ptype,
1223 { "Packet type", "xtp.cmd.ptype",
1224 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
1226 { &hf_xtp_cmd_ptype_ver,
1227 { "Version", "xtp.cmd.ptype.ver",
1228 FT_UINT8, BASE_DEC, VALS(version_vals), 0x0, NULL, HFILL }
1230 { &hf_xtp_cmd_ptype_pformat,
1231 { "Format", "xtp.cmd.ptype.pformat",
1232 FT_UINT8, BASE_DEC, VALS(pformat_vals), 0x0, NULL, HFILL }
1234 { &hf_xtp_dlen,
1235 { "Data length", "xtp.dlen",
1236 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1238 { &hf_xtp_sort,
1239 { "Sort", "xtp.sort",
1240 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1242 { &hf_xtp_sync,
1243 { "Synchronizing handshake", "xtp.sync",
1244 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1246 { &hf_xtp_seq,
1247 { "Sequence number", "xtp.seq",
1248 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1250 /* control segment */
1251 { &hf_xtp_cntl_rseq,
1252 { "Received sequence number", "xtp.cntl.rseq",
1253 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1255 { &hf_xtp_cntl_alloc,
1256 { "Allocation", "xtp.cntl.alloc",
1257 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1259 { &hf_xtp_cntl_echo,
1260 { "Synchronizing handshake echo", "xtp.cntl.echo",
1261 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1263 { &hf_xtp_ecntl_rseq,
1264 { "Received sequence number", "xtp.ecntl.rseq",
1265 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1267 { &hf_xtp_ecntl_alloc,
1268 { "Allocation", "xtp.ecntl.alloc",
1269 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1271 { &hf_xtp_ecntl_echo,
1272 { "Synchronizing handshake echo", "xtp.ecntl.echo",
1273 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1275 { &hf_xtp_ecntl_nspan,
1276 { "Number of spans", "xtp.ecntl.nspan",
1277 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1279 { &hf_xtp_ecntl_span_left,
1280 { "Span left edge", "xtp.ecntl.span_le",
1281 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1283 { &hf_xtp_ecntl_span_right,
1284 { "Span right edge", "xtp.ecntl.span_re",
1285 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1287 { &hf_xtp_tcntl_rseq,
1288 { "Received sequence number", "xtp.tcntl.rseq",
1289 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1291 { &hf_xtp_tcntl_alloc,
1292 { "Allocation", "xtp.tcntl.alloc",
1293 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1295 { &hf_xtp_tcntl_echo,
1296 { "Synchronizing handshake echo", "xtp.tcntl.echo",
1297 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1299 { &hf_xtp_tcntl_rsvd,
1300 { "Reserved", "xtp.tcntl.rsvd",
1301 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1303 { &hf_xtp_tcntl_xkey,
1304 { "Exchange key", "xtp.tcntl.xkey",
1305 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }
1307 /* traffic specifier */
1308 { &hf_xtp_tspec_tlen,
1309 { "Length", "xtp.tspec.tlen",
1310 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1312 { &hf_xtp_tspec_service,
1313 { "Service", "xtp.tspec.service",
1314 FT_UINT8, BASE_DEC, VALS(service_vals), 0x0, NULL, HFILL }
1316 { &hf_xtp_tspec_tformat,
1317 { "Format", "xtp.tspec.format",
1318 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
1320 { &hf_xtp_tspec_traffic,
1321 { "Traffic", "xtp.tspec.traffic",
1322 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1324 { &hf_xtp_tspec_maxdata,
1325 { "Maxdata", "xtp.tspec.maxdata",
1326 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1328 { &hf_xtp_tspec_inrate,
1329 { "Incoming rate", "xtp.tspec.inrate",
1330 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1332 { &hf_xtp_tspec_inburst,
1333 { "Incoming burst size", "xtp.tspec.inburst",
1334 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1336 { &hf_xtp_tspec_outrate,
1337 { "Outgoing rate", "xtp.tspec.outrate",
1338 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1340 { &hf_xtp_tspec_outburst,
1341 { "Outgoing burst size", "xtp.tspec.outburst",
1342 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1344 /* address segment */
1345 { &hf_xtp_aseg_alen,
1346 { "Length", "xtp.aseg.alen",
1347 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1349 { &hf_xtp_aseg_adomain,
1350 { "Domain", "xtp.aseg.adomain",
1351 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
1353 { &hf_xtp_aseg_aformat,
1354 { "Format", "xtp.aseg.aformat",
1355 FT_UINT8, BASE_DEC, VALS(aformat_vals), 0x0, NULL, HFILL }
1357 { &hf_xtp_aseg_address,
1358 { "Traffic", "xtp.aseg.address",
1359 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1361 { &hf_xtp_aseg_dsthost,
1362 { "Destination host", "xtp.aseg.dsthost",
1363 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }
1365 { &hf_xtp_aseg_srchost,
1366 { "Source host", "xtp.aseg.srchost",
1367 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }
1369 { &hf_xtp_aseg_dstport,
1370 { "Destination port", "xtp.aseg.dstport",
1371 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1373 { &hf_xtp_aseg_srcport,
1374 { "Source port", "xtp.aseg.srcport",
1375 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1377 /* others */
1378 { &hf_xtp_btag,
1379 { "Beginning tag", "xtp.data.btag",
1380 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }
1382 { &hf_xtp_diag_code,
1383 { "Diagnostic code", "xtp.diag.code",
1384 FT_UINT32, BASE_DEC, VALS(diag_code_vals), 0x0, NULL, HFILL }
1386 { &hf_xtp_diag_val,
1387 { "Diagnostic value", "xtp.diag.val",
1388 FT_UINT32, BASE_DEC, VALS(diag_val_vals), 0x0, NULL, HFILL }
1390 { &hf_xtp_diag_msg,
1391 { "Message", "xtp.diag.msg",
1392 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
1396 static gint *ett[] = {
1397 &ett_xtp,
1398 &ett_xtp_cmd,
1399 &ett_xtp_cmd_options,
1400 &ett_xtp_cmd_ptype,
1401 &ett_xtp_cntl,
1402 &ett_xtp_ecntl,
1403 &ett_xtp_tcntl,
1404 &ett_xtp_tspec,
1405 &ett_xtp_jcntl,
1406 &ett_xtp_first,
1407 &ett_xtp_aseg,
1408 &ett_xtp_data,
1409 &ett_xtp_diag,
1412 static ei_register_info ei[] = {
1413 { &ei_xtp_spans_bad, { "xtp.spans_bad", PI_MALFORMED, PI_ERROR, "Number of spans incorrect", EXPFILL }},
1416 expert_module_t* expert_xtp;
1418 expert_xtp = expert_register_protocol(proto_xtp);
1419 expert_register_field_array(expert_xtp, ei, array_length(ei));
1421 proto_xtp = proto_register_protocol("Xpress Transport Protocol",
1422 "XTP", "xtp");
1423 proto_register_field_array(proto_xtp, hf, array_length(hf));
1424 proto_register_subtree_array(ett, array_length(ett));
1427 void
1428 proto_reg_handoff_xtp(void)
1430 dissector_handle_t xtp_handle;
1432 xtp_handle = new_create_dissector_handle(dissect_xtp, proto_xtp);
1433 dissector_add_uint("ip.proto", IP_PROTO_XTP, xtp_handle);