2 * Routines for x25 packet disassembly
3 * Olivier Abad <abad@daba.dhis.net>
5 * $Id: packet-x25.c,v 1.17 2000/01/30 05:58:02 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>
44 #define X25_CALL_REQUEST 0x0B
45 #define X25_CALL_ACCEPTED 0x0F
46 #define X25_CLEAR_REQUEST 0x13
47 #define X25_CLEAR_CONFIRMATION 0x17
48 #define X25_INTERRUPT 0x23
49 #define X25_INTERRUPT_CONFIRMATION 0x27
50 #define X25_RESET_REQUEST 0x1B
51 #define X25_RESET_CONFIRMATION 0x1F
52 #define X25_RESTART_REQUEST 0xFB
53 #define X25_RESTART_CONFIRMATION 0xFF
54 #define X25_REGISTRATION_REQUEST 0xF3
55 #define X25_REGISTRATION_CONFIRMATION 0xF7
56 #define X25_DIAGNOSTIC 0xF1
62 #define X25_FAC_CLASS_MASK 0xC0
64 #define X25_FAC_CLASS_A 0x00
65 #define X25_FAC_CLASS_B 0x40
66 #define X25_FAC_CLASS_C 0x80
67 #define X25_FAC_CLASS_D 0xC0
69 #define X25_FAC_COMP_MARK 0x00
70 #define X25_FAC_REVERSE 0x01
71 #define X25_FAC_THROUGHPUT 0x02
72 #define X25_FAC_CUG 0x03
73 #define X25_FAC_CALLED_MODIF 0x08
74 #define X25_FAC_CUG_OUTGOING_ACC 0x09
75 #define X25_FAC_THROUGHPUT_MIN 0x0A
76 #define X25_FAC_EXPRESS_DATA 0x0B
77 #define X25_FAC_BILATERAL_CUG 0x41
78 #define X25_FAC_PACKET_SIZE 0x42
79 #define X25_FAC_WINDOW_SIZE 0x43
80 #define X25_FAC_RPOA_SELECTION 0x44
81 #define X25_FAC_TRANSIT_DELAY 0x49
82 #define X25_FAC_CALL_TRANSFER 0xC3
83 #define X25_FAC_CALLED_ADDR_EXT 0xC9
84 #define X25_FAC_ETE_TRANSIT_DELAY 0xCA
85 #define X25_FAC_CALLING_ADDR_EXT 0xCB
86 #define X25_FAC_CALL_DEFLECT 0xD1
87 #define X25_FAC_PRIORITY 0xD2
89 static int proto_x25 = -1;
90 static int hf_x25_qbit = -1;
91 static int hf_x25_dbit = -1;
92 static int hf_x25_mod = -1;
93 static int hf_x25_lcn = -1;
94 static int hf_x25_type = -1;
95 static int hf_x25_p_r = -1;
96 static int hf_x25_mbit = -1;
97 static int hf_x25_p_s = -1;
98 static int proto_ex25 = -1;
99 static int hf_ex25_qbit = -1;
100 static int hf_ex25_dbit = -1;
101 static int hf_ex25_mod = -1;
102 static int hf_ex25_lcn = -1;
103 static int hf_ex25_type = -1;
104 static int hf_ex25_p_r = -1;
105 static int hf_ex25_mbit = -1;
106 static int hf_ex25_p_s = -1;
108 static gint ett_x25 = -1;
109 static gint ett_x25_fac = -1;
110 static gint ett_x25_fac_unknown = -1;
111 static gint ett_x25_fac_mark = -1;
112 static gint ett_x25_fac_reverse = -1;
113 static gint ett_x25_fac_throughput = -1;
114 static gint ett_x25_fac_cug = -1;
115 static gint ett_x25_fac_called_modif = -1;
116 static gint ett_x25_fac_cug_outgoing_acc = -1;
117 static gint ett_x25_fac_throughput_min = -1;
118 static gint ett_x25_fac_express_data = -1;
119 static gint ett_x25_fac_bilateral_cug = -1;
120 static gint ett_x25_fac_packet_size = -1;
121 static gint ett_x25_fac_window_size = -1;
122 static gint ett_x25_fac_rpoa_selection = -1;
123 static gint ett_x25_fac_transit_delay = -1;
124 static gint ett_x25_fac_call_transfer = -1;
125 static gint ett_x25_fac_called_addr_ext = -1;
126 static gint ett_x25_fac_ete_transit_delay = -1;
127 static gint ett_x25_fac_calling_addr_ext = -1;
128 static gint ett_x25_fac_call_deflect = -1;
129 static gint ett_x25_fac_priority = -1;
131 static const value_string vals_modulo[] = {
137 static const value_string vals_x25_type[] = {
138 { X25_CALL_REQUEST, "Call" },
139 { X25_CALL_ACCEPTED, "Call Accepted" },
140 { X25_CLEAR_REQUEST, "Clear" },
141 { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
142 { X25_INTERRUPT, "Interrupt" },
143 { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
144 { X25_RESET_REQUEST, "Reset" },
145 { X25_RESET_CONFIRMATION, "Reset Confirmation" },
146 { X25_RESTART_REQUEST, "Restart" },
147 { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
148 { X25_REGISTRATION_REQUEST, "Registration" },
149 { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
150 { X25_DIAGNOSTIC, "Diagnostic" },
154 { X25_DATA, "DATA" },
159 * each vc_info node contains :
160 * the time of the first frame using this dissector (secs and usecs)
161 * the time of the last frame using this dissector (0 if it is unknown)
162 * a pointer to the dissector
164 * the "time of first frame" is initialized when a Call Req. is received
165 * the "time of last frame" is initialized when a Clear, Reset, or Restart
168 typedef struct _vc_info {
169 guint32 first_frame_secs, first_frame_usecs;
170 guint32 last_frame_secs, last_frame_usecs;
171 void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
172 struct _vc_info *next;
176 * the hash table will contain linked lists of global_vc_info
177 * each global_vc_info struct contains :
178 * the VC number (the hash table is indexed with VC % 64)
179 * a linked list of vc_info
181 typedef struct _global_vc_info {
184 struct _global_vc_info *next;
187 static global_vc_info *hash_table[64];
190 free_vc_info(vc_info *pt)
206 for (i=0; i<64; i++) {
207 if (hash_table[i]) /* not NULL ==> free */
209 global_vc_info *hash_ent, *hash_ent2;
210 hash_ent2 = hash_ent = hash_table[i];
213 hash_ent2 = hash_ent;
214 hash_ent = hash_ent->next;
215 free_vc_info(hash_ent2->info);
224 x25_hash_add_proto_start(guint16 vc, guint32 frame_secs, guint32 frame_usecs,
225 void (*dissect)(const u_char *, int, frame_data *,
229 global_vc_info *hash_ent;
230 global_vc_info *hash_ent2;
232 if (hash_table[idx] == 0)
234 hash_ent = (global_vc_info *)g_malloc(sizeof(global_vc_info));
236 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
239 hash_ent->vc_num = vc;
241 hash_ent->info = (vc_info *)g_malloc(sizeof(vc_info));
242 if (!hash_ent->info) {
243 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
246 hash_ent->info->first_frame_secs = frame_secs;
247 hash_ent->info->first_frame_usecs = frame_usecs;
248 hash_ent->info->last_frame_secs = 0;
249 hash_ent->info->last_frame_usecs = 0;
250 hash_ent->info->dissect = dissect;
251 hash_ent->info->next = 0;
252 hash_table[idx] = hash_ent;
256 hash_ent2 = hash_ent = hash_table[idx];
257 /* search an entry with the same VC number */
258 while (hash_ent != NULL && hash_ent->vc_num != vc) {
259 hash_ent2 = hash_ent;
260 hash_ent = hash_ent->next;
262 if (hash_ent != NULL) /* hash_ent->vc_num == vc */
264 vc_info *vci = hash_ent->info;
265 while (vci->next) vci = vci->next; /* last element */
266 if (vci->dissect == dissect) {
267 vci->last_frame_secs = 0;
268 vci->last_frame_usecs = 0;
271 vci->next = (vc_info *)g_malloc(sizeof(vc_info));
272 if (vci->next == 0) {
273 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
276 vci->next->first_frame_secs = frame_secs;
277 vci->next->first_frame_usecs = frame_usecs;
278 vci->next->last_frame_secs = 0;
279 vci->next->last_frame_usecs = 0;
280 vci->next->dissect = dissect;
284 else /* new vc number */
286 hash_ent2->next = (global_vc_info *)g_malloc(sizeof(global_vc_info));
287 if (!hash_ent2->next) {
288 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
291 hash_ent2->next->info = (vc_info *)g_malloc(sizeof(vc_info));
292 if (!hash_ent2->next->info) {
293 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
296 hash_ent2->next->info->first_frame_secs = frame_secs;
297 hash_ent2->next->info->first_frame_usecs = frame_usecs;
298 hash_ent2->next->info->last_frame_secs = 0;
299 hash_ent2->next->info->last_frame_usecs = 0;
300 hash_ent2->next->info->dissect = dissect;
301 hash_ent2->next->info->next = 0;
307 x25_hash_add_proto_end(guint16 vc, guint32 frame_secs, guint32 frame_usecs)
309 global_vc_info *hash_ent = hash_table[vc%64];
312 if (!hash_ent) return;
313 while(hash_ent->vc_num != vc) hash_ent = hash_ent->next;
314 if (!hash_ent) return;
316 vci = hash_ent->info;
317 while (vci->next) vci = vci->next;
318 vci->last_frame_secs = frame_secs;
319 vci->last_frame_usecs = frame_usecs;
322 void (*x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc))(const u_char *, int, frame_data *, proto_tree *)
324 global_vc_info *hash_ent = hash_table[vc%64];
328 if (!hash_ent) return 0;
330 while(hash_ent && hash_ent->vc_num != vc) hash_ent = hash_ent->next;
331 if (!hash_ent) return 0;
333 /* a hash_ent was found for this VC number */
334 vci2 = vci = hash_ent->info;
336 /* looking for an entry matching our frame time */
337 while (vci && (vci->last_frame_secs < frame_secs ||
338 (vci->last_frame_secs == frame_secs &&
339 vci->last_frame_usecs < frame_usecs))) {
343 /* we reached last record, and previous record has a non zero
344 * last frame time ==> no dissector */
345 if (!vci && (vci2->last_frame_secs || vci2->last_frame_usecs)) return 0;
347 /* we reached last record, and previous record has a zero last frame time
348 * ==> dissector for previous frame has not been "stopped" by a Clear, etc */
350 /* if the start time for vci2 is greater than our frame time
351 * ==> no dissector */
352 if (frame_secs < vci2->first_frame_secs ||
353 (frame_secs == vci2->first_frame_secs &&
354 frame_usecs < vci2->first_frame_usecs))
357 return vci2->dissect;
360 /* our frame time is before vci's end. Check if it is adter vci's start */
361 if (frame_secs < vci->first_frame_secs ||
362 (frame_secs == vci->first_frame_secs &&
363 frame_usecs < vci->first_frame_usecs))
369 static char *clear_code(unsigned char code)
371 static char buffer[25];
373 if (code == 0x00 || (code & 0x80) == 0x80)
374 return "DTE Originated";
376 return "Number Busy";
378 return "Out Of Order";
380 return "Remote Procedure Error";
382 return "Reverse Charging Acceptance Not Subscribed";
384 return "Incompatible Destination";
386 return "Fast Select Acceptance Not Subscribed";
388 return "Destination Absent";
390 return "Invalid Facility Requested";
392 return "Access Barred";
394 return "Local Procedure Error";
396 return "Network Congestion";
398 return "Not Obtainable";
400 return "RPOA Out Of Order";
402 sprintf(buffer, "Unknown %02X", code);
407 static char *clear_diag(unsigned char code)
409 static char buffer[25];
412 return "No additional information";
414 return "Invalid P(S)";
416 return "Invalid P(R)";
418 return "Packet type invalid";
420 return "Packet type invalid for state r1";
422 return "Packet type invalid for state r2";
424 return "Packet type invalid for state r3";
426 return "Packet type invalid for state p1";
428 return "Packet type invalid for state p2";
430 return "Packet type invalid for state p3";
432 return "Packet type invalid for state p4";
434 return "Packet type invalid for state p5";
436 return "Packet type invalid for state p6";
438 return "Packet type invalid for state p7";
440 return "Packet type invalid for state d1";
442 return "Packet type invalid for state d2";
444 return "Packet type invalid for state d3";
446 return "Packet not allowed";
448 return "Unidentifiable packet";
450 return "Call on one-way logical channel";
452 return "Invalid packet type on a PVC";
454 return "Packet on unassigned LC";
456 return "Reject not subscribed to";
458 return "Packet too short";
460 return "Packet too long";
462 return "Invalid general format identifier";
464 return "Restart/registration packet with nonzero bits";
466 return "Packet type not compatible with facility";
468 return "Unauthorised interrupt confirmation";
470 return "Unauthorised interrupt";
472 return "Unauthorised reject";
474 return "Time expired";
476 return "Time expired for incoming call";
478 return "Time expired for clear indication";
480 return "Time expired for reset indication";
482 return "Time expired for restart indication";
484 return "Time expired for call deflection";
486 return "Call set-up/clearing or registration pb.";
488 return "Facility/registration code not allowed";
490 return "Facility parameter not allowed";
492 return "Invalid called DTE address";
494 return "Invalid calling DTE address";
496 return "Invalid facility/registration length";
498 return "Incoming call barred";
500 return "No logical channel available";
502 return "Call collision";
504 return "Duplicate facility requested";
506 return "Non zero address length";
508 return "Non zero facility length";
510 return "Facility not provided when expected";
512 return "Invalid CCITT-specified DTE facility";
514 return "Max. nb of call redir/defl. exceeded";
516 return "Miscellaneous";
518 return "Improper cause code from DTE";
520 return "Not aligned octet";
522 return "Inconsistent Q bit setting";
524 return "NUI problem";
526 return "International problem";
528 return "Remote network problem";
530 return "International protocol problem";
532 return "International link out of order";
534 return "International link busy";
536 return "Transit network facility problem";
538 return "Remote network facility problem";
540 return "International routing problem";
542 return "Temporary routing problem";
544 return "Unknown called DNIC";
546 return "Maintenance action";
548 sprintf(buffer, "Unknown %d", code);
553 static char *reset_code(unsigned char code)
555 static char buffer[25];
557 if (code == 0x00 || (code & 0x80) == 0x80)
558 return "DTE Originated";
560 return "Out of order";
562 return "Remote Procedure Error";
564 return "Local Procedure Error";
566 return "Network Congestion";
568 return "Remote DTE operational";
570 return "Network operational";
572 return "Incompatible Destination";
574 return "Network out of order";
576 sprintf(buffer, "Unknown %02X", code);
581 static char *restart_code(unsigned char code)
583 static char buffer[25];
585 if (code == 0x00 || (code & 0x80) == 0x80)
586 return "DTE Originated";
588 return "Local Procedure Error";
590 return "Network Congestion";
592 return "Network Operational";
594 return "Registration/cancellation confirmed";
596 sprintf(buffer, "Unknown %02X", code);
601 static char *registration_code(unsigned char code)
603 static char buffer[25];
606 return "Invalid facility request";
608 return "Network congestion";
610 return "Local procedure error";
612 return "Registration/cancellation confirmed";
614 sprintf(buffer, "Unknown %02X", code);
620 dump_facilities(proto_tree *tree, int *offset, const guint8 *p)
622 const guint8 *ptr = p;
623 guint32 len; /* facilities length */
625 proto_tree *fac_tree = 0;
626 proto_tree *fac_subtree;
630 ti = proto_tree_add_text(tree, *offset, len + 1,
632 fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
633 proto_tree_add_text(fac_tree, *offset, 1,
634 "Facilities length: %d", len);
639 switch(*ptr & X25_FAC_CLASS_MASK) {
640 case X25_FAC_CLASS_A:
642 case X25_FAC_COMP_MARK:
644 ti = proto_tree_add_text(fac_tree, *offset, 1,
645 "Code : 00 (Marker)");
649 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
650 proto_tree_add_text(fac_subtree, *offset+1, 1,
651 "Parameter : 00 (Network complementary "
652 "services - calling DTE)");
657 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
658 proto_tree_add_text(fac_subtree, *offset+1, 1,
659 "Parameter : FF (Network complementary "
660 "services - called DTE)");
665 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
666 proto_tree_add_text(fac_subtree, *offset+1, 1,
667 "Parameter : 0F (DTE complementary "
673 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
674 proto_tree_add_text(fac_subtree, *offset+1, 1,
675 "Parameter : %02X (Unknown marker)",
681 case X25_FAC_REVERSE:
683 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
684 "(Reverse charging / Fast select)", *ptr);
685 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
686 proto_tree_add_text(fac_subtree, *offset+1, 1, "Parameter : %02X",
689 proto_tree_add_text(fac_subtree, *offset+1, 1,
690 "11.. .... = Fast select with restriction");
691 else if (ptr[1] & 0x80)
692 proto_tree_add_text(fac_subtree, *offset+1, 1,
693 "10.. .... = Fast select - no restriction");
695 proto_tree_add_text(fac_subtree, *offset+1, 1,
696 "00.. .... = Fast select not requested");
697 proto_tree_add_text(fac_subtree, *offset+1, 1,
698 decode_boolean_bitfield(ptr[1], 0x01, 1*8,
699 "Reverse charging requested",
700 "Reverse charging not requested"));
703 case X25_FAC_THROUGHPUT:
707 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
708 "(Throughput class negociation)", *ptr);
709 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
721 sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
722 75*(1<<((ptr[1] >> 4)-3)));
725 sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
728 sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
731 sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
733 proto_tree_add_text(fac_subtree, *offset+1, 1,
734 decode_numeric_bitfield(ptr[1], 0xF0, 1*8, tmpbuf));
735 switch (ptr[1] & 0x0F)
746 sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
747 75*(1<<((ptr[1] & 0x0F)-3)));
750 sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
753 sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
756 sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
758 proto_tree_add_text(fac_subtree, *offset+1, 1,
759 decode_numeric_bitfield(ptr[1], 0x0F, 1*8, tmpbuf));
764 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
765 "(Closed user group selection)", *ptr);
766 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
767 proto_tree_add_text(fac_subtree, *offset+1, 1,
768 "Closed user group: %02X", ptr[1]);
771 case X25_FAC_CALLED_MODIF:
773 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
774 "(Called address modified)", *ptr);
775 fac_subtree = proto_item_add_subtree(ti,
776 ett_x25_fac_called_modif);
777 proto_tree_add_text(fac_tree, *offset, 2,
778 "Parameter %02X", ptr[1]);
781 case X25_FAC_CUG_OUTGOING_ACC:
783 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
784 "(Closed user group with outgoing access selection)",
786 fac_subtree = proto_item_add_subtree(ti,
787 ett_x25_fac_cug_outgoing_acc);
788 proto_tree_add_text(fac_subtree, *offset+1, 1,
789 "Closed user group: %02X", ptr[1]);
792 case X25_FAC_THROUGHPUT_MIN:
794 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
795 "(Minimum throughput class)", *ptr);
796 fac_subtree = proto_item_add_subtree(ti,
797 ett_x25_fac_throughput_min);
798 proto_tree_add_text(fac_subtree, *offset+1, 1,
799 "Parameter %02X", ptr[1]);
802 case X25_FAC_EXPRESS_DATA:
804 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
805 "(Negociation of express data)", *ptr);
806 fac_subtree = proto_item_add_subtree(ti,
807 ett_x25_fac_express_data);
808 proto_tree_add_text(fac_subtree, *offset+1, 1,
809 "Parameter %02X", ptr[1]);
814 ti = proto_tree_add_text(fac_tree, *offset, 1,
815 "Code : %02X (Unknown class A)", *ptr);
816 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
817 proto_tree_add_text(fac_subtree, *offset+1, 1,
818 "Parameter %02X", ptr[1]);
826 case X25_FAC_CLASS_B:
828 case X25_FAC_BILATERAL_CUG:
830 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
831 "(Bilateral closed user group selection)", *ptr);
832 fac_subtree = proto_item_add_subtree(ti,
833 ett_x25_fac_bilateral_cug);
834 proto_tree_add_text(fac_subtree, *offset+1, 2,
835 "Bilateral CUG: %02X%02X",
839 case X25_FAC_PACKET_SIZE:
844 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
845 "(Packet size)", *ptr);
846 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
850 sprintf(tmpbuf, "From the called DTE : %%u (16)");
853 sprintf(tmpbuf, "From the called DTE : %%u (32)");
856 sprintf(tmpbuf, "From the called DTE : %%u (64)");
859 sprintf(tmpbuf, "From the called DTE : %%u (128)");
862 sprintf(tmpbuf, "From the called DTE : %%u (256)");
865 sprintf(tmpbuf, "From the called DTE : %%u (512)");
868 sprintf(tmpbuf, "From the called DTE : %%u (1024)");
871 sprintf(tmpbuf, "From the called DTE : %%u (2048)");
874 sprintf(tmpbuf, "From the called DTE : %%u (4096)");
877 sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
880 proto_tree_add_text(fac_subtree, *offset+1, 1,
881 decode_numeric_bitfield(ptr[1], 0x0F, 1*8, tmpbuf));
886 sprintf(tmpbuf, "From the calling DTE : %%u (16)");
889 sprintf(tmpbuf, "From the calling DTE : %%u (32)");
892 sprintf(tmpbuf, "From the calling DTE : %%u (64)");
895 sprintf(tmpbuf, "From the calling DTE : %%u (128)");
898 sprintf(tmpbuf, "From the calling DTE : %%u (256)");
901 sprintf(tmpbuf, "From the calling DTE : %%u (512)");
904 sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
907 sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
910 sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
913 sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
916 proto_tree_add_text(fac_subtree, *offset+2, 1,
917 decode_numeric_bitfield(ptr[2], 0x0F, 1*8, tmpbuf));
920 case X25_FAC_WINDOW_SIZE:
922 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
923 "(Window size)", *ptr);
924 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
925 proto_tree_add_text(fac_subtree, *offset+1, 1,
926 decode_numeric_bitfield(ptr[1], 0x7F, 1*8,
927 "From the called DTE: %u"));
928 proto_tree_add_text(fac_subtree, *offset+2, 1,
929 decode_numeric_bitfield(ptr[2], 0x7F, 1*8,
930 "From the calling DTE: %u"));
933 case X25_FAC_RPOA_SELECTION:
935 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
936 "(RPOA selection)", *ptr);
937 fac_subtree = proto_item_add_subtree(ti,
938 ett_x25_fac_rpoa_selection);
939 proto_tree_add_text(fac_subtree, *offset+1, 2,
940 "Data network identification code : %02X%02X",
944 case X25_FAC_TRANSIT_DELAY:
946 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
947 "(Transit delay selection and indication)", *ptr);
948 fac_subtree = proto_item_add_subtree(ti,
949 ett_x25_fac_transit_delay);
950 proto_tree_add_text(fac_subtree, *offset+1, 2,
951 "Transit delay: %d ms",
952 (ptr[1]<<8) + ptr[2]);
957 ti = proto_tree_add_text(fac_tree, *offset, 1,
958 "Code : %02X (Unknown class B)", *ptr);
959 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
960 proto_tree_add_text(fac_subtree, *offset+1, 2,
961 "Parameter %02X%02X", ptr[1], ptr[2]);
969 case X25_FAC_CLASS_C:
971 ti = proto_tree_add_text(fac_tree, *offset, 1,
972 "Code : %02X (Unknown class C)", *ptr);
973 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
974 proto_tree_add_text(fac_subtree, *offset+1, 3,
975 "Parameter %02X%02X%02X",
976 ptr[1], ptr[2], ptr[3]);
982 case X25_FAC_CLASS_D:
984 case X25_FAC_CALL_TRANSFER:
989 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
990 "(Call redirection or deflection notification)", *ptr);
991 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
992 proto_tree_add_text(fac_subtree, *offset+1, 1,
993 "Length : %u", ptr[1]);
994 if ((ptr[2] & 0xC0) == 0xC0) {
995 proto_tree_add_text(fac_subtree, *offset+2, 1,
996 "Reason : call deflection by the originally "
997 "called DTE address");
1002 proto_tree_add_text(fac_subtree, *offset+2, 1,
1003 "Reason : originally called DTE busy");
1006 proto_tree_add_text(fac_subtree, *offset+2, 1,
1007 "Reason : call dist. within a hunt group");
1010 proto_tree_add_text(fac_subtree, *offset+2, 1,
1011 "Reason : originally called DTE out of order");
1014 proto_tree_add_text(fac_subtree, *offset+2, 1,
1015 "Reason : systematic call redirection");
1018 proto_tree_add_text(fac_subtree, *offset+2, 1,
1019 "Reason : unknown");
1023 proto_tree_add_text(fac_subtree, *offset+3, 1,
1024 "Number of semi-octets in DTE address : %u", ptr[3]);
1025 for (i = 0; i < ptr[3]; i++) {
1027 tmpbuf[i] = ((ptr[4+i/2] >> 4) & 0x0F) + '0';
1028 /* if > 9, convert to the right hexadecimal letter */
1029 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1031 tmpbuf[i] = (ptr[4+i/2] & 0x0F) + '0';
1032 /* if > 9, convert to the right hexadecimal letter */
1033 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1037 proto_tree_add_text(fac_subtree, *offset+4, ptr[1] - 2,
1038 "DTE address : %s", tmpbuf);
1041 case X25_FAC_CALLING_ADDR_EXT:
1046 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1047 "(Calling address extension)", *ptr);
1048 fac_subtree = proto_item_add_subtree(ti,
1049 ett_x25_fac_calling_addr_ext);
1050 proto_tree_add_text(fac_subtree, *offset+1, 1,
1051 "Length : %u", ptr[1]);
1052 proto_tree_add_text(fac_subtree, *offset+2, 1,
1053 "Number of semi-octets in DTE address : %u", ptr[2]);
1054 for (i = 0; i < ptr[2]; i++) {
1056 tmpbuf[i] = ((ptr[3+i/2] >> 4) & 0x0F) + '0';
1057 /* if > 9, convert to the right hexadecimal letter */
1058 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1060 tmpbuf[i] = (ptr[3+i/2] & 0x0F) + '0';
1061 /* if > 9, convert to the right hexadecimal letter */
1062 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1066 proto_tree_add_text(fac_subtree, *offset+3, ptr[1] - 1,
1067 "DTE address : %s", tmpbuf);
1070 case X25_FAC_CALLED_ADDR_EXT:
1075 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1076 "(Called address extension)", *ptr);
1077 fac_subtree = proto_item_add_subtree(ti,
1078 ett_x25_fac_called_addr_ext);
1079 proto_tree_add_text(fac_subtree, *offset+1, 1,
1080 "Length : %u", ptr[1]);
1081 proto_tree_add_text(fac_subtree, *offset+2, 1,
1082 "Number of semi-octets in DTE address : %u", ptr[2]);
1083 for (i = 0; i < ptr[2]; i++) {
1085 tmpbuf[i] = ((ptr[3+i/2] >> 4) & 0x0F) + '0';
1086 /* if > 9, convert to the right hexadecimal letter */
1087 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1089 tmpbuf[i] = (ptr[3+i/2] & 0x0F) + '0';
1090 /* if > 9, convert to the right hexadecimal letter */
1091 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1095 proto_tree_add_text(fac_subtree, *offset+3, ptr[1] - 1,
1096 "DTE address : %s", tmpbuf);
1099 case X25_FAC_ETE_TRANSIT_DELAY:
1101 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1102 "(End to end transit delay)", *ptr);
1103 fac_subtree = proto_item_add_subtree(ti,
1104 ett_x25_fac_ete_transit_delay);
1105 proto_tree_add_text(fac_subtree, *offset+1, 1,
1106 "Length : %u", ptr[1]);
1107 proto_tree_add_text(fac_subtree, *offset+2, ptr[1], "Value");
1110 case X25_FAC_CALL_DEFLECT:
1115 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1116 "(Call deflection selection)", *ptr);
1117 fac_subtree = proto_item_add_subtree(ti,
1118 ett_x25_fac_call_deflect);
1119 proto_tree_add_text(fac_subtree, *offset+1, 1,
1120 "Length : %u", ptr[1]);
1121 if ((ptr[2] & 0xC0) == 0xC0)
1122 proto_tree_add_text(fac_subtree, *offset+2, 1,
1123 "Reason : call DTE originated");
1125 proto_tree_add_text(fac_subtree, *offset+2, 1,
1126 "Reason : unknown");
1127 proto_tree_add_text(fac_subtree, *offset+3, 1,
1128 "Number of semi-octets in the alternative DTE address : %u",
1130 for (i = 0; i < ptr[3]; i++) {
1132 tmpbuf[i] = ((ptr[4+i/2] >> 4) & 0x0F) + '0';
1133 /* if > 9, convert to the right hexadecimal letter */
1134 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1136 tmpbuf[i] = (ptr[4+i/2] & 0x0F) + '0';
1137 /* if > 9, convert to the right hexadecimal letter */
1138 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1142 proto_tree_add_text(fac_subtree, *offset+4, ptr[1] - 2,
1143 "Alternative DTE address : %s", tmpbuf);
1146 case X25_FAC_PRIORITY:
1148 ti = proto_tree_add_text(fac_tree, *offset, 1,
1149 "Code : %02X (Priority)", *ptr);
1150 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
1151 proto_tree_add_text(fac_subtree, *offset+1, 1,
1152 "Length : %u", ptr[1]);
1153 proto_tree_add_text(fac_subtree, *offset+2, ptr[1], "Value");
1158 ti = proto_tree_add_text(fac_tree, *offset, 1,
1159 "Code : %02X (Unknown class D)", *ptr);
1160 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1161 proto_tree_add_text(fac_subtree, *offset+1, 1,
1162 "Length : %u", ptr[1]);
1163 proto_tree_add_text(fac_subtree, *offset+2, ptr[1], "Value");
1166 (*offset) += ptr[1]+2;
1175 x25_ntoa(proto_tree *tree, int *offset, const guint8 *p,
1176 frame_data *fd, gboolean toa)
1180 char addr1[16], addr2[16];
1181 char *first, *second;
1183 len1 = (*p >> 4) & 0x0F;
1184 len2 = (*p >> 0) & 0x0F;
1186 proto_tree_add_text(tree, *offset, 1,
1187 decode_numeric_bitfield(*p, 0xF0, 1*8,
1188 toa ? "Called address length : %u" :
1189 "Calling address length : %u"));
1190 proto_tree_add_text(tree, *offset, 1,
1191 decode_numeric_bitfield(*p, 0x0F, 1*8,
1192 toa ? "Calling address length : %u" :
1193 "Called address length : %u"));
1201 for (i = 0; i < (len1 + len2); i++) {
1204 *first++ = ((*p >> 0) & 0x0F) + '0';
1207 *first++ = ((*p >> 4) & 0x0F) + '0';
1211 *second++ = ((*p >> 0) & 0x0F) + '0';
1214 *second++ = ((*p >> 4) & 0x0F) + '0';
1224 if (check_col(fd, COL_RES_DL_DST))
1225 col_add_str(fd, COL_RES_DL_DST, addr1);
1228 if(check_col(fd, COL_RES_DL_SRC))
1229 col_add_str(fd, COL_RES_DL_SRC, addr1);
1232 proto_tree_add_text(tree, *offset,
1235 toa ? "Called" : "Calling",
1240 if (check_col(fd, COL_RES_DL_SRC))
1241 col_add_str(fd, COL_RES_DL_SRC, addr2);
1244 if(check_col(fd, COL_RES_DL_DST))
1245 col_add_str(fd, COL_RES_DL_DST, addr2);
1248 proto_tree_add_text(tree, *offset + len1/2,
1249 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1251 toa ? "Calling" : "Called",
1254 (*offset) += ((len1 + len2 + 1) / 2);
1258 get_x25_pkt_len(const char *data, frame_data *fd, int offset)
1260 int length, called_len, calling_len, dte_len, dce_len;
1262 /* packet size should always be > 3 */
1263 if (!BYTES_ARE_IN_FRAME(offset, 3)) return END_OF_FRAME;
1265 switch ((guint8)data[2])
1267 case X25_CALL_REQUEST:
1268 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1270 called_len = (data[3] >> 0) & 0x0F;
1271 calling_len = (data[3] >> 4) & 0x0F;
1272 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1273 if (length+offset < pi.captured_len)
1274 length += (1 + data[length]); /* facilities */
1276 else length = END_OF_FRAME;
1277 return MIN(END_OF_FRAME,length);
1279 case X25_CALL_ACCEPTED:
1280 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1282 called_len = (data[3] >> 0) & 0x0F;
1283 calling_len = (data[3] >> 4) & 0x0F;
1284 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1285 if (length+offset < pi.captured_len)
1286 length += (1 + data[length]); /* facilities */
1288 else length = END_OF_FRAME;
1289 return MIN(END_OF_FRAME,length);
1291 case X25_CLEAR_REQUEST:
1292 case X25_RESET_REQUEST:
1293 case X25_RESTART_REQUEST:
1294 return MIN(END_OF_FRAME,5);
1296 case X25_DIAGNOSTIC:
1297 return MIN(END_OF_FRAME,4);
1299 case X25_CLEAR_CONFIRMATION:
1301 case X25_INTERRUPT_CONFIRMATION:
1302 case X25_RESET_CONFIRMATION:
1303 case X25_RESTART_CONFIRMATION:
1304 return MIN(END_OF_FRAME,3);
1306 case X25_REGISTRATION_REQUEST:
1307 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1309 dce_len = (data[3] >> 0) & 0x0F;
1310 dte_len = (data[3] >> 4) & 0x0F;
1311 length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1312 if (length+offset < pi.captured_len)
1313 length += (1 + data[length]); /* registration */
1315 else length = END_OF_FRAME;
1316 return MIN(END_OF_FRAME,length);
1318 case X25_REGISTRATION_CONFIRMATION:
1319 if (BYTES_ARE_IN_FRAME(offset, 6)) /* pkt size >= 6 */
1321 dce_len = (data[5] >> 0) & 0x0F;
1322 dte_len = (data[5] >> 4) & 0x0F;
1323 length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1324 if (length+offset < pi.captured_len)
1325 length += (1 + data[length]); /* registration */
1327 else length = END_OF_FRAME;
1328 return MIN(END_OF_FRAME,length);
1331 if ((data[2] & 0x01) == X25_DATA) return MIN(END_OF_FRAME,3);
1333 switch (data[2] & 0x1F)
1336 return MIN(END_OF_FRAME,3);
1339 return MIN(END_OF_FRAME,3);
1342 return MIN(END_OF_FRAME,3);
1348 #define PRT_ID_ISO_8073 0x01
1350 static const value_string prt_id_vals[] = {
1351 {PRT_ID_ISO_8073, "ISO 8073 COTP"},
1353 {0x03, "ISO 10732 in conjunction with ISO 8073"},
1354 {0x04, "ISO 10736 in conjunction with ISO 8602"},
1358 static const value_string sharing_strategy_vals[] = {
1359 {0x00, "No sharing"},
1364 dissect_x25(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1366 proto_tree *x25_tree=0, *ti;
1367 int localoffset=offset;
1371 void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
1372 gboolean toa; /* TOA/NPI address format */
1374 if (check_col(fd, COL_PROTOCOL))
1375 col_add_str(fd, COL_PROTOCOL, "X.25");
1377 modulo = ((pd[localoffset] & 0x20) ? 128 : 8);
1379 if (pd[localoffset] & 0x80) toa = TRUE;
1382 x25_pkt_len = get_x25_pkt_len(&pd[localoffset], fd, offset);
1383 if (x25_pkt_len < 3) /* packet too short */
1385 if (check_col(fd, COL_INFO))
1386 col_add_str(fd, COL_INFO, "Invalid/short X.25 packet");
1388 proto_tree_add_item_format(tree, (modulo == 8 ? proto_x25 : proto_ex25),
1389 localoffset, END_OF_FRAME, NULL,
1390 "Invalid/short X.25 packet");
1393 vc = (int)(pd[localoffset] & 0x0F)*256 + (int)pd[localoffset+1];
1395 ti = proto_tree_add_item(tree, (modulo == 8) ? proto_x25 : proto_ex25,
1396 localoffset, x25_pkt_len, NULL);
1397 x25_tree = proto_item_add_subtree(ti, ett_x25);
1398 if (pd[localoffset] & 0x80)
1399 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_qbit : hf_ex25_qbit,
1400 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1401 if (pd[localoffset] & 0x40)
1402 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_dbit : hf_ex25_dbit,
1403 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1404 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_mod : hf_ex25_mod,
1405 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1407 switch (pd[localoffset+2]) {
1408 case X25_CALL_REQUEST:
1409 if (check_col(fd, COL_INFO))
1410 col_add_fstr(fd, COL_INFO, "%s VC:%d",
1411 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Inc. call"
1415 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1416 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1417 proto_tree_add_item_format(x25_tree,
1418 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1419 localoffset+2, 1, X25_CALL_REQUEST,
1420 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Incoming call"
1424 if (localoffset < x25_pkt_len+offset) /* calling/called addresses */
1425 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1427 if (localoffset < x25_pkt_len+offset) /* facilities */
1428 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1430 if (IS_DATA_IN_FRAME(localoffset)) /* user data */
1435 /* Compare the first octet of the CALL REQUEST packet with
1436 various ISO 9577 NLPIDs, as per Annex A of ISO 9577. */
1437 spi = pd[localoffset];
1440 /* XXX - handle other NLPIDs, e.g. PPP? */
1443 x25_hash_add_proto_start(vc, fd->abs_secs,
1444 fd->abs_usecs, dissect_ip);
1446 proto_tree_add_text(x25_tree, localoffset, 1,
1447 "X.224 secondary protocol ID: IP");
1452 if ((pd[localoffset] >= 0x03 && pd[localoffset] <= 0x82)
1453 && pd[localoffset+1] == 0x01) {
1454 /* ISO 9577 claims that a SPI in that range is a
1455 length field for X.224/ISO 8073 or X.264/ISO 11570;
1456 however, some of them collide with NLPIDs such
1457 as 0x81 for ISO 8473 CLNP or ISO 8542 ESIS, so
1458 I don't know how you run those over X.25, assuming
1461 I'm also not sure what the "or" means there; it
1462 looks as if X.264 specifies the layout of a
1463 "UN TPDU" ("Use of network connection TPDU"),
1464 which specifies the transport protocol to use
1465 over this network connection, and 0x03 0x01 0x01
1466 0x00 is such a TPDU, with a length of 3, a UN
1467 field of 1 (as is required), a PRT-ID ("protocol
1468 identifier") field of 1 (X.224/ISO 8073, a/k/a
1469 COTP service), and a SHARE ("sharing strategy")
1470 field of 0 ("no sharing", which is the only one
1473 So we'll assume that's what it is, as the SPI
1474 is in the right range for a length, and the UN
1476 prt_id = pd[localoffset+2];
1478 proto_tree_add_text(x25_tree, localoffset, 1,
1479 "X.264 length indicator: %u",
1481 proto_tree_add_text(x25_tree, localoffset+1, 1,
1482 "X.264 UN TPDU identifier: 0x%02X",
1484 proto_tree_add_text(x25_tree, localoffset+2, 1,
1485 "X.264 protocol identifier: %s",
1486 val_to_str(prt_id, prt_id_vals, "Unknown (0x%02X)"));
1487 proto_tree_add_text(x25_tree, localoffset+3, 1,
1488 "X.264 sharing strategy: %s",
1489 val_to_str(pd[localoffset+3], sharing_strategy_vals, "Unknown (0x%02X)"));
1492 /* XXX - dissect the variable part? */
1494 /* The length doesn't include the length octet itself. */
1495 localoffset += pd[localoffset] + 1;
1499 case PRT_ID_ISO_8073:
1501 x25_hash_add_proto_start(vc, fd->abs_secs,
1502 fd->abs_usecs, dissect_cotp);
1511 if (IS_DATA_IN_FRAME(localoffset))
1512 proto_tree_add_text(x25_tree, localoffset,
1513 pi.captured_len-localoffset, "Data");
1515 localoffset = pi.captured_len;
1520 case X25_CALL_ACCEPTED:
1521 if(check_col(fd, COL_INFO))
1522 col_add_fstr(fd, COL_INFO, "%s VC:%d",
1523 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Call conn."
1527 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1528 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1529 proto_tree_add_item_format(x25_tree,
1530 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1531 localoffset+2, 1, X25_CALL_ACCEPTED,
1532 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Call connected"
1536 if (localoffset < x25_pkt_len+offset) /* calling/called addresses */
1537 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1539 if (localoffset < x25_pkt_len+offset) /* facilities */
1540 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1542 if (IS_DATA_IN_FRAME(localoffset)) { /* user data */
1544 proto_tree_add_text(x25_tree, localoffset,
1545 pi.captured_len-localoffset, "Data");
1546 localoffset=pi.captured_len;
1549 case X25_CLEAR_REQUEST:
1550 if(check_col(fd, COL_INFO)) {
1551 col_add_fstr(fd, COL_INFO, "%s VC:%d %s - %s",
1552 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Clear ind."
1554 vc, clear_code(pd[localoffset+3]),
1555 clear_diag(pd[localoffset+4]));
1557 x25_hash_add_proto_end(vc, fd->abs_secs, fd->abs_usecs);
1559 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1560 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1561 proto_tree_add_item_format(x25_tree,
1562 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1563 localoffset+2, 1, X25_CLEAR_REQUEST,
1564 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Clear indication"
1566 if (localoffset+3 < x25_pkt_len+offset)
1567 proto_tree_add_text(x25_tree, localoffset+3, 1,
1568 "Cause : %s", clear_code(pd[localoffset+3]));
1569 if (localoffset+4 < x25_pkt_len+offset)
1570 proto_tree_add_text(x25_tree, localoffset+4, 1,
1572 clear_diag(pd[localoffset+4]));
1574 localoffset += x25_pkt_len;
1576 case X25_CLEAR_CONFIRMATION:
1577 if(check_col(fd, COL_INFO))
1578 col_add_fstr(fd, COL_INFO, "Clear Conf. VC:%d", vc);
1580 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1581 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1582 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1583 localoffset+2, 1, X25_CLEAR_CONFIRMATION);
1585 localoffset += x25_pkt_len;
1587 if (IS_DATA_IN_FRAME(localoffset)) /* extended clear conf format */
1588 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1590 if (IS_DATA_IN_FRAME(localoffset)) /* facilities */
1591 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1593 case X25_DIAGNOSTIC:
1594 if(check_col(fd, COL_INFO)) {
1595 col_add_fstr(fd, COL_INFO, "Diag. %d", (int)pd[localoffset+3]);
1598 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1599 localoffset+2, 1, X25_DIAGNOSTIC);
1600 if (localoffset+3 < x25_pkt_len+offset)
1601 proto_tree_add_text(x25_tree, localoffset+3, 1,
1602 "Diagnostic : %d", (int)pd[localoffset+3]);
1604 localoffset += x25_pkt_len;
1607 if(check_col(fd, COL_INFO))
1608 col_add_fstr(fd, COL_INFO, "Interrupt VC:%d", vc);
1610 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1611 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1612 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1613 localoffset+2, 1, X25_INTERRUPT);
1615 localoffset += x25_pkt_len;
1617 case X25_INTERRUPT_CONFIRMATION:
1618 if(check_col(fd, COL_INFO))
1619 col_add_fstr(fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
1621 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1622 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1623 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1624 localoffset+2, 1, X25_INTERRUPT_CONFIRMATION);
1626 localoffset += x25_pkt_len;
1628 case X25_RESET_REQUEST:
1629 if(check_col(fd, COL_INFO)) {
1630 col_add_fstr(fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
1631 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Reset ind."
1633 vc, reset_code(pd[localoffset+3]),
1634 (int)pd[localoffset+4]);
1636 x25_hash_add_proto_end(vc, fd->abs_secs, fd->abs_usecs);
1638 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1639 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1640 proto_tree_add_item_format(x25_tree,
1641 (modulo == 8) ? hf_x25_type : hf_ex25_type, localoffset+2, 1,
1643 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Reset indication"
1645 if (localoffset+3 < x25_pkt_len+offset)
1646 proto_tree_add_text(x25_tree, localoffset+3, 1,
1647 "Cause : %s", reset_code(pd[localoffset+3]));
1648 if (localoffset+4 < x25_pkt_len+offset)
1649 proto_tree_add_text(x25_tree, localoffset+4, 1,
1650 "Diagnostic : %d", (int)pd[localoffset+4]);
1652 localoffset += x25_pkt_len;
1654 case X25_RESET_CONFIRMATION:
1655 if(check_col(fd, COL_INFO))
1656 col_add_fstr(fd, COL_INFO, "Reset conf. VC:%d", vc);
1658 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1659 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1660 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1661 localoffset+2, 1, X25_RESET_CONFIRMATION);
1663 localoffset += x25_pkt_len;
1665 case X25_RESTART_REQUEST:
1666 if(check_col(fd, COL_INFO)) {
1667 col_add_fstr(fd, COL_INFO, "%s %s - Diag.:%d",
1668 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Restart ind."
1670 restart_code(pd[localoffset+3]),
1671 (int)pd[localoffset+4]);
1674 proto_tree_add_item_format(x25_tree,
1675 (modulo == 8) ? hf_x25_type : hf_ex25_type, localoffset+2, 1,
1676 X25_RESTART_REQUEST,
1677 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Restart indication"
1678 : "Restart request");
1679 if (localoffset+3 < x25_pkt_len+offset)
1680 proto_tree_add_text(x25_tree, localoffset+3, 1,
1681 "Cause : %s", restart_code(pd[localoffset+3]));
1682 if (localoffset+4 < x25_pkt_len+offset)
1683 proto_tree_add_text(x25_tree, localoffset+4, 1,
1684 "Diagnostic : %d", (int)pd[localoffset+4]);
1686 localoffset += x25_pkt_len;
1688 case X25_RESTART_CONFIRMATION:
1689 if(check_col(fd, COL_INFO))
1690 col_add_str(fd, COL_INFO, "Restart conf.");
1692 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1693 localoffset+2, 1, X25_RESTART_CONFIRMATION);
1694 localoffset += x25_pkt_len;
1696 case X25_REGISTRATION_REQUEST:
1697 if(check_col(fd, COL_INFO))
1698 col_add_str(fd, COL_INFO, "Registration req.");
1700 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1701 localoffset+2, 1, X25_REGISTRATION_REQUEST);
1703 if (localoffset < x25_pkt_len+offset)
1704 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, FALSE);
1707 if (localoffset < x25_pkt_len+offset)
1708 proto_tree_add_text(x25_tree, localoffset, 1,
1709 "Registration length: %d", pd[localoffset] & 0x7F);
1710 if (localoffset+1 < x25_pkt_len+offset)
1711 proto_tree_add_text(x25_tree, localoffset+1,
1712 pd[localoffset] & 0x7F, "Registration");
1714 localoffset = pi.captured_len;
1716 case X25_REGISTRATION_CONFIRMATION:
1717 if(check_col(fd, COL_INFO))
1718 col_add_str(fd, COL_INFO, "Registration conf.");
1720 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1721 localoffset+2, 1, X25_REGISTRATION_CONFIRMATION);
1722 if (localoffset+3 < x25_pkt_len+offset)
1723 proto_tree_add_text(x25_tree, localoffset+3, 1,
1724 "Cause: %s", registration_code(pd[localoffset+3]));
1725 if (localoffset+4 < x25_pkt_len+offset)
1726 proto_tree_add_text(x25_tree, localoffset+4, 1,
1727 "Diagnostic: %s", registration_code(pd[localoffset+4]));
1730 if (localoffset < x25_pkt_len+offset)
1731 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, TRUE);
1734 if (localoffset < x25_pkt_len+offset)
1735 proto_tree_add_text(x25_tree, localoffset, 1,
1736 "Registration length: %d", pd[localoffset] & 0x7F);
1737 if (localoffset+1 < x25_pkt_len+offset)
1738 proto_tree_add_text(x25_tree, localoffset+1,
1739 pd[localoffset] & 0x7F, "Registration");
1741 localoffset = pi.captured_len;
1745 if ((pd[localoffset] & 0x01) == X25_DATA)
1747 if(check_col(fd, COL_INFO)) {
1749 col_add_fstr(fd, COL_INFO,
1750 "Data VC:%d P(S):%d P(R):%d %s", vc,
1751 (pd[localoffset] >> 1) & 0x07,
1752 (pd[localoffset] >> 5) & 0x07,
1753 ((pd[localoffset]>>4) & 0x01) ? " M" : "");
1755 col_add_fstr(fd, COL_INFO,
1756 "Data VC:%d P(S):%d P(R):%d %s", vc,
1757 pd[localoffset+1] >> 1,
1758 pd[localoffset] >> 1,
1759 (pd[localoffset+1] & 0x01) ? " M" : "");
1762 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1763 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1765 proto_tree_add_item_hidden(x25_tree, hf_x25_type, localoffset, 1,
1767 proto_tree_add_item(x25_tree, hf_x25_p_r, localoffset, 1,
1769 if (pd[localoffset] & 0x10)
1770 proto_tree_add_item(x25_tree, hf_x25_mbit, localoffset, 1,
1772 proto_tree_add_item(x25_tree, hf_x25_p_s, localoffset, 1,
1774 proto_tree_add_text(x25_tree, localoffset, 1,
1775 decode_boolean_bitfield(pd[localoffset], 0x01, 1*8,
1779 proto_tree_add_item_hidden(x25_tree, hf_ex25_type, localoffset, 1,
1781 proto_tree_add_item(x25_tree, hf_x25_p_r, localoffset, 1,
1783 proto_tree_add_item(x25_tree, hf_x25_p_s, localoffset+1, 1,
1785 if (pd[localoffset+1] & 0x01)
1786 proto_tree_add_item(x25_tree, hf_ex25_mbit, localoffset+1, 1,
1790 localoffset += (modulo == 8) ? 1 : 2;
1793 switch (pd[localoffset] & 0x1F)
1796 if(check_col(fd, COL_INFO)) {
1798 col_add_fstr(fd, COL_INFO, "RR VC:%d P(R):%d",
1799 vc, (pd[localoffset] >> 5) & 0x07);
1801 col_add_fstr(fd, COL_INFO, "RR VC:%d P(R):%d",
1802 vc, pd[localoffset+1] >> 1);
1805 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1806 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1808 proto_tree_add_item(x25_tree, hf_x25_p_r,
1809 localoffset, 1, pd[localoffset]);
1810 proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_RR);
1813 proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_RR);
1814 proto_tree_add_item(x25_tree, hf_ex25_p_r,
1815 localoffset+1, 1, pd[localoffset+1]);
1821 if(check_col(fd, COL_INFO)) {
1823 col_add_fstr(fd, COL_INFO, "RNR VC:%d P(R):%d",
1824 vc, (pd[localoffset] >> 5) & 0x07);
1826 col_add_fstr(fd, COL_INFO, "RNR VC:%d P(R):%d",
1827 vc, pd[localoffset+1] >> 1);
1830 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1831 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1833 proto_tree_add_item(x25_tree, hf_x25_p_r,
1834 localoffset, 1, pd[localoffset]);
1835 proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_RNR);
1838 proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_RNR);
1839 proto_tree_add_item(x25_tree, hf_ex25_p_r,
1840 localoffset+1, 1, pd[localoffset+1]);
1846 if(check_col(fd, COL_INFO)) {
1848 col_add_fstr(fd, COL_INFO, "REJ VC:%d P(R):%d",
1849 vc, (pd[localoffset] >> 5) & 0x07);
1851 col_add_fstr(fd, COL_INFO, "REJ VC:%d P(R):%d",
1852 vc, pd[localoffset+1] >> 1);
1855 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1856 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1858 proto_tree_add_item(x25_tree, hf_x25_p_r,
1859 localoffset, 1, pd[localoffset]);
1860 proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_REJ);
1863 proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_REJ);
1864 proto_tree_add_item(x25_tree, hf_ex25_p_r,
1865 localoffset+1, 1, pd[localoffset+1]);
1869 localoffset += (modulo == 8) ? 1 : 2;
1872 if (!IS_DATA_IN_FRAME(localoffset)) return;
1874 /* search the dissector in the hash table */
1875 if ((dissect = x25_hash_get_dissect(fd->abs_secs, fd->abs_usecs, vc)))
1876 (*dissect)(pd, localoffset, fd, tree);
1878 if (pd[localoffset] == 0x45) /* If the Call Req. has not been captured,
1879 * assume these packets carry IP */
1881 x25_hash_add_proto_start(vc, fd->abs_secs,
1882 fd->abs_usecs, dissect_ip);
1883 dissect_ip(pd, localoffset, fd, tree);
1886 dissect_data(pd, localoffset, fd, tree);
1892 proto_register_x25(void)
1894 static hf_register_info hf8[] = {
1896 { "Q Bit", "x25.q", FT_BOOLEAN, 2, NULL, 0x8000,
1897 "Qualifier Bit" } },
1899 { "D Bit", "x25.d", FT_BOOLEAN, 2, NULL, 0x4000,
1900 "Delivery Confirmation Bit" } },
1902 { "Modulo", "x25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1903 "Specifies whether the frame is modulo 8 or 128" } },
1905 { "Logical Channel", "x25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
1906 "Logical Channel Number" } },
1908 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1911 { "P(R)", "x25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
1912 "Packet Receive Sequence Number" } },
1914 { "M Bit", "x25.m", FT_BOOLEAN, 1, NULL, 0x10,
1917 { "P(S)", "x25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
1918 "Packet Send Sequence Number" } },
1921 static hf_register_info hf128[] = {
1923 { "Q Bit", "ex25.q", FT_BOOLEAN, 2, NULL, 0x8000,
1924 "Qualifier Bit" } },
1926 { "D Bit", "ex25.d", FT_BOOLEAN, 2, NULL, 0x4000,
1927 "Delivery Confirmation Bit" } },
1929 { "Modulo", "ex25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1930 "Specifies whether the frame is modulo 8 or 128" } },
1932 { "Logical Channel", "ex25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
1933 "Logical Channel Number" } },
1935 { "Packet Type", "ex25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1938 { "P(R)", "ex25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
1939 "Packet Receive Sequence Number" } },
1941 { "M Bit", "ex25.m", FT_BOOLEAN, 1, NULL, 0x01,
1944 { "P(S)", "ex25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
1945 "Packet Send Sequence Number" } },
1947 static gint *ett[] = {
1950 &ett_x25_fac_unknown,
1952 &ett_x25_fac_reverse,
1953 &ett_x25_fac_throughput,
1955 &ett_x25_fac_called_modif,
1956 &ett_x25_fac_cug_outgoing_acc,
1957 &ett_x25_fac_throughput_min,
1958 &ett_x25_fac_express_data,
1959 &ett_x25_fac_bilateral_cug,
1960 &ett_x25_fac_packet_size,
1961 &ett_x25_fac_window_size,
1962 &ett_x25_fac_rpoa_selection,
1963 &ett_x25_fac_transit_delay,
1964 &ett_x25_fac_call_transfer,
1965 &ett_x25_fac_called_addr_ext,
1966 &ett_x25_fac_ete_transit_delay,
1967 &ett_x25_fac_calling_addr_ext,
1968 &ett_x25_fac_call_deflect,
1969 &ett_x25_fac_priority
1972 proto_x25 = proto_register_protocol ("X.25", "x25");
1973 proto_ex25 = proto_register_protocol ("Extended X.25 (modulo 128)", "ex25");
1974 proto_register_field_array (proto_x25, hf8, array_length(hf8));
1975 proto_register_field_array (proto_ex25, hf128, array_length(hf128));
1976 proto_register_subtree_array(ett, array_length(ett));