2 * Routines for x25 packet disassembly
3 * Olivier Abad <oabad@cybercable.fr>
5 * $Id: packet-x25.c,v 1.53 2001/07/18 15:49:29 oabad Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
45 #define X25_CALL_REQUEST 0x0B
46 #define X25_CALL_ACCEPTED 0x0F
47 #define X25_CLEAR_REQUEST 0x13
48 #define X25_CLEAR_CONFIRMATION 0x17
49 #define X25_INTERRUPT 0x23
50 #define X25_INTERRUPT_CONFIRMATION 0x27
51 #define X25_RESET_REQUEST 0x1B
52 #define X25_RESET_CONFIRMATION 0x1F
53 #define X25_RESTART_REQUEST 0xFB
54 #define X25_RESTART_CONFIRMATION 0xFF
55 #define X25_REGISTRATION_REQUEST 0xF3
56 #define X25_REGISTRATION_CONFIRMATION 0xF7
57 #define X25_DIAGNOSTIC 0xF1
63 #define X25_FAC_CLASS_MASK 0xC0
65 #define X25_FAC_CLASS_A 0x00
66 #define X25_FAC_CLASS_B 0x40
67 #define X25_FAC_CLASS_C 0x80
68 #define X25_FAC_CLASS_D 0xC0
70 #define X25_FAC_COMP_MARK 0x00
71 #define X25_FAC_REVERSE 0x01
72 #define X25_FAC_THROUGHPUT 0x02
73 #define X25_FAC_CUG 0x03
74 #define X25_FAC_CALLED_MODIF 0x08
75 #define X25_FAC_CUG_OUTGOING_ACC 0x09
76 #define X25_FAC_THROUGHPUT_MIN 0x0A
77 #define X25_FAC_EXPRESS_DATA 0x0B
78 #define X25_FAC_BILATERAL_CUG 0x41
79 #define X25_FAC_PACKET_SIZE 0x42
80 #define X25_FAC_WINDOW_SIZE 0x43
81 #define X25_FAC_RPOA_SELECTION 0x44
82 #define X25_FAC_TRANSIT_DELAY 0x49
83 #define X25_FAC_CALL_TRANSFER 0xC3
84 #define X25_FAC_CALLED_ADDR_EXT 0xC9
85 #define X25_FAC_ETE_TRANSIT_DELAY 0xCA
86 #define X25_FAC_CALLING_ADDR_EXT 0xCB
87 #define X25_FAC_CALL_DEFLECT 0xD1
88 #define X25_FAC_PRIORITY 0xD2
90 static int proto_x25 = -1;
91 static int hf_x25_gfi = -1;
92 static int hf_x25_abit = -1;
93 static int hf_x25_qbit = -1;
94 static int hf_x25_dbit = -1;
95 static int hf_x25_mod = -1;
96 static int hf_x25_lcn = -1;
97 static int hf_x25_type = -1;
98 static int hf_x25_p_r_mod8 = -1;
99 static int hf_x25_p_r_mod128 = -1;
100 static int hf_x25_mbit_mod8 = -1;
101 static int hf_x25_mbit_mod128 = -1;
102 static int hf_x25_p_s_mod8 = -1;
103 static int hf_x25_p_s_mod128 = -1;
105 static gint ett_x25 = -1;
106 static gint ett_x25_gfi = -1;
107 static gint ett_x25_fac = -1;
108 static gint ett_x25_fac_unknown = -1;
109 static gint ett_x25_fac_mark = -1;
110 static gint ett_x25_fac_reverse = -1;
111 static gint ett_x25_fac_throughput = -1;
112 static gint ett_x25_fac_cug = -1;
113 static gint ett_x25_fac_called_modif = -1;
114 static gint ett_x25_fac_cug_outgoing_acc = -1;
115 static gint ett_x25_fac_throughput_min = -1;
116 static gint ett_x25_fac_express_data = -1;
117 static gint ett_x25_fac_bilateral_cug = -1;
118 static gint ett_x25_fac_packet_size = -1;
119 static gint ett_x25_fac_window_size = -1;
120 static gint ett_x25_fac_rpoa_selection = -1;
121 static gint ett_x25_fac_transit_delay = -1;
122 static gint ett_x25_fac_call_transfer = -1;
123 static gint ett_x25_fac_called_addr_ext = -1;
124 static gint ett_x25_fac_ete_transit_delay = -1;
125 static gint ett_x25_fac_calling_addr_ext = -1;
126 static gint ett_x25_fac_call_deflect = -1;
127 static gint ett_x25_fac_priority = -1;
129 static const value_string vals_modulo[] = {
135 static const value_string vals_x25_type[] = {
136 { X25_CALL_REQUEST, "Call" },
137 { X25_CALL_ACCEPTED, "Call Accepted" },
138 { X25_CLEAR_REQUEST, "Clear" },
139 { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
140 { X25_INTERRUPT, "Interrupt" },
141 { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
142 { X25_RESET_REQUEST, "Reset" },
143 { X25_RESET_CONFIRMATION, "Reset Confirmation" },
144 { X25_RESTART_REQUEST, "Restart" },
145 { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
146 { X25_REGISTRATION_REQUEST, "Registration" },
147 { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
148 { X25_DIAGNOSTIC, "Diagnostic" },
152 { X25_DATA, "DATA" },
156 static dissector_handle_t ip_handle;
157 static dissector_handle_t ositp_handle;
160 * each vc_info node contains :
161 * the time of the first frame using this dissector (secs and usecs)
162 * the time of the last frame using this dissector (0 if it is unknown)
163 * a pointer to the dissector
165 * the "time of first frame" is initialized when a Call Req. is received
166 * the "time of last frame" is initialized when a Clear, Reset, or Restart
169 typedef struct _vc_info {
170 guint32 first_frame_secs, first_frame_usecs;
171 guint32 last_frame_secs, last_frame_usecs;
172 dissector_handle_t dissect;
173 struct _vc_info *next;
177 * the hash table will contain linked lists of global_vc_info
178 * each global_vc_info struct contains :
179 * the VC number (the hash table is indexed with VC % 64)
180 * a linked list of vc_info
182 typedef struct _global_vc_info {
185 struct _global_vc_info *next;
188 static global_vc_info *hash_table[64];
191 free_vc_info(vc_info *pt)
203 reinit_x25_hashtable(void)
207 for (i=0; i<64; i++) {
208 if (hash_table[i]) /* not NULL ==> free */
210 global_vc_info *hash_ent, *hash_ent2;
211 hash_ent2 = hash_ent = hash_table[i];
214 hash_ent2 = hash_ent;
215 hash_ent = hash_ent->next;
216 free_vc_info(hash_ent2->info);
225 x25_hash_add_proto_start(guint16 vc, guint32 frame_secs, guint32 frame_usecs,
226 dissector_handle_t dissect)
229 global_vc_info *hash_ent;
230 global_vc_info *hash_ent2;
232 if (hash_table[idx] == 0)
234 hash_ent = (global_vc_info *)g_malloc(sizeof(global_vc_info));
236 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
239 hash_ent->vc_num = vc;
241 hash_ent->info = (vc_info *)g_malloc(sizeof(vc_info));
242 if (!hash_ent->info) {
243 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
246 hash_ent->info->first_frame_secs = frame_secs;
247 hash_ent->info->first_frame_usecs = frame_usecs;
248 hash_ent->info->last_frame_secs = 0;
249 hash_ent->info->last_frame_usecs = 0;
250 hash_ent->info->dissect = dissect;
251 hash_ent->info->next = 0;
252 hash_table[idx] = hash_ent;
256 hash_ent2 = hash_ent = hash_table[idx];
257 /* search an entry with the same VC number */
258 while (hash_ent != NULL && hash_ent->vc_num != vc) {
259 hash_ent2 = hash_ent;
260 hash_ent = hash_ent->next;
262 if (hash_ent != NULL) /* hash_ent->vc_num == vc */
264 vc_info *vci = hash_ent->info;
265 while (vci->next) vci = vci->next; /* last element */
266 if (vci->dissect == dissect) {
267 vci->last_frame_secs = 0;
268 vci->last_frame_usecs = 0;
271 vci->next = (vc_info *)g_malloc(sizeof(vc_info));
272 if (vci->next == 0) {
273 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
276 vci->next->first_frame_secs = frame_secs;
277 vci->next->first_frame_usecs = frame_usecs;
278 vci->next->last_frame_secs = 0;
279 vci->next->last_frame_usecs = 0;
280 vci->next->dissect = dissect;
284 else /* new vc number */
286 hash_ent2->next = (global_vc_info *)g_malloc(sizeof(global_vc_info));
287 if (!hash_ent2->next) {
288 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
291 hash_ent2->next->info = (vc_info *)g_malloc(sizeof(vc_info));
292 if (!hash_ent2->next->info) {
293 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
296 hash_ent2->next->info->first_frame_secs = frame_secs;
297 hash_ent2->next->info->first_frame_usecs = frame_usecs;
298 hash_ent2->next->info->last_frame_secs = 0;
299 hash_ent2->next->info->last_frame_usecs = 0;
300 hash_ent2->next->info->dissect = dissect;
301 hash_ent2->next->info->next = 0;
307 x25_hash_add_proto_end(guint16 vc, guint32 frame_secs, guint32 frame_usecs)
309 global_vc_info *hash_ent = hash_table[vc%64];
312 if (!hash_ent) return;
313 while(hash_ent->vc_num != vc) hash_ent = hash_ent->next;
314 if (!hash_ent) return;
316 vci = hash_ent->info;
317 while (vci->next) vci = vci->next;
318 vci->last_frame_secs = frame_secs;
319 vci->last_frame_usecs = frame_usecs;
322 static dissector_handle_t
323 x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc)
325 global_vc_info *hash_ent = hash_table[vc%64];
329 if (!hash_ent) return 0;
331 while(hash_ent && hash_ent->vc_num != vc) hash_ent = hash_ent->next;
332 if (!hash_ent) return 0;
334 /* a hash_ent was found for this VC number */
335 vci2 = vci = hash_ent->info;
337 /* looking for an entry matching our frame time */
338 while (vci && (vci->last_frame_secs < frame_secs ||
339 (vci->last_frame_secs == frame_secs &&
340 vci->last_frame_usecs < frame_usecs))) {
344 /* we reached last record, and previous record has a non zero
345 * last frame time ==> no dissector */
346 if (!vci && (vci2->last_frame_secs || vci2->last_frame_usecs)) return 0;
348 /* we reached last record, and previous record has a zero last frame time
349 * ==> dissector for previous frame has not been "stopped" by a Clear, etc */
351 /* if the start time for vci2 is greater than our frame time
352 * ==> no dissector */
353 if (frame_secs < vci2->first_frame_secs ||
354 (frame_secs == vci2->first_frame_secs &&
355 frame_usecs < vci2->first_frame_usecs))
358 return vci2->dissect;
361 /* our frame time is before vci's end. Check if it is adter vci's start */
362 if (frame_secs < vci->first_frame_secs ||
363 (frame_secs == vci->first_frame_secs &&
364 frame_usecs < vci->first_frame_usecs))
370 static char *clear_code(unsigned char code)
372 static char buffer[25];
374 if (code == 0x00 || (code & 0x80) == 0x80)
375 return "DTE Originated";
377 return "Number Busy";
379 return "Invalid Facility Requested";
381 return "Network Congestion";
383 return "Out Of Order";
385 return "Access Barred";
387 return "Not Obtainable";
389 return "Remote Procedure Error";
391 return "Local Procedure Error";
393 return "RPOA Out Of Order";
395 return "Reverse Charging Acceptance Not Subscribed";
397 return "Incompatible Destination";
399 return "Fast Select Acceptance Not Subscribed";
401 return "Destination Absent";
403 sprintf(buffer, "Unknown %02X", code);
408 static char *clear_diag(unsigned char code)
410 static char buffer[25];
413 return "No additional information";
415 return "Invalid P(S)";
417 return "Invalid P(R)";
419 return "Packet type invalid";
421 return "Packet type invalid for state r1";
423 return "Packet type invalid for state r2";
425 return "Packet type invalid for state r3";
427 return "Packet type invalid for state p1";
429 return "Packet type invalid for state p2";
431 return "Packet type invalid for state p3";
433 return "Packet type invalid for state p4";
435 return "Packet type invalid for state p5";
437 return "Packet type invalid for state p6";
439 return "Packet type invalid for state p7";
441 return "Packet type invalid for state d1";
443 return "Packet type invalid for state d2";
445 return "Packet type invalid for state d3";
447 return "Packet not allowed";
449 return "Unidentifiable packet";
451 return "Call on one-way logical channel";
453 return "Invalid packet type on a PVC";
455 return "Packet on unassigned LC";
457 return "Reject not subscribed to";
459 return "Packet too short";
461 return "Packet too long";
463 return "Invalid general format identifier";
465 return "Restart/registration packet with nonzero bits";
467 return "Packet type not compatible with facility";
469 return "Unauthorised interrupt confirmation";
471 return "Unauthorised interrupt";
473 return "Unauthorised reject";
475 return "Time expired";
477 return "Time expired for incoming call";
479 return "Time expired for clear indication";
481 return "Time expired for reset indication";
483 return "Time expired for restart indication";
485 return "Time expired for call deflection";
487 return "Call set-up/clearing or registration pb.";
489 return "Facility/registration code not allowed";
491 return "Facility parameter not allowed";
493 return "Invalid called DTE address";
495 return "Invalid calling DTE address";
497 return "Invalid facility/registration length";
499 return "Incoming call barred";
501 return "No logical channel available";
503 return "Call collision";
505 return "Duplicate facility requested";
507 return "Non zero address length";
509 return "Non zero facility length";
511 return "Facility not provided when expected";
513 return "Invalid CCITT-specified DTE facility";
515 return "Max. nb of call redir/defl. exceeded";
517 return "Miscellaneous";
519 return "Improper cause code from DTE";
521 return "Not aligned octet";
523 return "Inconsistent Q bit setting";
525 return "NUI problem";
527 return "International problem";
529 return "Remote network problem";
531 return "International protocol problem";
533 return "International link out of order";
535 return "International link busy";
537 return "Transit network facility problem";
539 return "Remote network facility problem";
541 return "International routing problem";
543 return "Temporary routing problem";
545 return "Unknown called DNIC";
547 return "Maintenance action";
549 return "Timer expired or retransmission count surpassed";
551 return "Timer expired or retransmission count surpassed for INTERRUPT";
553 return "Timer expired or retransmission count surpassed for DATA "
554 "packet transmission";
556 return "Timer expired or retransmission count surpassed for REJECT";
558 return "DTE-specific signals";
560 return "DTE operational";
562 return "DTE not operational";
564 return "DTE resource constraint";
566 return "Fast select not subscribed";
568 return "Invalid partially full DATA packet";
570 return "D-bit procedure not supported";
572 return "Registration/Cancellation confirmed";
574 return "OSI network service problem";
576 return "Disconnection (transient condition)";
578 return "Disconnection (permanent condition)";
580 return "Connection rejection - reason unspecified (transient "
583 return "Connection rejection - reason unspecified (permanent "
586 return "Connection rejection - quality of service not available "
587 "transient condition)";
589 return "Connection rejection - quality of service not available "
590 "permanent condition)";
592 return "Connection rejection - NSAP unreachable (transient condition)";
594 return "Connection rejection - NSAP unreachable (permanent condition)";
596 return "reset - reason unspecified";
598 return "reset - congestion";
600 return "Connection rejection - NSAP address unknown (permanent "
603 return "Higher layer initiated";
605 return "Disconnection - normal";
607 return "Disconnection - abnormal";
609 return "Disconnection - incompatible information in user data";
611 return "Connection rejection - reason unspecified (transient "
614 return "Connection rejection - reason unspecified (permanent "
617 return "Connection rejection - quality of service not available "
618 "(transient condition)";
620 return "Connection rejection - quality of service not available "
621 "(permanent condition)";
623 return "Connection rejection - incompatible information in user data";
625 return "Connection rejection - unrecognizable protocol indentifier "
628 return "Reset - user resynchronization";
630 sprintf(buffer, "Unknown %d", code);
635 static char *reset_code(unsigned char code)
637 static char buffer[25];
639 if (code == 0x00 || (code & 0x80) == 0x80)
640 return "DTE Originated";
642 return "Out of order";
644 return "Remote Procedure Error";
646 return "Local Procedure Error";
648 return "Network Congestion";
650 return "Remote DTE operational";
652 return "Network operational";
654 return "Incompatible Destination";
656 return "Network out of order";
658 sprintf(buffer, "Unknown %02X", code);
663 static char *restart_code(unsigned char code)
665 static char buffer[25];
667 if (code == 0x00 || (code & 0x80) == 0x80)
668 return "DTE Originated";
670 return "Local Procedure Error";
672 return "Network Congestion";
674 return "Network Operational";
676 return "Registration/cancellation confirmed";
678 sprintf(buffer, "Unknown %02X", code);
683 static char *registration_code(unsigned char code)
685 static char buffer[25];
688 return "Invalid facility request";
690 return "Network congestion";
692 return "Local procedure error";
694 return "Registration/cancellation confirmed";
696 sprintf(buffer, "Unknown %02X", code);
702 dump_facilities(proto_tree *tree, int *offset, tvbuff_t *tvb)
704 guint8 fac, byte1, byte2, byte3;
705 guint32 len; /* facilities length */
707 proto_tree *fac_tree = 0;
708 proto_tree *fac_subtree;
710 len = tvb_get_guint8(tvb, *offset);
712 ti = proto_tree_add_text(tree, tvb, *offset, len + 1,
714 fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
715 proto_tree_add_text(fac_tree, tvb, *offset, 1,
716 "Facilities length: %d", len);
721 fac = tvb_get_guint8(tvb, *offset);
722 switch(fac & X25_FAC_CLASS_MASK) {
723 case X25_FAC_CLASS_A:
725 case X25_FAC_COMP_MARK:
727 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
728 "Code : 00 (Marker)");
729 switch (tvb_get_guint8(tvb, *offset + 1)) {
732 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
733 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
734 "Parameter : 00 (Network complementary "
735 "services - calling DTE)");
740 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
741 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
742 "Parameter : FF (Network complementary "
743 "services - called DTE)");
748 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
749 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
750 "Parameter : 0F (DTE complementary "
756 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
757 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
758 "Parameter : %02X (Unknown marker)",
759 tvb_get_guint8(tvb, *offset+1));
764 case X25_FAC_REVERSE:
766 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
767 "(Reverse charging / Fast select)", fac);
768 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
769 byte1 = tvb_get_guint8(tvb, *offset + 1);
770 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
771 "Parameter : %02X", byte1);
773 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
774 "11.. .... = Fast select with restriction");
775 else if (byte1 & 0x80)
776 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
777 "10.. .... = Fast select - no restriction");
779 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
780 "00.. .... = Fast select not requested");
781 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
782 decode_boolean_bitfield(byte1, 0x01, 1*8,
783 "Reverse charging requested",
784 "Reverse charging not requested"));
787 case X25_FAC_THROUGHPUT:
791 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
792 "(Throughput class negociation)", fac);
793 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
794 byte1 = tvb_get_guint8(tvb, *offset + 1);
806 sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
807 75*(1<<((byte1 >> 4)-3)));
810 sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
813 sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
816 sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
818 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
819 decode_numeric_bitfield(byte1, 0xF0, 1*8, tmpbuf));
820 switch (byte1 & 0x0F)
831 sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
832 75*(1<<((byte1 & 0x0F)-3)));
835 sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
838 sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
841 sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
843 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
844 decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
849 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
850 "(Closed user group selection)", fac);
851 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
852 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
853 "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
856 case X25_FAC_CALLED_MODIF:
858 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
859 "(Called address modified)", fac);
860 fac_subtree = proto_item_add_subtree(ti,
861 ett_x25_fac_called_modif);
862 proto_tree_add_text(fac_tree, tvb, *offset+1, 1,
863 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
866 case X25_FAC_CUG_OUTGOING_ACC:
868 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
869 "(Closed user group with outgoing access selection)",
871 fac_subtree = proto_item_add_subtree(ti,
872 ett_x25_fac_cug_outgoing_acc);
873 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
874 "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
877 case X25_FAC_THROUGHPUT_MIN:
879 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
880 "(Minimum throughput class)", fac);
881 fac_subtree = proto_item_add_subtree(ti,
882 ett_x25_fac_throughput_min);
883 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
884 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
887 case X25_FAC_EXPRESS_DATA:
889 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
890 "(Negociation of express data)", fac);
891 fac_subtree = proto_item_add_subtree(ti,
892 ett_x25_fac_express_data);
893 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
894 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
899 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
900 "Code : %02X (Unknown class A)", fac);
901 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
902 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
903 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
910 case X25_FAC_CLASS_B:
912 case X25_FAC_BILATERAL_CUG:
914 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
915 "(Bilateral closed user group selection)", fac);
916 fac_subtree = proto_item_add_subtree(ti,
917 ett_x25_fac_bilateral_cug);
918 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
919 "Bilateral CUG: %04X",
920 tvb_get_ntohs(tvb, *offset+1));
923 case X25_FAC_PACKET_SIZE:
928 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
929 "(Packet size)", fac);
930 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
931 byte1 = tvb_get_guint8(tvb, *offset + 1);
935 sprintf(tmpbuf, "From the called DTE : %%u (16)");
938 sprintf(tmpbuf, "From the called DTE : %%u (32)");
941 sprintf(tmpbuf, "From the called DTE : %%u (64)");
944 sprintf(tmpbuf, "From the called DTE : %%u (128)");
947 sprintf(tmpbuf, "From the called DTE : %%u (256)");
950 sprintf(tmpbuf, "From the called DTE : %%u (512)");
953 sprintf(tmpbuf, "From the called DTE : %%u (1024)");
956 sprintf(tmpbuf, "From the called DTE : %%u (2048)");
959 sprintf(tmpbuf, "From the called DTE : %%u (4096)");
962 sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
965 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
966 decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
968 byte2 = tvb_get_guint8(tvb, *offset + 1);
972 sprintf(tmpbuf, "From the calling DTE : %%u (16)");
975 sprintf(tmpbuf, "From the calling DTE : %%u (32)");
978 sprintf(tmpbuf, "From the calling DTE : %%u (64)");
981 sprintf(tmpbuf, "From the calling DTE : %%u (128)");
984 sprintf(tmpbuf, "From the calling DTE : %%u (256)");
987 sprintf(tmpbuf, "From the calling DTE : %%u (512)");
990 sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
993 sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
996 sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
999 sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
1002 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1003 decode_numeric_bitfield(byte2, 0x0F, 1*8, tmpbuf));
1006 case X25_FAC_WINDOW_SIZE:
1008 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1009 "(Window size)", fac);
1010 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
1011 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1012 decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+1),
1013 0x7F, 1*8, "From the called DTE: %u"));
1014 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1015 decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+2),
1016 0x7F, 1*8, "From the calling DTE: %u"));
1019 case X25_FAC_RPOA_SELECTION:
1021 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1022 "(RPOA selection)", fac);
1023 fac_subtree = proto_item_add_subtree(ti,
1024 ett_x25_fac_rpoa_selection);
1025 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
1026 "Data network identification code : %04X",
1027 tvb_get_ntohs(tvb, *offset+1));
1030 case X25_FAC_TRANSIT_DELAY:
1032 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1033 "(Transit delay selection and indication)", fac);
1034 fac_subtree = proto_item_add_subtree(ti,
1035 ett_x25_fac_transit_delay);
1036 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
1037 "Transit delay: %d ms",
1038 tvb_get_ntohs(tvb, *offset+1));
1043 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1044 "Code : %02X (Unknown class B)", fac);
1045 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1046 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
1047 "Parameter %04X", tvb_get_ntohs(tvb, *offset+1));
1054 case X25_FAC_CLASS_C:
1056 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1057 "Code : %02X (Unknown class C)", fac);
1058 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1059 proto_tree_add_text(fac_subtree, tvb, *offset+1, 3,
1061 tvb_get_ntoh24(tvb, *offset+1));
1066 case X25_FAC_CLASS_D:
1068 case X25_FAC_CALL_TRANSFER:
1073 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1074 "(Call redirection or deflection notification)", fac);
1075 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
1076 byte1 = tvb_get_guint8(tvb, *offset+1);
1077 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1078 "Length : %u", byte1);
1079 byte2 = tvb_get_guint8(tvb, *offset+2);
1080 if ((byte2 & 0xC0) == 0xC0) {
1081 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1082 "Reason : call deflection by the originally "
1083 "called DTE address");
1088 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1089 "Reason : originally called DTE busy");
1092 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1093 "Reason : call dist. within a hunt group");
1096 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1097 "Reason : originally called DTE out of order");
1100 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1101 "Reason : systematic call redirection");
1104 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1105 "Reason : unknown");
1109 byte3 = tvb_get_guint8(tvb, *offset+3);
1110 proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1111 "Number of semi-octets in DTE address : %u",
1113 for (i = 0; i < byte3; i++) {
1115 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1117 /* if > 9, convert to the right hexadecimal letter */
1118 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1120 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1122 /* if > 9, convert to the right hexadecimal letter */
1123 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1127 proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1128 "DTE address : %s", tmpbuf);
1131 case X25_FAC_CALLING_ADDR_EXT:
1136 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1137 "(Calling address extension)", fac);
1138 fac_subtree = proto_item_add_subtree(ti,
1139 ett_x25_fac_calling_addr_ext);
1140 byte1 = tvb_get_guint8(tvb, *offset+1);
1141 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1142 "Length : %u", byte1);
1143 byte2 = tvb_get_guint8(tvb, *offset+2);
1144 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1145 "Number of semi-octets in DTE address : %u", byte2);
1146 for (i = 0; i < byte2; i++) {
1148 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1150 /* if > 9, convert to the right hexadecimal letter */
1151 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1153 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1155 /* if > 9, convert to the right hexadecimal letter */
1156 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1160 proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1161 "DTE address : %s", tmpbuf);
1164 case X25_FAC_CALLED_ADDR_EXT:
1169 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1170 "(Called address extension)", fac);
1171 fac_subtree = proto_item_add_subtree(ti,
1172 ett_x25_fac_called_addr_ext);
1173 byte1 = tvb_get_guint8(tvb, *offset+1);
1174 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1175 "Length : %u", byte1);
1176 byte2 = tvb_get_guint8(tvb, *offset+2);
1177 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1178 "Number of semi-octets in DTE address : %u", byte2);
1179 for (i = 0; i < byte2; i++) {
1181 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1183 /* if > 9, convert to the right hexadecimal letter */
1184 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1186 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1188 /* if > 9, convert to the right hexadecimal letter */
1189 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1193 proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1194 "DTE address : %s", tmpbuf);
1197 case X25_FAC_ETE_TRANSIT_DELAY:
1199 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1200 "(End to end transit delay)", fac);
1201 fac_subtree = proto_item_add_subtree(ti,
1202 ett_x25_fac_ete_transit_delay);
1203 byte1 = tvb_get_guint8(tvb, *offset+1);
1204 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1205 "Length : %u", byte1);
1206 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1209 case X25_FAC_CALL_DEFLECT:
1214 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1215 "(Call deflection selection)", fac);
1216 fac_subtree = proto_item_add_subtree(ti,
1217 ett_x25_fac_call_deflect);
1218 byte1 = tvb_get_guint8(tvb, *offset+1);
1219 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1220 "Length : %u", byte1);
1221 byte2 = tvb_get_guint8(tvb, *offset+2);
1222 if ((byte2 & 0xC0) == 0xC0)
1223 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1224 "Reason : call DTE originated");
1226 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1227 "Reason : unknown");
1228 byte3 = tvb_get_guint8(tvb, *offset+3);
1229 proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1230 "Number of semi-octets in the alternative DTE address : %u",
1232 for (i = 0; i < byte3; i++) {
1234 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1236 /* if > 9, convert to the right hexadecimal letter */
1237 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1239 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1241 /* if > 9, convert to the right hexadecimal letter */
1242 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1246 proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1247 "Alternative DTE address : %s", tmpbuf);
1250 case X25_FAC_PRIORITY:
1252 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1253 "Code : %02X (Priority)", fac);
1254 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
1255 byte1 = tvb_get_guint8(tvb, *offset+1);
1256 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1257 "Length : %u", byte1);
1258 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1263 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1264 "Code : %02X (Unknown class D)", fac);
1265 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1266 byte1 = tvb_get_guint8(tvb, *offset+1);
1267 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1268 "Length : %u", byte1);
1269 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1272 byte1 = tvb_get_guint8(tvb, *offset+1);
1273 (*offset) += byte1+2;
1281 x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1282 frame_data *fd, gboolean toa)
1286 char addr1[16], addr2[16];
1287 char *first, *second;
1291 byte = tvb_get_guint8(tvb, *offset);
1292 len1 = (byte >> 4) & 0x0F;
1293 len2 = (byte >> 0) & 0x0F;
1295 proto_tree_add_text(tree, tvb, *offset, 1,
1296 decode_numeric_bitfield(byte, 0xF0, 1*8,
1297 toa ? "Called address length : %u" :
1298 "Calling address length : %u"));
1299 proto_tree_add_text(tree, tvb, *offset, 1,
1300 decode_numeric_bitfield(byte, 0x0F, 1*8,
1301 toa ? "Calling address length : %u" :
1302 "Called address length : %u"));
1306 localoffset = *offset;
1307 byte = tvb_get_guint8(tvb, localoffset);
1311 for (i = 0; i < (len1 + len2); i++) {
1314 *first++ = ((byte >> 0) & 0x0F) + '0';
1316 byte = tvb_get_guint8(tvb, localoffset);
1318 *first++ = ((byte >> 4) & 0x0F) + '0';
1322 *second++ = ((byte >> 0) & 0x0F) + '0';
1324 byte = tvb_get_guint8(tvb, localoffset);
1326 *second++ = ((byte >> 4) & 0x0F) + '0';
1336 if (check_col(fd, COL_RES_DL_DST))
1337 col_add_str(fd, COL_RES_DL_DST, addr1);
1340 if(check_col(fd, COL_RES_DL_SRC))
1341 col_add_str(fd, COL_RES_DL_SRC, addr1);
1344 proto_tree_add_text(tree, tvb, *offset,
1347 toa ? "Called" : "Calling",
1352 if (check_col(fd, COL_RES_DL_SRC))
1353 col_add_str(fd, COL_RES_DL_SRC, addr2);
1356 if(check_col(fd, COL_RES_DL_DST))
1357 col_add_str(fd, COL_RES_DL_DST, addr2);
1360 proto_tree_add_text(tree, tvb, *offset + len1/2,
1361 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1363 toa ? "Calling" : "Called",
1366 (*offset) += ((len1 + len2 + 1) / 2);
1370 get_x25_pkt_len(tvbuff_t *tvb)
1372 guint length, called_len, calling_len, dte_len, dce_len;
1373 guint8 byte2, bytex;
1375 byte2 = tvb_get_guint8(tvb, 2);
1378 case X25_CALL_REQUEST:
1379 bytex = tvb_get_guint8(tvb, 3);
1380 called_len = (bytex >> 0) & 0x0F;
1381 calling_len = (bytex >> 4) & 0x0F;
1382 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1383 if (length < tvb_reported_length(tvb))
1384 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1386 return MIN(tvb_reported_length(tvb),length);
1388 case X25_CALL_ACCEPTED:
1389 /* The calling/called address length byte (following the packet type)
1390 * is not mandatory, so we must check the packet length before trying
1392 if (tvb_reported_length(tvb) == 3)
1394 bytex = tvb_get_guint8(tvb, 3);
1395 called_len = (bytex >> 0) & 0x0F;
1396 calling_len = (bytex >> 4) & 0x0F;
1397 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1398 if (length < tvb_reported_length(tvb))
1399 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1401 return MIN(tvb_reported_length(tvb),length);
1403 case X25_CLEAR_REQUEST:
1404 case X25_RESET_REQUEST:
1405 case X25_RESTART_REQUEST:
1406 return MIN(tvb_reported_length(tvb),5);
1408 case X25_DIAGNOSTIC:
1409 return MIN(tvb_reported_length(tvb),4);
1411 case X25_CLEAR_CONFIRMATION:
1413 case X25_INTERRUPT_CONFIRMATION:
1414 case X25_RESET_CONFIRMATION:
1415 case X25_RESTART_CONFIRMATION:
1416 return MIN(tvb_reported_length(tvb),3);
1418 case X25_REGISTRATION_REQUEST:
1419 bytex = tvb_get_guint8(tvb, 3);
1420 dce_len = (bytex >> 0) & 0x0F;
1421 dte_len = (bytex >> 4) & 0x0F;
1422 length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1423 if (length < tvb_reported_length(tvb))
1424 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1426 return MIN(tvb_reported_length(tvb),length);
1428 case X25_REGISTRATION_CONFIRMATION:
1429 bytex = tvb_get_guint8(tvb, 5);
1430 dce_len = (bytex >> 0) & 0x0F;
1431 dte_len = (bytex >> 4) & 0x0F;
1432 length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1433 if (length < tvb_reported_length(tvb))
1434 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1436 return MIN(tvb_reported_length(tvb),length);
1439 if ((byte2 & 0x01) == X25_DATA) return MIN(tvb_reported_length(tvb),3);
1441 switch (byte2 & 0x1F)
1444 return MIN(tvb_reported_length(tvb),3);
1447 return MIN(tvb_reported_length(tvb),3);
1450 return MIN(tvb_reported_length(tvb),3);
1456 #define PRT_ID_ISO_8073 0x01
1458 static const value_string prt_id_vals[] = {
1459 {PRT_ID_ISO_8073, "ISO 8073 COTP"},
1461 {0x03, "ISO 10732 in conjunction with ISO 8073"},
1462 {0x04, "ISO 10736 in conjunction with ISO 8602"},
1466 static const value_string sharing_strategy_vals[] = {
1467 {0x00, "No sharing"},
1472 dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1474 proto_tree *x25_tree=0, *gfi_tree=0;
1476 guint localoffset=0;
1480 dissector_handle_t dissect;
1481 gboolean toa; /* TOA/NPI address format */
1486 if (check_col(pinfo->fd, COL_PROTOCOL))
1487 col_set_str(pinfo->fd, COL_PROTOCOL, "X.25");
1489 bytes0_1 = tvb_get_ntohs(tvb, 0);
1491 modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
1492 vc = (int)(bytes0_1 & 0x0FFF);
1494 if (bytes0_1 & 0x8000) toa = TRUE;
1497 x25_pkt_len = get_x25_pkt_len(tvb);
1498 if (x25_pkt_len < 3) /* packet too short */
1500 if (check_col(pinfo->fd, COL_INFO))
1501 col_set_str(pinfo->fd, COL_INFO, "Invalid/short X.25 packet");
1503 proto_tree_add_protocol_format(tree, proto_x25, tvb, 0,
1504 tvb_length(tvb), "Invalid/short X.25 packet");
1508 pkt_type = tvb_get_guint8(tvb, 2);
1511 ti = proto_tree_add_item(tree, proto_x25, tvb, 0, x25_pkt_len, FALSE);
1512 x25_tree = proto_item_add_subtree(ti, ett_x25);
1513 ti = proto_tree_add_item(x25_tree, hf_x25_gfi, tvb, 0, 2, FALSE);
1514 gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
1515 if ((pkt_type & 0x01) == X25_DATA)
1516 proto_tree_add_boolean(gfi_tree, hf_x25_qbit, tvb, 0, 2,
1518 else if (pkt_type == X25_CALL_REQUEST ||
1519 pkt_type == X25_CALL_ACCEPTED ||
1520 pkt_type == X25_CLEAR_REQUEST ||
1521 pkt_type == X25_CLEAR_CONFIRMATION)
1522 proto_tree_add_boolean(gfi_tree, hf_x25_abit, tvb, 0, 2,
1524 if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
1525 (pkt_type & 0x01) == X25_DATA)
1526 proto_tree_add_boolean(gfi_tree, hf_x25_dbit, tvb, 0, 2,
1528 proto_tree_add_uint(gfi_tree, hf_x25_mod, tvb, 0, 2, bytes0_1);
1532 case X25_CALL_REQUEST:
1533 if (check_col(pinfo->fd, COL_INFO))
1534 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1535 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Inc. call"
1539 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb,
1541 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1543 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Incoming call"
1547 if (localoffset < x25_pkt_len) /* calling/called addresses */
1548 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1550 if (localoffset < x25_pkt_len) /* facilities */
1551 dump_facilities(x25_tree, &localoffset, tvb);
1553 if (localoffset < tvb_reported_length(tvb)) /* user data */
1558 /* Compare the first octet of the CALL REQUEST packet with
1559 various ISO 9577 NLPIDs, as per Annex A of ISO 9577. */
1560 spi = tvb_get_guint8(tvb, localoffset);
1564 * XXX - handle other NLPIDs, e.g. PPP?
1565 * See RFC 1356 for information on at least some other
1566 * ways of running other protocols atop X.25.
1569 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1570 pinfo->fd->abs_usecs, ip_handle);
1572 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1573 "X.224 secondary protocol ID: IP");
1578 if ((spi >= 0x03 && spi <= 0x82)
1579 && tvb_get_guint8(tvb, localoffset+1) == 0x01) {
1580 /* ISO 9577 claims that a SPI in that range is a
1581 length field for X.224/ISO 8073 or X.264/ISO 11570;
1582 however, some of them collide with NLPIDs such
1583 as 0x81 for ISO 8473 CLNP or ISO 8542 ESIS, so
1584 I don't know how you run those over X.25, assuming
1587 I'm also not sure what the "or" means there; it
1588 looks as if X.264 specifies the layout of a
1589 "UN TPDU" ("Use of network connection TPDU"),
1590 which specifies the transport protocol to use
1591 over this network connection, and 0x03 0x01 0x01
1592 0x00 is such a TPDU, with a length of 3, a UN
1593 field of 1 (as is required), a PRT-ID ("protocol
1594 identifier") field of 1 (X.224/ISO 8073, a/k/a
1595 COTP service), and a SHARE ("sharing strategy")
1596 field of 0 ("no sharing", which is the only one
1599 So we'll assume that's what it is, as the SPI
1600 is in the right range for a length, and the UN
1602 prt_id = tvb_get_guint8(tvb, localoffset+2);
1604 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1605 "X.264 length indicator: %u",
1607 proto_tree_add_text(x25_tree, tvb, localoffset+1, 1,
1608 "X.264 UN TPDU identifier: 0x%02X",
1609 tvb_get_guint8(tvb, localoffset+1));
1610 proto_tree_add_text(x25_tree, tvb, localoffset+2, 1,
1611 "X.264 protocol identifier: %s",
1612 val_to_str(prt_id, prt_id_vals,
1613 "Unknown (0x%02X)"));
1614 proto_tree_add_text(x25_tree, tvb, localoffset+3, 1,
1615 "X.264 sharing strategy: %s",
1616 val_to_str(tvb_get_guint8(tvb, localoffset+3),
1617 sharing_strategy_vals, "Unknown (0x%02X)"));
1620 /* XXX - dissect the variable part? */
1622 /* The length doesn't include the length octet itself. */
1623 localoffset += spi + 1;
1627 case PRT_ID_ISO_8073:
1629 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1630 pinfo->fd->abs_usecs, ositp_handle);
1639 proto_tree_add_text(x25_tree, tvb, localoffset,
1640 tvb_reported_length(tvb)-localoffset, "Data");
1642 localoffset = tvb_reported_length(tvb);
1647 case X25_CALL_ACCEPTED:
1648 if(check_col(pinfo->fd, COL_INFO))
1649 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1650 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call conn."
1654 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1655 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1657 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call connected"
1661 if (localoffset < x25_pkt_len) /* calling/called addresses */
1662 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1664 if (localoffset < x25_pkt_len) /* facilities */
1665 dump_facilities(x25_tree, &localoffset, tvb);
1667 if (localoffset < tvb_reported_length(tvb)) { /* user data */
1669 proto_tree_add_text(x25_tree, tvb, localoffset,
1670 tvb_reported_length(tvb)-localoffset, "Data");
1671 localoffset=tvb_reported_length(tvb);
1674 case X25_CLEAR_REQUEST:
1675 if(check_col(pinfo->fd, COL_INFO)) {
1676 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - %s",
1677 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear ind."
1679 vc, clear_code(tvb_get_guint8(tvb, 3)),
1680 clear_diag(tvb_get_guint8(tvb, 4)));
1682 x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1684 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1685 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb,
1686 localoffset+2, 1, X25_CLEAR_REQUEST,
1687 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear indication"
1689 proto_tree_add_text(x25_tree, tvb, 3, 1,
1690 "Cause : %s", clear_code(tvb_get_guint8(tvb, 3)));
1691 proto_tree_add_text(x25_tree, tvb, 4, 1,
1692 "Diagnostic : %s", clear_diag(tvb_get_guint8(tvb, 4)));
1694 localoffset = x25_pkt_len;
1696 case X25_CLEAR_CONFIRMATION:
1697 if(check_col(pinfo->fd, COL_INFO))
1698 col_add_fstr(pinfo->fd, COL_INFO, "Clear Conf. VC:%d", vc);
1700 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1701 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1702 X25_CLEAR_CONFIRMATION);
1704 localoffset = x25_pkt_len;
1706 if (localoffset < tvb_reported_length(tvb)) /* extended clear conf format */
1707 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1709 if (localoffset < tvb_reported_length(tvb)) /* facilities */
1710 dump_facilities(x25_tree, &localoffset, tvb);
1712 case X25_DIAGNOSTIC:
1713 if(check_col(pinfo->fd, COL_INFO)) {
1714 col_add_fstr(pinfo->fd, COL_INFO, "Diag. %d",
1715 (int)tvb_get_guint8(tvb, 3));
1718 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1720 proto_tree_add_text(x25_tree, tvb, 3, 1,
1721 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 3));
1723 localoffset = x25_pkt_len;
1726 if(check_col(pinfo->fd, COL_INFO))
1727 col_add_fstr(pinfo->fd, COL_INFO, "Interrupt VC:%d", vc);
1729 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1730 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1733 localoffset = x25_pkt_len;
1735 case X25_INTERRUPT_CONFIRMATION:
1736 if(check_col(pinfo->fd, COL_INFO))
1737 col_add_fstr(pinfo->fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
1739 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1740 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1741 X25_INTERRUPT_CONFIRMATION);
1743 localoffset = x25_pkt_len;
1745 case X25_RESET_REQUEST:
1746 if(check_col(pinfo->fd, COL_INFO)) {
1747 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
1748 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset ind."
1750 vc, reset_code(tvb_get_guint8(tvb, 3)),
1751 (int)tvb_get_guint8(tvb, 4));
1753 x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1755 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1756 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1758 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset indication"
1760 proto_tree_add_text(x25_tree, tvb, 3, 1,
1761 "Cause : %s", reset_code(tvb_get_guint8(tvb, 3)));
1762 proto_tree_add_text(x25_tree, tvb, 4, 1,
1763 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1765 localoffset = x25_pkt_len;
1767 case X25_RESET_CONFIRMATION:
1768 if(check_col(pinfo->fd, COL_INFO))
1769 col_add_fstr(pinfo->fd, COL_INFO, "Reset conf. VC:%d", vc);
1771 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1772 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1773 X25_RESET_CONFIRMATION);
1775 localoffset = x25_pkt_len;
1777 case X25_RESTART_REQUEST:
1778 if(check_col(pinfo->fd, COL_INFO)) {
1779 col_add_fstr(pinfo->fd, COL_INFO, "%s %s - Diag.:%d",
1780 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart ind."
1782 restart_code(tvb_get_guint8(tvb, 3)),
1783 (int)tvb_get_guint8(tvb, 3));
1786 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1787 X25_RESTART_REQUEST,
1788 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart indication"
1789 : "Restart request");
1790 proto_tree_add_text(x25_tree, tvb, 3, 1,
1791 "Cause : %s", restart_code(tvb_get_guint8(tvb, 3)));
1792 proto_tree_add_text(x25_tree, tvb, 4, 1,
1793 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1795 localoffset = x25_pkt_len;
1797 case X25_RESTART_CONFIRMATION:
1798 if(check_col(pinfo->fd, COL_INFO))
1799 col_set_str(pinfo->fd, COL_INFO, "Restart conf.");
1801 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1802 X25_RESTART_CONFIRMATION);
1803 localoffset = x25_pkt_len;
1805 case X25_REGISTRATION_REQUEST:
1806 if(check_col(pinfo->fd, COL_INFO))
1807 col_set_str(pinfo->fd, COL_INFO, "Registration req.");
1809 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1810 X25_REGISTRATION_REQUEST);
1812 if (localoffset < x25_pkt_len)
1813 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, FALSE);
1816 if (localoffset < x25_pkt_len)
1817 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1818 "Registration length: %d",
1819 tvb_get_guint8(tvb, localoffset) & 0x7F);
1820 if (localoffset+1 < x25_pkt_len)
1821 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1822 tvb_get_guint8(tvb, localoffset) & 0x7F,
1825 localoffset = tvb_reported_length(tvb);
1827 case X25_REGISTRATION_CONFIRMATION:
1828 if(check_col(pinfo->fd, COL_INFO))
1829 col_set_str(pinfo->fd, COL_INFO, "Registration conf.");
1831 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1832 X25_REGISTRATION_CONFIRMATION);
1833 proto_tree_add_text(x25_tree, tvb, 3, 1,
1834 "Cause: %s", registration_code(tvb_get_guint8(tvb, 3)));
1835 proto_tree_add_text(x25_tree, tvb, 4, 1,
1836 "Diagnostic: %s", registration_code(tvb_get_guint8(tvb, 4)));
1839 if (localoffset < x25_pkt_len)
1840 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, TRUE);
1843 if (localoffset < x25_pkt_len)
1844 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1845 "Registration length: %d",
1846 tvb_get_guint8(tvb, localoffset) & 0x7F);
1847 if (localoffset+1 < x25_pkt_len)
1848 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1849 tvb_get_guint8(tvb, localoffset) & 0x7F,
1852 localoffset = tvb_reported_length(tvb);
1856 if ((pkt_type & 0x01) == X25_DATA)
1858 if(check_col(pinfo->fd, COL_INFO)) {
1860 col_add_fstr(pinfo->fd, COL_INFO,
1861 "Data VC:%d P(S):%d P(R):%d %s", vc,
1862 (pkt_type >> 1) & 0x07,
1863 (pkt_type >> 5) & 0x07,
1864 ((pkt_type >> 4) & 0x01) ? " M" : "");
1866 col_add_fstr(pinfo->fd, COL_INFO,
1867 "Data VC:%d P(S):%d P(R):%d %s", vc,
1868 tvb_get_guint8(tvb, localoffset+1) >> 1,
1870 (tvb_get_guint8(tvb, localoffset+1) & 0x01) ? " M" : "");
1873 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1875 proto_tree_add_uint_hidden(x25_tree, hf_x25_type, tvb,
1876 localoffset, 1, X25_DATA);
1878 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1879 localoffset, 1, pkt_type);
1880 if (pkt_type & 0x10)
1881 proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod8, tvb,
1882 localoffset, 1, pkt_type);
1883 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod8, tvb,
1884 localoffset, 1, pkt_type);
1885 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1886 decode_boolean_bitfield(pkt_type, 0x01, 1*8,
1890 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod128, tvb,
1891 localoffset, 1, pkt_type);
1892 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod128, tvb,
1894 tvb_get_guint8(tvb, localoffset+1));
1895 if (tvb_get_guint8(tvb, localoffset+1) & 0x01)
1896 proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod128, tvb,
1898 tvb_get_guint8(tvb, localoffset+1));
1901 localoffset += (modulo == 8) ? 1 : 2;
1904 switch (pkt_type & 0x1F)
1907 if(check_col(pinfo->fd, COL_INFO)) {
1909 col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
1910 vc, (pkt_type >> 5) & 0x07);
1912 col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
1913 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1916 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1919 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1920 localoffset, 1, pkt_type);
1921 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1922 localoffset, 1, X25_RR);
1925 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1926 localoffset, 1, X25_RR);
1927 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
1928 localoffset+1, 1, FALSE);
1934 if(check_col(pinfo->fd, COL_INFO)) {
1936 col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
1937 vc, (pkt_type >> 5) & 0x07);
1939 col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
1940 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1943 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1946 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1947 localoffset, 1, pkt_type);
1948 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1949 localoffset, 1, X25_RNR);
1952 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1953 localoffset, 1, X25_RNR);
1954 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
1955 localoffset+1, 1, FALSE);
1961 if(check_col(pinfo->fd, COL_INFO)) {
1963 col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
1964 vc, (pkt_type >> 5) & 0x07);
1966 col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
1967 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1970 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1973 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1974 localoffset, 1, pkt_type);
1975 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1976 localoffset, 1, X25_REJ);
1979 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1980 localoffset, 1, X25_REJ);
1981 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
1982 localoffset+1, 1, FALSE);
1986 localoffset += (modulo == 8) ? 1 : 2;
1989 if (localoffset >= tvb_reported_length(tvb)) return;
1991 next_tvb = tvb_new_subset(tvb, localoffset, -1, -1);
1992 /* search the dissector in the hash table */
1993 if ((dissect = x25_hash_get_dissect(pinfo->fd->abs_secs, pinfo->fd->abs_usecs, vc)))
1994 call_dissector(dissect, next_tvb, pinfo, tree);
1996 /* If the Call Req. has not been captured, assume these packets carry IP */
1997 if (tvb_get_guint8(tvb, localoffset) == 0x45) {
1998 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1999 pinfo->fd->abs_usecs, ip_handle);
2000 call_dissector(ip_handle, next_tvb, pinfo, tree);
2003 dissect_data(next_tvb, 0, pinfo, tree);
2009 proto_register_x25(void)
2011 static hf_register_info hf[] = {
2013 { "GFI", "x.25.gfi", FT_UINT16, BASE_BIN, NULL, 0xF000,
2014 "General format identifier", HFILL }},
2016 { "A Bit", "x.25.a", FT_BOOLEAN, 16, NULL, 0x8000,
2017 "Address Bit", HFILL }},
2019 { "Q Bit", "x.25.q", FT_BOOLEAN, 16, NULL, 0x8000,
2020 "Qualifier Bit", HFILL }},
2022 { "D Bit", "x.25.d", FT_BOOLEAN, 16, NULL, 0x4000,
2023 "Delivery Confirmation Bit", HFILL }},
2025 { "Modulo", "x.25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
2026 "Specifies whether the frame is modulo 8 or 128", HFILL }},
2028 { "Logical Channel", "x.25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
2029 "Logical Channel Number", HFILL }},
2031 { "Packet Type", "x.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
2032 "Packet Type", HFILL }},
2034 { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
2035 "Packet Receive Sequence Number", HFILL }},
2036 { &hf_x25_p_r_mod128,
2037 { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
2038 "Packet Receive Sequence Number", HFILL }},
2039 { &hf_x25_mbit_mod8,
2040 { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x10,
2041 "More Bit", HFILL }},
2042 { &hf_x25_mbit_mod128,
2043 { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x01,
2044 "More Bit", HFILL }},
2046 { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
2047 "Packet Send Sequence Number", HFILL }},
2048 { &hf_x25_p_s_mod128,
2049 { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
2050 "Packet Send Sequence Number", HFILL }},
2052 static gint *ett[] = {
2056 &ett_x25_fac_unknown,
2058 &ett_x25_fac_reverse,
2059 &ett_x25_fac_throughput,
2061 &ett_x25_fac_called_modif,
2062 &ett_x25_fac_cug_outgoing_acc,
2063 &ett_x25_fac_throughput_min,
2064 &ett_x25_fac_express_data,
2065 &ett_x25_fac_bilateral_cug,
2066 &ett_x25_fac_packet_size,
2067 &ett_x25_fac_window_size,
2068 &ett_x25_fac_rpoa_selection,
2069 &ett_x25_fac_transit_delay,
2070 &ett_x25_fac_call_transfer,
2071 &ett_x25_fac_called_addr_ext,
2072 &ett_x25_fac_ete_transit_delay,
2073 &ett_x25_fac_calling_addr_ext,
2074 &ett_x25_fac_call_deflect,
2075 &ett_x25_fac_priority
2078 proto_x25 = proto_register_protocol ("X.25", "X.25", "x.25");
2079 proto_register_field_array (proto_x25, hf, array_length(hf));
2080 proto_register_subtree_array(ett, array_length(ett));
2081 register_init_routine(&reinit_x25_hashtable);
2083 register_dissector("x.25", dissect_x25, proto_x25);
2087 proto_reg_handoff_x25(void)
2090 * Get handles for the IP and OSI TP (COTP/CLTP) dissectors.
2092 ip_handle = find_dissector("ip");
2093 ositp_handle = find_dissector("ositp");
2095 dissector_add("llc.dsap", SAP_X25, dissect_x25, proto_x25);