Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-xtp.c
blob1366842b0789e7037b306d09a3f2e366cf96c41d
1 /* packet-xtp.c
2 * Routines for Xpress Transport Protocol dissection
3 * Copyright 2008, Shigeo Nakamura <naka_shigeo@yahoo.co.jp>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
11 * Ref: http://www.packeteer.com/resources/prod-sol/XTP.pdf
14 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/expert.h>
18 #include <epan/ipproto.h>
19 #include <epan/in_cksum.h>
20 #include <epan/tfs.h>
21 #include <wsutil/array.h>
23 #define XTP_VERSION_4 0x001
25 /* XTP type of Service */
26 #define XTP_TOS_UNSPEC 0
27 #define XTP_TOS_UNACKED_DGRAM 1
28 #define XTP_TOS_ACKED_DGRAM 2
29 #define XTP_TOS_TRANS 3
30 #define XTP_TOS_UNICAST_STREAM 4
31 #define XTP_TOS_UNACKED_MULTICAST_STREAM 5
32 #define XTP_TOS_MULTICAST_STREAM 6
34 /* Address Format */
35 #define XTP_ADDR_NULL 0
36 #define XTP_ADDR_IP 1
37 #define XTP_ADDR_ISO 2
38 #define XTP_ADDR_XEROX 3
39 #define XTP_ADDR_IPX 4
40 #define XTP_ADDR_LOCAL 5
41 #define XTP_ADDR_IP6 6
43 /* packet type */
44 #define XTP_DATA_PKT 0
45 #define XTP_CNTL_PKT 1
46 #define XTP_FIRST_PKT 2
47 #define XTP_ECNTL_PKT 3
48 #define XTP_TCNTL_PKT 5
49 #define XTP_JOIN_PKT 6
50 #define XTP_JCNTL_PKT 7
51 #define XTP_DIAG_PKT 8
53 /* cmd options mask */
54 #define XTP_CMD_OPTIONS_NOCHECK 0x400000
55 #define XTP_CMD_OPTIONS_EDGE 0x200000
56 #define XTP_CMD_OPTIONS_NOERR 0x100000
57 #define XTP_CMD_OPTIONS_MULTI 0x080000
58 #define XTP_CMD_OPTIONS_RES 0x040000
59 #define XTP_CMD_OPTIONS_SORT 0x020000
60 #define XTP_CMD_OPTIONS_NOFLOW 0x010000
61 #define XTP_CMD_OPTIONS_FASTNAK 0x008000
62 #define XTP_CMD_OPTIONS_SREQ 0x004000
63 #define XTP_CMD_OPTIONS_DREQ 0x002000
64 #define XTP_CMD_OPTIONS_RCLOSE 0x001000
65 #define XTP_CMD_OPTIONS_WCLOSE 0x000800
66 #define XTP_CMD_OPTIONS_EOM 0x000400
67 #define XTP_CMD_OPTIONS_END 0x000200
68 #define XTP_CMD_OPTIONS_BTAG 0x000100
70 #define XTP_KEY_RTN ((uint64_t)1<<63)
72 void proto_register_xtp(void);
73 void proto_reg_handoff_xtp(void);
75 static dissector_handle_t xtp_handle;
77 /** packet structures definition **/
78 struct xtp_cntl {
79 uint64_t rseq;
80 uint64_t alloc;
81 uint32_t echo;
83 #define XTP_CNTL_PKT_LEN 20
85 struct xtp_ecntl {
86 uint64_t rseq;
87 uint64_t alloc;
88 uint32_t echo;
89 uint32_t nspan;
91 #define MIN_XTP_ECNTL_PKT_LEN 24
93 struct xtp_traffic_cntl {
94 uint64_t rseq;
95 uint64_t alloc;
96 uint32_t echo;
97 uint32_t rsvd;
98 uint64_t xkey;
100 #define XTP_TRAFFIC_CNTL_LEN 32
102 /* tformat = 0x00 */
103 struct xtp_traffic_spec0 {
104 uint16_t tlen;
105 uint8_t service;
106 uint8_t tformat;
107 uint32_t none;
109 #define XTP_TRAFFIC_SPEC0_LEN 8
111 /* tformat = 0x01 */
112 struct xtp_traffic_spec1 {
113 uint16_t tlen;
114 uint8_t service;
115 uint8_t tformat;
116 uint32_t maxdata;
117 uint32_t inrate;
118 uint32_t inburst;
119 uint32_t outrate;
120 uint32_t outburst;
122 #define XTP_TRAFFIC_SPEC1_LEN 24
124 struct xtp_ip_addr_seg {
125 uint16_t alen;
126 uint8_t adomain;
127 uint8_t aformat;
128 uint32_t dsthost;
129 uint32_t srchost;
130 uint16_t dstport;
131 uint16_t srcport;
133 #define XTP_IP_ADDR_SEG_LEN 16
134 #define XTP_NULL_ADDR_SEG_LEN 8
136 struct xtp_diag {
137 uint32_t code;
138 uint32_t val;
139 char *msg;
141 #define XTP_DIAG_PKT_HEADER_LEN 8
143 struct xtphdr {
144 uint64_t key;
145 uint32_t cmd;
146 uint32_t cmd_options; /* 24 bits */
147 uint8_t cmd_ptype;
148 uint8_t cmd_ptype_ver; /* 3 bits */
149 uint8_t cmd_ptype_pformat; /* 5 bits */
150 uint32_t dlen;
151 uint16_t check;
152 uint16_t sort;
153 uint32_t sync;
154 uint64_t seq;
156 #define XTP_HEADER_LEN 32
159 static const value_string version_vals[] = {
160 { XTP_VERSION_4, "XTP version 4.0" },
161 { 0, NULL }
164 static const value_string service_vals[] = {
165 { XTP_TOS_UNSPEC, "Unspecified" },
166 { XTP_TOS_UNACKED_DGRAM, "Traditional Unacknowledged Datagram Service" },
167 { XTP_TOS_ACKED_DGRAM, "Acknowledged Datagram Service" },
168 { XTP_TOS_TRANS, "Transaction Service" },
169 { XTP_TOS_UNICAST_STREAM, "Traditional Reliable Unicast Stream Service" },
170 { XTP_TOS_UNACKED_MULTICAST_STREAM, "Unacknowledged Multicast Stream Service" },
171 { XTP_TOS_MULTICAST_STREAM, "Reliable Multicast Stream Service" },
172 { 0, NULL }
175 static const value_string aformat_vals[] = {
176 { XTP_ADDR_NULL, "Null Address" },
177 { XTP_ADDR_IP, "Internet Protocol Address" },
178 { XTP_ADDR_ISO, "ISO Connectionless Network Layer Protocol Address" },
179 { XTP_ADDR_XEROX, "Xerox Network System Address" },
180 { XTP_ADDR_IPX, "IPX Address" },
181 { XTP_ADDR_LOCAL, "Local Address" },
182 { XTP_ADDR_IP6, "Internet Protocol Version 6 Address" },
183 { 0, NULL }
186 static const value_string pformat_vals[] = {
187 { XTP_DATA_PKT, "DATA" },
188 { XTP_CNTL_PKT, "CNTL" },
189 { XTP_FIRST_PKT, "FIRST" },
190 { XTP_ECNTL_PKT, "ECNTL" },
191 { XTP_TCNTL_PKT, "TCNTL" },
192 { XTP_JOIN_PKT, "JOIN<obsolete>" },
193 { XTP_JCNTL_PKT, "JCNTL" },
194 { XTP_DIAG_PKT, "DIAG" },
195 { 0, NULL }
198 static const value_string diag_code_vals[] = {
199 { 1, "Context Refused" },
200 { 2, "Context Abandoned" },
201 { 3, "Invalid Context" },
202 { 4, "Request Refused" },
203 { 5, "Join Refused" },
204 { 6, "Protocol Error" },
205 { 7, "Maximum Packet Size Error" },
206 { 0, NULL }
209 static const value_string diag_val_vals[] = {
210 { 0, "Unspecified" },
211 { 1, "No listener" },
212 { 2, "Options refused" },
213 { 3, "Address format not supported" },
214 { 4, "Malformed address format" },
215 { 5, "Traffic format not supported" },
216 { 6, "Traffic specification refused" },
217 { 7, "Malformed traffic format" },
218 { 8, "No provider for service" },
219 { 9, "No resource" },
220 { 10, "Host going down" },
221 { 11, "Invalid retransmission request" },
222 { 12, "Context in improper state" },
223 { 13, "Join request denied" },
224 { 0, NULL }
227 /* Initialize the protocol and registered fields */
228 static int proto_xtp;
229 /* common header */
230 static int hf_xtp_key;
231 static int hf_xtp_cmd;
232 static int hf_xtp_cmd_options;
233 static int hf_xtp_cmd_options_nocheck;
234 static int hf_xtp_cmd_options_edge;
235 static int hf_xtp_cmd_options_noerr;
236 static int hf_xtp_cmd_options_multi;
237 static int hf_xtp_cmd_options_res;
238 static int hf_xtp_cmd_options_sort;
239 static int hf_xtp_cmd_options_noflow;
240 static int hf_xtp_cmd_options_fastnak;
241 static int hf_xtp_cmd_options_sreq;
242 static int hf_xtp_cmd_options_dreq;
243 static int hf_xtp_cmd_options_rclose;
244 static int hf_xtp_cmd_options_wclose;
245 static int hf_xtp_cmd_options_eom;
246 static int hf_xtp_cmd_options_end;
247 static int hf_xtp_cmd_options_btag;
248 static int hf_xtp_cmd_ptype;
249 static int hf_xtp_cmd_ptype_ver;
250 static int hf_xtp_cmd_ptype_pformat;
251 static int hf_xtp_dlen;
252 static int hf_xtp_sort;
253 static int hf_xtp_sync;
254 static int hf_xtp_seq;
255 /* control segment */
256 static int hf_xtp_cntl_rseq;
257 static int hf_xtp_cntl_alloc;
258 static int hf_xtp_cntl_echo;
259 static int hf_xtp_ecntl_rseq;
260 static int hf_xtp_ecntl_alloc;
261 static int hf_xtp_ecntl_echo;
262 static int hf_xtp_ecntl_nspan;
263 static int hf_xtp_ecntl_span_left;
264 static int hf_xtp_ecntl_span_right;
265 static int hf_xtp_tcntl_rseq;
266 static int hf_xtp_tcntl_alloc;
267 static int hf_xtp_tcntl_echo;
268 static int hf_xtp_tcntl_rsvd;
269 static int hf_xtp_tcntl_xkey;
270 /* traffic specifier */
271 static int hf_xtp_tspec_tlen;
272 static int hf_xtp_tspec_service;
273 static int hf_xtp_tspec_tformat;
274 static int hf_xtp_tspec_traffic;
275 static int hf_xtp_tspec_maxdata;
276 static int hf_xtp_tspec_inrate;
277 static int hf_xtp_tspec_outrate;
278 static int hf_xtp_tspec_inburst;
279 static int hf_xtp_tspec_outburst;
280 /* address segment */
281 static int hf_xtp_aseg_alen;
282 static int hf_xtp_aseg_adomain;
283 static int hf_xtp_aseg_aformat;
284 static int hf_xtp_aseg_address;
285 static int hf_xtp_aseg_dsthost;
286 static int hf_xtp_aseg_srchost;
287 static int hf_xtp_aseg_dstport;
288 static int hf_xtp_aseg_srcport;
289 /* others */
290 static int hf_xtp_btag;
291 static int hf_xtp_diag_code;
292 static int hf_xtp_diag_val;
293 static int hf_xtp_diag_msg;
294 static int hf_xtp_checksum;
295 static int hf_xtp_checksum_status;
296 static int hf_xtp_data;
298 /* Initialize the subtree pointers */
299 static int ett_xtp;
300 static int ett_xtp_cmd;
301 static int ett_xtp_cmd_options;
302 static int ett_xtp_cmd_ptype;
303 static int ett_xtp_cntl;
304 static int ett_xtp_ecntl;
305 static int ett_xtp_tcntl;
306 static int ett_xtp_tspec;
307 static int ett_xtp_jcntl;
308 static int ett_xtp_first;
309 static int ett_xtp_aseg;
310 static int ett_xtp_data;
311 static int ett_xtp_diag;
313 static expert_field ei_xtp_spans_bad;
314 static expert_field ei_xtp_checksum;
316 /* dissector of each payload */
317 static int
318 dissect_xtp_aseg(tvbuff_t *tvb, proto_tree *tree, uint32_t offset) {
319 uint32_t len = tvb_reported_length_remaining(tvb, offset);
320 uint32_t start = offset;
321 proto_item *ti, *ti2, *top_ti;
322 proto_tree *xtp_subtree;
323 struct xtp_ip_addr_seg aseg[1];
324 int error = 0;
326 xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_xtp_aseg, &top_ti, "Address Segment");
328 if (len < XTP_NULL_ADDR_SEG_LEN) {
329 proto_item_append_text(top_ti, ", bogus length(%u, must be at least %u)",
330 len, XTP_NULL_ADDR_SEG_LEN);
331 return 0;
334 /** parse common fields **/
335 /* alen(2) */
336 aseg->alen = tvb_get_ntohs(tvb, offset);
337 offset += 2;
338 /* adomain(1) */
339 aseg->adomain = tvb_get_uint8(tvb, offset);
340 offset++;
341 /* aformat(1) */
342 aseg->aformat = tvb_get_uint8(tvb, offset);
344 /** display common fields **/
345 offset = start;
346 /* alen(2) */
347 ti = proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_alen,
348 tvb, offset, 2, aseg->alen);
349 offset += 2;
350 if (aseg->alen > len) {
351 proto_item_append_text(ti, ", bogus length(%u, must be at most %u)",
352 aseg->alen, len);
353 error = 1;
355 /* adomain(1) */
356 proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_adomain,
357 tvb, offset, 1, aseg->adomain);
358 offset++;
359 /* aformat(1) */
360 ti2 = proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_aformat,
361 tvb, offset, 1, aseg->aformat);
362 offset++;
363 switch (aseg->aformat) {
364 case 0:
365 if (aseg->alen != XTP_NULL_ADDR_SEG_LEN) {
366 proto_item_append_text(ti, ", bogus length(%u, must be %u)",
367 aseg->alen, XTP_NULL_ADDR_SEG_LEN);
368 error = 1;
370 break;
371 case 1:
372 if (aseg->alen != XTP_IP_ADDR_SEG_LEN) {
373 proto_item_append_text(ti, ", bogus length(%u, must be %u)",
374 aseg->alen, XTP_IP_ADDR_SEG_LEN);
375 error = 1;
377 break;
378 default:
379 if (aseg->aformat < 128) {
380 proto_item_append_text(ti2,
381 ", Unsupported aformat(%u)", aseg->aformat);
382 error = 1;
384 break;
387 if (error)
388 return (offset - start);
390 /** parse and display each address fileds */
391 switch (aseg->aformat) {
392 case 0:
393 /* address(4) */
394 aseg->dsthost = tvb_get_ntohl(tvb, offset);
395 proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_address,
396 tvb, offset, 4, aseg->dsthost);
397 offset += 4;
398 break;
399 case 1:
400 /* dsthost(4) */
401 aseg->dsthost = tvb_get_ipv4(tvb, offset);
402 proto_tree_add_ipv4(xtp_subtree, hf_xtp_aseg_dsthost,
403 tvb, offset, 4, aseg->dsthost);
404 offset += 4;
405 /* srchost(4) */
406 aseg->srchost = tvb_get_ipv4(tvb, offset);
407 proto_tree_add_ipv4(xtp_subtree, hf_xtp_aseg_srchost,
408 tvb, offset, 4, aseg->srchost);
409 offset += 4;
410 /* dstport(2) */
411 aseg->dstport = tvb_get_ntohs(tvb, offset);
412 proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_dstport,
413 tvb, offset, 2, aseg->dstport);
414 offset += 2;
415 /* srcport(2) */
416 aseg->srcport = tvb_get_ntohs(tvb, offset);
417 proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_srcport,
418 tvb, offset, 2, aseg->srcport);
419 offset += 2;
421 /** add summary **/
422 proto_item_append_text(top_ti, ", Dst Port: %u", aseg->dstport);
423 proto_item_append_text(top_ti, ", Src Port: %u", aseg->srcport);
424 break;
425 default:
426 break;
429 return (offset - start);
432 static int
433 dissect_xtp_traffic_cntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
434 uint32_t offset) {
435 uint32_t len = tvb_reported_length_remaining(tvb, offset);
436 uint32_t start = offset;
437 proto_item *top_ti;
438 proto_tree *xtp_subtree;
439 struct xtp_traffic_cntl tcntl[1];
441 xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len,
442 ett_xtp_tcntl, &top_ti, "Traffic Control Segment");
444 if (len < XTP_TRAFFIC_CNTL_LEN) {
445 proto_item_append_text(top_ti,
446 ", bogus length(%u, must be at least %u)",
447 len, XTP_TRAFFIC_CNTL_LEN);
448 return 0;
451 /** parse **/
452 /* rseq(8) */
453 tcntl->rseq = tvb_get_ntohl(tvb, offset);
454 tcntl->rseq <<= 32;
455 tcntl->rseq += tvb_get_ntohl(tvb, offset+4);
456 offset += 8;
457 /* alloc(8) */
458 tcntl->alloc = tvb_get_ntohl(tvb, offset);
459 tcntl->alloc <<= 32;
460 tcntl->alloc += tvb_get_ntohl(tvb, offset+4);
461 offset += 8;
462 /* echo(4) */
463 tcntl->echo = tvb_get_ntohl(tvb, offset);
464 offset += 4;
465 /* rsvd(4) */
466 tcntl->rsvd = tvb_get_ntohl(tvb, offset);
467 offset += 4;
468 /* xkey(8) */
469 tcntl->xkey = tvb_get_ntohl(tvb, offset);
470 tcntl->xkey <<= 32;
471 tcntl->xkey += tvb_get_ntohl(tvb, offset+4);
473 /** add summary **/
474 col_append_fstr(pinfo->cinfo, COL_INFO,
475 " Recv-Seq=%" PRIu64, tcntl->rseq);
476 col_append_fstr(pinfo->cinfo, COL_INFO,
477 " Alloc=%" PRIu64, tcntl->alloc);
479 proto_item_append_text(top_ti,
480 ", Recv-Seq: %" PRIu64, tcntl->rseq);
482 /** display **/
483 offset = start;
484 /* rseq(8) */
485 proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_rseq,
486 tvb, offset, 8, tcntl->rseq);
487 offset += 8;
488 /* alloc(8) */
489 proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_alloc,
490 tvb, offset, 8, tcntl->alloc);
491 offset += 4;
492 /* echo(4) */
493 proto_tree_add_uint(xtp_subtree, hf_xtp_tcntl_echo,
494 tvb, offset, 4, tcntl->echo);
495 offset += 4;
496 /* rsvd(4) */
497 proto_tree_add_uint(xtp_subtree, hf_xtp_tcntl_rsvd,
498 tvb, offset, 4, tcntl->rsvd);
499 offset += 4;
500 /* xkey(8) */
501 proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_xkey,
502 tvb, offset, 8, tcntl->xkey);
503 offset += 8;
505 return (offset - start);
508 static int
509 dissect_xtp_tspec(tvbuff_t *tvb, proto_tree *tree, uint32_t offset) {
510 uint32_t len = tvb_reported_length_remaining(tvb, offset);
511 uint32_t start = offset;
512 proto_item *ti, *ti2;
513 proto_tree *xtp_subtree;
514 struct xtp_traffic_spec1 tspec[1];
515 int error = 0;
517 xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_xtp_tspec, &ti, "Traffic Specifier");
519 if (len < XTP_TRAFFIC_SPEC0_LEN) {
520 proto_item_append_text(ti,
521 ", bogus length(%u, must be at least %u)",
522 len, XTP_TRAFFIC_SPEC0_LEN);
523 return 0;
526 /** parse common fields **/
527 /* tlen(2) */
528 tspec->tlen = tvb_get_ntohs(tvb, offset);
529 offset += 2;
530 /* service(1) */
531 tspec->service = tvb_get_uint8(tvb, offset);
532 offset++;
533 /* tformat(1) */
534 tspec->tformat = tvb_get_uint8(tvb, offset);
536 /** display common fields */
537 offset = start;
538 /* tlen(2) */
539 ti = proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_tlen,
540 tvb, offset, 2, tspec->tlen);
541 offset += 2;
542 if (tspec->tlen > len) {
543 proto_item_append_text(ti, ", bogus length(%u, must be at most %u)",
544 tspec->tlen, len);
545 error = 1;
547 /* service(1) */
548 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_service,
549 tvb, offset, 1, tspec->service);
550 offset++;
551 /* tformat(1) */
552 ti2 = proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_tformat,
553 tvb, offset, 1, tspec->tformat);
554 offset++;
555 switch (tspec->tformat) {
556 case 0:
557 if (tspec->tlen != XTP_TRAFFIC_SPEC0_LEN) {
558 proto_item_append_text(ti, ", bogus length(%u, must be %u)",
559 tspec->tlen, XTP_TRAFFIC_SPEC0_LEN);
560 error = 1;
562 break;
563 case 1:
564 if (tspec->tlen != XTP_TRAFFIC_SPEC1_LEN) {
565 proto_item_append_text(ti, ", bogus length(%u, must be %u)",
566 tspec->tlen, XTP_TRAFFIC_SPEC1_LEN);
567 error = 1;
569 break;
570 default:
571 proto_item_append_text(ti2, ", Unsupported tformat(%u)",
572 tspec->tformat);
573 error = 1;
574 break;
577 if (error)
578 return (offset - start);
580 /** parse and display each traffic fields **/
581 switch (tspec->tformat) {
582 case 0:
583 /* traffic(4) */
584 tspec->maxdata = tvb_get_ntohl(tvb, offset);
585 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_traffic,
586 tvb, offset, 4, tspec->maxdata);
587 offset += 4;
588 break;
589 case 1:
590 /* maxdata(4) */
591 tspec->maxdata = tvb_get_ntohl(tvb, offset);
592 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_maxdata,
593 tvb, offset, 4, tspec->maxdata);
594 offset += 4;
595 /* inrate(4) */
596 tspec->inrate = tvb_get_ntohl(tvb, offset);
597 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_inrate,
598 tvb, offset, 4, tspec->inrate);
599 offset += 4;
600 /* inburst(4) */
601 tspec->inburst = tvb_get_ntohl(tvb, offset);
602 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_inburst,
603 tvb, offset, 4, tspec->inburst);
604 offset += 4;
605 /* outrate(4) */
606 tspec->outrate = tvb_get_ntohl(tvb, offset);
607 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_outrate,
608 tvb, offset, 4, tspec->outrate);
609 offset += 4;
610 /* outburst(4) */
611 tspec->outburst = tvb_get_ntohl(tvb, offset);
612 proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_outburst,
613 tvb, offset, 4, tspec->outburst);
614 offset += 4;
615 break;
616 default:
617 break;
620 return (offset - start);
623 static void
624 dissect_xtp_data(tvbuff_t *tvb, proto_tree *tree, uint32_t offset, bool have_btag) {
625 uint32_t len = tvb_reported_length_remaining(tvb, offset);
626 proto_tree *xtp_subtree;
627 uint64_t btag;
629 xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_xtp_data, NULL, "Data Segment");
631 if (have_btag) {
632 btag = tvb_get_ntohl(tvb, offset);
633 btag <<= 32;
634 btag += tvb_get_ntohl(tvb, offset+4);
635 proto_tree_add_uint64(xtp_subtree, hf_xtp_btag, tvb, offset, 8, btag);
636 offset += 8;
637 len -= 8;
640 proto_tree_add_item(xtp_subtree, hf_xtp_data, tvb, offset, len, ENC_NA);
642 return;
645 static void
646 dissect_xtp_cntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
647 uint32_t offset) {
648 uint32_t len = tvb_reported_length_remaining(tvb, offset);
649 uint32_t start = offset;
650 proto_item *top_ti;
651 proto_tree *xtp_subtree;
652 struct xtp_cntl cntl[1];
654 xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len,
655 ett_xtp_cntl, &top_ti, "Common Control Segment");
657 if (len != XTP_CNTL_PKT_LEN) {
658 proto_item_append_text(top_ti, ", bogus length(%u, must be %u)",
659 len, XTP_CNTL_PKT_LEN);
660 return;
663 /** parse **/
664 /* rseq(8) */
665 cntl->rseq = tvb_get_ntohl(tvb, offset);
666 cntl->rseq <<= 32;
667 cntl->rseq += tvb_get_ntohl(tvb, offset+4);
668 offset += 8;
669 /* alloc(8) */
670 cntl->alloc = tvb_get_ntohl(tvb, offset);
671 cntl->alloc <<= 32;
672 cntl->alloc += tvb_get_ntohl(tvb, offset+4);
673 offset += 8;
674 /* echo(4) */
675 cntl->echo = tvb_get_ntohl(tvb, offset);
677 /** add summary **/
678 col_append_fstr(pinfo->cinfo, COL_INFO,
679 " Recv-Seq=%" PRIu64, cntl->rseq);
680 col_append_fstr(pinfo->cinfo, COL_INFO,
681 " Alloc=%" PRIu64, cntl->alloc);
683 proto_item_append_text(top_ti,
684 ", Recv-Seq: %" PRIu64, cntl->rseq);
686 /** display **/
687 offset = start;
688 /* rseq(8) */
689 proto_tree_add_uint64(xtp_subtree, hf_xtp_cntl_rseq,
690 tvb, offset, 8, cntl->rseq);
691 offset += 8;
692 /* alloc(8) */
693 proto_tree_add_uint64(xtp_subtree, hf_xtp_cntl_alloc,
694 tvb, offset, 8, cntl->alloc);
695 offset += 4;
696 /* echo(4) */
697 proto_tree_add_uint(xtp_subtree, hf_xtp_cntl_echo,
698 tvb, offset, 4, cntl->echo);
700 return;
703 static void
704 dissect_xtp_first(tvbuff_t *tvb, proto_tree *tree, uint32_t offset) {
706 if (!dissect_xtp_aseg(tvb, tree, offset))
707 return;
709 offset += XTP_IP_ADDR_SEG_LEN;
710 dissect_xtp_tspec(tvb, tree, offset);
712 return;
715 #define XTP_MAX_NSPANS 10000 /* Arbitrary. (Documentation link is dead.) */
716 static void
717 dissect_xtp_ecntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
718 uint32_t offset) {
719 uint32_t len = tvb_reported_length_remaining(tvb, offset);
720 uint32_t start = offset;
721 proto_item *top_ti;
722 proto_tree *xtp_subtree;
723 struct xtp_ecntl ecntl[1];
724 unsigned spans_len;
725 unsigned i;
727 xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len,
728 ett_xtp_ecntl, &top_ti, "Error Control Segment");
730 if (len < MIN_XTP_ECNTL_PKT_LEN) {
731 proto_item_append_text(top_ti,
732 ", bogus length (%u, must be at least %u)",
733 len, MIN_XTP_ECNTL_PKT_LEN);
734 return;
737 /** parse **/
738 /* rseq(8) */
739 ecntl->rseq = tvb_get_ntohl(tvb, offset);
740 ecntl->rseq <<= 32;
741 ecntl->rseq += tvb_get_ntohl(tvb, offset+4);
742 offset += 8;
743 /* alloc(8) */
744 ecntl->alloc = tvb_get_ntohl(tvb, offset);
745 ecntl->alloc <<= 32;
746 ecntl->alloc += tvb_get_ntohl(tvb, offset+4);
747 offset += 8;
748 /* echo(4) */
749 ecntl->echo = tvb_get_ntohl(tvb, offset);
750 offset += 4;
751 /* nspan(4) */
752 ecntl->nspan = tvb_get_ntohl(tvb, offset);
753 offset += 4;
754 len = len + XTP_HEADER_LEN - offset;
755 spans_len = 16 * ecntl->nspan;
757 if (len != spans_len) {
758 expert_add_info_format(pinfo, top_ti, &ei_xtp_spans_bad, "Number of spans (%u) incorrect. Should be %u.", ecntl->nspan, len);
759 return;
762 if (ecntl->nspan > XTP_MAX_NSPANS) {
763 expert_add_info_format(pinfo, top_ti, &ei_xtp_spans_bad, "Too many spans: %u", ecntl->nspan);
764 return;
767 /** add summary **/
768 col_append_fstr(pinfo->cinfo, COL_INFO,
769 " Recv-Seq=%" PRIu64, ecntl->rseq);
770 col_append_fstr(pinfo->cinfo, COL_INFO,
771 " Alloc=%" PRIu64, ecntl->alloc);
773 proto_item_append_text(top_ti,
774 ", Recv-Seq: %" PRIu64, ecntl->rseq);
776 /** display **/
777 offset = start;
778 /* rseq(8) */
779 proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_rseq,
780 tvb, offset, 8, ecntl->rseq);
781 offset += 8;
782 /* alloc(8) */
783 proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_alloc,
784 tvb, offset, 8, ecntl->alloc);
785 offset += 8;
786 /* echo(4) */
787 proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_echo,
788 tvb, offset, 4, ecntl->echo);
789 offset += 4;
790 /* nspan(4) */
791 proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_nspan,
792 tvb, offset, 4, ecntl->nspan);
793 offset += 4;
794 /* spans(16n) */
795 for (i = 0; i < ecntl->nspan; i++) {
796 proto_tree_add_item(xtp_subtree, hf_xtp_ecntl_span_left,
797 tvb, offset, 8, ENC_LITTLE_ENDIAN);
798 offset += 8;
799 proto_tree_add_item(xtp_subtree, hf_xtp_ecntl_span_right,
800 tvb, offset, 8, ENC_LITTLE_ENDIAN);
801 offset += 8;
804 return;
807 static void
808 dissect_xtp_tcntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
809 uint32_t offset) {
811 if (!dissect_xtp_traffic_cntl(tvb, pinfo, tree, offset))
812 return;
814 offset += XTP_TRAFFIC_CNTL_LEN;
815 dissect_xtp_tspec(tvb, tree, offset);
817 return;
820 static void
821 dissect_xtp_jcntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
822 uint32_t offset) {
824 if (!dissect_xtp_traffic_cntl(tvb, pinfo, tree, offset))
825 return;
827 offset += XTP_TRAFFIC_CNTL_LEN;
828 if (!dissect_xtp_aseg(tvb, tree, offset))
829 return;
831 offset += XTP_IP_ADDR_SEG_LEN;
832 dissect_xtp_tspec(tvb, tree, offset);
834 return;
837 static void
838 dissect_xtp_diag(tvbuff_t *tvb, proto_tree *tree, uint32_t offset) {
839 uint32_t len = tvb_reported_length_remaining(tvb, offset);
840 proto_item *ti;
841 proto_tree *xtp_subtree;
843 xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_xtp_diag, &ti, "Diagnostic Segment");
845 if (len < XTP_DIAG_PKT_HEADER_LEN) {
846 proto_item_append_text(ti,
847 ", bogus length (%u, must be at least %u)",
848 len, XTP_DIAG_PKT_HEADER_LEN);
849 return;
852 /* code(4) */
853 proto_tree_add_item(xtp_subtree, hf_xtp_diag_code,
854 tvb, offset, 4, ENC_BIG_ENDIAN);
855 offset += 4;
856 /* val(4) */
857 proto_tree_add_item(xtp_subtree, hf_xtp_diag_val,
858 tvb, offset, 4, ENC_BIG_ENDIAN);
859 offset += 4;
860 /* message(n) */
861 proto_tree_add_item(xtp_subtree, hf_xtp_diag_msg,
862 tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_ASCII);
864 return;
867 /* main dissector */
868 static int
869 dissect_xtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
870 uint32_t offset, len;
871 proto_item *ti;
872 proto_tree *xtp_tree, *xtp_cmd_tree, *xtp_subtree;
873 struct xtphdr xtph[1];
874 int error = 0;
875 char *options;
876 static const char *fstr[] = { "<None>", "NOCHECK", "EDGE", "NOERR", "MULTI", "RES",
877 "SORT", "NOFLOW", "FASTNAK", "SREQ", "DREQ",
878 "RCLOSE", "WCLOSE", "EOM", "END", "BTAG" };
879 int fpos = 0, returned_length;
880 unsigned i, bpos;
881 unsigned cmd_options;
882 vec_t cksum_vec[1];
883 bool have_btag;
884 static int * const cmd_options_flags[] = {
885 &hf_xtp_cmd_options_nocheck,
886 &hf_xtp_cmd_options_edge,
887 &hf_xtp_cmd_options_noerr,
888 &hf_xtp_cmd_options_multi,
889 &hf_xtp_cmd_options_res,
890 &hf_xtp_cmd_options_sort,
891 &hf_xtp_cmd_options_noflow,
892 &hf_xtp_cmd_options_fastnak,
893 &hf_xtp_cmd_options_sreq,
894 &hf_xtp_cmd_options_dreq,
895 &hf_xtp_cmd_options_rclose,
896 &hf_xtp_cmd_options_wclose,
897 &hf_xtp_cmd_options_eom,
898 &hf_xtp_cmd_options_end,
899 &hf_xtp_cmd_options_btag,
900 NULL
903 if ((len = tvb_reported_length(tvb)) < XTP_HEADER_LEN)
904 return 0;
906 col_set_str(pinfo->cinfo, COL_PROTOCOL, "XTP");
907 col_clear(pinfo->cinfo, COL_INFO);
909 /** parse header **/
910 offset = 0;
911 /* key(8) */
912 xtph->key = tvb_get_ntohl(tvb, offset);
913 xtph->key <<= 32;
914 xtph->key += tvb_get_ntohl(tvb, offset+4);
915 offset += 8;
916 /* cmd(4) */
917 xtph->cmd = tvb_get_ntohl(tvb, offset);
918 xtph->cmd_options = xtph->cmd >> 8;
919 xtph->cmd_ptype = xtph->cmd & 0xff;
920 xtph->cmd_ptype_ver = (xtph->cmd_ptype & 0xe0) >> 5;
921 xtph->cmd_ptype_pformat = xtph->cmd_ptype & 0x1f;
922 offset += 4;
923 /* dlen(4) */
924 xtph->dlen = tvb_get_ntohl(tvb, offset);
925 offset += 4;
926 /* check(2) */
927 xtph->check = tvb_get_ntohs(tvb, offset);
928 offset += 2;
929 /* sort(2) */
930 xtph->sort = tvb_get_ntohs(tvb, offset);
931 offset += 2;
932 /* sync(4) */
933 xtph->sync = tvb_get_ntohl(tvb, offset);
934 offset += 4;
935 /* seq(8) */
936 xtph->seq = tvb_get_ntohl(tvb, offset);
937 xtph->seq <<= 32;
938 xtph->seq += tvb_get_ntohl(tvb, offset+4);
940 #define MAX_OPTIONS_LEN 128
941 options=(char *)wmem_alloc(pinfo->pool, MAX_OPTIONS_LEN);
942 options[0]=0;
943 cmd_options = xtph->cmd_options >> 8;
944 for (i = 0; i < 16; i++) {
945 bpos = 1 << (15 - i);
946 if (cmd_options & bpos) {
947 returned_length = snprintf(&options[fpos],
948 MAX_OPTIONS_LEN-fpos, "%s%s",
949 fpos?", ":"",
950 fstr[i]);
951 fpos += MIN(returned_length, MAX_OPTIONS_LEN-fpos);
955 col_add_str(pinfo->cinfo, COL_INFO,
956 val_to_str(xtph->cmd_ptype_pformat,
957 pformat_vals, "Unknown pformat (%u)"));
958 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", options);
959 col_append_fstr(pinfo->cinfo, COL_INFO,
960 " Seq=%" PRIu64, xtph->seq);
961 col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", xtph->dlen);
963 /* if (tree) */ {
964 ti = proto_tree_add_item(tree, proto_xtp, tvb, 0, -1, ENC_NA);
965 /** add summary **/
966 proto_item_append_text(ti,
967 ", Key: 0x%016" PRIX64, xtph->key);
968 proto_item_append_text(ti,
969 ", Seq: %" PRIu64, xtph->seq);
970 proto_item_append_text(ti, ", Len: %u", xtph->dlen);
972 xtp_tree = proto_item_add_subtree(ti, ett_xtp);
973 /* key(8) */
974 offset = 0;
975 proto_tree_add_uint64(xtp_tree, hf_xtp_key,
976 tvb, offset, 8, xtph->key);
977 offset += 8;
978 /* cmd(4) */
979 ti = proto_tree_add_uint(xtp_tree, hf_xtp_cmd,
980 tvb, offset, 4, xtph->cmd);
981 xtp_cmd_tree = proto_item_add_subtree(ti, ett_xtp_cmd);
982 proto_tree_add_bitmask(xtp_cmd_tree, tvb, offset, hf_xtp_cmd_options, ett_xtp_cmd_options, cmd_options_flags, ENC_BIG_ENDIAN);
983 offset += 3;
985 ti = proto_tree_add_uint(xtp_cmd_tree, hf_xtp_cmd_ptype,
986 tvb, offset, 1, xtph->cmd_ptype);
987 xtp_subtree = proto_item_add_subtree(ti, ett_xtp_cmd_ptype);
988 proto_tree_add_uint(xtp_subtree, hf_xtp_cmd_ptype_ver,
989 tvb, offset, 1, xtph->cmd_ptype_ver);
990 if (xtph->cmd_ptype_ver != XTP_VERSION_4) {
991 proto_item_append_text(ti,
992 ", Unknown XTP version (%03X)", xtph->cmd_ptype_ver);
993 error = 1;
995 proto_tree_add_uint(xtp_subtree, hf_xtp_cmd_ptype_pformat,
996 tvb, offset, 1, xtph->cmd_ptype_pformat);
997 offset++;
998 /* dlen(4) */
999 ti = proto_tree_add_uint(xtp_tree, hf_xtp_dlen,
1000 tvb, offset, 4, xtph->dlen);
1001 if (xtph->dlen != len - XTP_HEADER_LEN) {
1002 proto_item_append_text(ti, ", bogus length (%u, must be %u)",
1003 xtph->dlen, len - XTP_HEADER_LEN);
1004 error = 1;
1006 offset += 4;
1007 /* check(2) */
1008 if (!pinfo->fragmented) {
1009 uint32_t check_len = XTP_HEADER_LEN;
1010 if (!(xtph->cmd_options & XTP_CMD_OPTIONS_NOCHECK))
1011 check_len += xtph->dlen;
1012 SET_CKSUM_VEC_TVB(cksum_vec[0], tvb, 0, check_len);
1013 proto_tree_add_checksum(xtp_tree, tvb, offset, hf_xtp_checksum, hf_xtp_checksum_status, &ei_xtp_checksum,
1014 pinfo, in_cksum(cksum_vec, 1), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
1016 else {
1017 proto_tree_add_checksum(xtp_tree, tvb, offset, hf_xtp_checksum, hf_xtp_checksum_status, &ei_xtp_checksum,
1018 pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1020 offset += 2;
1021 /* sort(2) */
1022 proto_tree_add_uint(xtp_tree, hf_xtp_sort, tvb, offset, 2, xtph->sort);
1023 offset += 2;
1024 /* sync(4) */
1025 proto_tree_add_uint(xtp_tree, hf_xtp_sync, tvb, offset, 4, xtph->sync);
1026 offset += 4;
1027 /* seq(8) */
1028 proto_tree_add_uint64(xtp_tree, hf_xtp_seq, tvb, offset, 8, xtph->seq);
1029 offset += 8;
1031 if (!error) {
1032 switch (xtph->cmd_ptype_pformat) {
1033 case XTP_DATA_PKT:
1034 have_btag = !!(xtph->cmd_options & XTP_CMD_OPTIONS_BTAG);
1035 dissect_xtp_data(tvb, xtp_tree, offset, have_btag);
1036 break;
1037 case XTP_CNTL_PKT:
1038 dissect_xtp_cntl(tvb, pinfo, xtp_tree, offset);
1039 break;
1040 case XTP_FIRST_PKT:
1041 dissect_xtp_first(tvb, xtp_tree, offset);
1042 break;
1043 case XTP_ECNTL_PKT:
1044 dissect_xtp_ecntl(tvb, pinfo, xtp_tree, offset);
1045 break;
1046 case XTP_TCNTL_PKT:
1047 dissect_xtp_tcntl(tvb, pinfo, xtp_tree, offset);
1048 break;
1049 case XTP_JOIN_PKT:
1050 /* obsolete */
1051 break;
1052 case XTP_JCNTL_PKT:
1053 dissect_xtp_jcntl(tvb, pinfo, xtp_tree, offset);
1054 break;
1055 case XTP_DIAG_PKT:
1056 dissect_xtp_diag(tvb, xtp_tree, offset);
1057 break;
1058 default:
1059 /* error */
1060 break;
1065 return tvb_reported_length(tvb);
1068 void
1069 proto_register_xtp(void)
1071 static hf_register_info hf[] = {
1072 /* command header */
1073 { &hf_xtp_key,
1074 { "Key", "xtp.key",
1075 FT_UINT64, BASE_HEX, NULL, 0x0,
1076 NULL, HFILL }
1078 { &hf_xtp_cmd,
1079 { "Command", "xtp.cmd",
1080 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }
1082 { &hf_xtp_cmd_options,
1083 { "Options", "xtp.cmd.options",
1084 FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL }
1086 { &hf_xtp_cmd_options_nocheck,
1087 { "NOCHECK", "xtp.cmd.options.nocheck",
1088 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1089 XTP_CMD_OPTIONS_NOCHECK, NULL, HFILL }
1091 { &hf_xtp_cmd_options_edge,
1092 { "EDGE", "xtp.cmd.options.edge",
1093 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1094 XTP_CMD_OPTIONS_EDGE, NULL, HFILL }
1096 { &hf_xtp_cmd_options_noerr,
1097 { "NOERR", "xtp.cmd.options.noerr",
1098 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1099 XTP_CMD_OPTIONS_NOERR, NULL, HFILL }
1101 { &hf_xtp_cmd_options_multi,
1102 { "MULTI", "xtp.cmd.options.multi",
1103 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1104 XTP_CMD_OPTIONS_MULTI, NULL, HFILL }
1106 { &hf_xtp_cmd_options_res,
1107 { "RES", "xtp.cmd.options.res",
1108 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1109 XTP_CMD_OPTIONS_RES, NULL, HFILL }
1111 { &hf_xtp_cmd_options_sort,
1112 { "SORT", "xtp.cmd.options.sort",
1113 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1114 XTP_CMD_OPTIONS_SORT, NULL, HFILL }
1116 { &hf_xtp_cmd_options_noflow,
1117 { "NOFLOW", "xtp.cmd.options.noflow",
1118 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1119 XTP_CMD_OPTIONS_NOFLOW, NULL, HFILL }
1121 { &hf_xtp_cmd_options_fastnak,
1122 { "FASTNAK", "xtp.cmd.options.fastnak",
1123 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1124 XTP_CMD_OPTIONS_FASTNAK, NULL, HFILL }
1126 { &hf_xtp_cmd_options_sreq,
1127 { "SREQ", "xtp.cmd.options.sreq",
1128 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1129 XTP_CMD_OPTIONS_SREQ, NULL, HFILL }
1131 { &hf_xtp_cmd_options_dreq,
1132 { "DREQ", "xtp.cmd.options.dreq",
1133 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1134 XTP_CMD_OPTIONS_DREQ, NULL, HFILL }
1136 { &hf_xtp_cmd_options_rclose,
1137 { "RCLOSE", "xtp.cmd.options.rclose",
1138 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1139 XTP_CMD_OPTIONS_RCLOSE, NULL, HFILL }
1141 { &hf_xtp_cmd_options_wclose,
1142 { "WCLOSE", "xtp.cmd.options.wclose",
1143 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1144 XTP_CMD_OPTIONS_WCLOSE, NULL, HFILL }
1146 { &hf_xtp_cmd_options_eom,
1147 { "EOM", "xtp.cmd.options.eom",
1148 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1149 XTP_CMD_OPTIONS_EOM, NULL, HFILL }
1151 { &hf_xtp_cmd_options_end,
1152 { "END", "xtp.cmd.options.end",
1153 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1154 XTP_CMD_OPTIONS_END, NULL, HFILL }
1156 { &hf_xtp_cmd_options_btag,
1157 { "BTAG", "xtp.cmd.options.btag",
1158 FT_BOOLEAN, 24, TFS(&tfs_set_notset),
1159 XTP_CMD_OPTIONS_BTAG, NULL, HFILL }
1161 { &hf_xtp_cmd_ptype,
1162 { "Packet type", "xtp.cmd.ptype",
1163 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
1165 { &hf_xtp_cmd_ptype_ver,
1166 { "Version", "xtp.cmd.ptype.ver",
1167 FT_UINT8, BASE_DEC, VALS(version_vals), 0x0, NULL, HFILL }
1169 { &hf_xtp_cmd_ptype_pformat,
1170 { "Format", "xtp.cmd.ptype.pformat",
1171 FT_UINT8, BASE_DEC, VALS(pformat_vals), 0x0, NULL, HFILL }
1173 { &hf_xtp_dlen,
1174 { "Data length", "xtp.dlen",
1175 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1177 { &hf_xtp_sort,
1178 { "Sort", "xtp.sort",
1179 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1181 { &hf_xtp_sync,
1182 { "Synchronizing handshake", "xtp.sync",
1183 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1185 { &hf_xtp_seq,
1186 { "Sequence number", "xtp.seq",
1187 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1189 /* control segment */
1190 { &hf_xtp_cntl_rseq,
1191 { "Received sequence number", "xtp.cntl.rseq",
1192 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1194 { &hf_xtp_cntl_alloc,
1195 { "Allocation", "xtp.cntl.alloc",
1196 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1198 { &hf_xtp_cntl_echo,
1199 { "Synchronizing handshake echo", "xtp.cntl.echo",
1200 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1202 { &hf_xtp_ecntl_rseq,
1203 { "Received sequence number", "xtp.ecntl.rseq",
1204 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1206 { &hf_xtp_ecntl_alloc,
1207 { "Allocation", "xtp.ecntl.alloc",
1208 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1210 { &hf_xtp_ecntl_echo,
1211 { "Synchronizing handshake echo", "xtp.ecntl.echo",
1212 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1214 { &hf_xtp_ecntl_nspan,
1215 { "Number of spans", "xtp.ecntl.nspan",
1216 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1218 { &hf_xtp_ecntl_span_left,
1219 { "Span left edge", "xtp.ecntl.span_le",
1220 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1222 { &hf_xtp_ecntl_span_right,
1223 { "Span right edge", "xtp.ecntl.span_re",
1224 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1226 { &hf_xtp_tcntl_rseq,
1227 { "Received sequence number", "xtp.tcntl.rseq",
1228 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1230 { &hf_xtp_tcntl_alloc,
1231 { "Allocation", "xtp.tcntl.alloc",
1232 FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
1234 { &hf_xtp_tcntl_echo,
1235 { "Synchronizing handshake echo", "xtp.tcntl.echo",
1236 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1238 { &hf_xtp_tcntl_rsvd,
1239 { "Reserved", "xtp.tcntl.rsvd",
1240 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1242 { &hf_xtp_tcntl_xkey,
1243 { "Exchange key", "xtp.tcntl.xkey",
1244 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }
1246 /* traffic specifier */
1247 { &hf_xtp_tspec_tlen,
1248 { "Length", "xtp.tspec.tlen",
1249 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1251 { &hf_xtp_tspec_service,
1252 { "Service", "xtp.tspec.service",
1253 FT_UINT8, BASE_DEC, VALS(service_vals), 0x0, NULL, HFILL }
1255 { &hf_xtp_tspec_tformat,
1256 { "Format", "xtp.tspec.format",
1257 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
1259 { &hf_xtp_tspec_traffic,
1260 { "Traffic", "xtp.tspec.traffic",
1261 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1263 { &hf_xtp_tspec_maxdata,
1264 { "Maxdata", "xtp.tspec.maxdata",
1265 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1267 { &hf_xtp_tspec_inrate,
1268 { "Incoming rate", "xtp.tspec.inrate",
1269 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1271 { &hf_xtp_tspec_inburst,
1272 { "Incoming burst size", "xtp.tspec.inburst",
1273 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1275 { &hf_xtp_tspec_outrate,
1276 { "Outgoing rate", "xtp.tspec.outrate",
1277 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1279 { &hf_xtp_tspec_outburst,
1280 { "Outgoing burst size", "xtp.tspec.outburst",
1281 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1283 /* address segment */
1284 { &hf_xtp_aseg_alen,
1285 { "Length", "xtp.aseg.alen",
1286 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1288 { &hf_xtp_aseg_adomain,
1289 { "Domain", "xtp.aseg.adomain",
1290 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
1292 { &hf_xtp_aseg_aformat,
1293 { "Format", "xtp.aseg.aformat",
1294 FT_UINT8, BASE_DEC, VALS(aformat_vals), 0x0, NULL, HFILL }
1296 { &hf_xtp_aseg_address,
1297 { "Traffic", "xtp.aseg.address",
1298 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
1300 { &hf_xtp_aseg_dsthost,
1301 { "Destination host", "xtp.aseg.dsthost",
1302 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }
1304 { &hf_xtp_aseg_srchost,
1305 { "Source host", "xtp.aseg.srchost",
1306 FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }
1308 { &hf_xtp_aseg_dstport,
1309 { "Destination port", "xtp.aseg.dstport",
1310 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1312 { &hf_xtp_aseg_srcport,
1313 { "Source port", "xtp.aseg.srcport",
1314 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1316 /* others */
1317 { &hf_xtp_btag,
1318 { "Beginning tag", "xtp.data.btag",
1319 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }
1321 { &hf_xtp_diag_code,
1322 { "Diagnostic code", "xtp.diag.code",
1323 FT_UINT32, BASE_DEC, VALS(diag_code_vals), 0x0, NULL, HFILL }
1325 { &hf_xtp_diag_val,
1326 { "Diagnostic value", "xtp.diag.val",
1327 FT_UINT32, BASE_DEC, VALS(diag_val_vals), 0x0, NULL, HFILL }
1329 { &hf_xtp_diag_msg,
1330 { "Message", "xtp.diag.msg",
1331 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
1333 { &hf_xtp_checksum,
1334 { "Checksum", "xtp.checksum",
1335 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
1337 { &hf_xtp_checksum_status,
1338 { "Checksum Status", "xtp.checksum.status",
1339 FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }
1341 { &hf_xtp_data,
1342 { "Data", "xtp.data",
1343 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
1347 static int *ett[] = {
1348 &ett_xtp,
1349 &ett_xtp_cmd,
1350 &ett_xtp_cmd_options,
1351 &ett_xtp_cmd_ptype,
1352 &ett_xtp_cntl,
1353 &ett_xtp_ecntl,
1354 &ett_xtp_tcntl,
1355 &ett_xtp_tspec,
1356 &ett_xtp_jcntl,
1357 &ett_xtp_first,
1358 &ett_xtp_aseg,
1359 &ett_xtp_data,
1360 &ett_xtp_diag,
1363 static ei_register_info ei[] = {
1364 { &ei_xtp_spans_bad,
1365 { "xtp.spans_bad", PI_MALFORMED, PI_ERROR, "Number of spans incorrect", EXPFILL }},
1366 { &ei_xtp_checksum,
1367 { "xtp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
1370 expert_module_t* expert_xtp;
1372 proto_xtp = proto_register_protocol("Xpress Transport Protocol", "XTP", "xtp");
1373 proto_register_field_array(proto_xtp, hf, array_length(hf));
1374 proto_register_subtree_array(ett, array_length(ett));
1376 expert_xtp = expert_register_protocol(proto_xtp);
1377 expert_register_field_array(expert_xtp, ei, array_length(ei));
1379 xtp_handle = register_dissector("xtp", dissect_xtp, proto_xtp);
1382 void
1383 proto_reg_handoff_xtp(void)
1385 dissector_add_uint("ip.proto", IP_PROTO_XTP, xtp_handle);
1389 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1391 * Local variables:
1392 * c-basic-offset: 8
1393 * tab-width: 8
1394 * indent-tabs-mode: t
1395 * End:
1397 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1398 * :indentSize=8:tabSize=8:noTabs=false: