2 * Routines for x25 packet disassembly
3 * Olivier Abad <abad@daba.dhis.net>
5 * $Id: packet-x25.c,v 1.25 2000/05/11 08:15:56 gram 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>
41 #include "packet-ip.h"
42 #include "packet-osi.h"
43 #include "packet-clnp.h"
48 #define X25_CALL_REQUEST 0x0B
49 #define X25_CALL_ACCEPTED 0x0F
50 #define X25_CLEAR_REQUEST 0x13
51 #define X25_CLEAR_CONFIRMATION 0x17
52 #define X25_INTERRUPT 0x23
53 #define X25_INTERRUPT_CONFIRMATION 0x27
54 #define X25_RESET_REQUEST 0x1B
55 #define X25_RESET_CONFIRMATION 0x1F
56 #define X25_RESTART_REQUEST 0xFB
57 #define X25_RESTART_CONFIRMATION 0xFF
58 #define X25_REGISTRATION_REQUEST 0xF3
59 #define X25_REGISTRATION_CONFIRMATION 0xF7
60 #define X25_DIAGNOSTIC 0xF1
66 #define X25_FAC_CLASS_MASK 0xC0
68 #define X25_FAC_CLASS_A 0x00
69 #define X25_FAC_CLASS_B 0x40
70 #define X25_FAC_CLASS_C 0x80
71 #define X25_FAC_CLASS_D 0xC0
73 #define X25_FAC_COMP_MARK 0x00
74 #define X25_FAC_REVERSE 0x01
75 #define X25_FAC_THROUGHPUT 0x02
76 #define X25_FAC_CUG 0x03
77 #define X25_FAC_CALLED_MODIF 0x08
78 #define X25_FAC_CUG_OUTGOING_ACC 0x09
79 #define X25_FAC_THROUGHPUT_MIN 0x0A
80 #define X25_FAC_EXPRESS_DATA 0x0B
81 #define X25_FAC_BILATERAL_CUG 0x41
82 #define X25_FAC_PACKET_SIZE 0x42
83 #define X25_FAC_WINDOW_SIZE 0x43
84 #define X25_FAC_RPOA_SELECTION 0x44
85 #define X25_FAC_TRANSIT_DELAY 0x49
86 #define X25_FAC_CALL_TRANSFER 0xC3
87 #define X25_FAC_CALLED_ADDR_EXT 0xC9
88 #define X25_FAC_ETE_TRANSIT_DELAY 0xCA
89 #define X25_FAC_CALLING_ADDR_EXT 0xCB
90 #define X25_FAC_CALL_DEFLECT 0xD1
91 #define X25_FAC_PRIORITY 0xD2
93 static int proto_x25 = -1;
94 static int hf_x25_qbit = -1;
95 static int hf_x25_dbit = -1;
96 static int hf_x25_mod = -1;
97 static int hf_x25_lcn = -1;
98 static int hf_x25_type = -1;
99 static int hf_x25_p_r = -1;
100 static int hf_x25_mbit = -1;
101 static int hf_x25_p_s = -1;
102 static int proto_ex25 = -1;
103 static int hf_ex25_qbit = -1;
104 static int hf_ex25_dbit = -1;
105 static int hf_ex25_mod = -1;
106 static int hf_ex25_lcn = -1;
107 static int hf_ex25_type = -1;
108 static int hf_ex25_p_r = -1;
109 static int hf_ex25_mbit = -1;
110 static int hf_ex25_p_s = -1;
112 static gint ett_x25 = -1;
113 static gint ett_x25_fac = -1;
114 static gint ett_x25_fac_unknown = -1;
115 static gint ett_x25_fac_mark = -1;
116 static gint ett_x25_fac_reverse = -1;
117 static gint ett_x25_fac_throughput = -1;
118 static gint ett_x25_fac_cug = -1;
119 static gint ett_x25_fac_called_modif = -1;
120 static gint ett_x25_fac_cug_outgoing_acc = -1;
121 static gint ett_x25_fac_throughput_min = -1;
122 static gint ett_x25_fac_express_data = -1;
123 static gint ett_x25_fac_bilateral_cug = -1;
124 static gint ett_x25_fac_packet_size = -1;
125 static gint ett_x25_fac_window_size = -1;
126 static gint ett_x25_fac_rpoa_selection = -1;
127 static gint ett_x25_fac_transit_delay = -1;
128 static gint ett_x25_fac_call_transfer = -1;
129 static gint ett_x25_fac_called_addr_ext = -1;
130 static gint ett_x25_fac_ete_transit_delay = -1;
131 static gint ett_x25_fac_calling_addr_ext = -1;
132 static gint ett_x25_fac_call_deflect = -1;
133 static gint ett_x25_fac_priority = -1;
135 static const value_string vals_modulo[] = {
141 static const value_string vals_x25_type[] = {
142 { X25_CALL_REQUEST, "Call" },
143 { X25_CALL_ACCEPTED, "Call Accepted" },
144 { X25_CLEAR_REQUEST, "Clear" },
145 { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
146 { X25_INTERRUPT, "Interrupt" },
147 { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
148 { X25_RESET_REQUEST, "Reset" },
149 { X25_RESET_CONFIRMATION, "Reset Confirmation" },
150 { X25_RESTART_REQUEST, "Restart" },
151 { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
152 { X25_REGISTRATION_REQUEST, "Registration" },
153 { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
154 { X25_DIAGNOSTIC, "Diagnostic" },
158 { X25_DATA, "DATA" },
163 * each vc_info node contains :
164 * the time of the first frame using this dissector (secs and usecs)
165 * the time of the last frame using this dissector (0 if it is unknown)
166 * a pointer to the dissector
168 * the "time of first frame" is initialized when a Call Req. is received
169 * the "time of last frame" is initialized when a Clear, Reset, or Restart
172 typedef struct _vc_info {
173 guint32 first_frame_secs, first_frame_usecs;
174 guint32 last_frame_secs, last_frame_usecs;
175 void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
176 struct _vc_info *next;
180 * the hash table will contain linked lists of global_vc_info
181 * each global_vc_info struct contains :
182 * the VC number (the hash table is indexed with VC % 64)
183 * a linked list of vc_info
185 typedef struct _global_vc_info {
188 struct _global_vc_info *next;
191 static global_vc_info *hash_table[64];
194 free_vc_info(vc_info *pt)
206 reinit_x25_hashtable(void)
210 for (i=0; i<64; i++) {
211 if (hash_table[i]) /* not NULL ==> free */
213 global_vc_info *hash_ent, *hash_ent2;
214 hash_ent2 = hash_ent = hash_table[i];
217 hash_ent2 = hash_ent;
218 hash_ent = hash_ent->next;
219 free_vc_info(hash_ent2->info);
228 x25_hash_add_proto_start(guint16 vc, guint32 frame_secs, guint32 frame_usecs,
229 void (*dissect)(const u_char *, int, frame_data *,
233 global_vc_info *hash_ent;
234 global_vc_info *hash_ent2;
236 if (hash_table[idx] == 0)
238 hash_ent = (global_vc_info *)g_malloc(sizeof(global_vc_info));
240 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
243 hash_ent->vc_num = vc;
245 hash_ent->info = (vc_info *)g_malloc(sizeof(vc_info));
246 if (!hash_ent->info) {
247 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
250 hash_ent->info->first_frame_secs = frame_secs;
251 hash_ent->info->first_frame_usecs = frame_usecs;
252 hash_ent->info->last_frame_secs = 0;
253 hash_ent->info->last_frame_usecs = 0;
254 hash_ent->info->dissect = dissect;
255 hash_ent->info->next = 0;
256 hash_table[idx] = hash_ent;
260 hash_ent2 = hash_ent = hash_table[idx];
261 /* search an entry with the same VC number */
262 while (hash_ent != NULL && hash_ent->vc_num != vc) {
263 hash_ent2 = hash_ent;
264 hash_ent = hash_ent->next;
266 if (hash_ent != NULL) /* hash_ent->vc_num == vc */
268 vc_info *vci = hash_ent->info;
269 while (vci->next) vci = vci->next; /* last element */
270 if (vci->dissect == dissect) {
271 vci->last_frame_secs = 0;
272 vci->last_frame_usecs = 0;
275 vci->next = (vc_info *)g_malloc(sizeof(vc_info));
276 if (vci->next == 0) {
277 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
280 vci->next->first_frame_secs = frame_secs;
281 vci->next->first_frame_usecs = frame_usecs;
282 vci->next->last_frame_secs = 0;
283 vci->next->last_frame_usecs = 0;
284 vci->next->dissect = dissect;
288 else /* new vc number */
290 hash_ent2->next = (global_vc_info *)g_malloc(sizeof(global_vc_info));
291 if (!hash_ent2->next) {
292 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
295 hash_ent2->next->info = (vc_info *)g_malloc(sizeof(vc_info));
296 if (!hash_ent2->next->info) {
297 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
300 hash_ent2->next->info->first_frame_secs = frame_secs;
301 hash_ent2->next->info->first_frame_usecs = frame_usecs;
302 hash_ent2->next->info->last_frame_secs = 0;
303 hash_ent2->next->info->last_frame_usecs = 0;
304 hash_ent2->next->info->dissect = dissect;
305 hash_ent2->next->info->next = 0;
311 x25_hash_add_proto_end(guint16 vc, guint32 frame_secs, guint32 frame_usecs)
313 global_vc_info *hash_ent = hash_table[vc%64];
316 if (!hash_ent) return;
317 while(hash_ent->vc_num != vc) hash_ent = hash_ent->next;
318 if (!hash_ent) return;
320 vci = hash_ent->info;
321 while (vci->next) vci = vci->next;
322 vci->last_frame_secs = frame_secs;
323 vci->last_frame_usecs = frame_usecs;
326 void (*x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc))(const u_char *, int, frame_data *, proto_tree *)
328 global_vc_info *hash_ent = hash_table[vc%64];
332 if (!hash_ent) return 0;
334 while(hash_ent && hash_ent->vc_num != vc) hash_ent = hash_ent->next;
335 if (!hash_ent) return 0;
337 /* a hash_ent was found for this VC number */
338 vci2 = vci = hash_ent->info;
340 /* looking for an entry matching our frame time */
341 while (vci && (vci->last_frame_secs < frame_secs ||
342 (vci->last_frame_secs == frame_secs &&
343 vci->last_frame_usecs < frame_usecs))) {
347 /* we reached last record, and previous record has a non zero
348 * last frame time ==> no dissector */
349 if (!vci && (vci2->last_frame_secs || vci2->last_frame_usecs)) return 0;
351 /* we reached last record, and previous record has a zero last frame time
352 * ==> dissector for previous frame has not been "stopped" by a Clear, etc */
354 /* if the start time for vci2 is greater than our frame time
355 * ==> no dissector */
356 if (frame_secs < vci2->first_frame_secs ||
357 (frame_secs == vci2->first_frame_secs &&
358 frame_usecs < vci2->first_frame_usecs))
361 return vci2->dissect;
364 /* our frame time is before vci's end. Check if it is adter vci's start */
365 if (frame_secs < vci->first_frame_secs ||
366 (frame_secs == vci->first_frame_secs &&
367 frame_usecs < vci->first_frame_usecs))
373 static char *clear_code(unsigned char code)
375 static char buffer[25];
377 if (code == 0x00 || (code & 0x80) == 0x80)
378 return "DTE Originated";
380 return "Number Busy";
382 return "Out Of Order";
384 return "Remote Procedure Error";
386 return "Reverse Charging Acceptance Not Subscribed";
388 return "Incompatible Destination";
390 return "Fast Select Acceptance Not Subscribed";
392 return "Destination Absent";
394 return "Invalid Facility Requested";
396 return "Access Barred";
398 return "Local Procedure Error";
400 return "Network Congestion";
402 return "Not Obtainable";
404 return "RPOA Out Of Order";
406 sprintf(buffer, "Unknown %02X", code);
411 static char *clear_diag(unsigned char code)
413 static char buffer[25];
416 return "No additional information";
418 return "Invalid P(S)";
420 return "Invalid P(R)";
422 return "Packet type invalid";
424 return "Packet type invalid for state r1";
426 return "Packet type invalid for state r2";
428 return "Packet type invalid for state r3";
430 return "Packet type invalid for state p1";
432 return "Packet type invalid for state p2";
434 return "Packet type invalid for state p3";
436 return "Packet type invalid for state p4";
438 return "Packet type invalid for state p5";
440 return "Packet type invalid for state p6";
442 return "Packet type invalid for state p7";
444 return "Packet type invalid for state d1";
446 return "Packet type invalid for state d2";
448 return "Packet type invalid for state d3";
450 return "Packet not allowed";
452 return "Unidentifiable packet";
454 return "Call on one-way logical channel";
456 return "Invalid packet type on a PVC";
458 return "Packet on unassigned LC";
460 return "Reject not subscribed to";
462 return "Packet too short";
464 return "Packet too long";
466 return "Invalid general format identifier";
468 return "Restart/registration packet with nonzero bits";
470 return "Packet type not compatible with facility";
472 return "Unauthorised interrupt confirmation";
474 return "Unauthorised interrupt";
476 return "Unauthorised reject";
478 return "Time expired";
480 return "Time expired for incoming call";
482 return "Time expired for clear indication";
484 return "Time expired for reset indication";
486 return "Time expired for restart indication";
488 return "Time expired for call deflection";
490 return "Call set-up/clearing or registration pb.";
492 return "Facility/registration code not allowed";
494 return "Facility parameter not allowed";
496 return "Invalid called DTE address";
498 return "Invalid calling DTE address";
500 return "Invalid facility/registration length";
502 return "Incoming call barred";
504 return "No logical channel available";
506 return "Call collision";
508 return "Duplicate facility requested";
510 return "Non zero address length";
512 return "Non zero facility length";
514 return "Facility not provided when expected";
516 return "Invalid CCITT-specified DTE facility";
518 return "Max. nb of call redir/defl. exceeded";
520 return "Miscellaneous";
522 return "Improper cause code from DTE";
524 return "Not aligned octet";
526 return "Inconsistent Q bit setting";
528 return "NUI problem";
530 return "International problem";
532 return "Remote network problem";
534 return "International protocol problem";
536 return "International link out of order";
538 return "International link busy";
540 return "Transit network facility problem";
542 return "Remote network facility problem";
544 return "International routing problem";
546 return "Temporary routing problem";
548 return "Unknown called DNIC";
550 return "Maintenance action";
552 sprintf(buffer, "Unknown %d", code);
557 static char *reset_code(unsigned char code)
559 static char buffer[25];
561 if (code == 0x00 || (code & 0x80) == 0x80)
562 return "DTE Originated";
564 return "Out of order";
566 return "Remote Procedure Error";
568 return "Local Procedure Error";
570 return "Network Congestion";
572 return "Remote DTE operational";
574 return "Network operational";
576 return "Incompatible Destination";
578 return "Network out of order";
580 sprintf(buffer, "Unknown %02X", code);
585 static char *restart_code(unsigned char code)
587 static char buffer[25];
589 if (code == 0x00 || (code & 0x80) == 0x80)
590 return "DTE Originated";
592 return "Local Procedure Error";
594 return "Network Congestion";
596 return "Network Operational";
598 return "Registration/cancellation confirmed";
600 sprintf(buffer, "Unknown %02X", code);
605 static char *registration_code(unsigned char code)
607 static char buffer[25];
610 return "Invalid facility request";
612 return "Network congestion";
614 return "Local procedure error";
616 return "Registration/cancellation confirmed";
618 sprintf(buffer, "Unknown %02X", code);
624 dump_facilities(proto_tree *tree, int *offset, const guint8 *p)
626 const guint8 *ptr = p;
627 guint32 len; /* facilities length */
629 proto_tree *fac_tree = 0;
630 proto_tree *fac_subtree;
634 ti = proto_tree_add_text(tree, NullTVB, *offset, len + 1,
636 fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
637 proto_tree_add_text(fac_tree, NullTVB, *offset, 1,
638 "Facilities length: %d", len);
643 switch(*ptr & X25_FAC_CLASS_MASK) {
644 case X25_FAC_CLASS_A:
646 case X25_FAC_COMP_MARK:
648 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1,
649 "Code : 00 (Marker)");
653 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
654 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
655 "Parameter : 00 (Network complementary "
656 "services - calling DTE)");
661 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
662 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
663 "Parameter : FF (Network complementary "
664 "services - called DTE)");
669 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
670 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
671 "Parameter : 0F (DTE complementary "
677 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
678 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
679 "Parameter : %02X (Unknown marker)",
685 case X25_FAC_REVERSE:
687 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
688 "(Reverse charging / Fast select)", *ptr);
689 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
690 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1, "Parameter : %02X",
693 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
694 "11.. .... = Fast select with restriction");
695 else if (ptr[1] & 0x80)
696 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
697 "10.. .... = Fast select - no restriction");
699 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
700 "00.. .... = Fast select not requested");
701 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
702 decode_boolean_bitfield(ptr[1], 0x01, 1*8,
703 "Reverse charging requested",
704 "Reverse charging not requested"));
707 case X25_FAC_THROUGHPUT:
711 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
712 "(Throughput class negociation)", *ptr);
713 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
725 sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
726 75*(1<<((ptr[1] >> 4)-3)));
729 sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
732 sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
735 sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
737 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
738 decode_numeric_bitfield(ptr[1], 0xF0, 1*8, tmpbuf));
739 switch (ptr[1] & 0x0F)
750 sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
751 75*(1<<((ptr[1] & 0x0F)-3)));
754 sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
757 sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
760 sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
762 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
763 decode_numeric_bitfield(ptr[1], 0x0F, 1*8, tmpbuf));
768 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
769 "(Closed user group selection)", *ptr);
770 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
771 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
772 "Closed user group: %02X", ptr[1]);
775 case X25_FAC_CALLED_MODIF:
777 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
778 "(Called address modified)", *ptr);
779 fac_subtree = proto_item_add_subtree(ti,
780 ett_x25_fac_called_modif);
781 proto_tree_add_text(fac_tree, NullTVB, *offset, 2,
782 "Parameter %02X", ptr[1]);
785 case X25_FAC_CUG_OUTGOING_ACC:
787 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
788 "(Closed user group with outgoing access selection)",
790 fac_subtree = proto_item_add_subtree(ti,
791 ett_x25_fac_cug_outgoing_acc);
792 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
793 "Closed user group: %02X", ptr[1]);
796 case X25_FAC_THROUGHPUT_MIN:
798 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
799 "(Minimum throughput class)", *ptr);
800 fac_subtree = proto_item_add_subtree(ti,
801 ett_x25_fac_throughput_min);
802 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
803 "Parameter %02X", ptr[1]);
806 case X25_FAC_EXPRESS_DATA:
808 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
809 "(Negociation of express data)", *ptr);
810 fac_subtree = proto_item_add_subtree(ti,
811 ett_x25_fac_express_data);
812 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
813 "Parameter %02X", ptr[1]);
818 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1,
819 "Code : %02X (Unknown class A)", *ptr);
820 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
821 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
822 "Parameter %02X", ptr[1]);
830 case X25_FAC_CLASS_B:
832 case X25_FAC_BILATERAL_CUG:
834 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
835 "(Bilateral closed user group selection)", *ptr);
836 fac_subtree = proto_item_add_subtree(ti,
837 ett_x25_fac_bilateral_cug);
838 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 2,
839 "Bilateral CUG: %02X%02X",
843 case X25_FAC_PACKET_SIZE:
848 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
849 "(Packet size)", *ptr);
850 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
854 sprintf(tmpbuf, "From the called DTE : %%u (16)");
857 sprintf(tmpbuf, "From the called DTE : %%u (32)");
860 sprintf(tmpbuf, "From the called DTE : %%u (64)");
863 sprintf(tmpbuf, "From the called DTE : %%u (128)");
866 sprintf(tmpbuf, "From the called DTE : %%u (256)");
869 sprintf(tmpbuf, "From the called DTE : %%u (512)");
872 sprintf(tmpbuf, "From the called DTE : %%u (1024)");
875 sprintf(tmpbuf, "From the called DTE : %%u (2048)");
878 sprintf(tmpbuf, "From the called DTE : %%u (4096)");
881 sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
884 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
885 decode_numeric_bitfield(ptr[1], 0x0F, 1*8, tmpbuf));
890 sprintf(tmpbuf, "From the calling DTE : %%u (16)");
893 sprintf(tmpbuf, "From the calling DTE : %%u (32)");
896 sprintf(tmpbuf, "From the calling DTE : %%u (64)");
899 sprintf(tmpbuf, "From the calling DTE : %%u (128)");
902 sprintf(tmpbuf, "From the calling DTE : %%u (256)");
905 sprintf(tmpbuf, "From the calling DTE : %%u (512)");
908 sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
911 sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
914 sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
917 sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
920 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
921 decode_numeric_bitfield(ptr[2], 0x0F, 1*8, tmpbuf));
924 case X25_FAC_WINDOW_SIZE:
926 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
927 "(Window size)", *ptr);
928 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
929 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
930 decode_numeric_bitfield(ptr[1], 0x7F, 1*8,
931 "From the called DTE: %u"));
932 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
933 decode_numeric_bitfield(ptr[2], 0x7F, 1*8,
934 "From the calling DTE: %u"));
937 case X25_FAC_RPOA_SELECTION:
939 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
940 "(RPOA selection)", *ptr);
941 fac_subtree = proto_item_add_subtree(ti,
942 ett_x25_fac_rpoa_selection);
943 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 2,
944 "Data network identification code : %02X%02X",
948 case X25_FAC_TRANSIT_DELAY:
950 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
951 "(Transit delay selection and indication)", *ptr);
952 fac_subtree = proto_item_add_subtree(ti,
953 ett_x25_fac_transit_delay);
954 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 2,
955 "Transit delay: %d ms",
956 (ptr[1]<<8) + ptr[2]);
961 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1,
962 "Code : %02X (Unknown class B)", *ptr);
963 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
964 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 2,
965 "Parameter %02X%02X", ptr[1], ptr[2]);
973 case X25_FAC_CLASS_C:
975 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1,
976 "Code : %02X (Unknown class C)", *ptr);
977 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
978 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 3,
979 "Parameter %02X%02X%02X",
980 ptr[1], ptr[2], ptr[3]);
986 case X25_FAC_CLASS_D:
988 case X25_FAC_CALL_TRANSFER:
993 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
994 "(Call redirection or deflection notification)", *ptr);
995 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
996 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
997 "Length : %u", ptr[1]);
998 if ((ptr[2] & 0xC0) == 0xC0) {
999 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
1000 "Reason : call deflection by the originally "
1001 "called DTE address");
1006 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
1007 "Reason : originally called DTE busy");
1010 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
1011 "Reason : call dist. within a hunt group");
1014 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
1015 "Reason : originally called DTE out of order");
1018 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
1019 "Reason : systematic call redirection");
1022 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
1023 "Reason : unknown");
1027 proto_tree_add_text(fac_subtree, NullTVB, *offset+3, 1,
1028 "Number of semi-octets in DTE address : %u", ptr[3]);
1029 for (i = 0; i < ptr[3]; i++) {
1031 tmpbuf[i] = ((ptr[4+i/2] >> 4) & 0x0F) + '0';
1032 /* if > 9, convert to the right hexadecimal letter */
1033 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1035 tmpbuf[i] = (ptr[4+i/2] & 0x0F) + '0';
1036 /* if > 9, convert to the right hexadecimal letter */
1037 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1041 proto_tree_add_text(fac_subtree, NullTVB, *offset+4, ptr[1] - 2,
1042 "DTE address : %s", tmpbuf);
1045 case X25_FAC_CALLING_ADDR_EXT:
1050 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
1051 "(Calling address extension)", *ptr);
1052 fac_subtree = proto_item_add_subtree(ti,
1053 ett_x25_fac_calling_addr_ext);
1054 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
1055 "Length : %u", ptr[1]);
1056 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
1057 "Number of semi-octets in DTE address : %u", ptr[2]);
1058 for (i = 0; i < ptr[2]; i++) {
1060 tmpbuf[i] = ((ptr[3+i/2] >> 4) & 0x0F) + '0';
1061 /* if > 9, convert to the right hexadecimal letter */
1062 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1064 tmpbuf[i] = (ptr[3+i/2] & 0x0F) + '0';
1065 /* if > 9, convert to the right hexadecimal letter */
1066 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1070 proto_tree_add_text(fac_subtree, NullTVB, *offset+3, ptr[1] - 1,
1071 "DTE address : %s", tmpbuf);
1074 case X25_FAC_CALLED_ADDR_EXT:
1079 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
1080 "(Called address extension)", *ptr);
1081 fac_subtree = proto_item_add_subtree(ti,
1082 ett_x25_fac_called_addr_ext);
1083 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
1084 "Length : %u", ptr[1]);
1085 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
1086 "Number of semi-octets in DTE address : %u", ptr[2]);
1087 for (i = 0; i < ptr[2]; i++) {
1089 tmpbuf[i] = ((ptr[3+i/2] >> 4) & 0x0F) + '0';
1090 /* if > 9, convert to the right hexadecimal letter */
1091 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1093 tmpbuf[i] = (ptr[3+i/2] & 0x0F) + '0';
1094 /* if > 9, convert to the right hexadecimal letter */
1095 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1099 proto_tree_add_text(fac_subtree, NullTVB, *offset+3, ptr[1] - 1,
1100 "DTE address : %s", tmpbuf);
1103 case X25_FAC_ETE_TRANSIT_DELAY:
1105 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
1106 "(End to end transit delay)", *ptr);
1107 fac_subtree = proto_item_add_subtree(ti,
1108 ett_x25_fac_ete_transit_delay);
1109 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
1110 "Length : %u", ptr[1]);
1111 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, ptr[1], "Value");
1114 case X25_FAC_CALL_DEFLECT:
1119 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1, "Code : %02X "
1120 "(Call deflection selection)", *ptr);
1121 fac_subtree = proto_item_add_subtree(ti,
1122 ett_x25_fac_call_deflect);
1123 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
1124 "Length : %u", ptr[1]);
1125 if ((ptr[2] & 0xC0) == 0xC0)
1126 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
1127 "Reason : call DTE originated");
1129 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, 1,
1130 "Reason : unknown");
1131 proto_tree_add_text(fac_subtree, NullTVB, *offset+3, 1,
1132 "Number of semi-octets in the alternative DTE address : %u",
1134 for (i = 0; i < ptr[3]; i++) {
1136 tmpbuf[i] = ((ptr[4+i/2] >> 4) & 0x0F) + '0';
1137 /* if > 9, convert to the right hexadecimal letter */
1138 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1140 tmpbuf[i] = (ptr[4+i/2] & 0x0F) + '0';
1141 /* if > 9, convert to the right hexadecimal letter */
1142 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1146 proto_tree_add_text(fac_subtree, NullTVB, *offset+4, ptr[1] - 2,
1147 "Alternative DTE address : %s", tmpbuf);
1150 case X25_FAC_PRIORITY:
1152 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1,
1153 "Code : %02X (Priority)", *ptr);
1154 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
1155 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
1156 "Length : %u", ptr[1]);
1157 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, ptr[1], "Value");
1162 ti = proto_tree_add_text(fac_tree, NullTVB, *offset, 1,
1163 "Code : %02X (Unknown class D)", *ptr);
1164 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1165 proto_tree_add_text(fac_subtree, NullTVB, *offset+1, 1,
1166 "Length : %u", ptr[1]);
1167 proto_tree_add_text(fac_subtree, NullTVB, *offset+2, ptr[1], "Value");
1170 (*offset) += ptr[1]+2;
1179 x25_ntoa(proto_tree *tree, int *offset, const guint8 *p,
1180 frame_data *fd, gboolean toa)
1184 char addr1[16], addr2[16];
1185 char *first, *second;
1187 len1 = (*p >> 4) & 0x0F;
1188 len2 = (*p >> 0) & 0x0F;
1190 proto_tree_add_text(tree, NullTVB, *offset, 1,
1191 decode_numeric_bitfield(*p, 0xF0, 1*8,
1192 toa ? "Called address length : %u" :
1193 "Calling address length : %u"));
1194 proto_tree_add_text(tree, NullTVB, *offset, 1,
1195 decode_numeric_bitfield(*p, 0x0F, 1*8,
1196 toa ? "Calling address length : %u" :
1197 "Called address length : %u"));
1205 for (i = 0; i < (len1 + len2); i++) {
1208 *first++ = ((*p >> 0) & 0x0F) + '0';
1211 *first++ = ((*p >> 4) & 0x0F) + '0';
1215 *second++ = ((*p >> 0) & 0x0F) + '0';
1218 *second++ = ((*p >> 4) & 0x0F) + '0';
1228 if (check_col(fd, COL_RES_DL_DST))
1229 col_add_str(fd, COL_RES_DL_DST, addr1);
1232 if(check_col(fd, COL_RES_DL_SRC))
1233 col_add_str(fd, COL_RES_DL_SRC, addr1);
1236 proto_tree_add_text(tree, NullTVB, *offset,
1239 toa ? "Called" : "Calling",
1244 if (check_col(fd, COL_RES_DL_SRC))
1245 col_add_str(fd, COL_RES_DL_SRC, addr2);
1248 if(check_col(fd, COL_RES_DL_DST))
1249 col_add_str(fd, COL_RES_DL_DST, addr2);
1252 proto_tree_add_text(tree, NullTVB, *offset + len1/2,
1253 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1255 toa ? "Calling" : "Called",
1258 (*offset) += ((len1 + len2 + 1) / 2);
1262 get_x25_pkt_len(const char *data, frame_data *fd, int offset)
1264 int length, called_len, calling_len, dte_len, dce_len;
1266 /* packet size should always be > 3 */
1267 if (!BYTES_ARE_IN_FRAME(offset, 3)) return END_OF_FRAME;
1269 switch ((guint8)data[2])
1271 case X25_CALL_REQUEST:
1272 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1274 called_len = (data[3] >> 0) & 0x0F;
1275 calling_len = (data[3] >> 4) & 0x0F;
1276 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1277 if (length+offset < pi.captured_len)
1278 length += (1 + data[length]); /* facilities */
1280 else length = END_OF_FRAME;
1281 return MIN(END_OF_FRAME,length);
1283 case X25_CALL_ACCEPTED:
1284 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1286 called_len = (data[3] >> 0) & 0x0F;
1287 calling_len = (data[3] >> 4) & 0x0F;
1288 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1289 if (length+offset < pi.captured_len)
1290 length += (1 + data[length]); /* facilities */
1292 else length = END_OF_FRAME;
1293 return MIN(END_OF_FRAME,length);
1295 case X25_CLEAR_REQUEST:
1296 case X25_RESET_REQUEST:
1297 case X25_RESTART_REQUEST:
1298 return MIN(END_OF_FRAME,5);
1300 case X25_DIAGNOSTIC:
1301 return MIN(END_OF_FRAME,4);
1303 case X25_CLEAR_CONFIRMATION:
1305 case X25_INTERRUPT_CONFIRMATION:
1306 case X25_RESET_CONFIRMATION:
1307 case X25_RESTART_CONFIRMATION:
1308 return MIN(END_OF_FRAME,3);
1310 case X25_REGISTRATION_REQUEST:
1311 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1313 dce_len = (data[3] >> 0) & 0x0F;
1314 dte_len = (data[3] >> 4) & 0x0F;
1315 length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1316 if (length+offset < pi.captured_len)
1317 length += (1 + data[length]); /* registration */
1319 else length = END_OF_FRAME;
1320 return MIN(END_OF_FRAME,length);
1322 case X25_REGISTRATION_CONFIRMATION:
1323 if (BYTES_ARE_IN_FRAME(offset, 6)) /* pkt size >= 6 */
1325 dce_len = (data[5] >> 0) & 0x0F;
1326 dte_len = (data[5] >> 4) & 0x0F;
1327 length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1328 if (length+offset < pi.captured_len)
1329 length += (1 + data[length]); /* registration */
1331 else length = END_OF_FRAME;
1332 return MIN(END_OF_FRAME,length);
1335 if ((data[2] & 0x01) == X25_DATA) return MIN(END_OF_FRAME,3);
1337 switch (data[2] & 0x1F)
1340 return MIN(END_OF_FRAME,3);
1343 return MIN(END_OF_FRAME,3);
1346 return MIN(END_OF_FRAME,3);
1352 #define PRT_ID_ISO_8073 0x01
1354 static const value_string prt_id_vals[] = {
1355 {PRT_ID_ISO_8073, "ISO 8073 COTP"},
1357 {0x03, "ISO 10732 in conjunction with ISO 8073"},
1358 {0x04, "ISO 10736 in conjunction with ISO 8602"},
1362 static const value_string sharing_strategy_vals[] = {
1363 {0x00, "No sharing"},
1368 dissect_x25(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1370 proto_tree *x25_tree=0, *ti;
1371 int localoffset=offset;
1375 void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
1376 gboolean toa; /* TOA/NPI address format */
1378 if (check_col(fd, COL_PROTOCOL))
1379 col_add_str(fd, COL_PROTOCOL, "X.25");
1381 modulo = ((pd[localoffset] & 0x20) ? 128 : 8);
1383 if (pd[localoffset] & 0x80) toa = TRUE;
1386 x25_pkt_len = get_x25_pkt_len(&pd[localoffset], fd, offset);
1387 if (x25_pkt_len < 3) /* packet too short */
1389 if (check_col(fd, COL_INFO))
1390 col_add_str(fd, COL_INFO, "Invalid/short X.25 packet");
1392 proto_tree_add_protocol_format(tree, (modulo == 8 ? proto_x25 : proto_ex25), NullTVB,
1393 localoffset, END_OF_FRAME,
1394 "Invalid/short X.25 packet");
1397 vc = (int)(pd[localoffset] & 0x0F)*256 + (int)pd[localoffset+1];
1399 ti = proto_tree_add_item(tree, (modulo == 8) ? proto_x25 : proto_ex25, NullTVB,
1400 localoffset, x25_pkt_len, NULL);
1401 x25_tree = proto_item_add_subtree(ti, ett_x25);
1402 if (pd[localoffset] & 0x80)
1403 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_qbit : hf_ex25_qbit, NullTVB,
1404 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1405 if (pd[localoffset] & 0x40)
1406 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_dbit : hf_ex25_dbit, NullTVB,
1407 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1408 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_mod : hf_ex25_mod, NullTVB,
1409 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1411 switch (pd[localoffset+2]) {
1412 case X25_CALL_REQUEST:
1413 if (check_col(fd, COL_INFO))
1414 col_add_fstr(fd, COL_INFO, "%s VC:%d",
1415 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Inc. call"
1419 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1420 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1421 proto_tree_add_uint_format(x25_tree,
1422 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1423 NullTVB, localoffset+2, 1, X25_CALL_REQUEST,
1424 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Incoming call"
1428 if (localoffset < x25_pkt_len+offset) /* calling/called addresses */
1429 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1431 if (localoffset < x25_pkt_len+offset) /* facilities */
1432 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1434 if (IS_DATA_IN_FRAME(localoffset)) /* user data */
1439 /* Compare the first octet of the CALL REQUEST packet with
1440 various ISO 9577 NLPIDs, as per Annex A of ISO 9577. */
1441 spi = pd[localoffset];
1444 /* XXX - handle other NLPIDs, e.g. PPP? */
1447 x25_hash_add_proto_start(vc, fd->abs_secs,
1448 fd->abs_usecs, dissect_ip);
1450 proto_tree_add_text(x25_tree, NullTVB, localoffset, 1,
1451 "X.224 secondary protocol ID: IP");
1456 if ((pd[localoffset] >= 0x03 && pd[localoffset] <= 0x82)
1457 && pd[localoffset+1] == 0x01) {
1458 /* ISO 9577 claims that a SPI in that range is a
1459 length field for X.224/ISO 8073 or X.264/ISO 11570;
1460 however, some of them collide with NLPIDs such
1461 as 0x81 for ISO 8473 CLNP or ISO 8542 ESIS, so
1462 I don't know how you run those over X.25, assuming
1465 I'm also not sure what the "or" means there; it
1466 looks as if X.264 specifies the layout of a
1467 "UN TPDU" ("Use of network connection TPDU"),
1468 which specifies the transport protocol to use
1469 over this network connection, and 0x03 0x01 0x01
1470 0x00 is such a TPDU, with a length of 3, a UN
1471 field of 1 (as is required), a PRT-ID ("protocol
1472 identifier") field of 1 (X.224/ISO 8073, a/k/a
1473 COTP service), and a SHARE ("sharing strategy")
1474 field of 0 ("no sharing", which is the only one
1477 So we'll assume that's what it is, as the SPI
1478 is in the right range for a length, and the UN
1480 prt_id = pd[localoffset+2];
1482 proto_tree_add_text(x25_tree, NullTVB, localoffset, 1,
1483 "X.264 length indicator: %u",
1485 proto_tree_add_text(x25_tree, NullTVB, localoffset+1, 1,
1486 "X.264 UN TPDU identifier: 0x%02X",
1488 proto_tree_add_text(x25_tree, NullTVB, localoffset+2, 1,
1489 "X.264 protocol identifier: %s",
1490 val_to_str(prt_id, prt_id_vals, "Unknown (0x%02X)"));
1491 proto_tree_add_text(x25_tree, NullTVB, localoffset+3, 1,
1492 "X.264 sharing strategy: %s",
1493 val_to_str(pd[localoffset+3], sharing_strategy_vals, "Unknown (0x%02X)"));
1496 /* XXX - dissect the variable part? */
1498 /* The length doesn't include the length octet itself. */
1499 localoffset += pd[localoffset] + 1;
1503 case PRT_ID_ISO_8073:
1505 x25_hash_add_proto_start(vc, fd->abs_secs,
1506 fd->abs_usecs, dissect_cotp);
1515 if (IS_DATA_IN_FRAME(localoffset))
1516 proto_tree_add_text(x25_tree, NullTVB, localoffset,
1517 pi.captured_len-localoffset, "Data");
1519 localoffset = pi.captured_len;
1524 case X25_CALL_ACCEPTED:
1525 if(check_col(fd, COL_INFO))
1526 col_add_fstr(fd, COL_INFO, "%s VC:%d",
1527 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Call conn."
1531 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1532 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1533 proto_tree_add_uint_format(x25_tree,
1534 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1535 NullTVB, localoffset+2, 1, X25_CALL_ACCEPTED,
1536 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Call connected"
1540 if (localoffset < x25_pkt_len+offset) /* calling/called addresses */
1541 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1543 if (localoffset < x25_pkt_len+offset) /* facilities */
1544 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1546 if (IS_DATA_IN_FRAME(localoffset)) { /* user data */
1548 proto_tree_add_text(x25_tree, NullTVB, localoffset,
1549 pi.captured_len-localoffset, "Data");
1550 localoffset=pi.captured_len;
1553 case X25_CLEAR_REQUEST:
1554 if(check_col(fd, COL_INFO)) {
1555 col_add_fstr(fd, COL_INFO, "%s VC:%d %s - %s",
1556 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Clear ind."
1558 vc, clear_code(pd[localoffset+3]),
1559 clear_diag(pd[localoffset+4]));
1561 x25_hash_add_proto_end(vc, fd->abs_secs, fd->abs_usecs);
1563 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1564 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1565 proto_tree_add_uint_format(x25_tree,
1566 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1567 NullTVB, localoffset+2, 1, X25_CLEAR_REQUEST,
1568 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Clear indication"
1570 if (localoffset+3 < x25_pkt_len+offset)
1571 proto_tree_add_text(x25_tree, NullTVB, localoffset+3, 1,
1572 "Cause : %s", clear_code(pd[localoffset+3]));
1573 if (localoffset+4 < x25_pkt_len+offset)
1574 proto_tree_add_text(x25_tree, NullTVB, localoffset+4, 1,
1576 clear_diag(pd[localoffset+4]));
1578 localoffset += x25_pkt_len;
1580 case X25_CLEAR_CONFIRMATION:
1581 if(check_col(fd, COL_INFO))
1582 col_add_fstr(fd, COL_INFO, "Clear Conf. VC:%d", vc);
1584 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1585 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1586 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, NullTVB,
1587 localoffset+2, 1, X25_CLEAR_CONFIRMATION);
1589 localoffset += x25_pkt_len;
1591 if (IS_DATA_IN_FRAME(localoffset)) /* extended clear conf format */
1592 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1594 if (IS_DATA_IN_FRAME(localoffset)) /* facilities */
1595 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1597 case X25_DIAGNOSTIC:
1598 if(check_col(fd, COL_INFO)) {
1599 col_add_fstr(fd, COL_INFO, "Diag. %d", (int)pd[localoffset+3]);
1602 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, NullTVB,
1603 localoffset+2, 1, X25_DIAGNOSTIC);
1604 if (localoffset+3 < x25_pkt_len+offset)
1605 proto_tree_add_text(x25_tree, NullTVB, localoffset+3, 1,
1606 "Diagnostic : %d", (int)pd[localoffset+3]);
1608 localoffset += x25_pkt_len;
1611 if(check_col(fd, COL_INFO))
1612 col_add_fstr(fd, COL_INFO, "Interrupt VC:%d", vc);
1614 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1615 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1616 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, NullTVB,
1617 localoffset+2, 1, X25_INTERRUPT);
1619 localoffset += x25_pkt_len;
1621 case X25_INTERRUPT_CONFIRMATION:
1622 if(check_col(fd, COL_INFO))
1623 col_add_fstr(fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
1625 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1626 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1627 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, NullTVB,
1628 localoffset+2, 1, X25_INTERRUPT_CONFIRMATION);
1630 localoffset += x25_pkt_len;
1632 case X25_RESET_REQUEST:
1633 if(check_col(fd, COL_INFO)) {
1634 col_add_fstr(fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
1635 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Reset ind."
1637 vc, reset_code(pd[localoffset+3]),
1638 (int)pd[localoffset+4]);
1640 x25_hash_add_proto_end(vc, fd->abs_secs, fd->abs_usecs);
1642 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1643 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1644 proto_tree_add_uint_format(x25_tree,
1645 (modulo == 8) ? hf_x25_type : hf_ex25_type, NullTVB, localoffset+2, 1,
1647 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Reset indication"
1649 if (localoffset+3 < x25_pkt_len+offset)
1650 proto_tree_add_text(x25_tree, NullTVB, localoffset+3, 1,
1651 "Cause : %s", reset_code(pd[localoffset+3]));
1652 if (localoffset+4 < x25_pkt_len+offset)
1653 proto_tree_add_text(x25_tree, NullTVB, localoffset+4, 1,
1654 "Diagnostic : %d", (int)pd[localoffset+4]);
1656 localoffset += x25_pkt_len;
1658 case X25_RESET_CONFIRMATION:
1659 if(check_col(fd, COL_INFO))
1660 col_add_fstr(fd, COL_INFO, "Reset conf. VC:%d", vc);
1662 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1663 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1664 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, NullTVB,
1665 localoffset+2, 1, X25_RESET_CONFIRMATION);
1667 localoffset += x25_pkt_len;
1669 case X25_RESTART_REQUEST:
1670 if(check_col(fd, COL_INFO)) {
1671 col_add_fstr(fd, COL_INFO, "%s %s - Diag.:%d",
1672 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Restart ind."
1674 restart_code(pd[localoffset+3]),
1675 (int)pd[localoffset+4]);
1678 proto_tree_add_uint_format(x25_tree,
1679 (modulo == 8) ? hf_x25_type : hf_ex25_type, NullTVB, localoffset+2, 1,
1680 X25_RESTART_REQUEST,
1681 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Restart indication"
1682 : "Restart request");
1683 if (localoffset+3 < x25_pkt_len+offset)
1684 proto_tree_add_text(x25_tree, NullTVB, localoffset+3, 1,
1685 "Cause : %s", restart_code(pd[localoffset+3]));
1686 if (localoffset+4 < x25_pkt_len+offset)
1687 proto_tree_add_text(x25_tree, NullTVB, localoffset+4, 1,
1688 "Diagnostic : %d", (int)pd[localoffset+4]);
1690 localoffset += x25_pkt_len;
1692 case X25_RESTART_CONFIRMATION:
1693 if(check_col(fd, COL_INFO))
1694 col_add_str(fd, COL_INFO, "Restart conf.");
1696 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, NullTVB,
1697 localoffset+2, 1, X25_RESTART_CONFIRMATION);
1698 localoffset += x25_pkt_len;
1700 case X25_REGISTRATION_REQUEST:
1701 if(check_col(fd, COL_INFO))
1702 col_add_str(fd, COL_INFO, "Registration req.");
1704 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, NullTVB,
1705 localoffset+2, 1, X25_REGISTRATION_REQUEST);
1707 if (localoffset < x25_pkt_len+offset)
1708 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, FALSE);
1711 if (localoffset < x25_pkt_len+offset)
1712 proto_tree_add_text(x25_tree, NullTVB, localoffset, 1,
1713 "Registration length: %d", pd[localoffset] & 0x7F);
1714 if (localoffset+1 < x25_pkt_len+offset)
1715 proto_tree_add_text(x25_tree, NullTVB, localoffset+1,
1716 pd[localoffset] & 0x7F, "Registration");
1718 localoffset = pi.captured_len;
1720 case X25_REGISTRATION_CONFIRMATION:
1721 if(check_col(fd, COL_INFO))
1722 col_add_str(fd, COL_INFO, "Registration conf.");
1724 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, NullTVB,
1725 localoffset+2, 1, X25_REGISTRATION_CONFIRMATION);
1726 if (localoffset+3 < x25_pkt_len+offset)
1727 proto_tree_add_text(x25_tree, NullTVB, localoffset+3, 1,
1728 "Cause: %s", registration_code(pd[localoffset+3]));
1729 if (localoffset+4 < x25_pkt_len+offset)
1730 proto_tree_add_text(x25_tree, NullTVB, localoffset+4, 1,
1731 "Diagnostic: %s", registration_code(pd[localoffset+4]));
1734 if (localoffset < x25_pkt_len+offset)
1735 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, TRUE);
1738 if (localoffset < x25_pkt_len+offset)
1739 proto_tree_add_text(x25_tree, NullTVB, localoffset, 1,
1740 "Registration length: %d", pd[localoffset] & 0x7F);
1741 if (localoffset+1 < x25_pkt_len+offset)
1742 proto_tree_add_text(x25_tree, NullTVB, localoffset+1,
1743 pd[localoffset] & 0x7F, "Registration");
1745 localoffset = pi.captured_len;
1749 if ((pd[localoffset] & 0x01) == X25_DATA)
1751 if(check_col(fd, COL_INFO)) {
1753 col_add_fstr(fd, COL_INFO,
1754 "Data VC:%d P(S):%d P(R):%d %s", vc,
1755 (pd[localoffset] >> 1) & 0x07,
1756 (pd[localoffset] >> 5) & 0x07,
1757 ((pd[localoffset]>>4) & 0x01) ? " M" : "");
1759 col_add_fstr(fd, COL_INFO,
1760 "Data VC:%d P(S):%d P(R):%d %s", vc,
1761 pd[localoffset+1] >> 1,
1762 pd[localoffset] >> 1,
1763 (pd[localoffset+1] & 0x01) ? " M" : "");
1766 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1767 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1769 proto_tree_add_item_hidden(x25_tree, hf_x25_type, NullTVB, localoffset, 1,
1771 proto_tree_add_item(x25_tree, hf_x25_p_r, NullTVB, localoffset, 1,
1773 if (pd[localoffset] & 0x10)
1774 proto_tree_add_item(x25_tree, hf_x25_mbit, NullTVB, localoffset, 1,
1776 proto_tree_add_item(x25_tree, hf_x25_p_s, NullTVB, localoffset, 1,
1778 proto_tree_add_text(x25_tree, NullTVB, localoffset, 1,
1779 decode_boolean_bitfield(pd[localoffset], 0x01, 1*8,
1783 proto_tree_add_item_hidden(x25_tree, hf_ex25_type, NullTVB, localoffset, 1,
1785 proto_tree_add_item(x25_tree, hf_x25_p_r, NullTVB, localoffset, 1,
1787 proto_tree_add_item(x25_tree, hf_x25_p_s, NullTVB, localoffset+1, 1,
1789 if (pd[localoffset+1] & 0x01)
1790 proto_tree_add_item(x25_tree, hf_ex25_mbit, NullTVB, localoffset+1, 1,
1794 localoffset += (modulo == 8) ? 1 : 2;
1797 switch (pd[localoffset] & 0x1F)
1800 if(check_col(fd, COL_INFO)) {
1802 col_add_fstr(fd, COL_INFO, "RR VC:%d P(R):%d",
1803 vc, (pd[localoffset] >> 5) & 0x07);
1805 col_add_fstr(fd, COL_INFO, "RR VC:%d P(R):%d",
1806 vc, pd[localoffset+1] >> 1);
1809 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1810 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1812 proto_tree_add_item(x25_tree, hf_x25_p_r, NullTVB,
1813 localoffset, 1, pd[localoffset]);
1814 proto_tree_add_item(x25_tree, hf_x25_type, NullTVB, localoffset, 1, X25_RR);
1817 proto_tree_add_item(x25_tree, hf_ex25_type, NullTVB, localoffset, 1, X25_RR);
1818 proto_tree_add_item(x25_tree, hf_ex25_p_r, NullTVB,
1819 localoffset+1, 1, pd[localoffset+1]);
1825 if(check_col(fd, COL_INFO)) {
1827 col_add_fstr(fd, COL_INFO, "RNR VC:%d P(R):%d",
1828 vc, (pd[localoffset] >> 5) & 0x07);
1830 col_add_fstr(fd, COL_INFO, "RNR VC:%d P(R):%d",
1831 vc, pd[localoffset+1] >> 1);
1834 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1835 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1837 proto_tree_add_item(x25_tree, hf_x25_p_r, NullTVB,
1838 localoffset, 1, pd[localoffset]);
1839 proto_tree_add_item(x25_tree, hf_x25_type, NullTVB, localoffset, 1, X25_RNR);
1842 proto_tree_add_item(x25_tree, hf_ex25_type, NullTVB, localoffset, 1, X25_RNR);
1843 proto_tree_add_item(x25_tree, hf_ex25_p_r, NullTVB,
1844 localoffset+1, 1, pd[localoffset+1]);
1850 if(check_col(fd, COL_INFO)) {
1852 col_add_fstr(fd, COL_INFO, "REJ VC:%d P(R):%d",
1853 vc, (pd[localoffset] >> 5) & 0x07);
1855 col_add_fstr(fd, COL_INFO, "REJ VC:%d P(R):%d",
1856 vc, pd[localoffset+1] >> 1);
1859 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, NullTVB,
1860 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1862 proto_tree_add_item(x25_tree, hf_x25_p_r, NullTVB,
1863 localoffset, 1, pd[localoffset]);
1864 proto_tree_add_item(x25_tree, hf_x25_type, NullTVB, localoffset, 1, X25_REJ);
1867 proto_tree_add_item(x25_tree, hf_ex25_type, NullTVB, localoffset, 1, X25_REJ);
1868 proto_tree_add_item(x25_tree, hf_ex25_p_r, NullTVB,
1869 localoffset+1, 1, pd[localoffset+1]);
1873 localoffset += (modulo == 8) ? 1 : 2;
1876 if (!IS_DATA_IN_FRAME(localoffset)) return;
1878 /* search the dissector in the hash table */
1879 if ((dissect = x25_hash_get_dissect(fd->abs_secs, fd->abs_usecs, vc)))
1880 (*dissect)(pd, localoffset, fd, tree);
1882 if (pd[localoffset] == 0x45) /* If the Call Req. has not been captured,
1883 * assume these packets carry IP */
1885 x25_hash_add_proto_start(vc, fd->abs_secs,
1886 fd->abs_usecs, dissect_ip);
1887 dissect_ip(pd, localoffset, fd, tree);
1890 dissect_data(pd, localoffset, fd, tree);
1896 proto_register_x25(void)
1898 static hf_register_info hf8[] = {
1900 { "Q Bit", "x25.q", FT_BOOLEAN, 2, NULL, 0x8000,
1901 "Qualifier Bit" } },
1903 { "D Bit", "x25.d", FT_BOOLEAN, 2, NULL, 0x4000,
1904 "Delivery Confirmation Bit" } },
1906 { "Modulo", "x25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1907 "Specifies whether the frame is modulo 8 or 128" } },
1909 { "Logical Channel", "x25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
1910 "Logical Channel Number" } },
1912 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1915 { "P(R)", "x25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
1916 "Packet Receive Sequence Number" } },
1918 { "M Bit", "x25.m", FT_BOOLEAN, 1, NULL, 0x10,
1921 { "P(S)", "x25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
1922 "Packet Send Sequence Number" } },
1925 static hf_register_info hf128[] = {
1927 { "Q Bit", "ex25.q", FT_BOOLEAN, 2, NULL, 0x8000,
1928 "Qualifier Bit" } },
1930 { "D Bit", "ex25.d", FT_BOOLEAN, 2, NULL, 0x4000,
1931 "Delivery Confirmation Bit" } },
1933 { "Modulo", "ex25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1934 "Specifies whether the frame is modulo 8 or 128" } },
1936 { "Logical Channel", "ex25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
1937 "Logical Channel Number" } },
1939 { "Packet Type", "ex25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1942 { "P(R)", "ex25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
1943 "Packet Receive Sequence Number" } },
1945 { "M Bit", "ex25.m", FT_BOOLEAN, 1, NULL, 0x01,
1948 { "P(S)", "ex25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
1949 "Packet Send Sequence Number" } },
1951 static gint *ett[] = {
1954 &ett_x25_fac_unknown,
1956 &ett_x25_fac_reverse,
1957 &ett_x25_fac_throughput,
1959 &ett_x25_fac_called_modif,
1960 &ett_x25_fac_cug_outgoing_acc,
1961 &ett_x25_fac_throughput_min,
1962 &ett_x25_fac_express_data,
1963 &ett_x25_fac_bilateral_cug,
1964 &ett_x25_fac_packet_size,
1965 &ett_x25_fac_window_size,
1966 &ett_x25_fac_rpoa_selection,
1967 &ett_x25_fac_transit_delay,
1968 &ett_x25_fac_call_transfer,
1969 &ett_x25_fac_called_addr_ext,
1970 &ett_x25_fac_ete_transit_delay,
1971 &ett_x25_fac_calling_addr_ext,
1972 &ett_x25_fac_call_deflect,
1973 &ett_x25_fac_priority
1976 proto_x25 = proto_register_protocol ("X.25", "x25");
1977 proto_ex25 = proto_register_protocol ("Extended X.25 (modulo 128)", "ex25");
1978 proto_register_field_array (proto_x25, hf8, array_length(hf8));
1979 proto_register_field_array (proto_ex25, hf128, array_length(hf128));
1980 proto_register_subtree_array(ett, array_length(ett));
1981 register_init_routine(&reinit_x25_hashtable);
1985 proto_reg_handoff_x25(void)
1987 dissector_add("ethertype", ETHERTYPE_X25L3, dissect_x25);