2 * Routines for x25 packet disassembly
3 * Olivier Abad <oabad@cybercable.fr>
5 * $Id: packet-x25.c,v 1.50 2001/07/05 22:10:09 oabad Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
45 #define X25_CALL_REQUEST 0x0B
46 #define X25_CALL_ACCEPTED 0x0F
47 #define X25_CLEAR_REQUEST 0x13
48 #define X25_CLEAR_CONFIRMATION 0x17
49 #define X25_INTERRUPT 0x23
50 #define X25_INTERRUPT_CONFIRMATION 0x27
51 #define X25_RESET_REQUEST 0x1B
52 #define X25_RESET_CONFIRMATION 0x1F
53 #define X25_RESTART_REQUEST 0xFB
54 #define X25_RESTART_CONFIRMATION 0xFF
55 #define X25_REGISTRATION_REQUEST 0xF3
56 #define X25_REGISTRATION_CONFIRMATION 0xF7
57 #define X25_DIAGNOSTIC 0xF1
63 #define X25_FAC_CLASS_MASK 0xC0
65 #define X25_FAC_CLASS_A 0x00
66 #define X25_FAC_CLASS_B 0x40
67 #define X25_FAC_CLASS_C 0x80
68 #define X25_FAC_CLASS_D 0xC0
70 #define X25_FAC_COMP_MARK 0x00
71 #define X25_FAC_REVERSE 0x01
72 #define X25_FAC_THROUGHPUT 0x02
73 #define X25_FAC_CUG 0x03
74 #define X25_FAC_CALLED_MODIF 0x08
75 #define X25_FAC_CUG_OUTGOING_ACC 0x09
76 #define X25_FAC_THROUGHPUT_MIN 0x0A
77 #define X25_FAC_EXPRESS_DATA 0x0B
78 #define X25_FAC_BILATERAL_CUG 0x41
79 #define X25_FAC_PACKET_SIZE 0x42
80 #define X25_FAC_WINDOW_SIZE 0x43
81 #define X25_FAC_RPOA_SELECTION 0x44
82 #define X25_FAC_TRANSIT_DELAY 0x49
83 #define X25_FAC_CALL_TRANSFER 0xC3
84 #define X25_FAC_CALLED_ADDR_EXT 0xC9
85 #define X25_FAC_ETE_TRANSIT_DELAY 0xCA
86 #define X25_FAC_CALLING_ADDR_EXT 0xCB
87 #define X25_FAC_CALL_DEFLECT 0xD1
88 #define X25_FAC_PRIORITY 0xD2
90 static int proto_x25 = -1;
91 static int hf_x25_gfi = -1;
92 static int hf_x25_abit = -1;
93 static int hf_x25_qbit = -1;
94 static int hf_x25_dbit = -1;
95 static int hf_x25_mod = -1;
96 static int hf_x25_lcn = -1;
97 static int hf_x25_type = -1;
98 static int hf_x25_p_r_mod8 = -1;
99 static int hf_x25_p_r_mod128 = -1;
100 static int hf_x25_mbit_mod8 = -1;
101 static int hf_x25_mbit_mod128 = -1;
102 static int hf_x25_p_s_mod8 = -1;
103 static int hf_x25_p_s_mod128 = -1;
105 static gint ett_x25 = -1;
106 static gint ett_x25_gfi = -1;
107 static gint ett_x25_fac = -1;
108 static gint ett_x25_fac_unknown = -1;
109 static gint ett_x25_fac_mark = -1;
110 static gint ett_x25_fac_reverse = -1;
111 static gint ett_x25_fac_throughput = -1;
112 static gint ett_x25_fac_cug = -1;
113 static gint ett_x25_fac_called_modif = -1;
114 static gint ett_x25_fac_cug_outgoing_acc = -1;
115 static gint ett_x25_fac_throughput_min = -1;
116 static gint ett_x25_fac_express_data = -1;
117 static gint ett_x25_fac_bilateral_cug = -1;
118 static gint ett_x25_fac_packet_size = -1;
119 static gint ett_x25_fac_window_size = -1;
120 static gint ett_x25_fac_rpoa_selection = -1;
121 static gint ett_x25_fac_transit_delay = -1;
122 static gint ett_x25_fac_call_transfer = -1;
123 static gint ett_x25_fac_called_addr_ext = -1;
124 static gint ett_x25_fac_ete_transit_delay = -1;
125 static gint ett_x25_fac_calling_addr_ext = -1;
126 static gint ett_x25_fac_call_deflect = -1;
127 static gint ett_x25_fac_priority = -1;
129 static const value_string vals_modulo[] = {
135 static const value_string vals_x25_type[] = {
136 { X25_CALL_REQUEST, "Call" },
137 { X25_CALL_ACCEPTED, "Call Accepted" },
138 { X25_CLEAR_REQUEST, "Clear" },
139 { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
140 { X25_INTERRUPT, "Interrupt" },
141 { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
142 { X25_RESET_REQUEST, "Reset" },
143 { X25_RESET_CONFIRMATION, "Reset Confirmation" },
144 { X25_RESTART_REQUEST, "Restart" },
145 { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
146 { X25_REGISTRATION_REQUEST, "Registration" },
147 { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
148 { X25_DIAGNOSTIC, "Diagnostic" },
152 { X25_DATA, "DATA" },
156 static dissector_handle_t ip_handle;
157 static dissector_handle_t ositp_handle;
160 * each vc_info node contains :
161 * the time of the first frame using this dissector (secs and usecs)
162 * the time of the last frame using this dissector (0 if it is unknown)
163 * a pointer to the dissector
165 * the "time of first frame" is initialized when a Call Req. is received
166 * the "time of last frame" is initialized when a Clear, Reset, or Restart
169 typedef struct _vc_info {
170 guint32 first_frame_secs, first_frame_usecs;
171 guint32 last_frame_secs, last_frame_usecs;
172 dissector_handle_t dissect;
173 struct _vc_info *next;
177 * the hash table will contain linked lists of global_vc_info
178 * each global_vc_info struct contains :
179 * the VC number (the hash table is indexed with VC % 64)
180 * a linked list of vc_info
182 typedef struct _global_vc_info {
185 struct _global_vc_info *next;
188 static global_vc_info *hash_table[64];
191 free_vc_info(vc_info *pt)
203 reinit_x25_hashtable(void)
207 for (i=0; i<64; i++) {
208 if (hash_table[i]) /* not NULL ==> free */
210 global_vc_info *hash_ent, *hash_ent2;
211 hash_ent2 = hash_ent = hash_table[i];
214 hash_ent2 = hash_ent;
215 hash_ent = hash_ent->next;
216 free_vc_info(hash_ent2->info);
225 x25_hash_add_proto_start(guint16 vc, guint32 frame_secs, guint32 frame_usecs,
226 dissector_handle_t dissect)
229 global_vc_info *hash_ent;
230 global_vc_info *hash_ent2;
232 if (hash_table[idx] == 0)
234 hash_ent = (global_vc_info *)g_malloc(sizeof(global_vc_info));
236 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
239 hash_ent->vc_num = vc;
241 hash_ent->info = (vc_info *)g_malloc(sizeof(vc_info));
242 if (!hash_ent->info) {
243 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
246 hash_ent->info->first_frame_secs = frame_secs;
247 hash_ent->info->first_frame_usecs = frame_usecs;
248 hash_ent->info->last_frame_secs = 0;
249 hash_ent->info->last_frame_usecs = 0;
250 hash_ent->info->dissect = dissect;
251 hash_ent->info->next = 0;
252 hash_table[idx] = hash_ent;
256 hash_ent2 = hash_ent = hash_table[idx];
257 /* search an entry with the same VC number */
258 while (hash_ent != NULL && hash_ent->vc_num != vc) {
259 hash_ent2 = hash_ent;
260 hash_ent = hash_ent->next;
262 if (hash_ent != NULL) /* hash_ent->vc_num == vc */
264 vc_info *vci = hash_ent->info;
265 while (vci->next) vci = vci->next; /* last element */
266 if (vci->dissect == dissect) {
267 vci->last_frame_secs = 0;
268 vci->last_frame_usecs = 0;
271 vci->next = (vc_info *)g_malloc(sizeof(vc_info));
272 if (vci->next == 0) {
273 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
276 vci->next->first_frame_secs = frame_secs;
277 vci->next->first_frame_usecs = frame_usecs;
278 vci->next->last_frame_secs = 0;
279 vci->next->last_frame_usecs = 0;
280 vci->next->dissect = dissect;
284 else /* new vc number */
286 hash_ent2->next = (global_vc_info *)g_malloc(sizeof(global_vc_info));
287 if (!hash_ent2->next) {
288 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
291 hash_ent2->next->info = (vc_info *)g_malloc(sizeof(vc_info));
292 if (!hash_ent2->next->info) {
293 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
296 hash_ent2->next->info->first_frame_secs = frame_secs;
297 hash_ent2->next->info->first_frame_usecs = frame_usecs;
298 hash_ent2->next->info->last_frame_secs = 0;
299 hash_ent2->next->info->last_frame_usecs = 0;
300 hash_ent2->next->info->dissect = dissect;
301 hash_ent2->next->info->next = 0;
307 x25_hash_add_proto_end(guint16 vc, guint32 frame_secs, guint32 frame_usecs)
309 global_vc_info *hash_ent = hash_table[vc%64];
312 if (!hash_ent) return;
313 while(hash_ent->vc_num != vc) hash_ent = hash_ent->next;
314 if (!hash_ent) return;
316 vci = hash_ent->info;
317 while (vci->next) vci = vci->next;
318 vci->last_frame_secs = frame_secs;
319 vci->last_frame_usecs = frame_usecs;
322 static dissector_handle_t
323 x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc)
325 global_vc_info *hash_ent = hash_table[vc%64];
329 if (!hash_ent) return 0;
331 while(hash_ent && hash_ent->vc_num != vc) hash_ent = hash_ent->next;
332 if (!hash_ent) return 0;
334 /* a hash_ent was found for this VC number */
335 vci2 = vci = hash_ent->info;
337 /* looking for an entry matching our frame time */
338 while (vci && (vci->last_frame_secs < frame_secs ||
339 (vci->last_frame_secs == frame_secs &&
340 vci->last_frame_usecs < frame_usecs))) {
344 /* we reached last record, and previous record has a non zero
345 * last frame time ==> no dissector */
346 if (!vci && (vci2->last_frame_secs || vci2->last_frame_usecs)) return 0;
348 /* we reached last record, and previous record has a zero last frame time
349 * ==> dissector for previous frame has not been "stopped" by a Clear, etc */
351 /* if the start time for vci2 is greater than our frame time
352 * ==> no dissector */
353 if (frame_secs < vci2->first_frame_secs ||
354 (frame_secs == vci2->first_frame_secs &&
355 frame_usecs < vci2->first_frame_usecs))
358 return vci2->dissect;
361 /* our frame time is before vci's end. Check if it is adter vci's start */
362 if (frame_secs < vci->first_frame_secs ||
363 (frame_secs == vci->first_frame_secs &&
364 frame_usecs < vci->first_frame_usecs))
370 static char *clear_code(unsigned char code)
372 static char buffer[25];
374 if (code == 0x00 || (code & 0x80) == 0x80)
375 return "DTE Originated";
377 return "Number Busy";
379 return "Out Of Order";
381 return "Remote Procedure Error";
383 return "Reverse Charging Acceptance Not Subscribed";
385 return "Incompatible Destination";
387 return "Fast Select Acceptance Not Subscribed";
389 return "Destination Absent";
391 return "Invalid Facility Requested";
393 return "Access Barred";
395 return "Local Procedure Error";
397 return "Network Congestion";
399 return "Not Obtainable";
401 return "RPOA Out Of Order";
403 sprintf(buffer, "Unknown %02X", code);
408 static char *clear_diag(unsigned char code)
410 static char buffer[25];
413 return "No additional information";
415 return "Invalid P(S)";
417 return "Invalid P(R)";
419 return "Packet type invalid";
421 return "Packet type invalid for state r1";
423 return "Packet type invalid for state r2";
425 return "Packet type invalid for state r3";
427 return "Packet type invalid for state p1";
429 return "Packet type invalid for state p2";
431 return "Packet type invalid for state p3";
433 return "Packet type invalid for state p4";
435 return "Packet type invalid for state p5";
437 return "Packet type invalid for state p6";
439 return "Packet type invalid for state p7";
441 return "Packet type invalid for state d1";
443 return "Packet type invalid for state d2";
445 return "Packet type invalid for state d3";
447 return "Packet not allowed";
449 return "Unidentifiable packet";
451 return "Call on one-way logical channel";
453 return "Invalid packet type on a PVC";
455 return "Packet on unassigned LC";
457 return "Reject not subscribed to";
459 return "Packet too short";
461 return "Packet too long";
463 return "Invalid general format identifier";
465 return "Restart/registration packet with nonzero bits";
467 return "Packet type not compatible with facility";
469 return "Unauthorised interrupt confirmation";
471 return "Unauthorised interrupt";
473 return "Unauthorised reject";
475 return "Time expired";
477 return "Time expired for incoming call";
479 return "Time expired for clear indication";
481 return "Time expired for reset indication";
483 return "Time expired for restart indication";
485 return "Time expired for call deflection";
487 return "Call set-up/clearing or registration pb.";
489 return "Facility/registration code not allowed";
491 return "Facility parameter not allowed";
493 return "Invalid called DTE address";
495 return "Invalid calling DTE address";
497 return "Invalid facility/registration length";
499 return "Incoming call barred";
501 return "No logical channel available";
503 return "Call collision";
505 return "Duplicate facility requested";
507 return "Non zero address length";
509 return "Non zero facility length";
511 return "Facility not provided when expected";
513 return "Invalid CCITT-specified DTE facility";
515 return "Max. nb of call redir/defl. exceeded";
517 return "Miscellaneous";
519 return "Improper cause code from DTE";
521 return "Not aligned octet";
523 return "Inconsistent Q bit setting";
525 return "NUI problem";
527 return "International problem";
529 return "Remote network problem";
531 return "International protocol problem";
533 return "International link out of order";
535 return "International link busy";
537 return "Transit network facility problem";
539 return "Remote network facility problem";
541 return "International routing problem";
543 return "Temporary routing problem";
545 return "Unknown called DNIC";
547 return "Maintenance action";
549 sprintf(buffer, "Unknown %d", code);
554 static char *reset_code(unsigned char code)
556 static char buffer[25];
558 if (code == 0x00 || (code & 0x80) == 0x80)
559 return "DTE Originated";
561 return "Out of order";
563 return "Remote Procedure Error";
565 return "Local Procedure Error";
567 return "Network Congestion";
569 return "Remote DTE operational";
571 return "Network operational";
573 return "Incompatible Destination";
575 return "Network out of order";
577 sprintf(buffer, "Unknown %02X", code);
582 static char *restart_code(unsigned char code)
584 static char buffer[25];
586 if (code == 0x00 || (code & 0x80) == 0x80)
587 return "DTE Originated";
589 return "Local Procedure Error";
591 return "Network Congestion";
593 return "Network Operational";
595 return "Registration/cancellation confirmed";
597 sprintf(buffer, "Unknown %02X", code);
602 static char *registration_code(unsigned char code)
604 static char buffer[25];
607 return "Invalid facility request";
609 return "Network congestion";
611 return "Local procedure error";
613 return "Registration/cancellation confirmed";
615 sprintf(buffer, "Unknown %02X", code);
621 dump_facilities(proto_tree *tree, int *offset, tvbuff_t *tvb)
623 guint8 fac, byte1, byte2, byte3;
624 guint32 len; /* facilities length */
626 proto_tree *fac_tree = 0;
627 proto_tree *fac_subtree;
629 len = tvb_get_guint8(tvb, *offset);
631 ti = proto_tree_add_text(tree, tvb, *offset, len + 1,
633 fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
634 proto_tree_add_text(fac_tree, tvb, *offset, 1,
635 "Facilities length: %d", len);
640 fac = tvb_get_guint8(tvb, *offset);
641 switch(fac & X25_FAC_CLASS_MASK) {
642 case X25_FAC_CLASS_A:
644 case X25_FAC_COMP_MARK:
646 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
647 "Code : 00 (Marker)");
648 switch (tvb_get_guint8(tvb, *offset + 1)) {
651 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
652 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
653 "Parameter : 00 (Network complementary "
654 "services - calling DTE)");
659 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
660 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
661 "Parameter : FF (Network complementary "
662 "services - called DTE)");
667 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
668 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
669 "Parameter : 0F (DTE complementary "
675 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
676 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
677 "Parameter : %02X (Unknown marker)",
678 tvb_get_guint8(tvb, *offset+1));
683 case X25_FAC_REVERSE:
685 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
686 "(Reverse charging / Fast select)", fac);
687 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
688 byte1 = tvb_get_guint8(tvb, *offset + 1);
689 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
690 "Parameter : %02X", byte1);
692 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
693 "11.. .... = Fast select with restriction");
694 else if (byte1 & 0x80)
695 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
696 "10.. .... = Fast select - no restriction");
698 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
699 "00.. .... = Fast select not requested");
700 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
701 decode_boolean_bitfield(byte1, 0x01, 1*8,
702 "Reverse charging requested",
703 "Reverse charging not requested"));
706 case X25_FAC_THROUGHPUT:
710 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
711 "(Throughput class negociation)", fac);
712 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
713 byte1 = tvb_get_guint8(tvb, *offset + 1);
725 sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
726 75*(1<<((byte1 >> 4)-3)));
729 sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
732 sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
735 sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
737 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
738 decode_numeric_bitfield(byte1, 0xF0, 1*8, tmpbuf));
739 switch (byte1 & 0x0F)
750 sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
751 75*(1<<((byte1 & 0x0F)-3)));
754 sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
757 sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
760 sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
762 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
763 decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
768 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
769 "(Closed user group selection)", fac);
770 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
771 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
772 "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
775 case X25_FAC_CALLED_MODIF:
777 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
778 "(Called address modified)", fac);
779 fac_subtree = proto_item_add_subtree(ti,
780 ett_x25_fac_called_modif);
781 proto_tree_add_text(fac_tree, tvb, *offset+1, 1,
782 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
785 case X25_FAC_CUG_OUTGOING_ACC:
787 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
788 "(Closed user group with outgoing access selection)",
790 fac_subtree = proto_item_add_subtree(ti,
791 ett_x25_fac_cug_outgoing_acc);
792 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
793 "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
796 case X25_FAC_THROUGHPUT_MIN:
798 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
799 "(Minimum throughput class)", fac);
800 fac_subtree = proto_item_add_subtree(ti,
801 ett_x25_fac_throughput_min);
802 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
803 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
806 case X25_FAC_EXPRESS_DATA:
808 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
809 "(Negociation of express data)", fac);
810 fac_subtree = proto_item_add_subtree(ti,
811 ett_x25_fac_express_data);
812 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
813 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
818 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
819 "Code : %02X (Unknown class A)", fac);
820 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
821 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
822 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
829 case X25_FAC_CLASS_B:
831 case X25_FAC_BILATERAL_CUG:
833 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
834 "(Bilateral closed user group selection)", fac);
835 fac_subtree = proto_item_add_subtree(ti,
836 ett_x25_fac_bilateral_cug);
837 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
838 "Bilateral CUG: %04X",
839 tvb_get_ntohs(tvb, *offset+1));
842 case X25_FAC_PACKET_SIZE:
847 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
848 "(Packet size)", fac);
849 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
850 byte1 = tvb_get_guint8(tvb, *offset + 1);
854 sprintf(tmpbuf, "From the called DTE : %%u (16)");
857 sprintf(tmpbuf, "From the called DTE : %%u (32)");
860 sprintf(tmpbuf, "From the called DTE : %%u (64)");
863 sprintf(tmpbuf, "From the called DTE : %%u (128)");
866 sprintf(tmpbuf, "From the called DTE : %%u (256)");
869 sprintf(tmpbuf, "From the called DTE : %%u (512)");
872 sprintf(tmpbuf, "From the called DTE : %%u (1024)");
875 sprintf(tmpbuf, "From the called DTE : %%u (2048)");
878 sprintf(tmpbuf, "From the called DTE : %%u (4096)");
881 sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
884 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
885 decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
887 byte2 = tvb_get_guint8(tvb, *offset + 1);
891 sprintf(tmpbuf, "From the calling DTE : %%u (16)");
894 sprintf(tmpbuf, "From the calling DTE : %%u (32)");
897 sprintf(tmpbuf, "From the calling DTE : %%u (64)");
900 sprintf(tmpbuf, "From the calling DTE : %%u (128)");
903 sprintf(tmpbuf, "From the calling DTE : %%u (256)");
906 sprintf(tmpbuf, "From the calling DTE : %%u (512)");
909 sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
912 sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
915 sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
918 sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
921 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
922 decode_numeric_bitfield(byte2, 0x0F, 1*8, tmpbuf));
925 case X25_FAC_WINDOW_SIZE:
927 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
928 "(Window size)", fac);
929 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
930 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
931 decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+1),
932 0x7F, 1*8, "From the called DTE: %u"));
933 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
934 decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+2),
935 0x7F, 1*8, "From the calling DTE: %u"));
938 case X25_FAC_RPOA_SELECTION:
940 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
941 "(RPOA selection)", fac);
942 fac_subtree = proto_item_add_subtree(ti,
943 ett_x25_fac_rpoa_selection);
944 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
945 "Data network identification code : %04X",
946 tvb_get_ntohs(tvb, *offset+1));
949 case X25_FAC_TRANSIT_DELAY:
951 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
952 "(Transit delay selection and indication)", fac);
953 fac_subtree = proto_item_add_subtree(ti,
954 ett_x25_fac_transit_delay);
955 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
956 "Transit delay: %d ms",
957 tvb_get_ntohs(tvb, *offset+1));
962 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
963 "Code : %02X (Unknown class B)", fac);
964 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
965 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
966 "Parameter %04X", tvb_get_ntohs(tvb, *offset+1));
973 case X25_FAC_CLASS_C:
975 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
976 "Code : %02X (Unknown class C)", fac);
977 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
978 proto_tree_add_text(fac_subtree, tvb, *offset+1, 3,
980 tvb_get_ntoh24(tvb, *offset+1));
985 case X25_FAC_CLASS_D:
987 case X25_FAC_CALL_TRANSFER:
992 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
993 "(Call redirection or deflection notification)", fac);
994 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
995 byte1 = tvb_get_guint8(tvb, *offset+1);
996 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
997 "Length : %u", byte1);
998 byte2 = tvb_get_guint8(tvb, *offset+2);
999 if ((byte2 & 0xC0) == 0xC0) {
1000 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1001 "Reason : call deflection by the originally "
1002 "called DTE address");
1007 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1008 "Reason : originally called DTE busy");
1011 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1012 "Reason : call dist. within a hunt group");
1015 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1016 "Reason : originally called DTE out of order");
1019 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1020 "Reason : systematic call redirection");
1023 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1024 "Reason : unknown");
1028 byte3 = tvb_get_guint8(tvb, *offset+3);
1029 proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1030 "Number of semi-octets in DTE address : %u",
1032 for (i = 0; i < byte3; i++) {
1034 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1036 /* if > 9, convert to the right hexadecimal letter */
1037 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1039 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1041 /* if > 9, convert to the right hexadecimal letter */
1042 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1046 proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1047 "DTE address : %s", tmpbuf);
1050 case X25_FAC_CALLING_ADDR_EXT:
1055 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1056 "(Calling address extension)", fac);
1057 fac_subtree = proto_item_add_subtree(ti,
1058 ett_x25_fac_calling_addr_ext);
1059 byte1 = tvb_get_guint8(tvb, *offset+1);
1060 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1061 "Length : %u", byte1);
1062 byte2 = tvb_get_guint8(tvb, *offset+2);
1063 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1064 "Number of semi-octets in DTE address : %u", byte2);
1065 for (i = 0; i < byte2; i++) {
1067 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1069 /* if > 9, convert to the right hexadecimal letter */
1070 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1072 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1074 /* if > 9, convert to the right hexadecimal letter */
1075 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1079 proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1080 "DTE address : %s", tmpbuf);
1083 case X25_FAC_CALLED_ADDR_EXT:
1088 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1089 "(Called address extension)", fac);
1090 fac_subtree = proto_item_add_subtree(ti,
1091 ett_x25_fac_called_addr_ext);
1092 byte1 = tvb_get_guint8(tvb, *offset+1);
1093 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1094 "Length : %u", byte1);
1095 byte2 = tvb_get_guint8(tvb, *offset+2);
1096 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1097 "Number of semi-octets in DTE address : %u", byte2);
1098 for (i = 0; i < byte2; i++) {
1100 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1102 /* if > 9, convert to the right hexadecimal letter */
1103 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1105 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1107 /* if > 9, convert to the right hexadecimal letter */
1108 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1112 proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1113 "DTE address : %s", tmpbuf);
1116 case X25_FAC_ETE_TRANSIT_DELAY:
1118 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1119 "(End to end transit delay)", fac);
1120 fac_subtree = proto_item_add_subtree(ti,
1121 ett_x25_fac_ete_transit_delay);
1122 byte1 = tvb_get_guint8(tvb, *offset+1);
1123 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1124 "Length : %u", byte1);
1125 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1128 case X25_FAC_CALL_DEFLECT:
1133 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1134 "(Call deflection selection)", fac);
1135 fac_subtree = proto_item_add_subtree(ti,
1136 ett_x25_fac_call_deflect);
1137 byte1 = tvb_get_guint8(tvb, *offset+1);
1138 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1139 "Length : %u", byte1);
1140 byte2 = tvb_get_guint8(tvb, *offset+2);
1141 if ((byte2 & 0xC0) == 0xC0)
1142 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1143 "Reason : call DTE originated");
1145 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1146 "Reason : unknown");
1147 byte3 = tvb_get_guint8(tvb, *offset+3);
1148 proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1149 "Number of semi-octets in the alternative DTE address : %u",
1151 for (i = 0; i < byte3; i++) {
1153 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1155 /* if > 9, convert to the right hexadecimal letter */
1156 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1158 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1160 /* if > 9, convert to the right hexadecimal letter */
1161 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1165 proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1166 "Alternative DTE address : %s", tmpbuf);
1169 case X25_FAC_PRIORITY:
1171 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1172 "Code : %02X (Priority)", fac);
1173 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
1174 byte1 = tvb_get_guint8(tvb, *offset+1);
1175 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1176 "Length : %u", byte1);
1177 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1182 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1183 "Code : %02X (Unknown class D)", fac);
1184 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1185 byte1 = tvb_get_guint8(tvb, *offset+1);
1186 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1187 "Length : %u", byte1);
1188 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1191 byte1 = tvb_get_guint8(tvb, *offset+1);
1192 (*offset) += byte1+2;
1200 x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1201 frame_data *fd, gboolean toa)
1205 char addr1[16], addr2[16];
1206 char *first, *second;
1210 byte = tvb_get_guint8(tvb, *offset);
1211 len1 = (byte >> 4) & 0x0F;
1212 len2 = (byte >> 0) & 0x0F;
1214 proto_tree_add_text(tree, tvb, *offset, 1,
1215 decode_numeric_bitfield(byte, 0xF0, 1*8,
1216 toa ? "Called address length : %u" :
1217 "Calling address length : %u"));
1218 proto_tree_add_text(tree, tvb, *offset, 1,
1219 decode_numeric_bitfield(byte, 0x0F, 1*8,
1220 toa ? "Calling address length : %u" :
1221 "Called address length : %u"));
1225 localoffset = *offset;
1226 byte = tvb_get_guint8(tvb, localoffset);
1230 for (i = 0; i < (len1 + len2); i++) {
1233 *first++ = ((byte >> 0) & 0x0F) + '0';
1235 byte = tvb_get_guint8(tvb, localoffset);
1237 *first++ = ((byte >> 4) & 0x0F) + '0';
1241 *second++ = ((byte >> 0) & 0x0F) + '0';
1243 byte = tvb_get_guint8(tvb, localoffset);
1245 *second++ = ((byte >> 4) & 0x0F) + '0';
1255 if (check_col(fd, COL_RES_DL_DST))
1256 col_add_str(fd, COL_RES_DL_DST, addr1);
1259 if(check_col(fd, COL_RES_DL_SRC))
1260 col_add_str(fd, COL_RES_DL_SRC, addr1);
1263 proto_tree_add_text(tree, tvb, *offset,
1266 toa ? "Called" : "Calling",
1271 if (check_col(fd, COL_RES_DL_SRC))
1272 col_add_str(fd, COL_RES_DL_SRC, addr2);
1275 if(check_col(fd, COL_RES_DL_DST))
1276 col_add_str(fd, COL_RES_DL_DST, addr2);
1279 proto_tree_add_text(tree, tvb, *offset + len1/2,
1280 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1282 toa ? "Calling" : "Called",
1285 (*offset) += ((len1 + len2 + 1) / 2);
1289 get_x25_pkt_len(tvbuff_t *tvb)
1291 guint length, called_len, calling_len, dte_len, dce_len;
1292 guint8 byte2, bytex;
1294 byte2 = tvb_get_guint8(tvb, 2);
1297 case X25_CALL_REQUEST:
1298 bytex = tvb_get_guint8(tvb, 3);
1299 called_len = (bytex >> 0) & 0x0F;
1300 calling_len = (bytex >> 4) & 0x0F;
1301 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1302 if (length < tvb_reported_length(tvb))
1303 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1305 return MIN(tvb_reported_length(tvb),length);
1307 case X25_CALL_ACCEPTED:
1308 bytex = tvb_get_guint8(tvb, 3);
1309 called_len = (bytex >> 0) & 0x0F;
1310 calling_len = (bytex >> 4) & 0x0F;
1311 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1312 if (length < tvb_reported_length(tvb))
1313 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1315 return MIN(tvb_reported_length(tvb),length);
1317 case X25_CLEAR_REQUEST:
1318 case X25_RESET_REQUEST:
1319 case X25_RESTART_REQUEST:
1320 return MIN(tvb_reported_length(tvb),5);
1322 case X25_DIAGNOSTIC:
1323 return MIN(tvb_reported_length(tvb),4);
1325 case X25_CLEAR_CONFIRMATION:
1327 case X25_INTERRUPT_CONFIRMATION:
1328 case X25_RESET_CONFIRMATION:
1329 case X25_RESTART_CONFIRMATION:
1330 return MIN(tvb_reported_length(tvb),3);
1332 case X25_REGISTRATION_REQUEST:
1333 bytex = tvb_get_guint8(tvb, 3);
1334 dce_len = (bytex >> 0) & 0x0F;
1335 dte_len = (bytex >> 4) & 0x0F;
1336 length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1337 if (length < tvb_reported_length(tvb))
1338 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1340 return MIN(tvb_reported_length(tvb),length);
1342 case X25_REGISTRATION_CONFIRMATION:
1343 bytex = tvb_get_guint8(tvb, 5);
1344 dce_len = (bytex >> 0) & 0x0F;
1345 dte_len = (bytex >> 4) & 0x0F;
1346 length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1347 if (length < tvb_reported_length(tvb))
1348 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1350 return MIN(tvb_reported_length(tvb),length);
1353 if ((byte2 & 0x01) == X25_DATA) return MIN(tvb_reported_length(tvb),3);
1355 switch (byte2 & 0x1F)
1358 return MIN(tvb_reported_length(tvb),3);
1361 return MIN(tvb_reported_length(tvb),3);
1364 return MIN(tvb_reported_length(tvb),3);
1370 #define PRT_ID_ISO_8073 0x01
1372 static const value_string prt_id_vals[] = {
1373 {PRT_ID_ISO_8073, "ISO 8073 COTP"},
1375 {0x03, "ISO 10732 in conjunction with ISO 8073"},
1376 {0x04, "ISO 10736 in conjunction with ISO 8602"},
1380 static const value_string sharing_strategy_vals[] = {
1381 {0x00, "No sharing"},
1386 dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1388 proto_tree *x25_tree=0, *gfi_tree=0;
1390 guint localoffset=0;
1394 dissector_handle_t dissect;
1395 gboolean toa; /* TOA/NPI address format */
1400 if (check_col(pinfo->fd, COL_PROTOCOL))
1401 col_set_str(pinfo->fd, COL_PROTOCOL, "X.25");
1403 bytes0_1 = tvb_get_ntohs(tvb, 0);
1405 modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
1406 vc = (int)(bytes0_1 & 0x0FFF);
1408 if (bytes0_1 & 0x8000) toa = TRUE;
1411 x25_pkt_len = get_x25_pkt_len(tvb);
1412 if (x25_pkt_len < 3) /* packet too short */
1414 if (check_col(pinfo->fd, COL_INFO))
1415 col_set_str(pinfo->fd, COL_INFO, "Invalid/short X.25 packet");
1417 proto_tree_add_protocol_format(tree, proto_x25, tvb, 0,
1418 tvb_length(tvb), "Invalid/short X.25 packet");
1422 pkt_type = tvb_get_guint8(tvb, 2);
1425 ti = proto_tree_add_item(tree, proto_x25, tvb, 0, x25_pkt_len, FALSE);
1426 x25_tree = proto_item_add_subtree(ti, ett_x25);
1427 ti = proto_tree_add_item(x25_tree, hf_x25_gfi, tvb, 0, 2, FALSE);
1428 gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
1429 if ((pkt_type & 0x01) == X25_DATA)
1430 proto_tree_add_boolean(gfi_tree, hf_x25_qbit, tvb, 0, 2,
1432 else if (pkt_type == X25_CALL_REQUEST ||
1433 pkt_type == X25_CALL_ACCEPTED ||
1434 pkt_type == X25_CLEAR_REQUEST ||
1435 pkt_type == X25_CLEAR_CONFIRMATION)
1436 proto_tree_add_boolean(gfi_tree, hf_x25_abit, tvb, 0, 2,
1438 if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
1439 (pkt_type & 0x01) == X25_DATA)
1440 proto_tree_add_boolean(gfi_tree, hf_x25_dbit, tvb, 0, 2,
1442 proto_tree_add_uint(gfi_tree, hf_x25_mod, tvb, 0, 2, bytes0_1);
1446 case X25_CALL_REQUEST:
1447 if (check_col(pinfo->fd, COL_INFO))
1448 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1449 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Inc. call"
1453 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb,
1455 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1457 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Incoming call"
1461 if (localoffset < x25_pkt_len) /* calling/called addresses */
1462 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1464 if (localoffset < x25_pkt_len) /* facilities */
1465 dump_facilities(x25_tree, &localoffset, tvb);
1467 if (localoffset < tvb_reported_length(tvb)) /* user data */
1472 /* Compare the first octet of the CALL REQUEST packet with
1473 various ISO 9577 NLPIDs, as per Annex A of ISO 9577. */
1474 spi = tvb_get_guint8(tvb, localoffset);
1478 * XXX - handle other NLPIDs, e.g. PPP?
1479 * See RFC 1356 for information on at least some other
1480 * ways of running other protocols atop X.25.
1483 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1484 pinfo->fd->abs_usecs, ip_handle);
1486 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1487 "X.224 secondary protocol ID: IP");
1492 if ((spi >= 0x03 && spi <= 0x82)
1493 && tvb_get_guint8(tvb, localoffset+1) == 0x01) {
1494 /* ISO 9577 claims that a SPI in that range is a
1495 length field for X.224/ISO 8073 or X.264/ISO 11570;
1496 however, some of them collide with NLPIDs such
1497 as 0x81 for ISO 8473 CLNP or ISO 8542 ESIS, so
1498 I don't know how you run those over X.25, assuming
1501 I'm also not sure what the "or" means there; it
1502 looks as if X.264 specifies the layout of a
1503 "UN TPDU" ("Use of network connection TPDU"),
1504 which specifies the transport protocol to use
1505 over this network connection, and 0x03 0x01 0x01
1506 0x00 is such a TPDU, with a length of 3, a UN
1507 field of 1 (as is required), a PRT-ID ("protocol
1508 identifier") field of 1 (X.224/ISO 8073, a/k/a
1509 COTP service), and a SHARE ("sharing strategy")
1510 field of 0 ("no sharing", which is the only one
1513 So we'll assume that's what it is, as the SPI
1514 is in the right range for a length, and the UN
1516 prt_id = tvb_get_guint8(tvb, localoffset+2);
1518 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1519 "X.264 length indicator: %u",
1521 proto_tree_add_text(x25_tree, tvb, localoffset+1, 1,
1522 "X.264 UN TPDU identifier: 0x%02X",
1523 tvb_get_guint8(tvb, localoffset+1));
1524 proto_tree_add_text(x25_tree, tvb, localoffset+2, 1,
1525 "X.264 protocol identifier: %s",
1526 val_to_str(prt_id, prt_id_vals,
1527 "Unknown (0x%02X)"));
1528 proto_tree_add_text(x25_tree, tvb, localoffset+3, 1,
1529 "X.264 sharing strategy: %s",
1530 val_to_str(tvb_get_guint8(tvb, localoffset+3),
1531 sharing_strategy_vals, "Unknown (0x%02X)"));
1534 /* XXX - dissect the variable part? */
1536 /* The length doesn't include the length octet itself. */
1537 localoffset += spi + 1;
1541 case PRT_ID_ISO_8073:
1543 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1544 pinfo->fd->abs_usecs, ositp_handle);
1553 proto_tree_add_text(x25_tree, tvb, localoffset,
1554 tvb_reported_length(tvb)-localoffset, "Data");
1556 localoffset = tvb_reported_length(tvb);
1561 case X25_CALL_ACCEPTED:
1562 if(check_col(pinfo->fd, COL_INFO))
1563 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1564 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call conn."
1568 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1569 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1571 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call connected"
1575 if (localoffset < x25_pkt_len) /* calling/called addresses */
1576 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1578 if (localoffset < x25_pkt_len) /* facilities */
1579 dump_facilities(x25_tree, &localoffset, tvb);
1581 if (localoffset < tvb_reported_length(tvb)) { /* user data */
1583 proto_tree_add_text(x25_tree, tvb, localoffset,
1584 tvb_reported_length(tvb)-localoffset, "Data");
1585 localoffset=tvb_reported_length(tvb);
1588 case X25_CLEAR_REQUEST:
1589 if(check_col(pinfo->fd, COL_INFO)) {
1590 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - %s",
1591 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear ind."
1593 vc, clear_code(tvb_get_guint8(tvb, 3)),
1594 clear_diag(tvb_get_guint8(tvb, 4)));
1596 x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1598 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1599 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb,
1600 localoffset+2, 1, X25_CLEAR_REQUEST,
1601 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear indication"
1603 proto_tree_add_text(x25_tree, tvb, 3, 1,
1604 "Cause : %s", clear_code(tvb_get_guint8(tvb, 3)));
1605 proto_tree_add_text(x25_tree, tvb, 4, 1,
1606 "Diagnostic : %s", clear_diag(tvb_get_guint8(tvb, 4)));
1608 localoffset = x25_pkt_len;
1610 case X25_CLEAR_CONFIRMATION:
1611 if(check_col(pinfo->fd, COL_INFO))
1612 col_add_fstr(pinfo->fd, COL_INFO, "Clear Conf. VC:%d", vc);
1614 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1615 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1616 X25_CLEAR_CONFIRMATION);
1618 localoffset = x25_pkt_len;
1620 if (localoffset < tvb_reported_length(tvb)) /* extended clear conf format */
1621 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1623 if (localoffset < tvb_reported_length(tvb)) /* facilities */
1624 dump_facilities(x25_tree, &localoffset, tvb);
1626 case X25_DIAGNOSTIC:
1627 if(check_col(pinfo->fd, COL_INFO)) {
1628 col_add_fstr(pinfo->fd, COL_INFO, "Diag. %d",
1629 (int)tvb_get_guint8(tvb, 3));
1632 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1634 proto_tree_add_text(x25_tree, tvb, 3, 1,
1635 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 3));
1637 localoffset = x25_pkt_len;
1640 if(check_col(pinfo->fd, COL_INFO))
1641 col_add_fstr(pinfo->fd, COL_INFO, "Interrupt VC:%d", vc);
1643 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1644 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1647 localoffset = x25_pkt_len;
1649 case X25_INTERRUPT_CONFIRMATION:
1650 if(check_col(pinfo->fd, COL_INFO))
1651 col_add_fstr(pinfo->fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
1653 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1654 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1655 X25_INTERRUPT_CONFIRMATION);
1657 localoffset = x25_pkt_len;
1659 case X25_RESET_REQUEST:
1660 if(check_col(pinfo->fd, COL_INFO)) {
1661 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
1662 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset ind."
1664 vc, reset_code(tvb_get_guint8(tvb, 3)),
1665 (int)tvb_get_guint8(tvb, 4));
1667 x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1669 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1670 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1672 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset indication"
1674 proto_tree_add_text(x25_tree, tvb, 3, 1,
1675 "Cause : %s", reset_code(tvb_get_guint8(tvb, 3)));
1676 proto_tree_add_text(x25_tree, tvb, 4, 1,
1677 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1679 localoffset = x25_pkt_len;
1681 case X25_RESET_CONFIRMATION:
1682 if(check_col(pinfo->fd, COL_INFO))
1683 col_add_fstr(pinfo->fd, COL_INFO, "Reset conf. VC:%d", vc);
1685 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1686 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1687 X25_RESET_CONFIRMATION);
1689 localoffset = x25_pkt_len;
1691 case X25_RESTART_REQUEST:
1692 if(check_col(pinfo->fd, COL_INFO)) {
1693 col_add_fstr(pinfo->fd, COL_INFO, "%s %s - Diag.:%d",
1694 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart ind."
1696 restart_code(tvb_get_guint8(tvb, 3)),
1697 (int)tvb_get_guint8(tvb, 3));
1700 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1701 X25_RESTART_REQUEST,
1702 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart indication"
1703 : "Restart request");
1704 proto_tree_add_text(x25_tree, tvb, 3, 1,
1705 "Cause : %s", restart_code(tvb_get_guint8(tvb, 3)));
1706 proto_tree_add_text(x25_tree, tvb, 4, 1,
1707 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1709 localoffset = x25_pkt_len;
1711 case X25_RESTART_CONFIRMATION:
1712 if(check_col(pinfo->fd, COL_INFO))
1713 col_set_str(pinfo->fd, COL_INFO, "Restart conf.");
1715 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1716 X25_RESTART_CONFIRMATION);
1717 localoffset = x25_pkt_len;
1719 case X25_REGISTRATION_REQUEST:
1720 if(check_col(pinfo->fd, COL_INFO))
1721 col_set_str(pinfo->fd, COL_INFO, "Registration req.");
1723 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1724 X25_REGISTRATION_REQUEST);
1726 if (localoffset < x25_pkt_len)
1727 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, FALSE);
1730 if (localoffset < x25_pkt_len)
1731 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1732 "Registration length: %d",
1733 tvb_get_guint8(tvb, localoffset) & 0x7F);
1734 if (localoffset+1 < x25_pkt_len)
1735 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1736 tvb_get_guint8(tvb, localoffset) & 0x7F,
1739 localoffset = tvb_reported_length(tvb);
1741 case X25_REGISTRATION_CONFIRMATION:
1742 if(check_col(pinfo->fd, COL_INFO))
1743 col_set_str(pinfo->fd, COL_INFO, "Registration conf.");
1745 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1746 X25_REGISTRATION_CONFIRMATION);
1747 proto_tree_add_text(x25_tree, tvb, 3, 1,
1748 "Cause: %s", registration_code(tvb_get_guint8(tvb, 3)));
1749 proto_tree_add_text(x25_tree, tvb, 4, 1,
1750 "Diagnostic: %s", registration_code(tvb_get_guint8(tvb, 4)));
1753 if (localoffset < x25_pkt_len)
1754 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, TRUE);
1757 if (localoffset < x25_pkt_len)
1758 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1759 "Registration length: %d",
1760 tvb_get_guint8(tvb, localoffset) & 0x7F);
1761 if (localoffset+1 < x25_pkt_len)
1762 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1763 tvb_get_guint8(tvb, localoffset) & 0x7F,
1766 localoffset = tvb_reported_length(tvb);
1770 if ((pkt_type & 0x01) == X25_DATA)
1772 if(check_col(pinfo->fd, COL_INFO)) {
1774 col_add_fstr(pinfo->fd, COL_INFO,
1775 "Data VC:%d P(S):%d P(R):%d %s", vc,
1776 (pkt_type >> 1) & 0x07,
1777 (pkt_type >> 5) & 0x07,
1778 ((pkt_type >> 4) & 0x01) ? " M" : "");
1780 col_add_fstr(pinfo->fd, COL_INFO,
1781 "Data VC:%d P(S):%d P(R):%d %s", vc,
1782 tvb_get_guint8(tvb, localoffset+1) >> 1,
1784 (tvb_get_guint8(tvb, localoffset+1) & 0x01) ? " M" : "");
1787 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1789 proto_tree_add_uint_hidden(x25_tree, hf_x25_type, tvb,
1790 localoffset, 1, X25_DATA);
1792 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1793 localoffset, 1, pkt_type);
1794 if (pkt_type & 0x10)
1795 proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod8, tvb,
1796 localoffset, 1, pkt_type);
1797 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod8, tvb,
1798 localoffset, 1, pkt_type);
1799 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1800 decode_boolean_bitfield(pkt_type, 0x01, 1*8,
1804 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod128, tvb,
1805 localoffset, 1, pkt_type);
1806 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod128, tvb,
1808 tvb_get_guint8(tvb, localoffset+1));
1809 if (tvb_get_guint8(tvb, localoffset+1) & 0x01)
1810 proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod128, tvb,
1812 tvb_get_guint8(tvb, localoffset+1));
1815 localoffset += (modulo == 8) ? 1 : 2;
1818 switch (pkt_type & 0x1F)
1821 if(check_col(pinfo->fd, COL_INFO)) {
1823 col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
1824 vc, (pkt_type >> 5) & 0x07);
1826 col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
1827 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1830 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1833 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1834 localoffset, 1, pkt_type);
1835 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1836 localoffset, 1, X25_RR);
1839 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1840 localoffset, 1, X25_RR);
1841 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
1842 localoffset+1, 1, FALSE);
1848 if(check_col(pinfo->fd, COL_INFO)) {
1850 col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
1851 vc, (pkt_type >> 5) & 0x07);
1853 col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
1854 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1857 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1860 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1861 localoffset, 1, pkt_type);
1862 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1863 localoffset, 1, X25_RNR);
1866 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1867 localoffset, 1, X25_RNR);
1868 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
1869 localoffset+1, 1, FALSE);
1875 if(check_col(pinfo->fd, COL_INFO)) {
1877 col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
1878 vc, (pkt_type >> 5) & 0x07);
1880 col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
1881 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1884 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1887 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1888 localoffset, 1, pkt_type);
1889 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1890 localoffset, 1, X25_REJ);
1893 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1894 localoffset, 1, X25_REJ);
1895 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
1896 localoffset+1, 1, FALSE);
1900 localoffset += (modulo == 8) ? 1 : 2;
1903 if (localoffset >= tvb_reported_length(tvb)) return;
1905 next_tvb = tvb_new_subset(tvb, localoffset, -1, -1);
1906 /* search the dissector in the hash table */
1907 if ((dissect = x25_hash_get_dissect(pinfo->fd->abs_secs, pinfo->fd->abs_usecs, vc)))
1908 call_dissector(dissect, next_tvb, pinfo, tree);
1910 /* If the Call Req. has not been captured, assume these packets carry IP */
1911 if (tvb_get_guint8(tvb, localoffset) == 0x45) {
1912 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1913 pinfo->fd->abs_usecs, ip_handle);
1914 call_dissector(ip_handle, next_tvb, pinfo, tree);
1917 dissect_data(next_tvb, 0, pinfo, tree);
1923 proto_register_x25(void)
1925 static hf_register_info hf[] = {
1927 { "GFI", "x.25.gfi", FT_UINT16, BASE_BIN, NULL, 0xF000,
1928 "General format identifier", HFILL }},
1930 { "A Bit", "x.25.a", FT_BOOLEAN, 16, NULL, 0x8000,
1931 "Address Bit", HFILL }},
1933 { "Q Bit", "x.25.q", FT_BOOLEAN, 16, NULL, 0x8000,
1934 "Qualifier Bit", HFILL }},
1936 { "D Bit", "x.25.d", FT_BOOLEAN, 16, NULL, 0x4000,
1937 "Delivery Confirmation Bit", HFILL }},
1939 { "Modulo", "x.25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1940 "Specifies whether the frame is modulo 8 or 128", HFILL }},
1942 { "Logical Channel", "x.25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
1943 "Logical Channel Number", HFILL }},
1945 { "Packet Type", "x.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1946 "Packet Type", HFILL }},
1948 { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
1949 "Packet Receive Sequence Number", HFILL }},
1950 { &hf_x25_p_r_mod128,
1951 { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
1952 "Packet Receive Sequence Number", HFILL }},
1953 { &hf_x25_mbit_mod8,
1954 { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x10,
1955 "More Bit", HFILL }},
1956 { &hf_x25_mbit_mod128,
1957 { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x01,
1958 "More Bit", HFILL }},
1960 { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
1961 "Packet Send Sequence Number", HFILL }},
1962 { &hf_x25_p_s_mod128,
1963 { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
1964 "Packet Send Sequence Number", HFILL }},
1966 static gint *ett[] = {
1970 &ett_x25_fac_unknown,
1972 &ett_x25_fac_reverse,
1973 &ett_x25_fac_throughput,
1975 &ett_x25_fac_called_modif,
1976 &ett_x25_fac_cug_outgoing_acc,
1977 &ett_x25_fac_throughput_min,
1978 &ett_x25_fac_express_data,
1979 &ett_x25_fac_bilateral_cug,
1980 &ett_x25_fac_packet_size,
1981 &ett_x25_fac_window_size,
1982 &ett_x25_fac_rpoa_selection,
1983 &ett_x25_fac_transit_delay,
1984 &ett_x25_fac_call_transfer,
1985 &ett_x25_fac_called_addr_ext,
1986 &ett_x25_fac_ete_transit_delay,
1987 &ett_x25_fac_calling_addr_ext,
1988 &ett_x25_fac_call_deflect,
1989 &ett_x25_fac_priority
1992 proto_x25 = proto_register_protocol ("X.25", "X.25", "x.25");
1993 proto_register_field_array (proto_x25, hf, array_length(hf));
1994 proto_register_subtree_array(ett, array_length(ett));
1995 register_init_routine(&reinit_x25_hashtable);
1997 register_dissector("x.25", dissect_x25, proto_x25);
2001 proto_reg_handoff_x25(void)
2004 * Get handles for the IP and OSI TP (COTP/CLTP) dissectors.
2006 ip_handle = find_dissector("ip");
2007 ositp_handle = find_dissector("ositp");
2009 dissector_add("llc.dsap", SAP_X25, dissect_x25, proto_x25);