2 * Routines for x25 packet disassembly
3 * Olivier Abad <oabad@cybercable.fr>
5 * $Id: packet-x25.c,v 1.44 2001/01/05 19:07:38 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>
42 #include "packet-x25.h"
43 #include "packet-ip.h"
44 #include "packet-osi.h"
49 #define X25_CALL_REQUEST 0x0B
50 #define X25_CALL_ACCEPTED 0x0F
51 #define X25_CLEAR_REQUEST 0x13
52 #define X25_CLEAR_CONFIRMATION 0x17
53 #define X25_INTERRUPT 0x23
54 #define X25_INTERRUPT_CONFIRMATION 0x27
55 #define X25_RESET_REQUEST 0x1B
56 #define X25_RESET_CONFIRMATION 0x1F
57 #define X25_RESTART_REQUEST 0xFB
58 #define X25_RESTART_CONFIRMATION 0xFF
59 #define X25_REGISTRATION_REQUEST 0xF3
60 #define X25_REGISTRATION_CONFIRMATION 0xF7
61 #define X25_DIAGNOSTIC 0xF1
67 #define X25_FAC_CLASS_MASK 0xC0
69 #define X25_FAC_CLASS_A 0x00
70 #define X25_FAC_CLASS_B 0x40
71 #define X25_FAC_CLASS_C 0x80
72 #define X25_FAC_CLASS_D 0xC0
74 #define X25_FAC_COMP_MARK 0x00
75 #define X25_FAC_REVERSE 0x01
76 #define X25_FAC_THROUGHPUT 0x02
77 #define X25_FAC_CUG 0x03
78 #define X25_FAC_CALLED_MODIF 0x08
79 #define X25_FAC_CUG_OUTGOING_ACC 0x09
80 #define X25_FAC_THROUGHPUT_MIN 0x0A
81 #define X25_FAC_EXPRESS_DATA 0x0B
82 #define X25_FAC_BILATERAL_CUG 0x41
83 #define X25_FAC_PACKET_SIZE 0x42
84 #define X25_FAC_WINDOW_SIZE 0x43
85 #define X25_FAC_RPOA_SELECTION 0x44
86 #define X25_FAC_TRANSIT_DELAY 0x49
87 #define X25_FAC_CALL_TRANSFER 0xC3
88 #define X25_FAC_CALLED_ADDR_EXT 0xC9
89 #define X25_FAC_ETE_TRANSIT_DELAY 0xCA
90 #define X25_FAC_CALLING_ADDR_EXT 0xCB
91 #define X25_FAC_CALL_DEFLECT 0xD1
92 #define X25_FAC_PRIORITY 0xD2
94 static int proto_x25 = -1;
95 static int hf_x25_gfi = -1;
96 static int hf_x25_abit = -1;
97 static int hf_x25_qbit = -1;
98 static int hf_x25_dbit = -1;
99 static int hf_x25_mod = -1;
100 static int hf_x25_lcn = -1;
101 static int hf_x25_type = -1;
102 static int hf_x25_p_r = -1;
103 static int hf_x25_mbit = -1;
104 static int hf_x25_p_s = -1;
105 static int proto_ex25 = -1;
106 static int hf_ex25_gfi = -1;
107 static int hf_ex25_abit = -1;
108 static int hf_ex25_qbit = -1;
109 static int hf_ex25_dbit = -1;
110 static int hf_ex25_mod = -1;
111 static int hf_ex25_lcn = -1;
112 static int hf_ex25_type = -1;
113 static int hf_ex25_p_r = -1;
114 static int hf_ex25_mbit = -1;
115 static int hf_ex25_p_s = -1;
117 static gint ett_x25 = -1;
118 static gint ett_x25_gfi = -1;
119 static gint ett_x25_fac = -1;
120 static gint ett_x25_fac_unknown = -1;
121 static gint ett_x25_fac_mark = -1;
122 static gint ett_x25_fac_reverse = -1;
123 static gint ett_x25_fac_throughput = -1;
124 static gint ett_x25_fac_cug = -1;
125 static gint ett_x25_fac_called_modif = -1;
126 static gint ett_x25_fac_cug_outgoing_acc = -1;
127 static gint ett_x25_fac_throughput_min = -1;
128 static gint ett_x25_fac_express_data = -1;
129 static gint ett_x25_fac_bilateral_cug = -1;
130 static gint ett_x25_fac_packet_size = -1;
131 static gint ett_x25_fac_window_size = -1;
132 static gint ett_x25_fac_rpoa_selection = -1;
133 static gint ett_x25_fac_transit_delay = -1;
134 static gint ett_x25_fac_call_transfer = -1;
135 static gint ett_x25_fac_called_addr_ext = -1;
136 static gint ett_x25_fac_ete_transit_delay = -1;
137 static gint ett_x25_fac_calling_addr_ext = -1;
138 static gint ett_x25_fac_call_deflect = -1;
139 static gint ett_x25_fac_priority = -1;
141 static const value_string vals_modulo[] = {
147 static const value_string vals_x25_type[] = {
148 { X25_CALL_REQUEST, "Call" },
149 { X25_CALL_ACCEPTED, "Call Accepted" },
150 { X25_CLEAR_REQUEST, "Clear" },
151 { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
152 { X25_INTERRUPT, "Interrupt" },
153 { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
154 { X25_RESET_REQUEST, "Reset" },
155 { X25_RESET_CONFIRMATION, "Reset Confirmation" },
156 { X25_RESTART_REQUEST, "Restart" },
157 { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
158 { X25_REGISTRATION_REQUEST, "Registration" },
159 { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
160 { X25_DIAGNOSTIC, "Diagnostic" },
164 { X25_DATA, "DATA" },
168 static dissector_handle_t ip_handle;
169 static dissector_handle_t ositp_handle;
172 * each vc_info node contains :
173 * the time of the first frame using this dissector (secs and usecs)
174 * the time of the last frame using this dissector (0 if it is unknown)
175 * a pointer to the dissector
177 * the "time of first frame" is initialized when a Call Req. is received
178 * the "time of last frame" is initialized when a Clear, Reset, or Restart
181 typedef struct _vc_info {
182 guint32 first_frame_secs, first_frame_usecs;
183 guint32 last_frame_secs, last_frame_usecs;
184 dissector_handle_t dissect;
185 struct _vc_info *next;
189 * the hash table will contain linked lists of global_vc_info
190 * each global_vc_info struct contains :
191 * the VC number (the hash table is indexed with VC % 64)
192 * a linked list of vc_info
194 typedef struct _global_vc_info {
197 struct _global_vc_info *next;
200 static global_vc_info *hash_table[64];
203 free_vc_info(vc_info *pt)
215 reinit_x25_hashtable(void)
219 for (i=0; i<64; i++) {
220 if (hash_table[i]) /* not NULL ==> free */
222 global_vc_info *hash_ent, *hash_ent2;
223 hash_ent2 = hash_ent = hash_table[i];
226 hash_ent2 = hash_ent;
227 hash_ent = hash_ent->next;
228 free_vc_info(hash_ent2->info);
237 x25_hash_add_proto_start(guint16 vc, guint32 frame_secs, guint32 frame_usecs,
238 dissector_handle_t dissect)
241 global_vc_info *hash_ent;
242 global_vc_info *hash_ent2;
244 if (hash_table[idx] == 0)
246 hash_ent = (global_vc_info *)g_malloc(sizeof(global_vc_info));
248 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
251 hash_ent->vc_num = vc;
253 hash_ent->info = (vc_info *)g_malloc(sizeof(vc_info));
254 if (!hash_ent->info) {
255 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
258 hash_ent->info->first_frame_secs = frame_secs;
259 hash_ent->info->first_frame_usecs = frame_usecs;
260 hash_ent->info->last_frame_secs = 0;
261 hash_ent->info->last_frame_usecs = 0;
262 hash_ent->info->dissect = dissect;
263 hash_ent->info->next = 0;
264 hash_table[idx] = hash_ent;
268 hash_ent2 = hash_ent = hash_table[idx];
269 /* search an entry with the same VC number */
270 while (hash_ent != NULL && hash_ent->vc_num != vc) {
271 hash_ent2 = hash_ent;
272 hash_ent = hash_ent->next;
274 if (hash_ent != NULL) /* hash_ent->vc_num == vc */
276 vc_info *vci = hash_ent->info;
277 while (vci->next) vci = vci->next; /* last element */
278 if (vci->dissect == dissect) {
279 vci->last_frame_secs = 0;
280 vci->last_frame_usecs = 0;
283 vci->next = (vc_info *)g_malloc(sizeof(vc_info));
284 if (vci->next == 0) {
285 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
288 vci->next->first_frame_secs = frame_secs;
289 vci->next->first_frame_usecs = frame_usecs;
290 vci->next->last_frame_secs = 0;
291 vci->next->last_frame_usecs = 0;
292 vci->next->dissect = dissect;
296 else /* new vc number */
298 hash_ent2->next = (global_vc_info *)g_malloc(sizeof(global_vc_info));
299 if (!hash_ent2->next) {
300 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
303 hash_ent2->next->info = (vc_info *)g_malloc(sizeof(vc_info));
304 if (!hash_ent2->next->info) {
305 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
308 hash_ent2->next->info->first_frame_secs = frame_secs;
309 hash_ent2->next->info->first_frame_usecs = frame_usecs;
310 hash_ent2->next->info->last_frame_secs = 0;
311 hash_ent2->next->info->last_frame_usecs = 0;
312 hash_ent2->next->info->dissect = dissect;
313 hash_ent2->next->info->next = 0;
319 x25_hash_add_proto_end(guint16 vc, guint32 frame_secs, guint32 frame_usecs)
321 global_vc_info *hash_ent = hash_table[vc%64];
324 if (!hash_ent) return;
325 while(hash_ent->vc_num != vc) hash_ent = hash_ent->next;
326 if (!hash_ent) return;
328 vci = hash_ent->info;
329 while (vci->next) vci = vci->next;
330 vci->last_frame_secs = frame_secs;
331 vci->last_frame_usecs = frame_usecs;
334 static dissector_handle_t
335 x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc)
337 global_vc_info *hash_ent = hash_table[vc%64];
341 if (!hash_ent) return 0;
343 while(hash_ent && hash_ent->vc_num != vc) hash_ent = hash_ent->next;
344 if (!hash_ent) return 0;
346 /* a hash_ent was found for this VC number */
347 vci2 = vci = hash_ent->info;
349 /* looking for an entry matching our frame time */
350 while (vci && (vci->last_frame_secs < frame_secs ||
351 (vci->last_frame_secs == frame_secs &&
352 vci->last_frame_usecs < frame_usecs))) {
356 /* we reached last record, and previous record has a non zero
357 * last frame time ==> no dissector */
358 if (!vci && (vci2->last_frame_secs || vci2->last_frame_usecs)) return 0;
360 /* we reached last record, and previous record has a zero last frame time
361 * ==> dissector for previous frame has not been "stopped" by a Clear, etc */
363 /* if the start time for vci2 is greater than our frame time
364 * ==> no dissector */
365 if (frame_secs < vci2->first_frame_secs ||
366 (frame_secs == vci2->first_frame_secs &&
367 frame_usecs < vci2->first_frame_usecs))
370 return vci2->dissect;
373 /* our frame time is before vci's end. Check if it is adter vci's start */
374 if (frame_secs < vci->first_frame_secs ||
375 (frame_secs == vci->first_frame_secs &&
376 frame_usecs < vci->first_frame_usecs))
382 static char *clear_code(unsigned char code)
384 static char buffer[25];
386 if (code == 0x00 || (code & 0x80) == 0x80)
387 return "DTE Originated";
389 return "Number Busy";
391 return "Out Of Order";
393 return "Remote Procedure Error";
395 return "Reverse Charging Acceptance Not Subscribed";
397 return "Incompatible Destination";
399 return "Fast Select Acceptance Not Subscribed";
401 return "Destination Absent";
403 return "Invalid Facility Requested";
405 return "Access Barred";
407 return "Local Procedure Error";
409 return "Network Congestion";
411 return "Not Obtainable";
413 return "RPOA Out Of Order";
415 sprintf(buffer, "Unknown %02X", code);
420 static char *clear_diag(unsigned char code)
422 static char buffer[25];
425 return "No additional information";
427 return "Invalid P(S)";
429 return "Invalid P(R)";
431 return "Packet type invalid";
433 return "Packet type invalid for state r1";
435 return "Packet type invalid for state r2";
437 return "Packet type invalid for state r3";
439 return "Packet type invalid for state p1";
441 return "Packet type invalid for state p2";
443 return "Packet type invalid for state p3";
445 return "Packet type invalid for state p4";
447 return "Packet type invalid for state p5";
449 return "Packet type invalid for state p6";
451 return "Packet type invalid for state p7";
453 return "Packet type invalid for state d1";
455 return "Packet type invalid for state d2";
457 return "Packet type invalid for state d3";
459 return "Packet not allowed";
461 return "Unidentifiable packet";
463 return "Call on one-way logical channel";
465 return "Invalid packet type on a PVC";
467 return "Packet on unassigned LC";
469 return "Reject not subscribed to";
471 return "Packet too short";
473 return "Packet too long";
475 return "Invalid general format identifier";
477 return "Restart/registration packet with nonzero bits";
479 return "Packet type not compatible with facility";
481 return "Unauthorised interrupt confirmation";
483 return "Unauthorised interrupt";
485 return "Unauthorised reject";
487 return "Time expired";
489 return "Time expired for incoming call";
491 return "Time expired for clear indication";
493 return "Time expired for reset indication";
495 return "Time expired for restart indication";
497 return "Time expired for call deflection";
499 return "Call set-up/clearing or registration pb.";
501 return "Facility/registration code not allowed";
503 return "Facility parameter not allowed";
505 return "Invalid called DTE address";
507 return "Invalid calling DTE address";
509 return "Invalid facility/registration length";
511 return "Incoming call barred";
513 return "No logical channel available";
515 return "Call collision";
517 return "Duplicate facility requested";
519 return "Non zero address length";
521 return "Non zero facility length";
523 return "Facility not provided when expected";
525 return "Invalid CCITT-specified DTE facility";
527 return "Max. nb of call redir/defl. exceeded";
529 return "Miscellaneous";
531 return "Improper cause code from DTE";
533 return "Not aligned octet";
535 return "Inconsistent Q bit setting";
537 return "NUI problem";
539 return "International problem";
541 return "Remote network problem";
543 return "International protocol problem";
545 return "International link out of order";
547 return "International link busy";
549 return "Transit network facility problem";
551 return "Remote network facility problem";
553 return "International routing problem";
555 return "Temporary routing problem";
557 return "Unknown called DNIC";
559 return "Maintenance action";
561 sprintf(buffer, "Unknown %d", code);
566 static char *reset_code(unsigned char code)
568 static char buffer[25];
570 if (code == 0x00 || (code & 0x80) == 0x80)
571 return "DTE Originated";
573 return "Out of order";
575 return "Remote Procedure Error";
577 return "Local Procedure Error";
579 return "Network Congestion";
581 return "Remote DTE operational";
583 return "Network operational";
585 return "Incompatible Destination";
587 return "Network out of order";
589 sprintf(buffer, "Unknown %02X", code);
594 static char *restart_code(unsigned char code)
596 static char buffer[25];
598 if (code == 0x00 || (code & 0x80) == 0x80)
599 return "DTE Originated";
601 return "Local Procedure Error";
603 return "Network Congestion";
605 return "Network Operational";
607 return "Registration/cancellation confirmed";
609 sprintf(buffer, "Unknown %02X", code);
614 static char *registration_code(unsigned char code)
616 static char buffer[25];
619 return "Invalid facility request";
621 return "Network congestion";
623 return "Local procedure error";
625 return "Registration/cancellation confirmed";
627 sprintf(buffer, "Unknown %02X", code);
633 dump_facilities(proto_tree *tree, int *offset, tvbuff_t *tvb)
635 guint8 fac, byte1, byte2, byte3;
636 guint32 len; /* facilities length */
638 proto_tree *fac_tree = 0;
639 proto_tree *fac_subtree;
641 len = tvb_get_guint8(tvb, *offset);
643 ti = proto_tree_add_text(tree, tvb, *offset, len + 1,
645 fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
646 proto_tree_add_text(fac_tree, tvb, *offset, 1,
647 "Facilities length: %d", len);
652 fac = tvb_get_guint8(tvb, *offset);
653 switch(fac & X25_FAC_CLASS_MASK) {
654 case X25_FAC_CLASS_A:
656 case X25_FAC_COMP_MARK:
658 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
659 "Code : 00 (Marker)");
660 switch (tvb_get_guint8(tvb, *offset + 1)) {
663 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
664 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
665 "Parameter : 00 (Network complementary "
666 "services - calling DTE)");
671 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
672 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
673 "Parameter : FF (Network complementary "
674 "services - called DTE)");
679 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
680 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
681 "Parameter : 0F (DTE complementary "
687 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
688 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
689 "Parameter : %02X (Unknown marker)",
690 tvb_get_guint8(tvb, *offset+1));
695 case X25_FAC_REVERSE:
697 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
698 "(Reverse charging / Fast select)", fac);
699 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
700 byte1 = tvb_get_guint8(tvb, *offset + 1);
701 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
702 "Parameter : %02X", byte1);
704 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
705 "11.. .... = Fast select with restriction");
706 else if (byte1 & 0x80)
707 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
708 "10.. .... = Fast select - no restriction");
710 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
711 "00.. .... = Fast select not requested");
712 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
713 decode_boolean_bitfield(byte1, 0x01, 1*8,
714 "Reverse charging requested",
715 "Reverse charging not requested"));
718 case X25_FAC_THROUGHPUT:
722 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
723 "(Throughput class negociation)", fac);
724 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
725 byte1 = tvb_get_guint8(tvb, *offset + 1);
737 sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
738 75*(1<<((byte1 >> 4)-3)));
741 sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
744 sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
747 sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
749 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
750 decode_numeric_bitfield(byte1, 0xF0, 1*8, tmpbuf));
751 switch (byte1 & 0x0F)
762 sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
763 75*(1<<((byte1 & 0x0F)-3)));
766 sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
769 sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
772 sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
774 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
775 decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
780 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
781 "(Closed user group selection)", fac);
782 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
783 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
784 "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
787 case X25_FAC_CALLED_MODIF:
789 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
790 "(Called address modified)", fac);
791 fac_subtree = proto_item_add_subtree(ti,
792 ett_x25_fac_called_modif);
793 proto_tree_add_text(fac_tree, tvb, *offset+1, 1,
794 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
797 case X25_FAC_CUG_OUTGOING_ACC:
799 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
800 "(Closed user group with outgoing access selection)",
802 fac_subtree = proto_item_add_subtree(ti,
803 ett_x25_fac_cug_outgoing_acc);
804 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
805 "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
808 case X25_FAC_THROUGHPUT_MIN:
810 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
811 "(Minimum throughput class)", fac);
812 fac_subtree = proto_item_add_subtree(ti,
813 ett_x25_fac_throughput_min);
814 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
815 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
818 case X25_FAC_EXPRESS_DATA:
820 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
821 "(Negociation of express data)", fac);
822 fac_subtree = proto_item_add_subtree(ti,
823 ett_x25_fac_express_data);
824 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
825 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
830 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
831 "Code : %02X (Unknown class A)", fac);
832 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
833 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
834 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
841 case X25_FAC_CLASS_B:
843 case X25_FAC_BILATERAL_CUG:
845 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
846 "(Bilateral closed user group selection)", fac);
847 fac_subtree = proto_item_add_subtree(ti,
848 ett_x25_fac_bilateral_cug);
849 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
850 "Bilateral CUG: %04X",
851 tvb_get_ntohs(tvb, *offset+1));
854 case X25_FAC_PACKET_SIZE:
859 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
860 "(Packet size)", fac);
861 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
862 byte1 = tvb_get_guint8(tvb, *offset + 1);
866 sprintf(tmpbuf, "From the called DTE : %%u (16)");
869 sprintf(tmpbuf, "From the called DTE : %%u (32)");
872 sprintf(tmpbuf, "From the called DTE : %%u (64)");
875 sprintf(tmpbuf, "From the called DTE : %%u (128)");
878 sprintf(tmpbuf, "From the called DTE : %%u (256)");
881 sprintf(tmpbuf, "From the called DTE : %%u (512)");
884 sprintf(tmpbuf, "From the called DTE : %%u (1024)");
887 sprintf(tmpbuf, "From the called DTE : %%u (2048)");
890 sprintf(tmpbuf, "From the called DTE : %%u (4096)");
893 sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
896 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
897 decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
899 byte2 = tvb_get_guint8(tvb, *offset + 1);
903 sprintf(tmpbuf, "From the calling DTE : %%u (16)");
906 sprintf(tmpbuf, "From the calling DTE : %%u (32)");
909 sprintf(tmpbuf, "From the calling DTE : %%u (64)");
912 sprintf(tmpbuf, "From the calling DTE : %%u (128)");
915 sprintf(tmpbuf, "From the calling DTE : %%u (256)");
918 sprintf(tmpbuf, "From the calling DTE : %%u (512)");
921 sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
924 sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
927 sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
930 sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
933 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
934 decode_numeric_bitfield(byte2, 0x0F, 1*8, tmpbuf));
937 case X25_FAC_WINDOW_SIZE:
939 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
940 "(Window size)", fac);
941 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
942 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
943 decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+1),
944 0x7F, 1*8, "From the called DTE: %u"));
945 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
946 decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+2),
947 0x7F, 1*8, "From the calling DTE: %u"));
950 case X25_FAC_RPOA_SELECTION:
952 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
953 "(RPOA selection)", fac);
954 fac_subtree = proto_item_add_subtree(ti,
955 ett_x25_fac_rpoa_selection);
956 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
957 "Data network identification code : %04X",
958 tvb_get_ntohs(tvb, *offset+1));
961 case X25_FAC_TRANSIT_DELAY:
963 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
964 "(Transit delay selection and indication)", fac);
965 fac_subtree = proto_item_add_subtree(ti,
966 ett_x25_fac_transit_delay);
967 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
968 "Transit delay: %d ms",
969 tvb_get_ntohs(tvb, *offset+1));
974 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
975 "Code : %02X (Unknown class B)", fac);
976 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
977 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
978 "Parameter %04X", tvb_get_ntohs(tvb, *offset+1));
985 case X25_FAC_CLASS_C:
987 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
988 "Code : %02X (Unknown class C)", fac);
989 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
990 proto_tree_add_text(fac_subtree, tvb, *offset+1, 3,
992 tvb_get_ntoh24(tvb, *offset+1));
997 case X25_FAC_CLASS_D:
999 case X25_FAC_CALL_TRANSFER:
1004 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1005 "(Call redirection or deflection notification)", fac);
1006 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
1007 byte1 = tvb_get_guint8(tvb, *offset+1);
1008 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1009 "Length : %u", byte1);
1010 byte2 = tvb_get_guint8(tvb, *offset+2);
1011 if ((byte2 & 0xC0) == 0xC0) {
1012 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1013 "Reason : call deflection by the originally "
1014 "called DTE address");
1019 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1020 "Reason : originally called DTE busy");
1023 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1024 "Reason : call dist. within a hunt group");
1027 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1028 "Reason : originally called DTE out of order");
1031 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1032 "Reason : systematic call redirection");
1035 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1036 "Reason : unknown");
1040 byte3 = tvb_get_guint8(tvb, *offset+3);
1041 proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1042 "Number of semi-octets in DTE address : %u",
1044 for (i = 0; i < byte3; i++) {
1046 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1048 /* if > 9, convert to the right hexadecimal letter */
1049 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1051 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1053 /* if > 9, convert to the right hexadecimal letter */
1054 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1058 proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1059 "DTE address : %s", tmpbuf);
1062 case X25_FAC_CALLING_ADDR_EXT:
1067 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1068 "(Calling address extension)", fac);
1069 fac_subtree = proto_item_add_subtree(ti,
1070 ett_x25_fac_calling_addr_ext);
1071 byte1 = tvb_get_guint8(tvb, *offset+1);
1072 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1073 "Length : %u", byte1);
1074 byte2 = tvb_get_guint8(tvb, *offset+2);
1075 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1076 "Number of semi-octets in DTE address : %u", byte2);
1077 for (i = 0; i < byte2; i++) {
1079 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1081 /* if > 9, convert to the right hexadecimal letter */
1082 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1084 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1086 /* if > 9, convert to the right hexadecimal letter */
1087 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1091 proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1092 "DTE address : %s", tmpbuf);
1095 case X25_FAC_CALLED_ADDR_EXT:
1100 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1101 "(Called address extension)", fac);
1102 fac_subtree = proto_item_add_subtree(ti,
1103 ett_x25_fac_called_addr_ext);
1104 byte1 = tvb_get_guint8(tvb, *offset+1);
1105 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1106 "Length : %u", byte1);
1107 byte2 = tvb_get_guint8(tvb, *offset+2);
1108 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1109 "Number of semi-octets in DTE address : %u", byte2);
1110 for (i = 0; i < byte2; i++) {
1112 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1114 /* if > 9, convert to the right hexadecimal letter */
1115 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1117 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1119 /* if > 9, convert to the right hexadecimal letter */
1120 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1124 proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1125 "DTE address : %s", tmpbuf);
1128 case X25_FAC_ETE_TRANSIT_DELAY:
1130 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1131 "(End to end transit delay)", fac);
1132 fac_subtree = proto_item_add_subtree(ti,
1133 ett_x25_fac_ete_transit_delay);
1134 byte1 = tvb_get_guint8(tvb, *offset+1);
1135 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1136 "Length : %u", byte1);
1137 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1140 case X25_FAC_CALL_DEFLECT:
1145 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1146 "(Call deflection selection)", fac);
1147 fac_subtree = proto_item_add_subtree(ti,
1148 ett_x25_fac_call_deflect);
1149 byte1 = tvb_get_guint8(tvb, *offset+1);
1150 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1151 "Length : %u", byte1);
1152 byte2 = tvb_get_guint8(tvb, *offset+2);
1153 if ((byte2 & 0xC0) == 0xC0)
1154 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1155 "Reason : call DTE originated");
1157 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1158 "Reason : unknown");
1159 byte3 = tvb_get_guint8(tvb, *offset+3);
1160 proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1161 "Number of semi-octets in the alternative DTE address : %u",
1163 for (i = 0; i < byte3; i++) {
1165 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1167 /* if > 9, convert to the right hexadecimal letter */
1168 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1170 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1172 /* if > 9, convert to the right hexadecimal letter */
1173 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1177 proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1178 "Alternative DTE address : %s", tmpbuf);
1181 case X25_FAC_PRIORITY:
1183 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1184 "Code : %02X (Priority)", fac);
1185 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
1186 byte1 = tvb_get_guint8(tvb, *offset+1);
1187 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1188 "Length : %u", byte1);
1189 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1194 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1195 "Code : %02X (Unknown class D)", fac);
1196 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1197 byte1 = tvb_get_guint8(tvb, *offset+1);
1198 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1199 "Length : %u", byte1);
1200 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1203 byte1 = tvb_get_guint8(tvb, *offset+1);
1204 (*offset) += byte1+2;
1212 x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1213 frame_data *fd, gboolean toa)
1217 char addr1[16], addr2[16];
1218 char *first, *second;
1222 byte = tvb_get_guint8(tvb, *offset);
1223 len1 = (byte >> 4) & 0x0F;
1224 len2 = (byte >> 0) & 0x0F;
1226 proto_tree_add_text(tree, tvb, *offset, 1,
1227 decode_numeric_bitfield(byte, 0xF0, 1*8,
1228 toa ? "Called address length : %u" :
1229 "Calling address length : %u"));
1230 proto_tree_add_text(tree, tvb, *offset, 1,
1231 decode_numeric_bitfield(byte, 0x0F, 1*8,
1232 toa ? "Calling address length : %u" :
1233 "Called address length : %u"));
1237 localoffset = *offset;
1238 byte = tvb_get_guint8(tvb, localoffset);
1242 for (i = 0; i < (len1 + len2); i++) {
1245 *first++ = ((byte >> 0) & 0x0F) + '0';
1247 byte = tvb_get_guint8(tvb, localoffset);
1249 *first++ = ((byte >> 4) & 0x0F) + '0';
1253 *second++ = ((byte >> 0) & 0x0F) + '0';
1255 byte = tvb_get_guint8(tvb, localoffset);
1257 *second++ = ((byte >> 4) & 0x0F) + '0';
1267 if (check_col(fd, COL_RES_DL_DST))
1268 col_add_str(fd, COL_RES_DL_DST, addr1);
1271 if(check_col(fd, COL_RES_DL_SRC))
1272 col_add_str(fd, COL_RES_DL_SRC, addr1);
1275 proto_tree_add_text(tree, tvb, *offset,
1278 toa ? "Called" : "Calling",
1283 if (check_col(fd, COL_RES_DL_SRC))
1284 col_add_str(fd, COL_RES_DL_SRC, addr2);
1287 if(check_col(fd, COL_RES_DL_DST))
1288 col_add_str(fd, COL_RES_DL_DST, addr2);
1291 proto_tree_add_text(tree, tvb, *offset + len1/2,
1292 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1294 toa ? "Calling" : "Called",
1297 (*offset) += ((len1 + len2 + 1) / 2);
1301 get_x25_pkt_len(tvbuff_t *tvb)
1303 int length, called_len, calling_len, dte_len, dce_len;
1304 guint8 byte2, bytex;
1306 byte2 = tvb_get_guint8(tvb, 2);
1309 case X25_CALL_REQUEST:
1310 bytex = tvb_get_guint8(tvb, 3);
1311 called_len = (bytex >> 0) & 0x0F;
1312 calling_len = (bytex >> 4) & 0x0F;
1313 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1314 if (length < tvb_reported_length(tvb))
1315 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1317 return MIN(tvb_reported_length(tvb),length);
1319 case X25_CALL_ACCEPTED:
1320 bytex = tvb_get_guint8(tvb, 3);
1321 called_len = (bytex >> 0) & 0x0F;
1322 calling_len = (bytex >> 4) & 0x0F;
1323 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1324 if (length < tvb_reported_length(tvb))
1325 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1327 return MIN(tvb_reported_length(tvb),length);
1329 case X25_CLEAR_REQUEST:
1330 case X25_RESET_REQUEST:
1331 case X25_RESTART_REQUEST:
1332 return MIN(tvb_reported_length(tvb),5);
1334 case X25_DIAGNOSTIC:
1335 return MIN(tvb_reported_length(tvb),4);
1337 case X25_CLEAR_CONFIRMATION:
1339 case X25_INTERRUPT_CONFIRMATION:
1340 case X25_RESET_CONFIRMATION:
1341 case X25_RESTART_CONFIRMATION:
1342 return MIN(tvb_reported_length(tvb),3);
1344 case X25_REGISTRATION_REQUEST:
1345 bytex = tvb_get_guint8(tvb, 3);
1346 dce_len = (bytex >> 0) & 0x0F;
1347 dte_len = (bytex >> 4) & 0x0F;
1348 length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1349 if (length < tvb_reported_length(tvb))
1350 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1352 return MIN(tvb_reported_length(tvb),length);
1354 case X25_REGISTRATION_CONFIRMATION:
1355 bytex = tvb_get_guint8(tvb, 5);
1356 dce_len = (bytex >> 0) & 0x0F;
1357 dte_len = (bytex >> 4) & 0x0F;
1358 length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1359 if (length < tvb_reported_length(tvb))
1360 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1362 return MIN(tvb_reported_length(tvb),length);
1365 if ((byte2 & 0x01) == X25_DATA) return MIN(tvb_reported_length(tvb),3);
1367 switch (byte2 & 0x1F)
1370 return MIN(tvb_reported_length(tvb),3);
1373 return MIN(tvb_reported_length(tvb),3);
1376 return MIN(tvb_reported_length(tvb),3);
1382 #define PRT_ID_ISO_8073 0x01
1384 static const value_string prt_id_vals[] = {
1385 {PRT_ID_ISO_8073, "ISO 8073 COTP"},
1387 {0x03, "ISO 10732 in conjunction with ISO 8073"},
1388 {0x04, "ISO 10736 in conjunction with ISO 8602"},
1392 static const value_string sharing_strategy_vals[] = {
1393 {0x00, "No sharing"},
1398 dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1400 proto_tree *x25_tree=0, *gfi_tree=0;
1406 dissector_handle_t dissect;
1407 gboolean toa; /* TOA/NPI address format */
1412 pinfo->current_proto = "X.25";
1414 if (check_col(pinfo->fd, COL_PROTOCOL))
1415 col_set_str(pinfo->fd, COL_PROTOCOL, "X.25");
1417 bytes0_1 = tvb_get_ntohs(tvb, 0);
1419 modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
1420 vc = (int)(bytes0_1 & 0x0FFF);
1423 CHECK_DISPLAY_AS_DATA(proto_x25, tvb, pinfo, tree);
1425 CHECK_DISPLAY_AS_DATA(proto_ex25, tvb, pinfo, tree);
1428 if (bytes0_1 & 0x8000) toa = TRUE;
1431 x25_pkt_len = get_x25_pkt_len(tvb);
1432 if (x25_pkt_len < 3) /* packet too short */
1434 if (check_col(pinfo->fd, COL_INFO))
1435 col_set_str(pinfo->fd, COL_INFO, "Invalid/short X.25 packet");
1437 proto_tree_add_protocol_format(tree,
1438 (modulo == 8 ? proto_x25 : proto_ex25), tvb, 0,
1439 tvb_length(tvb), "Invalid/short X.25 packet");
1443 pkt_type = tvb_get_guint8(tvb, 2);
1446 ti = proto_tree_add_protocol_format(tree,
1447 (modulo == 8) ? proto_x25 : proto_ex25, tvb, 0, x25_pkt_len,
1449 x25_tree = proto_item_add_subtree(ti, ett_x25);
1450 ti = proto_tree_add_item(x25_tree,
1451 (modulo == 8) ? hf_x25_gfi : hf_ex25_gfi, tvb, 0, 2, FALSE);
1452 gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
1453 if ((pkt_type & 0x01) == X25_DATA)
1454 proto_tree_add_boolean(gfi_tree,
1455 (modulo == 8) ? hf_x25_qbit : hf_ex25_qbit, tvb, 0, 2,
1457 else if (pkt_type == X25_CALL_REQUEST ||
1458 pkt_type == X25_CALL_ACCEPTED ||
1459 pkt_type == X25_CLEAR_REQUEST ||
1460 pkt_type == X25_CLEAR_CONFIRMATION)
1461 proto_tree_add_boolean(gfi_tree,
1462 (modulo == 8) ? hf_x25_abit : hf_ex25_abit, tvb, 0, 2,
1464 if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
1465 (pkt_type & 0x01) == X25_DATA)
1466 proto_tree_add_boolean(gfi_tree,
1467 (modulo == 8) ? hf_x25_dbit : hf_ex25_dbit, tvb, 0, 2,
1469 proto_tree_add_uint(gfi_tree, (modulo == 8) ? hf_x25_mod : hf_ex25_mod,
1470 tvb, 0, 2, bytes0_1);
1474 case X25_CALL_REQUEST:
1475 if (check_col(pinfo->fd, COL_INFO))
1476 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1477 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Inc. call"
1481 proto_tree_add_uint(x25_tree,
1482 (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1484 proto_tree_add_uint_format(x25_tree,
1485 (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
1487 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Incoming call"
1491 if (localoffset < x25_pkt_len) /* calling/called addresses */
1492 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1494 if (localoffset < x25_pkt_len) /* facilities */
1495 dump_facilities(x25_tree, &localoffset, tvb);
1497 if (localoffset < tvb_reported_length(tvb)) /* user data */
1502 /* Compare the first octet of the CALL REQUEST packet with
1503 various ISO 9577 NLPIDs, as per Annex A of ISO 9577. */
1504 spi = tvb_get_guint8(tvb, localoffset);
1507 /* XXX - handle other NLPIDs, e.g. PPP? */
1510 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1511 pinfo->fd->abs_usecs, ip_handle);
1513 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1514 "X.224 secondary protocol ID: IP");
1519 if ((spi >= 0x03 && spi <= 0x82)
1520 && tvb_get_guint8(tvb, localoffset+1) == 0x01) {
1521 /* ISO 9577 claims that a SPI in that range is a
1522 length field for X.224/ISO 8073 or X.264/ISO 11570;
1523 however, some of them collide with NLPIDs such
1524 as 0x81 for ISO 8473 CLNP or ISO 8542 ESIS, so
1525 I don't know how you run those over X.25, assuming
1528 I'm also not sure what the "or" means there; it
1529 looks as if X.264 specifies the layout of a
1530 "UN TPDU" ("Use of network connection TPDU"),
1531 which specifies the transport protocol to use
1532 over this network connection, and 0x03 0x01 0x01
1533 0x00 is such a TPDU, with a length of 3, a UN
1534 field of 1 (as is required), a PRT-ID ("protocol
1535 identifier") field of 1 (X.224/ISO 8073, a/k/a
1536 COTP service), and a SHARE ("sharing strategy")
1537 field of 0 ("no sharing", which is the only one
1540 So we'll assume that's what it is, as the SPI
1541 is in the right range for a length, and the UN
1543 prt_id = tvb_get_guint8(tvb, localoffset+2);
1545 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1546 "X.264 length indicator: %u",
1548 proto_tree_add_text(x25_tree, tvb, localoffset+1, 1,
1549 "X.264 UN TPDU identifier: 0x%02X",
1550 tvb_get_guint8(tvb, localoffset+1));
1551 proto_tree_add_text(x25_tree, tvb, localoffset+2, 1,
1552 "X.264 protocol identifier: %s",
1553 val_to_str(prt_id, prt_id_vals,
1554 "Unknown (0x%02X)"));
1555 proto_tree_add_text(x25_tree, tvb, localoffset+3, 1,
1556 "X.264 sharing strategy: %s",
1557 val_to_str(tvb_get_guint8(tvb, localoffset+3),
1558 sharing_strategy_vals, "Unknown (0x%02X)"));
1561 /* XXX - dissect the variable part? */
1563 /* The length doesn't include the length octet itself. */
1564 localoffset += spi + 1;
1568 case PRT_ID_ISO_8073:
1570 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1571 pinfo->fd->abs_usecs, ositp_handle);
1580 proto_tree_add_text(x25_tree, tvb, localoffset,
1581 tvb_reported_length(tvb)-localoffset, "Data");
1583 localoffset = tvb_reported_length(tvb);
1588 case X25_CALL_ACCEPTED:
1589 if(check_col(pinfo->fd, COL_INFO))
1590 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1591 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call conn."
1595 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1596 tvb, 0, 2, bytes0_1);
1597 proto_tree_add_uint_format(x25_tree,
1598 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1599 tvb, 2, 1, X25_CALL_ACCEPTED,
1600 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call connected"
1604 if (localoffset < x25_pkt_len) /* calling/called addresses */
1605 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1607 if (localoffset < x25_pkt_len) /* facilities */
1608 dump_facilities(x25_tree, &localoffset, tvb);
1610 if (localoffset < tvb_reported_length(tvb)) { /* user data */
1612 proto_tree_add_text(x25_tree, tvb, localoffset,
1613 tvb_reported_length(tvb)-localoffset, "Data");
1614 localoffset=tvb_reported_length(tvb);
1617 case X25_CLEAR_REQUEST:
1618 if(check_col(pinfo->fd, COL_INFO)) {
1619 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - %s",
1620 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear ind."
1622 vc, clear_code(tvb_get_guint8(tvb, 3)),
1623 clear_diag(tvb_get_guint8(tvb, 4)));
1625 x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1627 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1629 proto_tree_add_uint_format(x25_tree,
1630 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1631 tvb, localoffset+2, 1, X25_CLEAR_REQUEST,
1632 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear indication"
1634 proto_tree_add_text(x25_tree, tvb, 3, 1,
1635 "Cause : %s", clear_code(tvb_get_guint8(tvb, 3)));
1636 proto_tree_add_text(x25_tree, tvb, 4, 1,
1637 "Diagnostic : %s", clear_diag(tvb_get_guint8(tvb, 4)));
1639 localoffset = x25_pkt_len;
1641 case X25_CLEAR_CONFIRMATION:
1642 if(check_col(pinfo->fd, COL_INFO))
1643 col_add_fstr(pinfo->fd, COL_INFO, "Clear Conf. VC:%d", vc);
1645 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1647 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1648 2, 1, X25_CLEAR_CONFIRMATION);
1650 localoffset = x25_pkt_len;
1652 if (localoffset < tvb_reported_length(tvb)) /* extended clear conf format */
1653 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1655 if (localoffset < tvb_reported_length(tvb)) /* facilities */
1656 dump_facilities(x25_tree, &localoffset, tvb);
1658 case X25_DIAGNOSTIC:
1659 if(check_col(pinfo->fd, COL_INFO)) {
1660 col_add_fstr(pinfo->fd, COL_INFO, "Diag. %d",
1661 (int)tvb_get_guint8(tvb, 3));
1664 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1665 2, 1, X25_DIAGNOSTIC);
1666 proto_tree_add_text(x25_tree, tvb, 3, 1,
1667 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 3));
1669 localoffset = x25_pkt_len;
1672 if(check_col(pinfo->fd, COL_INFO))
1673 col_add_fstr(pinfo->fd, COL_INFO, "Interrupt VC:%d", vc);
1675 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1677 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1678 2, 1, X25_INTERRUPT);
1680 localoffset = x25_pkt_len;
1682 case X25_INTERRUPT_CONFIRMATION:
1683 if(check_col(pinfo->fd, COL_INFO))
1684 col_add_fstr(pinfo->fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
1686 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1688 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1689 2, 1, X25_INTERRUPT_CONFIRMATION);
1691 localoffset = x25_pkt_len;
1693 case X25_RESET_REQUEST:
1694 if(check_col(pinfo->fd, COL_INFO)) {
1695 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
1696 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset ind."
1698 vc, reset_code(tvb_get_guint8(tvb, 3)),
1699 (int)tvb_get_guint8(tvb, 4));
1701 x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1703 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1705 proto_tree_add_uint_format(x25_tree,
1706 (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
1708 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset indication"
1710 proto_tree_add_text(x25_tree, tvb, 3, 1,
1711 "Cause : %s", reset_code(tvb_get_guint8(tvb, 3)));
1712 proto_tree_add_text(x25_tree, tvb, 4, 1,
1713 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1715 localoffset = x25_pkt_len;
1717 case X25_RESET_CONFIRMATION:
1718 if(check_col(pinfo->fd, COL_INFO))
1719 col_add_fstr(pinfo->fd, COL_INFO, "Reset conf. VC:%d", vc);
1721 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1723 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1724 2, 1, X25_RESET_CONFIRMATION);
1726 localoffset = x25_pkt_len;
1728 case X25_RESTART_REQUEST:
1729 if(check_col(pinfo->fd, COL_INFO)) {
1730 col_add_fstr(pinfo->fd, COL_INFO, "%s %s - Diag.:%d",
1731 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart ind."
1733 restart_code(tvb_get_guint8(tvb, 3)),
1734 (int)tvb_get_guint8(tvb, 3));
1737 proto_tree_add_uint_format(x25_tree,
1738 (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
1739 X25_RESTART_REQUEST,
1740 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart indication"
1741 : "Restart request");
1742 proto_tree_add_text(x25_tree, tvb, 3, 1,
1743 "Cause : %s", restart_code(tvb_get_guint8(tvb, 3)));
1744 proto_tree_add_text(x25_tree, tvb, 4, 1,
1745 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1747 localoffset = x25_pkt_len;
1749 case X25_RESTART_CONFIRMATION:
1750 if(check_col(pinfo->fd, COL_INFO))
1751 col_set_str(pinfo->fd, COL_INFO, "Restart conf.");
1753 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1754 2, 1, X25_RESTART_CONFIRMATION);
1755 localoffset = x25_pkt_len;
1757 case X25_REGISTRATION_REQUEST:
1758 if(check_col(pinfo->fd, COL_INFO))
1759 col_set_str(pinfo->fd, COL_INFO, "Registration req.");
1761 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1762 2, 1, X25_REGISTRATION_REQUEST);
1764 if (localoffset < x25_pkt_len)
1765 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, FALSE);
1768 if (localoffset < x25_pkt_len)
1769 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1770 "Registration length: %d",
1771 tvb_get_guint8(tvb, localoffset) & 0x7F);
1772 if (localoffset+1 < x25_pkt_len)
1773 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1774 tvb_get_guint8(tvb, localoffset) & 0x7F,
1777 localoffset = tvb_reported_length(tvb);
1779 case X25_REGISTRATION_CONFIRMATION:
1780 if(check_col(pinfo->fd, COL_INFO))
1781 col_set_str(pinfo->fd, COL_INFO, "Registration conf.");
1783 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1784 2, 1, X25_REGISTRATION_CONFIRMATION);
1785 proto_tree_add_text(x25_tree, tvb, 3, 1,
1786 "Cause: %s", registration_code(tvb_get_guint8(tvb, 3)));
1787 proto_tree_add_text(x25_tree, tvb, 4, 1,
1788 "Diagnostic: %s", registration_code(tvb_get_guint8(tvb, 4)));
1791 if (localoffset < x25_pkt_len)
1792 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, TRUE);
1795 if (localoffset < x25_pkt_len)
1796 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1797 "Registration length: %d",
1798 tvb_get_guint8(tvb, localoffset) & 0x7F);
1799 if (localoffset+1 < x25_pkt_len)
1800 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1801 tvb_get_guint8(tvb, localoffset) & 0x7F,
1804 localoffset = tvb_reported_length(tvb);
1808 if ((pkt_type & 0x01) == X25_DATA)
1810 if(check_col(pinfo->fd, COL_INFO)) {
1812 col_add_fstr(pinfo->fd, COL_INFO,
1813 "Data VC:%d P(S):%d P(R):%d %s", vc,
1814 (pkt_type >> 1) & 0x07,
1815 (pkt_type >> 5) & 0x07,
1816 ((pkt_type >> 4) & 0x01) ? " M" : "");
1818 col_add_fstr(pinfo->fd, COL_INFO,
1819 "Data VC:%d P(S):%d P(R):%d %s", vc,
1820 tvb_get_guint8(tvb, localoffset+1) >> 1,
1822 (tvb_get_guint8(tvb, localoffset+1) & 0x01) ? " M" : "");
1825 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1826 tvb, localoffset-2, 2, bytes0_1);
1828 proto_tree_add_uint_hidden(x25_tree, hf_x25_type, tvb,
1829 localoffset, 1, X25_DATA);
1830 proto_tree_add_uint(x25_tree, hf_x25_p_r, tvb,
1831 localoffset, 1, pkt_type);
1832 if (pkt_type & 0x10)
1833 proto_tree_add_boolean(x25_tree, hf_x25_mbit, tvb, localoffset, 1,
1835 proto_tree_add_uint(x25_tree, hf_x25_p_s, tvb, localoffset, 1,
1837 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1838 decode_boolean_bitfield(pkt_type, 0x01, 1*8,
1842 proto_tree_add_uint_hidden(x25_tree, hf_ex25_type, tvb,
1843 localoffset, 1, X25_DATA);
1844 proto_tree_add_uint(x25_tree, hf_x25_p_r, tvb,
1845 localoffset, 1, pkt_type);
1846 proto_tree_add_uint(x25_tree, hf_x25_p_s, tvb,
1847 localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
1848 if (tvb_get_guint8(tvb, localoffset+1) & 0x01)
1849 proto_tree_add_boolean(x25_tree, hf_ex25_mbit, tvb,
1850 localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
1853 localoffset += (modulo == 8) ? 1 : 2;
1856 switch (pkt_type & 0x1F)
1859 if(check_col(pinfo->fd, COL_INFO)) {
1861 col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
1862 vc, (pkt_type >> 5) & 0x07);
1864 col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
1865 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1868 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1869 tvb, localoffset-2, 2, bytes0_1);
1871 proto_tree_add_uint(x25_tree, hf_x25_p_r, tvb,
1872 localoffset, 1, pkt_type);
1873 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1874 localoffset, 1, X25_RR);
1877 proto_tree_add_uint(x25_tree, hf_ex25_type, tvb,
1878 localoffset, 1, X25_RR);
1879 proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
1880 localoffset+1, 1, FALSE);
1886 if(check_col(pinfo->fd, COL_INFO)) {
1888 col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
1889 vc, (pkt_type >> 5) & 0x07);
1891 col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
1892 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1895 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1896 tvb, localoffset-2, 2, bytes0_1);
1898 proto_tree_add_uint(x25_tree, hf_x25_p_r, tvb,
1899 localoffset, 1, pkt_type);
1900 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1901 localoffset, 1, X25_RNR);
1904 proto_tree_add_uint(x25_tree, hf_ex25_type, tvb,
1905 localoffset, 1, X25_RNR);
1906 proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
1907 localoffset+1, 1, FALSE);
1913 if(check_col(pinfo->fd, COL_INFO)) {
1915 col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
1916 vc, (pkt_type >> 5) & 0x07);
1918 col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
1919 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1922 proto_tree_add_uint(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1923 tvb, localoffset-2, 2, bytes0_1);
1925 proto_tree_add_uint(x25_tree, hf_x25_p_r, tvb,
1926 localoffset, 1, pkt_type);
1927 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1928 localoffset, 1, X25_REJ);
1931 proto_tree_add_uint(x25_tree, hf_ex25_type, tvb,
1932 localoffset, 1, X25_REJ);
1933 proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
1934 localoffset+1, 1, FALSE);
1938 localoffset += (modulo == 8) ? 1 : 2;
1941 if (localoffset >= tvb_reported_length(tvb)) return;
1943 next_tvb = tvb_new_subset(tvb, localoffset, -1, -1);
1944 /* search the dissector in the hash table */
1945 if ((dissect = x25_hash_get_dissect(pinfo->fd->abs_secs, pinfo->fd->abs_usecs, vc)))
1946 call_dissector(dissect, next_tvb, pinfo, tree);
1948 /* If the Call Req. has not been captured, assume these packets carry IP */
1949 if (tvb_get_guint8(tvb, localoffset) == 0x45) {
1950 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1951 pinfo->fd->abs_usecs, ip_handle);
1952 call_dissector(ip_handle, next_tvb, pinfo, tree);
1955 dissect_data(next_tvb, 0, pinfo, tree);
1961 proto_register_x25(void)
1963 static hf_register_info hf8[] = {
1965 { "GFI", "x.25.gfi", FT_UINT16, BASE_BIN, NULL, 0xF000,
1966 "General format identifier" } },
1968 { "A Bit", "x.25.a", FT_BOOLEAN, 16, NULL, 0x8000,
1971 { "Q Bit", "x.25.q", FT_BOOLEAN, 16, NULL, 0x8000,
1972 "Qualifier Bit" } },
1974 { "D Bit", "x.25.d", FT_BOOLEAN, 16, NULL, 0x4000,
1975 "Delivery Confirmation Bit" } },
1977 { "Modulo", "x.25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1978 "Specifies whether the frame is modulo 8 or 128" } },
1980 { "Logical Channel", "x.25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
1981 "Logical Channel Number" } },
1983 { "Packet Type", "x.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1986 { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
1987 "Packet Receive Sequence Number" } },
1989 { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x10,
1992 { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
1993 "Packet Send Sequence Number" } },
1996 static hf_register_info hf128[] = {
1998 { "GFI", "ex.25.gfi", FT_UINT16, BASE_BIN, NULL, 0xF000,
1999 "General format identifier" } },
2001 { "A Bit", "ex.25.a", FT_BOOLEAN, 16, NULL, 0x8000,
2004 { "Q Bit", "ex.25.q", FT_BOOLEAN, 16, NULL, 0x8000,
2005 "Qualifier Bit" } },
2007 { "D Bit", "ex.25.d", FT_BOOLEAN, 16, NULL, 0x4000,
2008 "Delivery Confirmation Bit" } },
2010 { "Modulo", "ex.25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
2011 "Specifies whether the frame is modulo 8 or 128" } },
2013 { "Logical Channel", "ex.25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
2014 "Logical Channel Number" } },
2016 { "Packet Type", "ex.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
2019 { "P(R)", "ex.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
2020 "Packet Receive Sequence Number" } },
2022 { "M Bit", "ex.25.m", FT_BOOLEAN, 8, NULL, 0x01,
2025 { "P(S)", "ex.25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
2026 "Packet Send Sequence Number" } },
2028 static gint *ett[] = {
2032 &ett_x25_fac_unknown,
2034 &ett_x25_fac_reverse,
2035 &ett_x25_fac_throughput,
2037 &ett_x25_fac_called_modif,
2038 &ett_x25_fac_cug_outgoing_acc,
2039 &ett_x25_fac_throughput_min,
2040 &ett_x25_fac_express_data,
2041 &ett_x25_fac_bilateral_cug,
2042 &ett_x25_fac_packet_size,
2043 &ett_x25_fac_window_size,
2044 &ett_x25_fac_rpoa_selection,
2045 &ett_x25_fac_transit_delay,
2046 &ett_x25_fac_call_transfer,
2047 &ett_x25_fac_called_addr_ext,
2048 &ett_x25_fac_ete_transit_delay,
2049 &ett_x25_fac_calling_addr_ext,
2050 &ett_x25_fac_call_deflect,
2051 &ett_x25_fac_priority
2054 proto_x25 = proto_register_protocol ("X.25", "X.25", "x.25");
2055 proto_ex25 = proto_register_protocol ("Extended X.25 (modulo 128)",
2056 "Extended X.25", "ex.25");
2057 proto_register_field_array (proto_x25, hf8, array_length(hf8));
2058 proto_register_field_array (proto_ex25, hf128, array_length(hf128));
2059 proto_register_subtree_array(ett, array_length(ett));
2060 register_init_routine(&reinit_x25_hashtable);
2064 proto_reg_handoff_x25(void)
2067 * Get handles for the IP and OSI TP (COTP/CLTP) dissectors.
2069 ip_handle = find_dissector("ip");
2070 ositp_handle = find_dissector("ositp");
2072 dissector_add("llc.dsap", SAP_X25, dissect_x25);