2 * Routines for x25 packet disassembly
3 * Olivier Abad <abad@daba.dhis.net>
5 * $Id: packet-x25.c,v 1.21 2000/02/22 07:42:49 guy 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>
40 #include "packet-ip.h"
41 #include "packet-osi.h"
46 #define X25_CALL_REQUEST 0x0B
47 #define X25_CALL_ACCEPTED 0x0F
48 #define X25_CLEAR_REQUEST 0x13
49 #define X25_CLEAR_CONFIRMATION 0x17
50 #define X25_INTERRUPT 0x23
51 #define X25_INTERRUPT_CONFIRMATION 0x27
52 #define X25_RESET_REQUEST 0x1B
53 #define X25_RESET_CONFIRMATION 0x1F
54 #define X25_RESTART_REQUEST 0xFB
55 #define X25_RESTART_CONFIRMATION 0xFF
56 #define X25_REGISTRATION_REQUEST 0xF3
57 #define X25_REGISTRATION_CONFIRMATION 0xF7
58 #define X25_DIAGNOSTIC 0xF1
64 #define X25_FAC_CLASS_MASK 0xC0
66 #define X25_FAC_CLASS_A 0x00
67 #define X25_FAC_CLASS_B 0x40
68 #define X25_FAC_CLASS_C 0x80
69 #define X25_FAC_CLASS_D 0xC0
71 #define X25_FAC_COMP_MARK 0x00
72 #define X25_FAC_REVERSE 0x01
73 #define X25_FAC_THROUGHPUT 0x02
74 #define X25_FAC_CUG 0x03
75 #define X25_FAC_CALLED_MODIF 0x08
76 #define X25_FAC_CUG_OUTGOING_ACC 0x09
77 #define X25_FAC_THROUGHPUT_MIN 0x0A
78 #define X25_FAC_EXPRESS_DATA 0x0B
79 #define X25_FAC_BILATERAL_CUG 0x41
80 #define X25_FAC_PACKET_SIZE 0x42
81 #define X25_FAC_WINDOW_SIZE 0x43
82 #define X25_FAC_RPOA_SELECTION 0x44
83 #define X25_FAC_TRANSIT_DELAY 0x49
84 #define X25_FAC_CALL_TRANSFER 0xC3
85 #define X25_FAC_CALLED_ADDR_EXT 0xC9
86 #define X25_FAC_ETE_TRANSIT_DELAY 0xCA
87 #define X25_FAC_CALLING_ADDR_EXT 0xCB
88 #define X25_FAC_CALL_DEFLECT 0xD1
89 #define X25_FAC_PRIORITY 0xD2
91 static int proto_x25 = -1;
92 static int hf_x25_qbit = -1;
93 static int hf_x25_dbit = -1;
94 static int hf_x25_mod = -1;
95 static int hf_x25_lcn = -1;
96 static int hf_x25_type = -1;
97 static int hf_x25_p_r = -1;
98 static int hf_x25_mbit = -1;
99 static int hf_x25_p_s = -1;
100 static int proto_ex25 = -1;
101 static int hf_ex25_qbit = -1;
102 static int hf_ex25_dbit = -1;
103 static int hf_ex25_mod = -1;
104 static int hf_ex25_lcn = -1;
105 static int hf_ex25_type = -1;
106 static int hf_ex25_p_r = -1;
107 static int hf_ex25_mbit = -1;
108 static int hf_ex25_p_s = -1;
110 static gint ett_x25 = -1;
111 static gint ett_x25_fac = -1;
112 static gint ett_x25_fac_unknown = -1;
113 static gint ett_x25_fac_mark = -1;
114 static gint ett_x25_fac_reverse = -1;
115 static gint ett_x25_fac_throughput = -1;
116 static gint ett_x25_fac_cug = -1;
117 static gint ett_x25_fac_called_modif = -1;
118 static gint ett_x25_fac_cug_outgoing_acc = -1;
119 static gint ett_x25_fac_throughput_min = -1;
120 static gint ett_x25_fac_express_data = -1;
121 static gint ett_x25_fac_bilateral_cug = -1;
122 static gint ett_x25_fac_packet_size = -1;
123 static gint ett_x25_fac_window_size = -1;
124 static gint ett_x25_fac_rpoa_selection = -1;
125 static gint ett_x25_fac_transit_delay = -1;
126 static gint ett_x25_fac_call_transfer = -1;
127 static gint ett_x25_fac_called_addr_ext = -1;
128 static gint ett_x25_fac_ete_transit_delay = -1;
129 static gint ett_x25_fac_calling_addr_ext = -1;
130 static gint ett_x25_fac_call_deflect = -1;
131 static gint ett_x25_fac_priority = -1;
133 static const value_string vals_modulo[] = {
139 static const value_string vals_x25_type[] = {
140 { X25_CALL_REQUEST, "Call" },
141 { X25_CALL_ACCEPTED, "Call Accepted" },
142 { X25_CLEAR_REQUEST, "Clear" },
143 { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
144 { X25_INTERRUPT, "Interrupt" },
145 { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
146 { X25_RESET_REQUEST, "Reset" },
147 { X25_RESET_CONFIRMATION, "Reset Confirmation" },
148 { X25_RESTART_REQUEST, "Restart" },
149 { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
150 { X25_REGISTRATION_REQUEST, "Registration" },
151 { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
152 { X25_DIAGNOSTIC, "Diagnostic" },
156 { X25_DATA, "DATA" },
161 * each vc_info node contains :
162 * the time of the first frame using this dissector (secs and usecs)
163 * the time of the last frame using this dissector (0 if it is unknown)
164 * a pointer to the dissector
166 * the "time of first frame" is initialized when a Call Req. is received
167 * the "time of last frame" is initialized when a Clear, Reset, or Restart
170 typedef struct _vc_info {
171 guint32 first_frame_secs, first_frame_usecs;
172 guint32 last_frame_secs, last_frame_usecs;
173 void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
174 struct _vc_info *next;
178 * the hash table will contain linked lists of global_vc_info
179 * each global_vc_info struct contains :
180 * the VC number (the hash table is indexed with VC % 64)
181 * a linked list of vc_info
183 typedef struct _global_vc_info {
186 struct _global_vc_info *next;
189 static global_vc_info *hash_table[64];
192 free_vc_info(vc_info *pt)
204 reinit_x25_hashtable(void)
208 for (i=0; i<64; i++) {
209 if (hash_table[i]) /* not NULL ==> free */
211 global_vc_info *hash_ent, *hash_ent2;
212 hash_ent2 = hash_ent = hash_table[i];
215 hash_ent2 = hash_ent;
216 hash_ent = hash_ent->next;
217 free_vc_info(hash_ent2->info);
226 x25_hash_add_proto_start(guint16 vc, guint32 frame_secs, guint32 frame_usecs,
227 void (*dissect)(const u_char *, int, frame_data *,
231 global_vc_info *hash_ent;
232 global_vc_info *hash_ent2;
234 if (hash_table[idx] == 0)
236 hash_ent = (global_vc_info *)g_malloc(sizeof(global_vc_info));
238 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
241 hash_ent->vc_num = vc;
243 hash_ent->info = (vc_info *)g_malloc(sizeof(vc_info));
244 if (!hash_ent->info) {
245 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
248 hash_ent->info->first_frame_secs = frame_secs;
249 hash_ent->info->first_frame_usecs = frame_usecs;
250 hash_ent->info->last_frame_secs = 0;
251 hash_ent->info->last_frame_usecs = 0;
252 hash_ent->info->dissect = dissect;
253 hash_ent->info->next = 0;
254 hash_table[idx] = hash_ent;
258 hash_ent2 = hash_ent = hash_table[idx];
259 /* search an entry with the same VC number */
260 while (hash_ent != NULL && hash_ent->vc_num != vc) {
261 hash_ent2 = hash_ent;
262 hash_ent = hash_ent->next;
264 if (hash_ent != NULL) /* hash_ent->vc_num == vc */
266 vc_info *vci = hash_ent->info;
267 while (vci->next) vci = vci->next; /* last element */
268 if (vci->dissect == dissect) {
269 vci->last_frame_secs = 0;
270 vci->last_frame_usecs = 0;
273 vci->next = (vc_info *)g_malloc(sizeof(vc_info));
274 if (vci->next == 0) {
275 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
278 vci->next->first_frame_secs = frame_secs;
279 vci->next->first_frame_usecs = frame_usecs;
280 vci->next->last_frame_secs = 0;
281 vci->next->last_frame_usecs = 0;
282 vci->next->dissect = dissect;
286 else /* new vc number */
288 hash_ent2->next = (global_vc_info *)g_malloc(sizeof(global_vc_info));
289 if (!hash_ent2->next) {
290 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
293 hash_ent2->next->info = (vc_info *)g_malloc(sizeof(vc_info));
294 if (!hash_ent2->next->info) {
295 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
298 hash_ent2->next->info->first_frame_secs = frame_secs;
299 hash_ent2->next->info->first_frame_usecs = frame_usecs;
300 hash_ent2->next->info->last_frame_secs = 0;
301 hash_ent2->next->info->last_frame_usecs = 0;
302 hash_ent2->next->info->dissect = dissect;
303 hash_ent2->next->info->next = 0;
309 x25_hash_add_proto_end(guint16 vc, guint32 frame_secs, guint32 frame_usecs)
311 global_vc_info *hash_ent = hash_table[vc%64];
314 if (!hash_ent) return;
315 while(hash_ent->vc_num != vc) hash_ent = hash_ent->next;
316 if (!hash_ent) return;
318 vci = hash_ent->info;
319 while (vci->next) vci = vci->next;
320 vci->last_frame_secs = frame_secs;
321 vci->last_frame_usecs = frame_usecs;
324 void (*x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc))(const u_char *, int, frame_data *, proto_tree *)
326 global_vc_info *hash_ent = hash_table[vc%64];
330 if (!hash_ent) return 0;
332 while(hash_ent && hash_ent->vc_num != vc) hash_ent = hash_ent->next;
333 if (!hash_ent) return 0;
335 /* a hash_ent was found for this VC number */
336 vci2 = vci = hash_ent->info;
338 /* looking for an entry matching our frame time */
339 while (vci && (vci->last_frame_secs < frame_secs ||
340 (vci->last_frame_secs == frame_secs &&
341 vci->last_frame_usecs < frame_usecs))) {
345 /* we reached last record, and previous record has a non zero
346 * last frame time ==> no dissector */
347 if (!vci && (vci2->last_frame_secs || vci2->last_frame_usecs)) return 0;
349 /* we reached last record, and previous record has a zero last frame time
350 * ==> dissector for previous frame has not been "stopped" by a Clear, etc */
352 /* if the start time for vci2 is greater than our frame time
353 * ==> no dissector */
354 if (frame_secs < vci2->first_frame_secs ||
355 (frame_secs == vci2->first_frame_secs &&
356 frame_usecs < vci2->first_frame_usecs))
359 return vci2->dissect;
362 /* our frame time is before vci's end. Check if it is adter vci's start */
363 if (frame_secs < vci->first_frame_secs ||
364 (frame_secs == vci->first_frame_secs &&
365 frame_usecs < vci->first_frame_usecs))
371 static char *clear_code(unsigned char code)
373 static char buffer[25];
375 if (code == 0x00 || (code & 0x80) == 0x80)
376 return "DTE Originated";
378 return "Number Busy";
380 return "Out Of Order";
382 return "Remote Procedure Error";
384 return "Reverse Charging Acceptance Not Subscribed";
386 return "Incompatible Destination";
388 return "Fast Select Acceptance Not Subscribed";
390 return "Destination Absent";
392 return "Invalid Facility Requested";
394 return "Access Barred";
396 return "Local Procedure Error";
398 return "Network Congestion";
400 return "Not Obtainable";
402 return "RPOA Out Of Order";
404 sprintf(buffer, "Unknown %02X", code);
409 static char *clear_diag(unsigned char code)
411 static char buffer[25];
414 return "No additional information";
416 return "Invalid P(S)";
418 return "Invalid P(R)";
420 return "Packet type invalid";
422 return "Packet type invalid for state r1";
424 return "Packet type invalid for state r2";
426 return "Packet type invalid for state r3";
428 return "Packet type invalid for state p1";
430 return "Packet type invalid for state p2";
432 return "Packet type invalid for state p3";
434 return "Packet type invalid for state p4";
436 return "Packet type invalid for state p5";
438 return "Packet type invalid for state p6";
440 return "Packet type invalid for state p7";
442 return "Packet type invalid for state d1";
444 return "Packet type invalid for state d2";
446 return "Packet type invalid for state d3";
448 return "Packet not allowed";
450 return "Unidentifiable packet";
452 return "Call on one-way logical channel";
454 return "Invalid packet type on a PVC";
456 return "Packet on unassigned LC";
458 return "Reject not subscribed to";
460 return "Packet too short";
462 return "Packet too long";
464 return "Invalid general format identifier";
466 return "Restart/registration packet with nonzero bits";
468 return "Packet type not compatible with facility";
470 return "Unauthorised interrupt confirmation";
472 return "Unauthorised interrupt";
474 return "Unauthorised reject";
476 return "Time expired";
478 return "Time expired for incoming call";
480 return "Time expired for clear indication";
482 return "Time expired for reset indication";
484 return "Time expired for restart indication";
486 return "Time expired for call deflection";
488 return "Call set-up/clearing or registration pb.";
490 return "Facility/registration code not allowed";
492 return "Facility parameter not allowed";
494 return "Invalid called DTE address";
496 return "Invalid calling DTE address";
498 return "Invalid facility/registration length";
500 return "Incoming call barred";
502 return "No logical channel available";
504 return "Call collision";
506 return "Duplicate facility requested";
508 return "Non zero address length";
510 return "Non zero facility length";
512 return "Facility not provided when expected";
514 return "Invalid CCITT-specified DTE facility";
516 return "Max. nb of call redir/defl. exceeded";
518 return "Miscellaneous";
520 return "Improper cause code from DTE";
522 return "Not aligned octet";
524 return "Inconsistent Q bit setting";
526 return "NUI problem";
528 return "International problem";
530 return "Remote network problem";
532 return "International protocol problem";
534 return "International link out of order";
536 return "International link busy";
538 return "Transit network facility problem";
540 return "Remote network facility problem";
542 return "International routing problem";
544 return "Temporary routing problem";
546 return "Unknown called DNIC";
548 return "Maintenance action";
550 sprintf(buffer, "Unknown %d", code);
555 static char *reset_code(unsigned char code)
557 static char buffer[25];
559 if (code == 0x00 || (code & 0x80) == 0x80)
560 return "DTE Originated";
562 return "Out of order";
564 return "Remote Procedure Error";
566 return "Local Procedure Error";
568 return "Network Congestion";
570 return "Remote DTE operational";
572 return "Network operational";
574 return "Incompatible Destination";
576 return "Network out of order";
578 sprintf(buffer, "Unknown %02X", code);
583 static char *restart_code(unsigned char code)
585 static char buffer[25];
587 if (code == 0x00 || (code & 0x80) == 0x80)
588 return "DTE Originated";
590 return "Local Procedure Error";
592 return "Network Congestion";
594 return "Network Operational";
596 return "Registration/cancellation confirmed";
598 sprintf(buffer, "Unknown %02X", code);
603 static char *registration_code(unsigned char code)
605 static char buffer[25];
608 return "Invalid facility request";
610 return "Network congestion";
612 return "Local procedure error";
614 return "Registration/cancellation confirmed";
616 sprintf(buffer, "Unknown %02X", code);
622 dump_facilities(proto_tree *tree, int *offset, const guint8 *p)
624 const guint8 *ptr = p;
625 guint32 len; /* facilities length */
627 proto_tree *fac_tree = 0;
628 proto_tree *fac_subtree;
632 ti = proto_tree_add_text(tree, *offset, len + 1,
634 fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
635 proto_tree_add_text(fac_tree, *offset, 1,
636 "Facilities length: %d", len);
641 switch(*ptr & X25_FAC_CLASS_MASK) {
642 case X25_FAC_CLASS_A:
644 case X25_FAC_COMP_MARK:
646 ti = proto_tree_add_text(fac_tree, *offset, 1,
647 "Code : 00 (Marker)");
651 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
652 proto_tree_add_text(fac_subtree, *offset+1, 1,
653 "Parameter : 00 (Network complementary "
654 "services - calling DTE)");
659 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
660 proto_tree_add_text(fac_subtree, *offset+1, 1,
661 "Parameter : FF (Network complementary "
662 "services - called DTE)");
667 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
668 proto_tree_add_text(fac_subtree, *offset+1, 1,
669 "Parameter : 0F (DTE complementary "
675 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
676 proto_tree_add_text(fac_subtree, *offset+1, 1,
677 "Parameter : %02X (Unknown marker)",
683 case X25_FAC_REVERSE:
685 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
686 "(Reverse charging / Fast select)", *ptr);
687 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
688 proto_tree_add_text(fac_subtree, *offset+1, 1, "Parameter : %02X",
691 proto_tree_add_text(fac_subtree, *offset+1, 1,
692 "11.. .... = Fast select with restriction");
693 else if (ptr[1] & 0x80)
694 proto_tree_add_text(fac_subtree, *offset+1, 1,
695 "10.. .... = Fast select - no restriction");
697 proto_tree_add_text(fac_subtree, *offset+1, 1,
698 "00.. .... = Fast select not requested");
699 proto_tree_add_text(fac_subtree, *offset+1, 1,
700 decode_boolean_bitfield(ptr[1], 0x01, 1*8,
701 "Reverse charging requested",
702 "Reverse charging not requested"));
705 case X25_FAC_THROUGHPUT:
709 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
710 "(Throughput class negociation)", *ptr);
711 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
723 sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
724 75*(1<<((ptr[1] >> 4)-3)));
727 sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
730 sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
733 sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
735 proto_tree_add_text(fac_subtree, *offset+1, 1,
736 decode_numeric_bitfield(ptr[1], 0xF0, 1*8, tmpbuf));
737 switch (ptr[1] & 0x0F)
748 sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
749 75*(1<<((ptr[1] & 0x0F)-3)));
752 sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
755 sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
758 sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
760 proto_tree_add_text(fac_subtree, *offset+1, 1,
761 decode_numeric_bitfield(ptr[1], 0x0F, 1*8, tmpbuf));
766 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
767 "(Closed user group selection)", *ptr);
768 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
769 proto_tree_add_text(fac_subtree, *offset+1, 1,
770 "Closed user group: %02X", ptr[1]);
773 case X25_FAC_CALLED_MODIF:
775 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
776 "(Called address modified)", *ptr);
777 fac_subtree = proto_item_add_subtree(ti,
778 ett_x25_fac_called_modif);
779 proto_tree_add_text(fac_tree, *offset, 2,
780 "Parameter %02X", ptr[1]);
783 case X25_FAC_CUG_OUTGOING_ACC:
785 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
786 "(Closed user group with outgoing access selection)",
788 fac_subtree = proto_item_add_subtree(ti,
789 ett_x25_fac_cug_outgoing_acc);
790 proto_tree_add_text(fac_subtree, *offset+1, 1,
791 "Closed user group: %02X", ptr[1]);
794 case X25_FAC_THROUGHPUT_MIN:
796 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
797 "(Minimum throughput class)", *ptr);
798 fac_subtree = proto_item_add_subtree(ti,
799 ett_x25_fac_throughput_min);
800 proto_tree_add_text(fac_subtree, *offset+1, 1,
801 "Parameter %02X", ptr[1]);
804 case X25_FAC_EXPRESS_DATA:
806 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
807 "(Negociation of express data)", *ptr);
808 fac_subtree = proto_item_add_subtree(ti,
809 ett_x25_fac_express_data);
810 proto_tree_add_text(fac_subtree, *offset+1, 1,
811 "Parameter %02X", ptr[1]);
816 ti = proto_tree_add_text(fac_tree, *offset, 1,
817 "Code : %02X (Unknown class A)", *ptr);
818 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
819 proto_tree_add_text(fac_subtree, *offset+1, 1,
820 "Parameter %02X", ptr[1]);
828 case X25_FAC_CLASS_B:
830 case X25_FAC_BILATERAL_CUG:
832 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
833 "(Bilateral closed user group selection)", *ptr);
834 fac_subtree = proto_item_add_subtree(ti,
835 ett_x25_fac_bilateral_cug);
836 proto_tree_add_text(fac_subtree, *offset+1, 2,
837 "Bilateral CUG: %02X%02X",
841 case X25_FAC_PACKET_SIZE:
846 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
847 "(Packet size)", *ptr);
848 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
852 sprintf(tmpbuf, "From the called DTE : %%u (16)");
855 sprintf(tmpbuf, "From the called DTE : %%u (32)");
858 sprintf(tmpbuf, "From the called DTE : %%u (64)");
861 sprintf(tmpbuf, "From the called DTE : %%u (128)");
864 sprintf(tmpbuf, "From the called DTE : %%u (256)");
867 sprintf(tmpbuf, "From the called DTE : %%u (512)");
870 sprintf(tmpbuf, "From the called DTE : %%u (1024)");
873 sprintf(tmpbuf, "From the called DTE : %%u (2048)");
876 sprintf(tmpbuf, "From the called DTE : %%u (4096)");
879 sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
882 proto_tree_add_text(fac_subtree, *offset+1, 1,
883 decode_numeric_bitfield(ptr[1], 0x0F, 1*8, tmpbuf));
888 sprintf(tmpbuf, "From the calling DTE : %%u (16)");
891 sprintf(tmpbuf, "From the calling DTE : %%u (32)");
894 sprintf(tmpbuf, "From the calling DTE : %%u (64)");
897 sprintf(tmpbuf, "From the calling DTE : %%u (128)");
900 sprintf(tmpbuf, "From the calling DTE : %%u (256)");
903 sprintf(tmpbuf, "From the calling DTE : %%u (512)");
906 sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
909 sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
912 sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
915 sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
918 proto_tree_add_text(fac_subtree, *offset+2, 1,
919 decode_numeric_bitfield(ptr[2], 0x0F, 1*8, tmpbuf));
922 case X25_FAC_WINDOW_SIZE:
924 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
925 "(Window size)", *ptr);
926 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
927 proto_tree_add_text(fac_subtree, *offset+1, 1,
928 decode_numeric_bitfield(ptr[1], 0x7F, 1*8,
929 "From the called DTE: %u"));
930 proto_tree_add_text(fac_subtree, *offset+2, 1,
931 decode_numeric_bitfield(ptr[2], 0x7F, 1*8,
932 "From the calling DTE: %u"));
935 case X25_FAC_RPOA_SELECTION:
937 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
938 "(RPOA selection)", *ptr);
939 fac_subtree = proto_item_add_subtree(ti,
940 ett_x25_fac_rpoa_selection);
941 proto_tree_add_text(fac_subtree, *offset+1, 2,
942 "Data network identification code : %02X%02X",
946 case X25_FAC_TRANSIT_DELAY:
948 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
949 "(Transit delay selection and indication)", *ptr);
950 fac_subtree = proto_item_add_subtree(ti,
951 ett_x25_fac_transit_delay);
952 proto_tree_add_text(fac_subtree, *offset+1, 2,
953 "Transit delay: %d ms",
954 (ptr[1]<<8) + ptr[2]);
959 ti = proto_tree_add_text(fac_tree, *offset, 1,
960 "Code : %02X (Unknown class B)", *ptr);
961 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
962 proto_tree_add_text(fac_subtree, *offset+1, 2,
963 "Parameter %02X%02X", ptr[1], ptr[2]);
971 case X25_FAC_CLASS_C:
973 ti = proto_tree_add_text(fac_tree, *offset, 1,
974 "Code : %02X (Unknown class C)", *ptr);
975 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
976 proto_tree_add_text(fac_subtree, *offset+1, 3,
977 "Parameter %02X%02X%02X",
978 ptr[1], ptr[2], ptr[3]);
984 case X25_FAC_CLASS_D:
986 case X25_FAC_CALL_TRANSFER:
991 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
992 "(Call redirection or deflection notification)", *ptr);
993 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
994 proto_tree_add_text(fac_subtree, *offset+1, 1,
995 "Length : %u", ptr[1]);
996 if ((ptr[2] & 0xC0) == 0xC0) {
997 proto_tree_add_text(fac_subtree, *offset+2, 1,
998 "Reason : call deflection by the originally "
999 "called DTE address");
1004 proto_tree_add_text(fac_subtree, *offset+2, 1,
1005 "Reason : originally called DTE busy");
1008 proto_tree_add_text(fac_subtree, *offset+2, 1,
1009 "Reason : call dist. within a hunt group");
1012 proto_tree_add_text(fac_subtree, *offset+2, 1,
1013 "Reason : originally called DTE out of order");
1016 proto_tree_add_text(fac_subtree, *offset+2, 1,
1017 "Reason : systematic call redirection");
1020 proto_tree_add_text(fac_subtree, *offset+2, 1,
1021 "Reason : unknown");
1025 proto_tree_add_text(fac_subtree, *offset+3, 1,
1026 "Number of semi-octets in DTE address : %u", ptr[3]);
1027 for (i = 0; i < ptr[3]; i++) {
1029 tmpbuf[i] = ((ptr[4+i/2] >> 4) & 0x0F) + '0';
1030 /* if > 9, convert to the right hexadecimal letter */
1031 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1033 tmpbuf[i] = (ptr[4+i/2] & 0x0F) + '0';
1034 /* if > 9, convert to the right hexadecimal letter */
1035 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1039 proto_tree_add_text(fac_subtree, *offset+4, ptr[1] - 2,
1040 "DTE address : %s", tmpbuf);
1043 case X25_FAC_CALLING_ADDR_EXT:
1048 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1049 "(Calling address extension)", *ptr);
1050 fac_subtree = proto_item_add_subtree(ti,
1051 ett_x25_fac_calling_addr_ext);
1052 proto_tree_add_text(fac_subtree, *offset+1, 1,
1053 "Length : %u", ptr[1]);
1054 proto_tree_add_text(fac_subtree, *offset+2, 1,
1055 "Number of semi-octets in DTE address : %u", ptr[2]);
1056 for (i = 0; i < ptr[2]; i++) {
1058 tmpbuf[i] = ((ptr[3+i/2] >> 4) & 0x0F) + '0';
1059 /* if > 9, convert to the right hexadecimal letter */
1060 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1062 tmpbuf[i] = (ptr[3+i/2] & 0x0F) + '0';
1063 /* if > 9, convert to the right hexadecimal letter */
1064 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1068 proto_tree_add_text(fac_subtree, *offset+3, ptr[1] - 1,
1069 "DTE address : %s", tmpbuf);
1072 case X25_FAC_CALLED_ADDR_EXT:
1077 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1078 "(Called address extension)", *ptr);
1079 fac_subtree = proto_item_add_subtree(ti,
1080 ett_x25_fac_called_addr_ext);
1081 proto_tree_add_text(fac_subtree, *offset+1, 1,
1082 "Length : %u", ptr[1]);
1083 proto_tree_add_text(fac_subtree, *offset+2, 1,
1084 "Number of semi-octets in DTE address : %u", ptr[2]);
1085 for (i = 0; i < ptr[2]; i++) {
1087 tmpbuf[i] = ((ptr[3+i/2] >> 4) & 0x0F) + '0';
1088 /* if > 9, convert to the right hexadecimal letter */
1089 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1091 tmpbuf[i] = (ptr[3+i/2] & 0x0F) + '0';
1092 /* if > 9, convert to the right hexadecimal letter */
1093 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1097 proto_tree_add_text(fac_subtree, *offset+3, ptr[1] - 1,
1098 "DTE address : %s", tmpbuf);
1101 case X25_FAC_ETE_TRANSIT_DELAY:
1103 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1104 "(End to end transit delay)", *ptr);
1105 fac_subtree = proto_item_add_subtree(ti,
1106 ett_x25_fac_ete_transit_delay);
1107 proto_tree_add_text(fac_subtree, *offset+1, 1,
1108 "Length : %u", ptr[1]);
1109 proto_tree_add_text(fac_subtree, *offset+2, ptr[1], "Value");
1112 case X25_FAC_CALL_DEFLECT:
1117 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1118 "(Call deflection selection)", *ptr);
1119 fac_subtree = proto_item_add_subtree(ti,
1120 ett_x25_fac_call_deflect);
1121 proto_tree_add_text(fac_subtree, *offset+1, 1,
1122 "Length : %u", ptr[1]);
1123 if ((ptr[2] & 0xC0) == 0xC0)
1124 proto_tree_add_text(fac_subtree, *offset+2, 1,
1125 "Reason : call DTE originated");
1127 proto_tree_add_text(fac_subtree, *offset+2, 1,
1128 "Reason : unknown");
1129 proto_tree_add_text(fac_subtree, *offset+3, 1,
1130 "Number of semi-octets in the alternative DTE address : %u",
1132 for (i = 0; i < ptr[3]; i++) {
1134 tmpbuf[i] = ((ptr[4+i/2] >> 4) & 0x0F) + '0';
1135 /* if > 9, convert to the right hexadecimal letter */
1136 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1138 tmpbuf[i] = (ptr[4+i/2] & 0x0F) + '0';
1139 /* if > 9, convert to the right hexadecimal letter */
1140 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1144 proto_tree_add_text(fac_subtree, *offset+4, ptr[1] - 2,
1145 "Alternative DTE address : %s", tmpbuf);
1148 case X25_FAC_PRIORITY:
1150 ti = proto_tree_add_text(fac_tree, *offset, 1,
1151 "Code : %02X (Priority)", *ptr);
1152 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
1153 proto_tree_add_text(fac_subtree, *offset+1, 1,
1154 "Length : %u", ptr[1]);
1155 proto_tree_add_text(fac_subtree, *offset+2, ptr[1], "Value");
1160 ti = proto_tree_add_text(fac_tree, *offset, 1,
1161 "Code : %02X (Unknown class D)", *ptr);
1162 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1163 proto_tree_add_text(fac_subtree, *offset+1, 1,
1164 "Length : %u", ptr[1]);
1165 proto_tree_add_text(fac_subtree, *offset+2, ptr[1], "Value");
1168 (*offset) += ptr[1]+2;
1177 x25_ntoa(proto_tree *tree, int *offset, const guint8 *p,
1178 frame_data *fd, gboolean toa)
1182 char addr1[16], addr2[16];
1183 char *first, *second;
1185 len1 = (*p >> 4) & 0x0F;
1186 len2 = (*p >> 0) & 0x0F;
1188 proto_tree_add_text(tree, *offset, 1,
1189 decode_numeric_bitfield(*p, 0xF0, 1*8,
1190 toa ? "Called address length : %u" :
1191 "Calling address length : %u"));
1192 proto_tree_add_text(tree, *offset, 1,
1193 decode_numeric_bitfield(*p, 0x0F, 1*8,
1194 toa ? "Calling address length : %u" :
1195 "Called address length : %u"));
1203 for (i = 0; i < (len1 + len2); i++) {
1206 *first++ = ((*p >> 0) & 0x0F) + '0';
1209 *first++ = ((*p >> 4) & 0x0F) + '0';
1213 *second++ = ((*p >> 0) & 0x0F) + '0';
1216 *second++ = ((*p >> 4) & 0x0F) + '0';
1226 if (check_col(fd, COL_RES_DL_DST))
1227 col_add_str(fd, COL_RES_DL_DST, addr1);
1230 if(check_col(fd, COL_RES_DL_SRC))
1231 col_add_str(fd, COL_RES_DL_SRC, addr1);
1234 proto_tree_add_text(tree, *offset,
1237 toa ? "Called" : "Calling",
1242 if (check_col(fd, COL_RES_DL_SRC))
1243 col_add_str(fd, COL_RES_DL_SRC, addr2);
1246 if(check_col(fd, COL_RES_DL_DST))
1247 col_add_str(fd, COL_RES_DL_DST, addr2);
1250 proto_tree_add_text(tree, *offset + len1/2,
1251 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1253 toa ? "Calling" : "Called",
1256 (*offset) += ((len1 + len2 + 1) / 2);
1260 get_x25_pkt_len(const char *data, frame_data *fd, int offset)
1262 int length, called_len, calling_len, dte_len, dce_len;
1264 /* packet size should always be > 3 */
1265 if (!BYTES_ARE_IN_FRAME(offset, 3)) return END_OF_FRAME;
1267 switch ((guint8)data[2])
1269 case X25_CALL_REQUEST:
1270 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1272 called_len = (data[3] >> 0) & 0x0F;
1273 calling_len = (data[3] >> 4) & 0x0F;
1274 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1275 if (length+offset < pi.captured_len)
1276 length += (1 + data[length]); /* facilities */
1278 else length = END_OF_FRAME;
1279 return MIN(END_OF_FRAME,length);
1281 case X25_CALL_ACCEPTED:
1282 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1284 called_len = (data[3] >> 0) & 0x0F;
1285 calling_len = (data[3] >> 4) & 0x0F;
1286 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1287 if (length+offset < pi.captured_len)
1288 length += (1 + data[length]); /* facilities */
1290 else length = END_OF_FRAME;
1291 return MIN(END_OF_FRAME,length);
1293 case X25_CLEAR_REQUEST:
1294 case X25_RESET_REQUEST:
1295 case X25_RESTART_REQUEST:
1296 return MIN(END_OF_FRAME,5);
1298 case X25_DIAGNOSTIC:
1299 return MIN(END_OF_FRAME,4);
1301 case X25_CLEAR_CONFIRMATION:
1303 case X25_INTERRUPT_CONFIRMATION:
1304 case X25_RESET_CONFIRMATION:
1305 case X25_RESTART_CONFIRMATION:
1306 return MIN(END_OF_FRAME,3);
1308 case X25_REGISTRATION_REQUEST:
1309 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1311 dce_len = (data[3] >> 0) & 0x0F;
1312 dte_len = (data[3] >> 4) & 0x0F;
1313 length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1314 if (length+offset < pi.captured_len)
1315 length += (1 + data[length]); /* registration */
1317 else length = END_OF_FRAME;
1318 return MIN(END_OF_FRAME,length);
1320 case X25_REGISTRATION_CONFIRMATION:
1321 if (BYTES_ARE_IN_FRAME(offset, 6)) /* pkt size >= 6 */
1323 dce_len = (data[5] >> 0) & 0x0F;
1324 dte_len = (data[5] >> 4) & 0x0F;
1325 length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1326 if (length+offset < pi.captured_len)
1327 length += (1 + data[length]); /* registration */
1329 else length = END_OF_FRAME;
1330 return MIN(END_OF_FRAME,length);
1333 if ((data[2] & 0x01) == X25_DATA) return MIN(END_OF_FRAME,3);
1335 switch (data[2] & 0x1F)
1338 return MIN(END_OF_FRAME,3);
1341 return MIN(END_OF_FRAME,3);
1344 return MIN(END_OF_FRAME,3);
1350 #define PRT_ID_ISO_8073 0x01
1352 static const value_string prt_id_vals[] = {
1353 {PRT_ID_ISO_8073, "ISO 8073 COTP"},
1355 {0x03, "ISO 10732 in conjunction with ISO 8073"},
1356 {0x04, "ISO 10736 in conjunction with ISO 8602"},
1360 static const value_string sharing_strategy_vals[] = {
1361 {0x00, "No sharing"},
1366 dissect_x25(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1368 proto_tree *x25_tree=0, *ti;
1369 int localoffset=offset;
1373 void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
1374 gboolean toa; /* TOA/NPI address format */
1376 if (check_col(fd, COL_PROTOCOL))
1377 col_add_str(fd, COL_PROTOCOL, "X.25");
1379 modulo = ((pd[localoffset] & 0x20) ? 128 : 8);
1381 if (pd[localoffset] & 0x80) toa = TRUE;
1384 x25_pkt_len = get_x25_pkt_len(&pd[localoffset], fd, offset);
1385 if (x25_pkt_len < 3) /* packet too short */
1387 if (check_col(fd, COL_INFO))
1388 col_add_str(fd, COL_INFO, "Invalid/short X.25 packet");
1390 proto_tree_add_item_format(tree, (modulo == 8 ? proto_x25 : proto_ex25),
1391 localoffset, END_OF_FRAME, NULL,
1392 "Invalid/short X.25 packet");
1395 vc = (int)(pd[localoffset] & 0x0F)*256 + (int)pd[localoffset+1];
1397 ti = proto_tree_add_item(tree, (modulo == 8) ? proto_x25 : proto_ex25,
1398 localoffset, x25_pkt_len, NULL);
1399 x25_tree = proto_item_add_subtree(ti, ett_x25);
1400 if (pd[localoffset] & 0x80)
1401 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_qbit : hf_ex25_qbit,
1402 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1403 if (pd[localoffset] & 0x40)
1404 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_dbit : hf_ex25_dbit,
1405 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1406 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_mod : hf_ex25_mod,
1407 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1409 switch (pd[localoffset+2]) {
1410 case X25_CALL_REQUEST:
1411 if (check_col(fd, COL_INFO))
1412 col_add_fstr(fd, COL_INFO, "%s VC:%d",
1413 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Inc. call"
1417 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1418 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1419 proto_tree_add_item_format(x25_tree,
1420 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1421 localoffset+2, 1, X25_CALL_REQUEST,
1422 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Incoming call"
1426 if (localoffset < x25_pkt_len+offset) /* calling/called addresses */
1427 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1429 if (localoffset < x25_pkt_len+offset) /* facilities */
1430 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1432 if (IS_DATA_IN_FRAME(localoffset)) /* user data */
1437 /* Compare the first octet of the CALL REQUEST packet with
1438 various ISO 9577 NLPIDs, as per Annex A of ISO 9577. */
1439 spi = pd[localoffset];
1442 /* XXX - handle other NLPIDs, e.g. PPP? */
1445 x25_hash_add_proto_start(vc, fd->abs_secs,
1446 fd->abs_usecs, dissect_ip);
1448 proto_tree_add_text(x25_tree, localoffset, 1,
1449 "X.224 secondary protocol ID: IP");
1454 if ((pd[localoffset] >= 0x03 && pd[localoffset] <= 0x82)
1455 && pd[localoffset+1] == 0x01) {
1456 /* ISO 9577 claims that a SPI in that range is a
1457 length field for X.224/ISO 8073 or X.264/ISO 11570;
1458 however, some of them collide with NLPIDs such
1459 as 0x81 for ISO 8473 CLNP or ISO 8542 ESIS, so
1460 I don't know how you run those over X.25, assuming
1463 I'm also not sure what the "or" means there; it
1464 looks as if X.264 specifies the layout of a
1465 "UN TPDU" ("Use of network connection TPDU"),
1466 which specifies the transport protocol to use
1467 over this network connection, and 0x03 0x01 0x01
1468 0x00 is such a TPDU, with a length of 3, a UN
1469 field of 1 (as is required), a PRT-ID ("protocol
1470 identifier") field of 1 (X.224/ISO 8073, a/k/a
1471 COTP service), and a SHARE ("sharing strategy")
1472 field of 0 ("no sharing", which is the only one
1475 So we'll assume that's what it is, as the SPI
1476 is in the right range for a length, and the UN
1478 prt_id = pd[localoffset+2];
1480 proto_tree_add_text(x25_tree, localoffset, 1,
1481 "X.264 length indicator: %u",
1483 proto_tree_add_text(x25_tree, localoffset+1, 1,
1484 "X.264 UN TPDU identifier: 0x%02X",
1486 proto_tree_add_text(x25_tree, localoffset+2, 1,
1487 "X.264 protocol identifier: %s",
1488 val_to_str(prt_id, prt_id_vals, "Unknown (0x%02X)"));
1489 proto_tree_add_text(x25_tree, localoffset+3, 1,
1490 "X.264 sharing strategy: %s",
1491 val_to_str(pd[localoffset+3], sharing_strategy_vals, "Unknown (0x%02X)"));
1494 /* XXX - dissect the variable part? */
1496 /* The length doesn't include the length octet itself. */
1497 localoffset += pd[localoffset] + 1;
1501 case PRT_ID_ISO_8073:
1503 x25_hash_add_proto_start(vc, fd->abs_secs,
1504 fd->abs_usecs, dissect_cotp);
1513 if (IS_DATA_IN_FRAME(localoffset))
1514 proto_tree_add_text(x25_tree, localoffset,
1515 pi.captured_len-localoffset, "Data");
1517 localoffset = pi.captured_len;
1522 case X25_CALL_ACCEPTED:
1523 if(check_col(fd, COL_INFO))
1524 col_add_fstr(fd, COL_INFO, "%s VC:%d",
1525 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Call conn."
1529 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1530 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1531 proto_tree_add_item_format(x25_tree,
1532 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1533 localoffset+2, 1, X25_CALL_ACCEPTED,
1534 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Call connected"
1538 if (localoffset < x25_pkt_len+offset) /* calling/called addresses */
1539 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1541 if (localoffset < x25_pkt_len+offset) /* facilities */
1542 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1544 if (IS_DATA_IN_FRAME(localoffset)) { /* user data */
1546 proto_tree_add_text(x25_tree, localoffset,
1547 pi.captured_len-localoffset, "Data");
1548 localoffset=pi.captured_len;
1551 case X25_CLEAR_REQUEST:
1552 if(check_col(fd, COL_INFO)) {
1553 col_add_fstr(fd, COL_INFO, "%s VC:%d %s - %s",
1554 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Clear ind."
1556 vc, clear_code(pd[localoffset+3]),
1557 clear_diag(pd[localoffset+4]));
1559 x25_hash_add_proto_end(vc, fd->abs_secs, fd->abs_usecs);
1561 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1562 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1563 proto_tree_add_item_format(x25_tree,
1564 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1565 localoffset+2, 1, X25_CLEAR_REQUEST,
1566 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Clear indication"
1568 if (localoffset+3 < x25_pkt_len+offset)
1569 proto_tree_add_text(x25_tree, localoffset+3, 1,
1570 "Cause : %s", clear_code(pd[localoffset+3]));
1571 if (localoffset+4 < x25_pkt_len+offset)
1572 proto_tree_add_text(x25_tree, localoffset+4, 1,
1574 clear_diag(pd[localoffset+4]));
1576 localoffset += x25_pkt_len;
1578 case X25_CLEAR_CONFIRMATION:
1579 if(check_col(fd, COL_INFO))
1580 col_add_fstr(fd, COL_INFO, "Clear Conf. VC:%d", vc);
1582 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1583 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1584 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1585 localoffset+2, 1, X25_CLEAR_CONFIRMATION);
1587 localoffset += x25_pkt_len;
1589 if (IS_DATA_IN_FRAME(localoffset)) /* extended clear conf format */
1590 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1592 if (IS_DATA_IN_FRAME(localoffset)) /* facilities */
1593 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1595 case X25_DIAGNOSTIC:
1596 if(check_col(fd, COL_INFO)) {
1597 col_add_fstr(fd, COL_INFO, "Diag. %d", (int)pd[localoffset+3]);
1600 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1601 localoffset+2, 1, X25_DIAGNOSTIC);
1602 if (localoffset+3 < x25_pkt_len+offset)
1603 proto_tree_add_text(x25_tree, localoffset+3, 1,
1604 "Diagnostic : %d", (int)pd[localoffset+3]);
1606 localoffset += x25_pkt_len;
1609 if(check_col(fd, COL_INFO))
1610 col_add_fstr(fd, COL_INFO, "Interrupt VC:%d", vc);
1612 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1613 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1614 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1615 localoffset+2, 1, X25_INTERRUPT);
1617 localoffset += x25_pkt_len;
1619 case X25_INTERRUPT_CONFIRMATION:
1620 if(check_col(fd, COL_INFO))
1621 col_add_fstr(fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
1623 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1624 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1625 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1626 localoffset+2, 1, X25_INTERRUPT_CONFIRMATION);
1628 localoffset += x25_pkt_len;
1630 case X25_RESET_REQUEST:
1631 if(check_col(fd, COL_INFO)) {
1632 col_add_fstr(fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
1633 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Reset ind."
1635 vc, reset_code(pd[localoffset+3]),
1636 (int)pd[localoffset+4]);
1638 x25_hash_add_proto_end(vc, fd->abs_secs, fd->abs_usecs);
1640 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1641 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1642 proto_tree_add_item_format(x25_tree,
1643 (modulo == 8) ? hf_x25_type : hf_ex25_type, localoffset+2, 1,
1645 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Reset indication"
1647 if (localoffset+3 < x25_pkt_len+offset)
1648 proto_tree_add_text(x25_tree, localoffset+3, 1,
1649 "Cause : %s", reset_code(pd[localoffset+3]));
1650 if (localoffset+4 < x25_pkt_len+offset)
1651 proto_tree_add_text(x25_tree, localoffset+4, 1,
1652 "Diagnostic : %d", (int)pd[localoffset+4]);
1654 localoffset += x25_pkt_len;
1656 case X25_RESET_CONFIRMATION:
1657 if(check_col(fd, COL_INFO))
1658 col_add_fstr(fd, COL_INFO, "Reset conf. VC:%d", vc);
1660 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1661 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1662 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1663 localoffset+2, 1, X25_RESET_CONFIRMATION);
1665 localoffset += x25_pkt_len;
1667 case X25_RESTART_REQUEST:
1668 if(check_col(fd, COL_INFO)) {
1669 col_add_fstr(fd, COL_INFO, "%s %s - Diag.:%d",
1670 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Restart ind."
1672 restart_code(pd[localoffset+3]),
1673 (int)pd[localoffset+4]);
1676 proto_tree_add_item_format(x25_tree,
1677 (modulo == 8) ? hf_x25_type : hf_ex25_type, localoffset+2, 1,
1678 X25_RESTART_REQUEST,
1679 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Restart indication"
1680 : "Restart request");
1681 if (localoffset+3 < x25_pkt_len+offset)
1682 proto_tree_add_text(x25_tree, localoffset+3, 1,
1683 "Cause : %s", restart_code(pd[localoffset+3]));
1684 if (localoffset+4 < x25_pkt_len+offset)
1685 proto_tree_add_text(x25_tree, localoffset+4, 1,
1686 "Diagnostic : %d", (int)pd[localoffset+4]);
1688 localoffset += x25_pkt_len;
1690 case X25_RESTART_CONFIRMATION:
1691 if(check_col(fd, COL_INFO))
1692 col_add_str(fd, COL_INFO, "Restart conf.");
1694 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1695 localoffset+2, 1, X25_RESTART_CONFIRMATION);
1696 localoffset += x25_pkt_len;
1698 case X25_REGISTRATION_REQUEST:
1699 if(check_col(fd, COL_INFO))
1700 col_add_str(fd, COL_INFO, "Registration req.");
1702 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1703 localoffset+2, 1, X25_REGISTRATION_REQUEST);
1705 if (localoffset < x25_pkt_len+offset)
1706 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, FALSE);
1709 if (localoffset < x25_pkt_len+offset)
1710 proto_tree_add_text(x25_tree, localoffset, 1,
1711 "Registration length: %d", pd[localoffset] & 0x7F);
1712 if (localoffset+1 < x25_pkt_len+offset)
1713 proto_tree_add_text(x25_tree, localoffset+1,
1714 pd[localoffset] & 0x7F, "Registration");
1716 localoffset = pi.captured_len;
1718 case X25_REGISTRATION_CONFIRMATION:
1719 if(check_col(fd, COL_INFO))
1720 col_add_str(fd, COL_INFO, "Registration conf.");
1722 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1723 localoffset+2, 1, X25_REGISTRATION_CONFIRMATION);
1724 if (localoffset+3 < x25_pkt_len+offset)
1725 proto_tree_add_text(x25_tree, localoffset+3, 1,
1726 "Cause: %s", registration_code(pd[localoffset+3]));
1727 if (localoffset+4 < x25_pkt_len+offset)
1728 proto_tree_add_text(x25_tree, localoffset+4, 1,
1729 "Diagnostic: %s", registration_code(pd[localoffset+4]));
1732 if (localoffset < x25_pkt_len+offset)
1733 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, TRUE);
1736 if (localoffset < x25_pkt_len+offset)
1737 proto_tree_add_text(x25_tree, localoffset, 1,
1738 "Registration length: %d", pd[localoffset] & 0x7F);
1739 if (localoffset+1 < x25_pkt_len+offset)
1740 proto_tree_add_text(x25_tree, localoffset+1,
1741 pd[localoffset] & 0x7F, "Registration");
1743 localoffset = pi.captured_len;
1747 if ((pd[localoffset] & 0x01) == X25_DATA)
1749 if(check_col(fd, COL_INFO)) {
1751 col_add_fstr(fd, COL_INFO,
1752 "Data VC:%d P(S):%d P(R):%d %s", vc,
1753 (pd[localoffset] >> 1) & 0x07,
1754 (pd[localoffset] >> 5) & 0x07,
1755 ((pd[localoffset]>>4) & 0x01) ? " M" : "");
1757 col_add_fstr(fd, COL_INFO,
1758 "Data VC:%d P(S):%d P(R):%d %s", vc,
1759 pd[localoffset+1] >> 1,
1760 pd[localoffset] >> 1,
1761 (pd[localoffset+1] & 0x01) ? " M" : "");
1764 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1765 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1767 proto_tree_add_item_hidden(x25_tree, hf_x25_type, localoffset, 1,
1769 proto_tree_add_item(x25_tree, hf_x25_p_r, localoffset, 1,
1771 if (pd[localoffset] & 0x10)
1772 proto_tree_add_item(x25_tree, hf_x25_mbit, localoffset, 1,
1774 proto_tree_add_item(x25_tree, hf_x25_p_s, localoffset, 1,
1776 proto_tree_add_text(x25_tree, localoffset, 1,
1777 decode_boolean_bitfield(pd[localoffset], 0x01, 1*8,
1781 proto_tree_add_item_hidden(x25_tree, hf_ex25_type, localoffset, 1,
1783 proto_tree_add_item(x25_tree, hf_x25_p_r, localoffset, 1,
1785 proto_tree_add_item(x25_tree, hf_x25_p_s, localoffset+1, 1,
1787 if (pd[localoffset+1] & 0x01)
1788 proto_tree_add_item(x25_tree, hf_ex25_mbit, localoffset+1, 1,
1792 localoffset += (modulo == 8) ? 1 : 2;
1795 switch (pd[localoffset] & 0x1F)
1798 if(check_col(fd, COL_INFO)) {
1800 col_add_fstr(fd, COL_INFO, "RR VC:%d P(R):%d",
1801 vc, (pd[localoffset] >> 5) & 0x07);
1803 col_add_fstr(fd, COL_INFO, "RR VC:%d P(R):%d",
1804 vc, pd[localoffset+1] >> 1);
1807 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1808 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1810 proto_tree_add_item(x25_tree, hf_x25_p_r,
1811 localoffset, 1, pd[localoffset]);
1812 proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_RR);
1815 proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_RR);
1816 proto_tree_add_item(x25_tree, hf_ex25_p_r,
1817 localoffset+1, 1, pd[localoffset+1]);
1823 if(check_col(fd, COL_INFO)) {
1825 col_add_fstr(fd, COL_INFO, "RNR VC:%d P(R):%d",
1826 vc, (pd[localoffset] >> 5) & 0x07);
1828 col_add_fstr(fd, COL_INFO, "RNR VC:%d P(R):%d",
1829 vc, pd[localoffset+1] >> 1);
1832 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1833 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1835 proto_tree_add_item(x25_tree, hf_x25_p_r,
1836 localoffset, 1, pd[localoffset]);
1837 proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_RNR);
1840 proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_RNR);
1841 proto_tree_add_item(x25_tree, hf_ex25_p_r,
1842 localoffset+1, 1, pd[localoffset+1]);
1848 if(check_col(fd, COL_INFO)) {
1850 col_add_fstr(fd, COL_INFO, "REJ VC:%d P(R):%d",
1851 vc, (pd[localoffset] >> 5) & 0x07);
1853 col_add_fstr(fd, COL_INFO, "REJ VC:%d P(R):%d",
1854 vc, pd[localoffset+1] >> 1);
1857 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1858 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1860 proto_tree_add_item(x25_tree, hf_x25_p_r,
1861 localoffset, 1, pd[localoffset]);
1862 proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_REJ);
1865 proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_REJ);
1866 proto_tree_add_item(x25_tree, hf_ex25_p_r,
1867 localoffset+1, 1, pd[localoffset+1]);
1871 localoffset += (modulo == 8) ? 1 : 2;
1874 if (!IS_DATA_IN_FRAME(localoffset)) return;
1876 /* search the dissector in the hash table */
1877 if ((dissect = x25_hash_get_dissect(fd->abs_secs, fd->abs_usecs, vc)))
1878 (*dissect)(pd, localoffset, fd, tree);
1880 if (pd[localoffset] == 0x45) /* If the Call Req. has not been captured,
1881 * assume these packets carry IP */
1883 x25_hash_add_proto_start(vc, fd->abs_secs,
1884 fd->abs_usecs, dissect_ip);
1885 dissect_ip(pd, localoffset, fd, tree);
1888 dissect_data(pd, localoffset, fd, tree);
1894 proto_register_x25(void)
1896 static hf_register_info hf8[] = {
1898 { "Q Bit", "x25.q", FT_BOOLEAN, 2, NULL, 0x8000,
1899 "Qualifier Bit" } },
1901 { "D Bit", "x25.d", FT_BOOLEAN, 2, NULL, 0x4000,
1902 "Delivery Confirmation Bit" } },
1904 { "Modulo", "x25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1905 "Specifies whether the frame is modulo 8 or 128" } },
1907 { "Logical Channel", "x25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
1908 "Logical Channel Number" } },
1910 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1913 { "P(R)", "x25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
1914 "Packet Receive Sequence Number" } },
1916 { "M Bit", "x25.m", FT_BOOLEAN, 1, NULL, 0x10,
1919 { "P(S)", "x25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
1920 "Packet Send Sequence Number" } },
1923 static hf_register_info hf128[] = {
1925 { "Q Bit", "ex25.q", FT_BOOLEAN, 2, NULL, 0x8000,
1926 "Qualifier Bit" } },
1928 { "D Bit", "ex25.d", FT_BOOLEAN, 2, NULL, 0x4000,
1929 "Delivery Confirmation Bit" } },
1931 { "Modulo", "ex25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1932 "Specifies whether the frame is modulo 8 or 128" } },
1934 { "Logical Channel", "ex25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
1935 "Logical Channel Number" } },
1937 { "Packet Type", "ex25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1940 { "P(R)", "ex25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
1941 "Packet Receive Sequence Number" } },
1943 { "M Bit", "ex25.m", FT_BOOLEAN, 1, NULL, 0x01,
1946 { "P(S)", "ex25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
1947 "Packet Send Sequence Number" } },
1949 static gint *ett[] = {
1952 &ett_x25_fac_unknown,
1954 &ett_x25_fac_reverse,
1955 &ett_x25_fac_throughput,
1957 &ett_x25_fac_called_modif,
1958 &ett_x25_fac_cug_outgoing_acc,
1959 &ett_x25_fac_throughput_min,
1960 &ett_x25_fac_express_data,
1961 &ett_x25_fac_bilateral_cug,
1962 &ett_x25_fac_packet_size,
1963 &ett_x25_fac_window_size,
1964 &ett_x25_fac_rpoa_selection,
1965 &ett_x25_fac_transit_delay,
1966 &ett_x25_fac_call_transfer,
1967 &ett_x25_fac_called_addr_ext,
1968 &ett_x25_fac_ete_transit_delay,
1969 &ett_x25_fac_calling_addr_ext,
1970 &ett_x25_fac_call_deflect,
1971 &ett_x25_fac_priority
1974 proto_x25 = proto_register_protocol ("X.25", "x25");
1975 proto_ex25 = proto_register_protocol ("Extended X.25 (modulo 128)", "ex25");
1976 proto_register_field_array (proto_x25, hf8, array_length(hf8));
1977 proto_register_field_array (proto_ex25, hf128, array_length(hf128));
1978 proto_register_subtree_array(ett, array_length(ett));
1979 register_init_routine(&reinit_x25_hashtable);