2 * Routines for x25 packet disassembly
3 * Olivier Abad <abad@daba.dhis.net>
5 * $Id: packet-x25.c,v 1.15 2000/01/24 03:51:35 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>
43 #define X25_CALL_REQUEST 0x0B
44 #define X25_CALL_ACCEPTED 0x0F
45 #define X25_CLEAR_REQUEST 0x13
46 #define X25_CLEAR_CONFIRMATION 0x17
47 #define X25_INTERRUPT 0x23
48 #define X25_INTERRUPT_CONFIRMATION 0x27
49 #define X25_RESET_REQUEST 0x1B
50 #define X25_RESET_CONFIRMATION 0x1F
51 #define X25_RESTART_REQUEST 0xFB
52 #define X25_RESTART_CONFIRMATION 0xFF
53 #define X25_REGISTRATION_REQUEST 0xF3
54 #define X25_REGISTRATION_CONFIRMATION 0xF7
55 #define X25_DIAGNOSTIC 0xF1
61 #define X25_FAC_CLASS_MASK 0xC0
63 #define X25_FAC_CLASS_A 0x00
64 #define X25_FAC_CLASS_B 0x40
65 #define X25_FAC_CLASS_C 0x80
66 #define X25_FAC_CLASS_D 0xC0
68 #define X25_FAC_COMP_MARK 0x00
69 #define X25_FAC_REVERSE 0x01
70 #define X25_FAC_THROUGHPUT 0x02
71 #define X25_FAC_CUG 0x03
72 #define X25_FAC_CALLED_MODIF 0x08
73 #define X25_FAC_CUG_OUTGOING_ACC 0x09
74 #define X25_FAC_THROUGHPUT_MIN 0x0A
75 #define X25_FAC_EXPRESS_DATA 0x0B
76 #define X25_FAC_BILATERAL_CUG 0x41
77 #define X25_FAC_PACKET_SIZE 0x42
78 #define X25_FAC_WINDOW_SIZE 0x43
79 #define X25_FAC_RPOA_SELECTION 0x44
80 #define X25_FAC_TRANSIT_DELAY 0x49
81 #define X25_FAC_CALL_TRANSFER 0xC3
82 #define X25_FAC_CALLED_ADDR_EXT 0xC9
83 #define X25_FAC_ETE_TRANSIT_DELAY 0xCA
84 #define X25_FAC_CALLING_ADDR_EXT 0xCB
85 #define X25_FAC_CALL_DEFLECT 0xD1
86 #define X25_FAC_PRIORITY 0xD2
88 static int proto_x25 = -1;
89 static int hf_x25_qbit = -1;
90 static int hf_x25_dbit = -1;
91 static int hf_x25_mod = -1;
92 static int hf_x25_lcn = -1;
93 static int hf_x25_type = -1;
94 static int hf_x25_p_r = -1;
95 static int hf_x25_mbit = -1;
96 static int hf_x25_p_s = -1;
97 static int proto_ex25 = -1;
98 static int hf_ex25_qbit = -1;
99 static int hf_ex25_dbit = -1;
100 static int hf_ex25_mod = -1;
101 static int hf_ex25_lcn = -1;
102 static int hf_ex25_type = -1;
103 static int hf_ex25_p_r = -1;
104 static int hf_ex25_mbit = -1;
105 static int hf_ex25_p_s = -1;
107 static gint ett_x25 = -1;
108 static gint ett_x25_fac = -1;
109 static gint ett_x25_fac_unknown = -1;
110 static gint ett_x25_fac_mark = -1;
111 static gint ett_x25_fac_reverse = -1;
112 static gint ett_x25_fac_throughput = -1;
113 static gint ett_x25_fac_cug = -1;
114 static gint ett_x25_fac_called_modif = -1;
115 static gint ett_x25_fac_cug_outgoing_acc = -1;
116 static gint ett_x25_fac_throughput_min = -1;
117 static gint ett_x25_fac_express_data = -1;
118 static gint ett_x25_fac_bilateral_cug = -1;
119 static gint ett_x25_fac_packet_size = -1;
120 static gint ett_x25_fac_window_size = -1;
121 static gint ett_x25_fac_rpoa_selection = -1;
122 static gint ett_x25_fac_transit_delay = -1;
123 static gint ett_x25_fac_call_transfer = -1;
124 static gint ett_x25_fac_called_addr_ext = -1;
125 static gint ett_x25_fac_ete_transit_delay = -1;
126 static gint ett_x25_fac_calling_addr_ext = -1;
127 static gint ett_x25_fac_call_deflect = -1;
128 static gint ett_x25_fac_priority = -1;
130 static const value_string vals_modulo[] = {
136 static const value_string vals_x25_type[] = {
137 { X25_CALL_REQUEST, "Call" },
138 { X25_CALL_ACCEPTED, "Call Accepted" },
139 { X25_CLEAR_REQUEST, "Clear" },
140 { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
141 { X25_INTERRUPT, "Interrupt" },
142 { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
143 { X25_RESET_REQUEST, "Reset" },
144 { X25_RESET_CONFIRMATION, "Reset Confirmation" },
145 { X25_RESTART_REQUEST, "Restart" },
146 { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
147 { X25_REGISTRATION_REQUEST, "Registration" },
148 { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
149 { X25_DIAGNOSTIC, "Diagnostic" },
153 { X25_DATA, "DATA" },
158 * each vc_info node contains :
159 * the time of the first frame using this dissector (secs and usecs)
160 * the time of the last frame using this dissector (0 if it is unknown)
161 * a pointer to the dissector
163 * the "time of first frame" is initialized when a Call Req. is received
164 * the "time of last frame" is initialized when a Clear, Reset, or Restart
167 typedef struct _vc_info {
168 guint32 first_frame_secs, first_frame_usecs;
169 guint32 last_frame_secs, last_frame_usecs;
170 void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
171 struct _vc_info *next;
175 * the hash table will contain linked lists of global_vc_info
176 * each global_vc_info struct contains :
177 * the VC number (the hash table is indexed with VC % 64)
178 * a linked list of vc_info
180 typedef struct _global_vc_info {
183 struct _global_vc_info *next;
186 static global_vc_info *hash_table[64];
189 free_vc_info(vc_info *pt)
205 for (i=0; i<64; i++) {
206 if (hash_table[i]) /* not NULL ==> free */
208 global_vc_info *hash_ent, *hash_ent2;
209 hash_ent2 = hash_ent = hash_table[i];
212 hash_ent2 = hash_ent;
213 hash_ent = hash_ent->next;
214 free_vc_info(hash_ent2->info);
223 x25_hash_add_proto_start(guint16 vc, guint32 frame_secs, guint32 frame_usecs,
224 void (*dissect)(const u_char *, int, frame_data *,
228 global_vc_info *hash_ent;
229 global_vc_info *hash_ent2;
231 if (hash_table[idx] == 0)
233 hash_ent = (global_vc_info *)g_malloc(sizeof(global_vc_info));
235 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
238 hash_ent->vc_num = vc;
240 hash_ent->info = (vc_info *)g_malloc(sizeof(vc_info));
241 if (!hash_ent->info) {
242 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
245 hash_ent->info->first_frame_secs = frame_secs;
246 hash_ent->info->first_frame_usecs = frame_usecs;
247 hash_ent->info->last_frame_secs = 0;
248 hash_ent->info->last_frame_usecs = 0;
249 hash_ent->info->dissect = dissect;
250 hash_ent->info->next = 0;
251 hash_table[idx] = hash_ent;
255 hash_ent2 = hash_ent = hash_table[idx];
256 /* search an entry with the same VC number */
257 while (hash_ent != NULL && hash_ent->vc_num != vc) {
258 hash_ent2 = hash_ent;
259 hash_ent = hash_ent->next;
261 if (hash_ent != NULL) /* hash_ent->vc_num == vc */
263 vc_info *vci = hash_ent->info;
264 while (vci->next) vci = vci->next; /* last element */
265 if (vci->dissect == dissect) {
266 vci->last_frame_secs = 0;
267 vci->last_frame_usecs = 0;
270 vci->next = (vc_info *)g_malloc(sizeof(vc_info));
271 if (vci->next == 0) {
272 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
275 vci->next->first_frame_secs = frame_secs;
276 vci->next->first_frame_usecs = frame_usecs;
277 vci->next->last_frame_secs = 0;
278 vci->next->last_frame_usecs = 0;
279 vci->next->dissect = dissect;
283 else /* new vc number */
285 hash_ent2->next = (global_vc_info *)g_malloc(sizeof(global_vc_info));
286 if (!hash_ent2->next) {
287 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
290 hash_ent2->next->info = (vc_info *)g_malloc(sizeof(vc_info));
291 if (!hash_ent2->next->info) {
292 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
295 hash_ent2->next->info->first_frame_secs = frame_secs;
296 hash_ent2->next->info->first_frame_usecs = frame_usecs;
297 hash_ent2->next->info->last_frame_secs = 0;
298 hash_ent2->next->info->last_frame_usecs = 0;
299 hash_ent2->next->info->dissect = dissect;
300 hash_ent2->next->info->next = 0;
306 x25_hash_add_proto_end(guint16 vc, guint32 frame_secs, guint32 frame_usecs)
308 global_vc_info *hash_ent = hash_table[vc%64];
311 if (!hash_ent) return;
312 while(hash_ent->vc_num != vc) hash_ent = hash_ent->next;
313 if (!hash_ent) return;
315 vci = hash_ent->info;
316 while (vci->next) vci = vci->next;
317 vci->last_frame_secs = frame_secs;
318 vci->last_frame_usecs = frame_usecs;
321 void (*x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc))(const u_char *, int, frame_data *, proto_tree *)
323 global_vc_info *hash_ent = hash_table[vc%64];
327 if (!hash_ent) return 0;
329 while(hash_ent && hash_ent->vc_num != vc) hash_ent = hash_ent->next;
330 if (!hash_ent) return 0;
332 /* a hash_ent was found for this VC number */
333 vci2 = vci = hash_ent->info;
335 /* looking for an entry matching our frame time */
336 while (vci && (vci->last_frame_secs < frame_secs ||
337 (vci->last_frame_secs == frame_secs &&
338 vci->last_frame_usecs < frame_usecs))) {
342 /* we reached last record, and previous record has a non zero
343 * last frame time ==> no dissector */
344 if (!vci && (vci2->last_frame_secs || vci2->last_frame_usecs)) return 0;
346 /* we reached last record, and previous record has a zero last frame time
347 * ==> dissector for previous frame has not been "stopped" by a Clear, etc */
349 /* if the start time for vci2 is greater than our frame time
350 * ==> no dissector */
351 if (frame_secs < vci2->first_frame_secs ||
352 (frame_secs == vci2->first_frame_secs &&
353 frame_usecs < vci2->first_frame_usecs))
356 return vci2->dissect;
359 /* our frame time is before vci's end. Check if it is adter vci's start */
360 if (frame_secs < vci->first_frame_secs ||
361 (frame_secs == vci->first_frame_secs &&
362 frame_usecs < vci->first_frame_usecs))
368 static char *clear_code(unsigned char code)
370 static char buffer[25];
372 if (code == 0x00 || (code & 0x80) == 0x80)
373 return "DTE Originated";
375 return "Number Busy";
377 return "Out Of Order";
379 return "Remote Procedure Error";
381 return "Reverse Charging Acceptance Not Subscribed";
383 return "Incompatible Destination";
385 return "Fast Select Acceptance Not Subscribed";
387 return "Destination Absent";
389 return "Invalid Facility Requested";
391 return "Access Barred";
393 return "Local Procedure Error";
395 return "Network Congestion";
397 return "Not Obtainable";
399 return "RPOA Out Of Order";
401 sprintf(buffer, "Unknown %02X", code);
406 static char *clear_diag(unsigned char code)
408 static char buffer[25];
411 return "No additional information";
413 return "Invalid P(S)";
415 return "Invalid P(R)";
417 return "Packet type invalid";
419 return "Packet type invalid for state r1";
421 return "Packet type invalid for state r2";
423 return "Packet type invalid for state r3";
425 return "Packet type invalid for state p1";
427 return "Packet type invalid for state p2";
429 return "Packet type invalid for state p3";
431 return "Packet type invalid for state p4";
433 return "Packet type invalid for state p5";
435 return "Packet type invalid for state p6";
437 return "Packet type invalid for state p7";
439 return "Packet type invalid for state d1";
441 return "Packet type invalid for state d2";
443 return "Packet type invalid for state d3";
445 return "Packet not allowed";
447 return "Unidentifiable packet";
449 return "Call on one-way logical channel";
451 return "Invalid packet type on a PVC";
453 return "Packet on unassigned LC";
455 return "Reject not subscribed to";
457 return "Packet too short";
459 return "Packet too long";
461 return "Invalid general format identifier";
463 return "Restart/registration packet with nonzero bits";
465 return "Packet type not compatible with facility";
467 return "Unauthorised interrupt confirmation";
469 return "Unauthorised interrupt";
471 return "Unauthorised reject";
473 return "Time expired";
475 return "Time expired for incoming call";
477 return "Time expired for clear indication";
479 return "Time expired for reset indication";
481 return "Time expired for restart indication";
483 return "Time expired for call deflection";
485 return "Call set-up/clearing or registration pb.";
487 return "Facility/registration code not allowed";
489 return "Facility parameter not allowed";
491 return "Invalid called DTE address";
493 return "Invalid calling DTE address";
495 return "Invalid facility/registration length";
497 return "Incoming call barred";
499 return "No logical channel available";
501 return "Call collision";
503 return "Duplicate facility requested";
505 return "Non zero address length";
507 return "Non zero facility length";
509 return "Facility not provided when expected";
511 return "Invalid CCITT-specified DTE facility";
513 return "Max. nb of call redir/defl. exceeded";
515 return "Miscellaneous";
517 return "Improper cause code from DTE";
519 return "Not aligned octet";
521 return "Inconsistent Q bit setting";
523 return "NUI problem";
525 return "International problem";
527 return "Remote network problem";
529 return "International protocol problem";
531 return "International link out of order";
533 return "International link busy";
535 return "Transit network facility problem";
537 return "Remote network facility problem";
539 return "International routing problem";
541 return "Temporary routing problem";
543 return "Unknown called DNIC";
545 return "Maintenance action";
547 sprintf(buffer, "Unknown %d", code);
552 static char *reset_code(unsigned char code)
554 static char buffer[25];
556 if (code == 0x00 || (code & 0x80) == 0x80)
557 return "DTE Originated";
559 return "Out of order";
561 return "Remote Procedure Error";
563 return "Local Procedure Error";
565 return "Network Congestion";
567 return "Remote DTE operational";
569 return "Network operational";
571 return "Incompatible Destination";
573 return "Network out of order";
575 sprintf(buffer, "Unknown %02X", code);
580 static char *restart_code(unsigned char code)
582 static char buffer[25];
584 if (code == 0x00 || (code & 0x80) == 0x80)
585 return "DTE Originated";
587 return "Local Procedure Error";
589 return "Network Congestion";
591 return "Network Operational";
593 return "Registration/cancellation confirmed";
595 sprintf(buffer, "Unknown %02X", code);
600 static char *registration_code(unsigned char code)
602 static char buffer[25];
605 return "Invalid facility request";
607 return "Network congestion";
609 return "Local procedure error";
611 return "Registration/cancellation confirmed";
613 sprintf(buffer, "Unknown %02X", code);
619 dump_facilities(proto_tree *tree, int *offset, const guint8 *p)
621 const guint8 *ptr = p;
622 guint32 len; /* facilities length */
624 proto_tree *fac_tree = 0;
625 proto_tree *fac_subtree;
629 ti = proto_tree_add_text(tree, *offset, len + 1,
631 fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
632 proto_tree_add_text(fac_tree, *offset, 1,
633 "Facilities length: %d", len);
638 switch(*ptr & X25_FAC_CLASS_MASK) {
639 case X25_FAC_CLASS_A:
641 case X25_FAC_COMP_MARK:
643 ti = proto_tree_add_text(fac_tree, *offset, 1,
644 "Code : 00 (Marker)");
648 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
649 proto_tree_add_text(fac_subtree, *offset+1, 1,
650 "Parameter : 00 (Network complementary "
651 "services - calling DTE)");
656 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
657 proto_tree_add_text(fac_subtree, *offset+1, 1,
658 "Parameter : FF (Network complementary "
659 "services - called DTE)");
664 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
665 proto_tree_add_text(fac_subtree, *offset+1, 1,
666 "Parameter : 0F (DTE complementary "
672 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
673 proto_tree_add_text(fac_subtree, *offset+1, 1,
674 "Parameter : %02X (Unknown marker)",
680 case X25_FAC_REVERSE:
682 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
683 "(Reverse charging / Fast select)", *ptr);
684 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
685 proto_tree_add_text(fac_subtree, *offset+1, 1, "Parameter : %02X",
688 proto_tree_add_text(fac_subtree, *offset+1, 1,
689 "11.. .... = Fast select with restriction");
690 else if (ptr[1] & 0x80)
691 proto_tree_add_text(fac_subtree, *offset+1, 1,
692 "10.. .... = Fast select - no restriction");
694 proto_tree_add_text(fac_subtree, *offset+1, 1,
695 "00.. .... = Fast select not requested");
696 proto_tree_add_text(fac_subtree, *offset+1, 1,
697 decode_boolean_bitfield(ptr[1], 0x01, 1*8,
698 "Reverse charging requested",
699 "Reverse charging not requested"));
702 case X25_FAC_THROUGHPUT:
706 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
707 "(Throughput class negociation)", *ptr);
708 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
720 sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
721 75*(1<<((ptr[1] >> 4)-3)));
724 sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
727 sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
730 sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
732 proto_tree_add_text(fac_subtree, *offset+1, 1,
733 decode_numeric_bitfield(ptr[1], 0xF0, 1*8, tmpbuf));
734 switch (ptr[1] & 0x0F)
745 sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
746 75*(1<<((ptr[1] & 0x0F)-3)));
749 sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
752 sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
755 sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
757 proto_tree_add_text(fac_subtree, *offset+1, 1,
758 decode_numeric_bitfield(ptr[1], 0x0F, 1*8, tmpbuf));
763 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
764 "(Closed user group selection)", *ptr);
765 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
766 proto_tree_add_text(fac_subtree, *offset+1, 1,
767 "Closed user group: %02X", ptr[1]);
770 case X25_FAC_CALLED_MODIF:
772 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
773 "(Called address modified)", *ptr);
774 fac_subtree = proto_item_add_subtree(ti,
775 ett_x25_fac_called_modif);
776 proto_tree_add_text(fac_tree, *offset, 2,
777 "Parameter %02X", ptr[1]);
780 case X25_FAC_CUG_OUTGOING_ACC:
782 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
783 "(Closed user group with outgoing access selection)",
785 fac_subtree = proto_item_add_subtree(ti,
786 ett_x25_fac_cug_outgoing_acc);
787 proto_tree_add_text(fac_subtree, *offset+1, 1,
788 "Closed user group: %02X", ptr[1]);
791 case X25_FAC_THROUGHPUT_MIN:
793 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
794 "(Minimum throughput class)", *ptr);
795 fac_subtree = proto_item_add_subtree(ti,
796 ett_x25_fac_throughput_min);
797 proto_tree_add_text(fac_subtree, *offset+1, 1,
798 "Parameter %02X", ptr[1]);
801 case X25_FAC_EXPRESS_DATA:
803 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
804 "(Negociation of express data)", *ptr);
805 fac_subtree = proto_item_add_subtree(ti,
806 ett_x25_fac_express_data);
807 proto_tree_add_text(fac_subtree, *offset+1, 1,
808 "Parameter %02X", ptr[1]);
813 ti = proto_tree_add_text(fac_tree, *offset, 1,
814 "Code : %02X (Unknown class A)", *ptr);
815 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
816 proto_tree_add_text(fac_subtree, *offset+1, 1,
817 "Parameter %02X", ptr[1]);
825 case X25_FAC_CLASS_B:
827 case X25_FAC_BILATERAL_CUG:
829 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
830 "(Bilateral closed user group selection)", *ptr);
831 fac_subtree = proto_item_add_subtree(ti,
832 ett_x25_fac_bilateral_cug);
833 proto_tree_add_text(fac_subtree, *offset+1, 2,
834 "Bilateral CUG: %02X%02X",
838 case X25_FAC_PACKET_SIZE:
843 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
844 "(Packet size)", *ptr);
845 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
849 sprintf(tmpbuf, "From the called DTE : %%u (16)");
852 sprintf(tmpbuf, "From the called DTE : %%u (32)");
855 sprintf(tmpbuf, "From the called DTE : %%u (64)");
858 sprintf(tmpbuf, "From the called DTE : %%u (128)");
861 sprintf(tmpbuf, "From the called DTE : %%u (256)");
864 sprintf(tmpbuf, "From the called DTE : %%u (512)");
867 sprintf(tmpbuf, "From the called DTE : %%u (1024)");
870 sprintf(tmpbuf, "From the called DTE : %%u (2048)");
873 sprintf(tmpbuf, "From the called DTE : %%u (4096)");
876 sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
879 proto_tree_add_text(fac_subtree, *offset+1, 1,
880 decode_numeric_bitfield(ptr[1], 0x0F, 1*8, tmpbuf));
885 sprintf(tmpbuf, "From the calling DTE : %%u (16)");
888 sprintf(tmpbuf, "From the calling DTE : %%u (32)");
891 sprintf(tmpbuf, "From the calling DTE : %%u (64)");
894 sprintf(tmpbuf, "From the calling DTE : %%u (128)");
897 sprintf(tmpbuf, "From the calling DTE : %%u (256)");
900 sprintf(tmpbuf, "From the calling DTE : %%u (512)");
903 sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
906 sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
909 sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
912 sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
915 proto_tree_add_text(fac_subtree, *offset+2, 1,
916 decode_numeric_bitfield(ptr[2], 0x0F, 1*8, tmpbuf));
919 case X25_FAC_WINDOW_SIZE:
921 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
922 "(Window size)", *ptr);
923 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
924 proto_tree_add_text(fac_subtree, *offset+1, 1,
925 decode_numeric_bitfield(ptr[1], 0x7F, 1*8,
926 "From the called DTE: %u"));
927 proto_tree_add_text(fac_subtree, *offset+2, 1,
928 decode_numeric_bitfield(ptr[2], 0x7F, 1*8,
929 "From the calling DTE: %u"));
932 case X25_FAC_RPOA_SELECTION:
934 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
935 "(RPOA selection)", *ptr);
936 fac_subtree = proto_item_add_subtree(ti,
937 ett_x25_fac_rpoa_selection);
938 proto_tree_add_text(fac_subtree, *offset+1, 2,
939 "Data network identification code : %02X%02X",
943 case X25_FAC_TRANSIT_DELAY:
945 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
946 "(Transit delay selection and indication)", *ptr);
947 fac_subtree = proto_item_add_subtree(ti,
948 ett_x25_fac_transit_delay);
949 proto_tree_add_text(fac_subtree, *offset+1, 2,
950 "Transit delay: %d ms",
951 (ptr[1]<<8) + ptr[2]);
956 ti = proto_tree_add_text(fac_tree, *offset, 1,
957 "Code : %02X (Unknown class B)", *ptr);
958 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
959 proto_tree_add_text(fac_subtree, *offset+1, 2,
960 "Parameter %02X%02X", ptr[1], ptr[2]);
968 case X25_FAC_CLASS_C:
970 ti = proto_tree_add_text(fac_tree, *offset, 1,
971 "Code : %02X (Unknown class C)", *ptr);
972 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
973 proto_tree_add_text(fac_subtree, *offset+1, 3,
974 "Parameter %02X%02X%02X",
975 ptr[1], ptr[2], ptr[3]);
981 case X25_FAC_CLASS_D:
983 case X25_FAC_CALL_TRANSFER:
988 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
989 "(Call redirection or deflection notification)", *ptr);
990 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
991 proto_tree_add_text(fac_subtree, *offset+1, 1,
992 "Length : %u", ptr[1]);
993 if ((ptr[2] & 0xC0) == 0xC0) {
994 proto_tree_add_text(fac_subtree, *offset+2, 1,
995 "Reason : call deflection by the originally "
996 "called DTE address");
1001 proto_tree_add_text(fac_subtree, *offset+2, 1,
1002 "Reason : originally called DTE busy");
1005 proto_tree_add_text(fac_subtree, *offset+2, 1,
1006 "Reason : call dist. within a hunt group");
1009 proto_tree_add_text(fac_subtree, *offset+2, 1,
1010 "Reason : originally called DTE out of order");
1013 proto_tree_add_text(fac_subtree, *offset+2, 1,
1014 "Reason : systematic call redirection");
1017 proto_tree_add_text(fac_subtree, *offset+2, 1,
1018 "Reason : unknown");
1022 proto_tree_add_text(fac_subtree, *offset+3, 1,
1023 "Number of semi-octets in DTE address : %u", ptr[3]);
1024 for (i = 0; i < ptr[3]; i++) {
1026 tmpbuf[i] = ((ptr[4+i/2] >> 4) & 0x0F) + '0';
1027 /* if > 9, convert to the right hexadecimal letter */
1028 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1030 tmpbuf[i] = (ptr[4+i/2] & 0x0F) + '0';
1031 /* if > 9, convert to the right hexadecimal letter */
1032 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1036 proto_tree_add_text(fac_subtree, *offset+4, ptr[1] - 2,
1037 "DTE address : %s", tmpbuf);
1040 case X25_FAC_CALLING_ADDR_EXT:
1045 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1046 "(Calling address extension)", *ptr);
1047 fac_subtree = proto_item_add_subtree(ti,
1048 ett_x25_fac_calling_addr_ext);
1049 proto_tree_add_text(fac_subtree, *offset+1, 1,
1050 "Length : %u", ptr[1]);
1051 proto_tree_add_text(fac_subtree, *offset+2, 1,
1052 "Number of semi-octets in DTE address : %u", ptr[2]);
1053 for (i = 0; i < ptr[2]; i++) {
1055 tmpbuf[i] = ((ptr[3+i/2] >> 4) & 0x0F) + '0';
1056 /* if > 9, convert to the right hexadecimal letter */
1057 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1059 tmpbuf[i] = (ptr[3+i/2] & 0x0F) + '0';
1060 /* if > 9, convert to the right hexadecimal letter */
1061 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1065 proto_tree_add_text(fac_subtree, *offset+3, ptr[1] - 1,
1066 "DTE address : %s", tmpbuf);
1069 case X25_FAC_CALLED_ADDR_EXT:
1074 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1075 "(Called address extension)", *ptr);
1076 fac_subtree = proto_item_add_subtree(ti,
1077 ett_x25_fac_called_addr_ext);
1078 proto_tree_add_text(fac_subtree, *offset+1, 1,
1079 "Length : %u", ptr[1]);
1080 proto_tree_add_text(fac_subtree, *offset+2, 1,
1081 "Number of semi-octets in DTE address : %u", ptr[2]);
1082 for (i = 0; i < ptr[2]; i++) {
1084 tmpbuf[i] = ((ptr[3+i/2] >> 4) & 0x0F) + '0';
1085 /* if > 9, convert to the right hexadecimal letter */
1086 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1088 tmpbuf[i] = (ptr[3+i/2] & 0x0F) + '0';
1089 /* if > 9, convert to the right hexadecimal letter */
1090 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1094 proto_tree_add_text(fac_subtree, *offset+3, ptr[1] - 1,
1095 "DTE address : %s", tmpbuf);
1098 case X25_FAC_ETE_TRANSIT_DELAY:
1100 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1101 "(End to end transit delay)", *ptr);
1102 fac_subtree = proto_item_add_subtree(ti,
1103 ett_x25_fac_ete_transit_delay);
1104 proto_tree_add_text(fac_subtree, *offset+1, 1,
1105 "Length : %u", ptr[1]);
1106 proto_tree_add_text(fac_subtree, *offset+2, ptr[1], "Value");
1109 case X25_FAC_CALL_DEFLECT:
1114 ti = proto_tree_add_text(fac_tree, *offset, 1, "Code : %02X "
1115 "(Call deflection selection)", *ptr);
1116 fac_subtree = proto_item_add_subtree(ti,
1117 ett_x25_fac_call_deflect);
1118 proto_tree_add_text(fac_subtree, *offset+1, 1,
1119 "Length : %u", ptr[1]);
1120 if ((ptr[2] & 0xC0) == 0xC0)
1121 proto_tree_add_text(fac_subtree, *offset+2, 1,
1122 "Reason : call DTE originated");
1124 proto_tree_add_text(fac_subtree, *offset+2, 1,
1125 "Reason : unknown");
1126 proto_tree_add_text(fac_subtree, *offset+3, 1,
1127 "Number of semi-octets in the alternative DTE address : %u",
1129 for (i = 0; i < ptr[3]; i++) {
1131 tmpbuf[i] = ((ptr[4+i/2] >> 4) & 0x0F) + '0';
1132 /* if > 9, convert to the right hexadecimal letter */
1133 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1135 tmpbuf[i] = (ptr[4+i/2] & 0x0F) + '0';
1136 /* if > 9, convert to the right hexadecimal letter */
1137 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1141 proto_tree_add_text(fac_subtree, *offset+4, ptr[1] - 2,
1142 "Alternative DTE address : %s", tmpbuf);
1145 case X25_FAC_PRIORITY:
1147 ti = proto_tree_add_text(fac_tree, *offset, 1,
1148 "Code : %02X (Priority)", *ptr);
1149 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
1150 proto_tree_add_text(fac_subtree, *offset+1, 1,
1151 "Length : %u", ptr[1]);
1152 proto_tree_add_text(fac_subtree, *offset+2, ptr[1], "Value");
1157 ti = proto_tree_add_text(fac_tree, *offset, 1,
1158 "Code : %02X (Unknown class D)", *ptr);
1159 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1160 proto_tree_add_text(fac_subtree, *offset+1, 1,
1161 "Length : %u", ptr[1]);
1162 proto_tree_add_text(fac_subtree, *offset+2, ptr[1], "Value");
1165 (*offset) += ptr[1]+2;
1174 x25_ntoa(proto_tree *tree, int *offset, const guint8 *p,
1175 frame_data *fd, gboolean toa)
1179 char addr1[16], addr2[16];
1180 char *first, *second;
1182 len1 = (*p >> 4) & 0x0F;
1183 len2 = (*p >> 0) & 0x0F;
1185 proto_tree_add_text(tree, *offset, 1,
1186 decode_numeric_bitfield(*p, 0xF0, 1*8,
1187 toa ? "Called address length : %u" :
1188 "Calling address length : %u"));
1189 proto_tree_add_text(tree, *offset, 1,
1190 decode_numeric_bitfield(*p, 0x0F, 1*8,
1191 toa ? "Calling address length : %u" :
1192 "Called address length : %u"));
1200 for (i = 0; i < (len1 + len2); i++) {
1203 *first++ = ((*p >> 0) & 0x0F) + '0';
1206 *first++ = ((*p >> 4) & 0x0F) + '0';
1210 *second++ = ((*p >> 0) & 0x0F) + '0';
1213 *second++ = ((*p >> 4) & 0x0F) + '0';
1223 if (check_col(fd, COL_RES_DL_DST))
1224 col_add_str(fd, COL_RES_DL_DST, addr1);
1227 if(check_col(fd, COL_RES_DL_SRC))
1228 col_add_str(fd, COL_RES_DL_SRC, addr1);
1231 proto_tree_add_text(tree, *offset,
1234 toa ? "Called" : "Calling",
1239 if (check_col(fd, COL_RES_DL_SRC))
1240 col_add_str(fd, COL_RES_DL_SRC, addr2);
1243 if(check_col(fd, COL_RES_DL_DST))
1244 col_add_str(fd, COL_RES_DL_DST, addr2);
1247 proto_tree_add_text(tree, *offset + len1/2,
1248 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1250 toa ? "Calling" : "Called",
1253 (*offset) += ((len1 + len2 + 1) / 2);
1257 get_x25_pkt_len(const char *data, frame_data *fd, int offset)
1259 int length, called_len, calling_len, dte_len, dce_len;
1261 /* packet size should always be > 3 */
1262 if (!BYTES_ARE_IN_FRAME(offset, 3)) return END_OF_FRAME;
1264 switch ((guint8)data[2])
1266 case X25_CALL_REQUEST:
1267 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1269 called_len = (data[3] >> 0) & 0x0F;
1270 calling_len = (data[3] >> 4) & 0x0F;
1271 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1272 if (length+offset < pi.captured_len)
1273 length += (1 + data[length]); /* facilities */
1275 else length = END_OF_FRAME;
1276 return MIN(END_OF_FRAME,length);
1278 case X25_CALL_ACCEPTED:
1279 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1281 called_len = (data[3] >> 0) & 0x0F;
1282 calling_len = (data[3] >> 4) & 0x0F;
1283 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1284 if (length+offset < pi.captured_len)
1285 length += (1 + data[length]); /* facilities */
1287 else length = END_OF_FRAME;
1288 return MIN(END_OF_FRAME,length);
1290 case X25_CLEAR_REQUEST:
1291 case X25_RESET_REQUEST:
1292 case X25_RESTART_REQUEST:
1293 return MIN(END_OF_FRAME,5);
1295 case X25_DIAGNOSTIC:
1296 return MIN(END_OF_FRAME,4);
1298 case X25_CLEAR_CONFIRMATION:
1300 case X25_INTERRUPT_CONFIRMATION:
1301 case X25_RESET_CONFIRMATION:
1302 case X25_RESTART_CONFIRMATION:
1303 return MIN(END_OF_FRAME,3);
1305 case X25_REGISTRATION_REQUEST:
1306 if (BYTES_ARE_IN_FRAME(offset, 4)) /* pkt size >= 4 */
1308 dce_len = (data[3] >> 0) & 0x0F;
1309 dte_len = (data[3] >> 4) & 0x0F;
1310 length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1311 if (length+offset < pi.captured_len)
1312 length += (1 + data[length]); /* registration */
1314 else length = END_OF_FRAME;
1315 return MIN(END_OF_FRAME,length);
1317 case X25_REGISTRATION_CONFIRMATION:
1318 if (BYTES_ARE_IN_FRAME(offset, 6)) /* pkt size >= 6 */
1320 dce_len = (data[5] >> 0) & 0x0F;
1321 dte_len = (data[5] >> 4) & 0x0F;
1322 length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1323 if (length+offset < pi.captured_len)
1324 length += (1 + data[length]); /* registration */
1326 else length = END_OF_FRAME;
1327 return MIN(END_OF_FRAME,length);
1330 if ((data[2] & 0x01) == X25_DATA) return MIN(END_OF_FRAME,3);
1332 switch (data[2] & 0x1F)
1335 return MIN(END_OF_FRAME,3);
1338 return MIN(END_OF_FRAME,3);
1341 return MIN(END_OF_FRAME,3);
1348 dissect_x25(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1350 proto_tree *x25_tree=0, *ti;
1351 int localoffset=offset;
1355 void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
1356 gboolean toa; /* TOA/NPI address format */
1358 if (check_col(fd, COL_PROTOCOL))
1359 col_add_str(fd, COL_PROTOCOL, "X.25");
1361 modulo = ((pd[localoffset] & 0x20) ? 128 : 8);
1363 if (pd[localoffset] & 0x80) toa = TRUE;
1366 x25_pkt_len = get_x25_pkt_len(&pd[localoffset], fd, offset);
1367 if (x25_pkt_len < 3) /* packet too short */
1369 if (check_col(fd, COL_INFO))
1370 col_add_str(fd, COL_INFO, "Invalid/short X.25 packet");
1372 proto_tree_add_item_format(tree, (modulo == 8 ? proto_x25 : proto_ex25),
1373 localoffset, END_OF_FRAME, NULL,
1374 "Invalid/short X.25 packet");
1377 vc = (int)(pd[localoffset] & 0x0F)*256 + (int)pd[localoffset+1];
1379 ti = proto_tree_add_item(tree, (modulo == 8) ? proto_x25 : proto_ex25,
1380 localoffset, x25_pkt_len, NULL);
1381 x25_tree = proto_item_add_subtree(ti, ett_x25);
1382 if (pd[localoffset] & 0x80)
1383 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_qbit : hf_ex25_qbit,
1384 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1385 if (pd[localoffset] & 0x40)
1386 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_dbit : hf_ex25_dbit,
1387 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1388 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_mod : hf_ex25_mod,
1389 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1391 switch (pd[localoffset+2]) {
1392 case X25_CALL_REQUEST:
1393 if (check_col(fd, COL_INFO))
1394 col_add_fstr(fd, COL_INFO, "%s VC:%d",
1395 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Inc. call"
1399 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1400 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1401 proto_tree_add_item_format(x25_tree,
1402 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1403 localoffset+2, 1, X25_CALL_REQUEST,
1404 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Incoming call"
1408 if (localoffset < x25_pkt_len+offset) /* calling/called addresses */
1409 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1411 if (localoffset < x25_pkt_len+offset) /* facilities */
1412 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1414 if (IS_DATA_IN_FRAME(localoffset)) /* user data */
1416 if (pd[localoffset] == 0xCC)
1418 x25_hash_add_proto_start(vc, fd->abs_secs,
1419 fd->abs_usecs, dissect_ip);
1421 proto_tree_add_text(x25_tree, localoffset, 1,
1425 else if (pd[localoffset] == 0x03 &&
1426 pd[localoffset+1] == 0x01 &&
1427 pd[localoffset+2] == 0x01 &&
1428 pd[localoffset+3] == 0x00)
1430 x25_hash_add_proto_start(vc, fd->abs_secs,
1431 fd->abs_usecs, dissect_cotp);
1433 proto_tree_add_text(x25_tree, localoffset, 4,
1439 proto_tree_add_text(x25_tree, localoffset,
1440 pi.captured_len-localoffset, "Data");
1441 localoffset = pi.captured_len;
1445 case X25_CALL_ACCEPTED:
1446 if(check_col(fd, COL_INFO))
1447 col_add_fstr(fd, COL_INFO, "%s VC:%d",
1448 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Call conn."
1452 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1453 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1454 proto_tree_add_item_format(x25_tree,
1455 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1456 localoffset+2, 1, X25_CALL_ACCEPTED,
1457 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Call connected"
1461 if (localoffset < x25_pkt_len+offset) /* calling/called addresses */
1462 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1464 if (localoffset < x25_pkt_len+offset) /* facilities */
1465 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1467 if (IS_DATA_IN_FRAME(localoffset)) { /* user data */
1469 proto_tree_add_text(x25_tree, localoffset,
1470 pi.captured_len-localoffset, "Data");
1471 localoffset=pi.captured_len;
1474 case X25_CLEAR_REQUEST:
1475 if(check_col(fd, COL_INFO)) {
1476 col_add_fstr(fd, COL_INFO, "%s VC:%d %s - %s",
1477 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Clear ind."
1479 vc, clear_code(pd[localoffset+3]),
1480 clear_diag(pd[localoffset+4]));
1482 x25_hash_add_proto_end(vc, fd->abs_secs, fd->abs_usecs);
1484 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1485 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1486 proto_tree_add_item_format(x25_tree,
1487 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1488 localoffset+2, 1, X25_CLEAR_REQUEST,
1489 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Clear indication"
1491 if (localoffset+3 < x25_pkt_len+offset)
1492 proto_tree_add_text(x25_tree, localoffset+3, 1,
1493 "Cause : %s", clear_code(pd[localoffset+3]));
1494 if (localoffset+4 < x25_pkt_len+offset)
1495 proto_tree_add_text(x25_tree, localoffset+4, 1,
1497 clear_diag(pd[localoffset+4]));
1499 localoffset += x25_pkt_len;
1501 case X25_CLEAR_CONFIRMATION:
1502 if(check_col(fd, COL_INFO))
1503 col_add_fstr(fd, COL_INFO, "Clear Conf. VC:%d", vc);
1505 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1506 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1507 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1508 localoffset+2, 1, X25_CLEAR_CONFIRMATION);
1510 localoffset += x25_pkt_len;
1512 if (IS_DATA_IN_FRAME(localoffset)) /* extended clear conf format */
1513 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
1515 if (IS_DATA_IN_FRAME(localoffset)) /* facilities */
1516 dump_facilities(x25_tree, &localoffset, &pd[localoffset]);
1518 case X25_DIAGNOSTIC:
1519 if(check_col(fd, COL_INFO)) {
1520 col_add_fstr(fd, COL_INFO, "Diag. %d", (int)pd[localoffset+3]);
1523 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1524 localoffset+2, 1, X25_DIAGNOSTIC);
1525 if (localoffset+3 < x25_pkt_len+offset)
1526 proto_tree_add_text(x25_tree, localoffset+3, 1,
1527 "Diagnostic : %d", (int)pd[localoffset+3]);
1529 localoffset += x25_pkt_len;
1532 if(check_col(fd, COL_INFO))
1533 col_add_fstr(fd, COL_INFO, "Interrupt VC:%d", vc);
1535 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1536 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1537 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1538 localoffset+2, 1, X25_INTERRUPT);
1540 localoffset += x25_pkt_len;
1542 case X25_INTERRUPT_CONFIRMATION:
1543 if(check_col(fd, COL_INFO))
1544 col_add_fstr(fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
1546 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1547 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1548 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1549 localoffset+2, 1, X25_INTERRUPT_CONFIRMATION);
1551 localoffset += x25_pkt_len;
1553 case X25_RESET_REQUEST:
1554 if(check_col(fd, COL_INFO)) {
1555 col_add_fstr(fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
1556 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Reset ind."
1558 vc, reset_code(pd[localoffset+3]),
1559 (int)pd[localoffset+4]);
1561 x25_hash_add_proto_end(vc, fd->abs_secs, fd->abs_usecs);
1563 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1564 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1565 proto_tree_add_item_format(x25_tree,
1566 (modulo == 8) ? hf_x25_type : hf_ex25_type, localoffset+2, 1,
1568 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Reset indication"
1570 if (localoffset+3 < x25_pkt_len+offset)
1571 proto_tree_add_text(x25_tree, localoffset+3, 1,
1572 "Cause : %s", reset_code(pd[localoffset+3]));
1573 if (localoffset+4 < x25_pkt_len+offset)
1574 proto_tree_add_text(x25_tree, localoffset+4, 1,
1575 "Diagnostic : %d", (int)pd[localoffset+4]);
1577 localoffset += x25_pkt_len;
1579 case X25_RESET_CONFIRMATION:
1580 if(check_col(fd, COL_INFO))
1581 col_add_fstr(fd, COL_INFO, "Reset conf. VC:%d", vc);
1583 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1584 localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
1585 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1586 localoffset+2, 1, X25_RESET_CONFIRMATION);
1588 localoffset += x25_pkt_len;
1590 case X25_RESTART_REQUEST:
1591 if(check_col(fd, COL_INFO)) {
1592 col_add_fstr(fd, COL_INFO, "%s %s - Diag.:%d",
1593 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Restart ind."
1595 restart_code(pd[localoffset+3]),
1596 (int)pd[localoffset+4]);
1599 proto_tree_add_item_format(x25_tree,
1600 (modulo == 8) ? hf_x25_type : hf_ex25_type, localoffset+2, 1,
1601 X25_RESTART_REQUEST,
1602 (fd->pseudo_header.x25.flags & FROM_DCE) ? "Restart indication"
1603 : "Restart request");
1604 if (localoffset+3 < x25_pkt_len+offset)
1605 proto_tree_add_text(x25_tree, localoffset+3, 1,
1606 "Cause : %s", restart_code(pd[localoffset+3]));
1607 if (localoffset+4 < x25_pkt_len+offset)
1608 proto_tree_add_text(x25_tree, localoffset+4, 1,
1609 "Diagnostic : %d", (int)pd[localoffset+4]);
1611 localoffset += x25_pkt_len;
1613 case X25_RESTART_CONFIRMATION:
1614 if(check_col(fd, COL_INFO))
1615 col_add_str(fd, COL_INFO, "Restart conf.");
1617 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1618 localoffset+2, 1, X25_RESTART_CONFIRMATION);
1619 localoffset += x25_pkt_len;
1621 case X25_REGISTRATION_REQUEST:
1622 if(check_col(fd, COL_INFO))
1623 col_add_str(fd, COL_INFO, "Registration req.");
1625 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1626 localoffset+2, 1, X25_REGISTRATION_REQUEST);
1628 if (localoffset < x25_pkt_len+offset)
1629 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, FALSE);
1632 if (localoffset < x25_pkt_len+offset)
1633 proto_tree_add_text(x25_tree, localoffset, 1,
1634 "Registration length: %d", pd[localoffset] & 0x7F);
1635 if (localoffset+1 < x25_pkt_len+offset)
1636 proto_tree_add_text(x25_tree, localoffset+1,
1637 pd[localoffset] & 0x7F, "Registration");
1639 localoffset = pi.captured_len;
1641 case X25_REGISTRATION_CONFIRMATION:
1642 if(check_col(fd, COL_INFO))
1643 col_add_str(fd, COL_INFO, "Registration conf.");
1645 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
1646 localoffset+2, 1, X25_REGISTRATION_CONFIRMATION);
1647 if (localoffset+3 < x25_pkt_len+offset)
1648 proto_tree_add_text(x25_tree, localoffset+3, 1,
1649 "Cause: %s", registration_code(pd[localoffset+3]));
1650 if (localoffset+4 < x25_pkt_len+offset)
1651 proto_tree_add_text(x25_tree, localoffset+4, 1,
1652 "Diagnostic: %s", registration_code(pd[localoffset+4]));
1655 if (localoffset < x25_pkt_len+offset)
1656 x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, TRUE);
1659 if (localoffset < x25_pkt_len+offset)
1660 proto_tree_add_text(x25_tree, localoffset, 1,
1661 "Registration length: %d", pd[localoffset] & 0x7F);
1662 if (localoffset+1 < x25_pkt_len+offset)
1663 proto_tree_add_text(x25_tree, localoffset+1,
1664 pd[localoffset] & 0x7F, "Registration");
1666 localoffset = pi.captured_len;
1670 if ((pd[localoffset] & 0x01) == X25_DATA)
1672 if(check_col(fd, COL_INFO)) {
1674 col_add_fstr(fd, COL_INFO,
1675 "Data VC:%d P(S):%d P(R):%d %s", vc,
1676 (pd[localoffset] >> 1) & 0x07,
1677 (pd[localoffset] >> 5) & 0x07,
1678 ((pd[localoffset]>>4) & 0x01) ? " M" : "");
1680 col_add_fstr(fd, COL_INFO,
1681 "Data VC:%d P(S):%d P(R):%d %s", vc,
1682 pd[localoffset+1] >> 1,
1683 pd[localoffset] >> 1,
1684 (pd[localoffset+1] & 0x01) ? " M" : "");
1687 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1688 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1690 proto_tree_add_item_hidden(x25_tree, hf_x25_type, localoffset, 1,
1692 proto_tree_add_item(x25_tree, hf_x25_p_r, localoffset, 1,
1694 if (pd[localoffset] & 0x10)
1695 proto_tree_add_item(x25_tree, hf_x25_mbit, localoffset, 1,
1697 proto_tree_add_item(x25_tree, hf_x25_p_s, localoffset, 1,
1699 proto_tree_add_text(x25_tree, localoffset, 1,
1700 decode_boolean_bitfield(pd[localoffset], 0x01, 1*8,
1704 proto_tree_add_item_hidden(x25_tree, hf_ex25_type, localoffset, 1,
1706 proto_tree_add_item(x25_tree, hf_x25_p_r, localoffset, 1,
1708 proto_tree_add_item(x25_tree, hf_x25_p_s, localoffset+1, 1,
1710 if (pd[localoffset+1] & 0x01)
1711 proto_tree_add_item(x25_tree, hf_ex25_mbit, localoffset+1, 1,
1715 localoffset += (modulo == 8) ? 1 : 2;
1718 switch (pd[localoffset] & 0x1F)
1721 if(check_col(fd, COL_INFO)) {
1723 col_add_fstr(fd, COL_INFO, "RR VC:%d P(R):%d",
1724 vc, (pd[localoffset] >> 5) & 0x07);
1726 col_add_fstr(fd, COL_INFO, "RR VC:%d P(R):%d",
1727 vc, pd[localoffset+1] >> 1);
1730 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1731 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1733 proto_tree_add_item(x25_tree, hf_x25_p_r,
1734 localoffset, 1, pd[localoffset]);
1735 proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_RR);
1738 proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_RR);
1739 proto_tree_add_item(x25_tree, hf_ex25_p_r,
1740 localoffset+1, 1, pd[localoffset+1]);
1746 if(check_col(fd, COL_INFO)) {
1748 col_add_fstr(fd, COL_INFO, "RNR VC:%d P(R):%d",
1749 vc, (pd[localoffset] >> 5) & 0x07);
1751 col_add_fstr(fd, COL_INFO, "RNR VC:%d P(R):%d",
1752 vc, pd[localoffset+1] >> 1);
1755 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1756 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1758 proto_tree_add_item(x25_tree, hf_x25_p_r,
1759 localoffset, 1, pd[localoffset]);
1760 proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_RNR);
1763 proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_RNR);
1764 proto_tree_add_item(x25_tree, hf_ex25_p_r,
1765 localoffset+1, 1, pd[localoffset+1]);
1771 if(check_col(fd, COL_INFO)) {
1773 col_add_fstr(fd, COL_INFO, "REJ VC:%d P(R):%d",
1774 vc, (pd[localoffset] >> 5) & 0x07);
1776 col_add_fstr(fd, COL_INFO, "REJ VC:%d P(R):%d",
1777 vc, pd[localoffset+1] >> 1);
1780 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1781 localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
1783 proto_tree_add_item(x25_tree, hf_x25_p_r,
1784 localoffset, 1, pd[localoffset]);
1785 proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_REJ);
1788 proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_REJ);
1789 proto_tree_add_item(x25_tree, hf_ex25_p_r,
1790 localoffset+1, 1, pd[localoffset+1]);
1794 localoffset += (modulo == 8) ? 1 : 2;
1797 if (!IS_DATA_IN_FRAME(localoffset)) return;
1799 /* search the dissector in the hash table */
1800 if ((dissect = x25_hash_get_dissect(fd->abs_secs, fd->abs_usecs, vc)))
1801 (*dissect)(pd, localoffset, fd, tree);
1803 if (pd[localoffset] == 0x45) /* If the Call Req. has not been captured,
1804 * assume these packets carry IP */
1806 x25_hash_add_proto_start(vc, fd->abs_secs,
1807 fd->abs_usecs, dissect_ip);
1808 dissect_ip(pd, localoffset, fd, tree);
1811 dissect_data(pd, localoffset, fd, tree);
1817 proto_register_x25(void)
1819 static hf_register_info hf8[] = {
1821 { "Q Bit", "x25.q", FT_BOOLEAN, 2, NULL, 0x8000,
1822 "Qualifier Bit" } },
1824 { "D Bit", "x25.d", FT_BOOLEAN, 2, NULL, 0x4000,
1825 "Delivery Confirmation Bit" } },
1827 { "Modulo", "x25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1828 "Specifies whether the frame is modulo 8 or 128" } },
1830 { "Logical Channel", "x25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
1831 "Logical Channel Number" } },
1833 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1836 { "P(R)", "x25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
1837 "Packet Receive Sequence Number" } },
1839 { "M Bit", "x25.m", FT_BOOLEAN, 1, NULL, 0x10,
1842 { "P(S)", "x25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
1843 "Packet Send Sequence Number" } },
1846 static hf_register_info hf128[] = {
1848 { "Q Bit", "ex25.q", FT_BOOLEAN, 2, NULL, 0x8000,
1849 "Qualifier Bit" } },
1851 { "D Bit", "ex25.d", FT_BOOLEAN, 2, NULL, 0x4000,
1852 "Delivery Confirmation Bit" } },
1854 { "Modulo", "ex25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1855 "Specifies whether the frame is modulo 8 or 128" } },
1857 { "Logical Channel", "ex25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
1858 "Logical Channel Number" } },
1860 { "Packet Type", "ex25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1863 { "P(R)", "ex25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
1864 "Packet Receive Sequence Number" } },
1866 { "M Bit", "ex25.m", FT_BOOLEAN, 1, NULL, 0x01,
1869 { "P(S)", "ex25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
1870 "Packet Send Sequence Number" } },
1872 static gint *ett[] = {
1875 &ett_x25_fac_unknown,
1877 &ett_x25_fac_reverse,
1878 &ett_x25_fac_throughput,
1880 &ett_x25_fac_called_modif,
1881 &ett_x25_fac_cug_outgoing_acc,
1882 &ett_x25_fac_throughput_min,
1883 &ett_x25_fac_express_data,
1884 &ett_x25_fac_bilateral_cug,
1885 &ett_x25_fac_packet_size,
1886 &ett_x25_fac_window_size,
1887 &ett_x25_fac_rpoa_selection,
1888 &ett_x25_fac_transit_delay,
1889 &ett_x25_fac_call_transfer,
1890 &ett_x25_fac_called_addr_ext,
1891 &ett_x25_fac_ete_transit_delay,
1892 &ett_x25_fac_calling_addr_ext,
1893 &ett_x25_fac_call_deflect,
1894 &ett_x25_fac_priority
1897 proto_x25 = proto_register_protocol ("X.25", "x25");
1898 proto_ex25 = proto_register_protocol ("Extended X.25 (modulo 128)", "ex25");
1899 proto_register_field_array (proto_x25, hf8, array_length(hf8));
1900 proto_register_field_array (proto_ex25, hf128, array_length(hf128));
1901 proto_register_subtree_array(ett, array_length(ett));