2 * Routines for x25 packet disassembly
3 * Olivier Abad <abad@daba.dhis.net>
5 * $Id: packet-x25.c,v 1.28 2000/05/25 21:34:57 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>
41 #include "packet-x25.h"
42 #include "packet-ip.h"
43 #include "packet-osi.h"
44 #include "packet-clnp.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_qbit = -1;
96 static int hf_x25_dbit = -1;
97 static int hf_x25_mod = -1;
98 static int hf_x25_lcn = -1;
99 static int hf_x25_type = -1;
100 static int hf_x25_p_r = -1;
101 static int hf_x25_mbit = -1;
102 static int hf_x25_p_s = -1;
103 static int proto_ex25 = -1;
104 static int hf_ex25_qbit = -1;
105 static int hf_ex25_dbit = -1;
106 static int hf_ex25_mod = -1;
107 static int hf_ex25_lcn = -1;
108 static int hf_ex25_type = -1;
109 static int hf_ex25_p_r = -1;
110 static int hf_ex25_mbit = -1;
111 static int hf_ex25_p_s = -1;
113 static gint ett_x25 = -1;
114 static gint ett_x25_fac = -1;
115 static gint ett_x25_fac_unknown = -1;
116 static gint ett_x25_fac_mark = -1;
117 static gint ett_x25_fac_reverse = -1;
118 static gint ett_x25_fac_throughput = -1;
119 static gint ett_x25_fac_cug = -1;
120 static gint ett_x25_fac_called_modif = -1;
121 static gint ett_x25_fac_cug_outgoing_acc = -1;
122 static gint ett_x25_fac_throughput_min = -1;
123 static gint ett_x25_fac_express_data = -1;
124 static gint ett_x25_fac_bilateral_cug = -1;
125 static gint ett_x25_fac_packet_size = -1;
126 static gint ett_x25_fac_window_size = -1;
127 static gint ett_x25_fac_rpoa_selection = -1;
128 static gint ett_x25_fac_transit_delay = -1;
129 static gint ett_x25_fac_call_transfer = -1;
130 static gint ett_x25_fac_called_addr_ext = -1;
131 static gint ett_x25_fac_ete_transit_delay = -1;
132 static gint ett_x25_fac_calling_addr_ext = -1;
133 static gint ett_x25_fac_call_deflect = -1;
134 static gint ett_x25_fac_priority = -1;
136 static const value_string vals_modulo[] = {
142 static const value_string vals_x25_type[] = {
143 { X25_CALL_REQUEST, "Call" },
144 { X25_CALL_ACCEPTED, "Call Accepted" },
145 { X25_CLEAR_REQUEST, "Clear" },
146 { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
147 { X25_INTERRUPT, "Interrupt" },
148 { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
149 { X25_RESET_REQUEST, "Reset" },
150 { X25_RESET_CONFIRMATION, "Reset Confirmation" },
151 { X25_RESTART_REQUEST, "Restart" },
152 { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
153 { X25_REGISTRATION_REQUEST, "Registration" },
154 { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
155 { X25_DIAGNOSTIC, "Diagnostic" },
159 { X25_DATA, "DATA" },
164 * each vc_info node contains :
165 * the time of the first frame using this dissector (secs and usecs)
166 * the time of the last frame using this dissector (0 if it is unknown)
167 * a pointer to the dissector
169 * the "time of first frame" is initialized when a Call Req. is received
170 * the "time of last frame" is initialized when a Clear, Reset, or Restart
173 typedef struct _vc_info {
174 guint32 first_frame_secs, first_frame_usecs;
175 guint32 last_frame_secs, last_frame_usecs;
176 void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
177 struct _vc_info *next;
181 * the hash table will contain linked lists of global_vc_info
182 * each global_vc_info struct contains :
183 * the VC number (the hash table is indexed with VC % 64)
184 * a linked list of vc_info
186 typedef struct _global_vc_info {
189 struct _global_vc_info *next;
192 static global_vc_info *hash_table[64];
195 free_vc_info(vc_info *pt)
207 reinit_x25_hashtable(void)
211 for (i=0; i<64; i++) {
212 if (hash_table[i]) /* not NULL ==> free */
214 global_vc_info *hash_ent, *hash_ent2;
215 hash_ent2 = hash_ent = hash_table[i];
218 hash_ent2 = hash_ent;
219 hash_ent = hash_ent->next;
220 free_vc_info(hash_ent2->info);
229 x25_hash_add_proto_start(guint16 vc, guint32 frame_secs, guint32 frame_usecs,
230 void (*dissect)(const u_char *, int, frame_data *,
234 global_vc_info *hash_ent;
235 global_vc_info *hash_ent2;
237 if (hash_table[idx] == 0)
239 hash_ent = (global_vc_info *)g_malloc(sizeof(global_vc_info));
241 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
244 hash_ent->vc_num = vc;
246 hash_ent->info = (vc_info *)g_malloc(sizeof(vc_info));
247 if (!hash_ent->info) {
248 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
251 hash_ent->info->first_frame_secs = frame_secs;
252 hash_ent->info->first_frame_usecs = frame_usecs;
253 hash_ent->info->last_frame_secs = 0;
254 hash_ent->info->last_frame_usecs = 0;
255 hash_ent->info->dissect = dissect;
256 hash_ent->info->next = 0;
257 hash_table[idx] = hash_ent;
261 hash_ent2 = hash_ent = hash_table[idx];
262 /* search an entry with the same VC number */
263 while (hash_ent != NULL && hash_ent->vc_num != vc) {
264 hash_ent2 = hash_ent;
265 hash_ent = hash_ent->next;
267 if (hash_ent != NULL) /* hash_ent->vc_num == vc */
269 vc_info *vci = hash_ent->info;
270 while (vci->next) vci = vci->next; /* last element */
271 if (vci->dissect == dissect) {
272 vci->last_frame_secs = 0;
273 vci->last_frame_usecs = 0;
276 vci->next = (vc_info *)g_malloc(sizeof(vc_info));
277 if (vci->next == 0) {
278 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
281 vci->next->first_frame_secs = frame_secs;
282 vci->next->first_frame_usecs = frame_usecs;
283 vci->next->last_frame_secs = 0;
284 vci->next->last_frame_usecs = 0;
285 vci->next->dissect = dissect;
289 else /* new vc number */
291 hash_ent2->next = (global_vc_info *)g_malloc(sizeof(global_vc_info));
292 if (!hash_ent2->next) {
293 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
296 hash_ent2->next->info = (vc_info *)g_malloc(sizeof(vc_info));
297 if (!hash_ent2->next->info) {
298 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
301 hash_ent2->next->info->first_frame_secs = frame_secs;
302 hash_ent2->next->info->first_frame_usecs = frame_usecs;
303 hash_ent2->next->info->last_frame_secs = 0;
304 hash_ent2->next->info->last_frame_usecs = 0;
305 hash_ent2->next->info->dissect = dissect;
306 hash_ent2->next->info->next = 0;
312 x25_hash_add_proto_end(guint16 vc, guint32 frame_secs, guint32 frame_usecs)
314 global_vc_info *hash_ent = hash_table[vc%64];
317 if (!hash_ent) return;
318 while(hash_ent->vc_num != vc) hash_ent = hash_ent->next;
319 if (!hash_ent) return;
321 vci = hash_ent->info;
322 while (vci->next) vci = vci->next;
323 vci->last_frame_secs = frame_secs;
324 vci->last_frame_usecs = frame_usecs;
327 void (*x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc))(const u_char *, int, frame_data *, proto_tree *)
329 global_vc_info *hash_ent = hash_table[vc%64];
333 if (!hash_ent) return 0;
335 while(hash_ent && hash_ent->vc_num != vc) hash_ent = hash_ent->next;
336 if (!hash_ent) return 0;
338 /* a hash_ent was found for this VC number */
339 vci2 = vci = hash_ent->info;
341 /* looking for an entry matching our frame time */
342 while (vci && (vci->last_frame_secs < frame_secs ||
343 (vci->last_frame_secs == frame_secs &&
344 vci->last_frame_usecs < frame_usecs))) {
348 /* we reached last record, and previous record has a non zero
349 * last frame time ==> no dissector */
350 if (!vci && (vci2->last_frame_secs || vci2->last_frame_usecs)) return 0;
352 /* we reached last record, and previous record has a zero last frame time
353 * ==> dissector for previous frame has not been "stopped" by a Clear, etc */
355 /* if the start time for vci2 is greater than our frame time
356 * ==> no dissector */
357 if (frame_secs < vci2->first_frame_secs ||
358 (frame_secs == vci2->first_frame_secs &&
359 frame_usecs < vci2->first_frame_usecs))
362 return vci2->dissect;
365 /* our frame time is before vci's end. Check if it is adter vci's start */
366 if (frame_secs < vci->first_frame_secs ||
367 (frame_secs == vci->first_frame_secs &&
368 frame_usecs < vci->first_frame_usecs))
374 static char *clear_code(unsigned char code)
376 static char buffer[25];
378 if (code == 0x00 || (code & 0x80) == 0x80)
379 return "DTE Originated";
381 return "Number Busy";
383 return "Out Of Order";
385 return "Remote Procedure Error";
387 return "Reverse Charging Acceptance Not Subscribed";
389 return "Incompatible Destination";
391 return "Fast Select Acceptance Not Subscribed";
393 return "Destination Absent";
395 return "Invalid Facility Requested";
397 return "Access Barred";
399 return "Local Procedure Error";
401 return "Network Congestion";
403 return "Not Obtainable";
405 return "RPOA Out Of Order";
407 sprintf(buffer, "Unknown %02X", code);
412 static char *clear_diag(unsigned char code)
414 static char buffer[25];
417 return "No additional information";
419 return "Invalid P(S)";
421 return "Invalid P(R)";
423 return "Packet type invalid";
425 return "Packet type invalid for state r1";
427 return "Packet type invalid for state r2";
429 return "Packet type invalid for state r3";
431 return "Packet type invalid for state p1";
433 return "Packet type invalid for state p2";
435 return "Packet type invalid for state p3";
437 return "Packet type invalid for state p4";
439 return "Packet type invalid for state p5";
441 return "Packet type invalid for state p6";
443 return "Packet type invalid for state p7";
445 return "Packet type invalid for state d1";
447 return "Packet type invalid for state d2";
449 return "Packet type invalid for state d3";
451 return "Packet not allowed";
453 return "Unidentifiable packet";
455 return "Call on one-way logical channel";
457 return "Invalid packet type on a PVC";
459 return "Packet on unassigned LC";
461 return "Reject not subscribed to";
463 return "Packet too short";
465 return "Packet too long";
467 return "Invalid general format identifier";
469 return "Restart/registration packet with nonzero bits";
471 return "Packet type not compatible with facility";
473 return "Unauthorised interrupt confirmation";
475 return "Unauthorised interrupt";
477 return "Unauthorised reject";
479 return "Time expired";
481 return "Time expired for incoming call";
483 return "Time expired for clear indication";
485 return "Time expired for reset indication";
487 return "Time expired for restart indication";
489 return "Time expired for call deflection";
491 return "Call set-up/clearing or registration pb.";
493 return "Facility/registration code not allowed";
495 return "Facility parameter not allowed";
497 return "Invalid called DTE address";
499 return "Invalid calling DTE address";
501 return "Invalid facility/registration length";
503 return "Incoming call barred";
505 return "No logical channel available";
507 return "Call collision";
509 return "Duplicate facility requested";
511 return "Non zero address length";
513 return "Non zero facility length";
515 return "Facility not provided when expected";
517 return "Invalid CCITT-specified DTE facility";
519 return "Max. nb of call redir/defl. exceeded";
521 return "Miscellaneous";
523 return "Improper cause code from DTE";
525 return "Not aligned octet";
527 return "Inconsistent Q bit setting";
529 return "NUI problem";
531 return "International problem";
533 return "Remote network problem";
535 return "International protocol problem";
537 return "International link out of order";
539 return "International link busy";
541 return "Transit network facility problem";
543 return "Remote network facility problem";
545 return "International routing problem";
547 return "Temporary routing problem";
549 return "Unknown called DNIC";
551 return "Maintenance action";
553 sprintf(buffer, "Unknown %d", code);
558 static char *reset_code(unsigned char code)
560 static char buffer[25];
562 if (code == 0x00 || (code & 0x80) == 0x80)
563 return "DTE Originated";
565 return "Out of order";
567 return "Remote Procedure Error";
569 return "Local Procedure Error";
571 return "Network Congestion";
573 return "Remote DTE operational";
575 return "Network operational";
577 return "Incompatible Destination";
579 return "Network out of order";
581 sprintf(buffer, "Unknown %02X", code);
586 static char *restart_code(unsigned char code)
588 static char buffer[25];
590 if (code == 0x00 || (code & 0x80) == 0x80)
591 return "DTE Originated";
593 return "Local Procedure Error";
595 return "Network Congestion";
597 return "Network Operational";
599 return "Registration/cancellation confirmed";
601 sprintf(buffer, "Unknown %02X", code);
606 static char *registration_code(unsigned char code)
608 static char buffer[25];
611 return "Invalid facility request";
613 return "Network congestion";
615 return "Local procedure error";
617 return "Registration/cancellation confirmed";
619 sprintf(buffer, "Unknown %02X", code);
625 dump_facilities(proto_tree *tree, int *offset, tvbuff_t *tvb)
627 guint8 fac, byte1, byte2, byte3;
628 guint32 len; /* facilities length */
630 proto_tree *fac_tree = 0;
631 proto_tree *fac_subtree;
633 len = tvb_get_guint8(tvb, *offset);
635 ti = proto_tree_add_text(tree, tvb, *offset, len + 1,
637 fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
638 proto_tree_add_text(fac_tree, tvb, *offset, 1,
639 "Facilities length: %d", len);
644 fac = tvb_get_guint8(tvb, *offset);
645 switch(fac & X25_FAC_CLASS_MASK) {
646 case X25_FAC_CLASS_A:
648 case X25_FAC_COMP_MARK:
650 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
651 "Code : 00 (Marker)");
652 switch (tvb_get_guint8(tvb, *offset + 1)) {
655 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
656 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
657 "Parameter : 00 (Network complementary "
658 "services - calling DTE)");
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 : FF (Network complementary "
666 "services - called 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 : 0F (DTE complementary "
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 : %02X (Unknown marker)",
682 tvb_get_guint8(tvb, *offset+1));
687 case X25_FAC_REVERSE:
689 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
690 "(Reverse charging / Fast select)", fac);
691 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
692 byte1 = tvb_get_guint8(tvb, *offset + 1);
693 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
694 "Parameter : %02X", byte1);
696 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
697 "11.. .... = Fast select with restriction");
698 else if (byte1 & 0x80)
699 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
700 "10.. .... = Fast select - no restriction");
702 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
703 "00.. .... = Fast select not requested");
704 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
705 decode_boolean_bitfield(byte1, 0x01, 1*8,
706 "Reverse charging requested",
707 "Reverse charging not requested"));
710 case X25_FAC_THROUGHPUT:
714 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
715 "(Throughput class negociation)", fac);
716 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
717 byte1 = tvb_get_guint8(tvb, *offset + 1);
729 sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
730 75*(1<<((byte1 >> 4)-3)));
733 sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
736 sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
739 sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
741 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
742 decode_numeric_bitfield(byte1, 0xF0, 1*8, tmpbuf));
743 switch (byte1 & 0x0F)
754 sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
755 75*(1<<((byte1 & 0x0F)-3)));
758 sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
761 sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
764 sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
766 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
767 decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
772 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
773 "(Closed user group selection)", fac);
774 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
775 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
776 "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
779 case X25_FAC_CALLED_MODIF:
781 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
782 "(Called address modified)", fac);
783 fac_subtree = proto_item_add_subtree(ti,
784 ett_x25_fac_called_modif);
785 proto_tree_add_text(fac_tree, tvb, *offset+1, 1,
786 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
789 case X25_FAC_CUG_OUTGOING_ACC:
791 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
792 "(Closed user group with outgoing access selection)",
794 fac_subtree = proto_item_add_subtree(ti,
795 ett_x25_fac_cug_outgoing_acc);
796 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
797 "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
800 case X25_FAC_THROUGHPUT_MIN:
802 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
803 "(Minimum throughput class)", fac);
804 fac_subtree = proto_item_add_subtree(ti,
805 ett_x25_fac_throughput_min);
806 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
807 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
810 case X25_FAC_EXPRESS_DATA:
812 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
813 "(Negociation of express data)", fac);
814 fac_subtree = proto_item_add_subtree(ti,
815 ett_x25_fac_express_data);
816 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
817 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
822 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
823 "Code : %02X (Unknown class A)", fac);
824 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
825 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
826 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
833 case X25_FAC_CLASS_B:
835 case X25_FAC_BILATERAL_CUG:
837 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
838 "(Bilateral closed user group selection)", fac);
839 fac_subtree = proto_item_add_subtree(ti,
840 ett_x25_fac_bilateral_cug);
841 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
842 "Bilateral CUG: %04X",
843 tvb_get_ntohs(tvb, *offset+1));
846 case X25_FAC_PACKET_SIZE:
851 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
852 "(Packet size)", fac);
853 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
854 byte1 = tvb_get_guint8(tvb, *offset + 1);
858 sprintf(tmpbuf, "From the called DTE : %%u (16)");
861 sprintf(tmpbuf, "From the called DTE : %%u (32)");
864 sprintf(tmpbuf, "From the called DTE : %%u (64)");
867 sprintf(tmpbuf, "From the called DTE : %%u (128)");
870 sprintf(tmpbuf, "From the called DTE : %%u (256)");
873 sprintf(tmpbuf, "From the called DTE : %%u (512)");
876 sprintf(tmpbuf, "From the called DTE : %%u (1024)");
879 sprintf(tmpbuf, "From the called DTE : %%u (2048)");
882 sprintf(tmpbuf, "From the called DTE : %%u (4096)");
885 sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
888 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
889 decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
891 byte2 = tvb_get_guint8(tvb, *offset + 1);
895 sprintf(tmpbuf, "From the calling DTE : %%u (16)");
898 sprintf(tmpbuf, "From the calling DTE : %%u (32)");
901 sprintf(tmpbuf, "From the calling DTE : %%u (64)");
904 sprintf(tmpbuf, "From the calling DTE : %%u (128)");
907 sprintf(tmpbuf, "From the calling DTE : %%u (256)");
910 sprintf(tmpbuf, "From the calling DTE : %%u (512)");
913 sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
916 sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
919 sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
922 sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
925 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
926 decode_numeric_bitfield(byte2, 0x0F, 1*8, tmpbuf));
929 case X25_FAC_WINDOW_SIZE:
931 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
932 "(Window size)", fac);
933 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
934 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
935 decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+1),
936 0x7F, 1*8, "From the called DTE: %u"));
937 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
938 decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+2),
939 0x7F, 1*8, "From the calling DTE: %u"));
942 case X25_FAC_RPOA_SELECTION:
944 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
945 "(RPOA selection)", fac);
946 fac_subtree = proto_item_add_subtree(ti,
947 ett_x25_fac_rpoa_selection);
948 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
949 "Data network identification code : %04X",
950 tvb_get_ntohs(tvb, *offset+1));
953 case X25_FAC_TRANSIT_DELAY:
955 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
956 "(Transit delay selection and indication)", fac);
957 fac_subtree = proto_item_add_subtree(ti,
958 ett_x25_fac_transit_delay);
959 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
960 "Transit delay: %d ms",
961 tvb_get_ntohs(tvb, *offset+1));
966 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
967 "Code : %02X (Unknown class B)", fac);
968 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
969 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
970 "Parameter %04X", tvb_get_ntohs(tvb, *offset+1));
977 case X25_FAC_CLASS_C:
979 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
980 "Code : %02X (Unknown class C)", fac);
981 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
982 proto_tree_add_text(fac_subtree, tvb, *offset+1, 3,
984 tvb_get_ntoh24(tvb, *offset+1));
989 case X25_FAC_CLASS_D:
991 case X25_FAC_CALL_TRANSFER:
996 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
997 "(Call redirection or deflection notification)", fac);
998 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
999 byte1 = tvb_get_guint8(tvb, *offset+1);
1000 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1001 "Length : %u", byte1);
1002 byte2 = tvb_get_guint8(tvb, *offset+2);
1003 if ((byte2 & 0xC0) == 0xC0) {
1004 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1005 "Reason : call deflection by the originally "
1006 "called DTE address");
1011 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1012 "Reason : originally called DTE busy");
1015 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1016 "Reason : call dist. within a hunt group");
1019 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1020 "Reason : originally called DTE out of order");
1023 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1024 "Reason : systematic call redirection");
1027 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1028 "Reason : unknown");
1032 byte3 = tvb_get_guint8(tvb, *offset+3);
1033 proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1034 "Number of semi-octets in DTE address : %u",
1036 for (i = 0; i < byte3; i++) {
1038 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1040 /* if > 9, convert to the right hexadecimal letter */
1041 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1043 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1045 /* if > 9, convert to the right hexadecimal letter */
1046 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1050 proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1051 "DTE address : %s", tmpbuf);
1054 case X25_FAC_CALLING_ADDR_EXT:
1059 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1060 "(Calling address extension)", fac);
1061 fac_subtree = proto_item_add_subtree(ti,
1062 ett_x25_fac_calling_addr_ext);
1063 byte1 = tvb_get_guint8(tvb, *offset+1);
1064 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1065 "Length : %u", byte1);
1066 byte2 = tvb_get_guint8(tvb, *offset+2);
1067 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1068 "Number of semi-octets in DTE address : %u", byte2);
1069 for (i = 0; i < byte2; i++) {
1071 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1073 /* if > 9, convert to the right hexadecimal letter */
1074 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1076 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1078 /* if > 9, convert to the right hexadecimal letter */
1079 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1083 proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1084 "DTE address : %s", tmpbuf);
1087 case X25_FAC_CALLED_ADDR_EXT:
1092 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1093 "(Called address extension)", fac);
1094 fac_subtree = proto_item_add_subtree(ti,
1095 ett_x25_fac_called_addr_ext);
1096 byte1 = tvb_get_guint8(tvb, *offset+1);
1097 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1098 "Length : %u", byte1);
1099 byte2 = tvb_get_guint8(tvb, *offset+2);
1100 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1101 "Number of semi-octets in DTE address : %u", byte2);
1102 for (i = 0; i < byte2; i++) {
1104 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1106 /* if > 9, convert to the right hexadecimal letter */
1107 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1109 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1111 /* if > 9, convert to the right hexadecimal letter */
1112 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1116 proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1117 "DTE address : %s", tmpbuf);
1120 case X25_FAC_ETE_TRANSIT_DELAY:
1122 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1123 "(End to end transit delay)", fac);
1124 fac_subtree = proto_item_add_subtree(ti,
1125 ett_x25_fac_ete_transit_delay);
1126 byte1 = tvb_get_guint8(tvb, *offset+1);
1127 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1128 "Length : %u", byte1);
1129 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1132 case X25_FAC_CALL_DEFLECT:
1137 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1138 "(Call deflection selection)", fac);
1139 fac_subtree = proto_item_add_subtree(ti,
1140 ett_x25_fac_call_deflect);
1141 byte1 = tvb_get_guint8(tvb, *offset+1);
1142 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1143 "Length : %u", byte1);
1144 byte2 = tvb_get_guint8(tvb, *offset+2);
1145 if ((byte2 & 0xC0) == 0xC0)
1146 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1147 "Reason : call DTE originated");
1149 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1150 "Reason : unknown");
1151 byte3 = tvb_get_guint8(tvb, *offset+3);
1152 proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1153 "Number of semi-octets in the alternative DTE address : %u",
1155 for (i = 0; i < byte3; i++) {
1157 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1159 /* if > 9, convert to the right hexadecimal letter */
1160 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1162 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1164 /* if > 9, convert to the right hexadecimal letter */
1165 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1169 proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1170 "Alternative DTE address : %s", tmpbuf);
1173 case X25_FAC_PRIORITY:
1175 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1176 "Code : %02X (Priority)", fac);
1177 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
1178 byte1 = tvb_get_guint8(tvb, *offset+1);
1179 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1180 "Length : %u", byte1);
1181 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1186 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1187 "Code : %02X (Unknown class D)", fac);
1188 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1189 byte1 = tvb_get_guint8(tvb, *offset+1);
1190 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1191 "Length : %u", byte1);
1192 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1195 byte1 = tvb_get_guint8(tvb, *offset+1);
1196 (*offset) += byte1+2;
1204 x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1205 frame_data *fd, gboolean toa)
1209 char addr1[16], addr2[16];
1210 char *first, *second;
1214 byte = tvb_get_guint8(tvb, *offset);
1215 len1 = (byte >> 4) & 0x0F;
1216 len2 = (byte >> 0) & 0x0F;
1218 proto_tree_add_text(tree, tvb, *offset, 1,
1219 decode_numeric_bitfield(byte, 0xF0, 1*8,
1220 toa ? "Called address length : %u" :
1221 "Calling address length : %u"));
1222 proto_tree_add_text(tree, tvb, *offset, 1,
1223 decode_numeric_bitfield(byte, 0x0F, 1*8,
1224 toa ? "Calling address length : %u" :
1225 "Called address length : %u"));
1229 localoffset = *offset;
1230 byte = tvb_get_guint8(tvb, localoffset);
1234 for (i = 0; i < (len1 + len2); i++) {
1237 *first++ = ((byte >> 0) & 0x0F) + '0';
1239 byte = tvb_get_guint8(tvb, localoffset);
1241 *first++ = ((byte >> 4) & 0x0F) + '0';
1245 *second++ = ((byte >> 0) & 0x0F) + '0';
1247 byte = tvb_get_guint8(tvb, localoffset);
1249 *second++ = ((byte >> 4) & 0x0F) + '0';
1259 if (check_col(fd, COL_RES_DL_DST))
1260 col_add_str(fd, COL_RES_DL_DST, addr1);
1263 if(check_col(fd, COL_RES_DL_SRC))
1264 col_add_str(fd, COL_RES_DL_SRC, addr1);
1267 proto_tree_add_text(tree, tvb, *offset,
1270 toa ? "Called" : "Calling",
1275 if (check_col(fd, COL_RES_DL_SRC))
1276 col_add_str(fd, COL_RES_DL_SRC, addr2);
1279 if(check_col(fd, COL_RES_DL_DST))
1280 col_add_str(fd, COL_RES_DL_DST, addr2);
1283 proto_tree_add_text(tree, tvb, *offset + len1/2,
1284 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1286 toa ? "Calling" : "Called",
1289 (*offset) += ((len1 + len2 + 1) / 2);
1293 get_x25_pkt_len(tvbuff_t *tvb)
1295 int length, called_len, calling_len, dte_len, dce_len;
1296 guint8 byte2, bytex;
1298 byte2 = tvb_get_guint8(tvb, 2);
1301 case X25_CALL_REQUEST:
1302 bytex = tvb_get_guint8(tvb, 3);
1303 called_len = (bytex >> 0) & 0x0F;
1304 calling_len = (bytex >> 4) & 0x0F;
1305 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1306 if (length < tvb_length(tvb))
1307 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1309 return MIN(tvb_length(tvb),length);
1311 case X25_CALL_ACCEPTED:
1312 bytex = tvb_get_guint8(tvb, 3);
1313 called_len = (bytex >> 0) & 0x0F;
1314 calling_len = (bytex >> 4) & 0x0F;
1315 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1316 if (length < tvb_length(tvb))
1317 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1319 return MIN(tvb_length(tvb),length);
1321 case X25_CLEAR_REQUEST:
1322 case X25_RESET_REQUEST:
1323 case X25_RESTART_REQUEST:
1324 return MIN(tvb_length(tvb),5);
1326 case X25_DIAGNOSTIC:
1327 return MIN(tvb_length(tvb),4);
1329 case X25_CLEAR_CONFIRMATION:
1331 case X25_INTERRUPT_CONFIRMATION:
1332 case X25_RESET_CONFIRMATION:
1333 case X25_RESTART_CONFIRMATION:
1334 return MIN(tvb_length(tvb),3);
1336 case X25_REGISTRATION_REQUEST:
1337 bytex = tvb_get_guint8(tvb, 3);
1338 dce_len = (bytex >> 0) & 0x0F;
1339 dte_len = (bytex >> 4) & 0x0F;
1340 length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1341 if (length < tvb_length(tvb))
1342 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1344 return MIN(tvb_length(tvb),length);
1346 case X25_REGISTRATION_CONFIRMATION:
1347 bytex = tvb_get_guint8(tvb, 5);
1348 dce_len = (bytex >> 0) & 0x0F;
1349 dte_len = (bytex >> 4) & 0x0F;
1350 length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1351 if (length < tvb_length(tvb))
1352 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1354 return MIN(tvb_length(tvb),length);
1357 if ((byte2 & 0x01) == X25_DATA) return MIN(tvb_length(tvb),3);
1359 switch (byte2 & 0x1F)
1362 return MIN(tvb_length(tvb),3);
1365 return MIN(tvb_length(tvb),3);
1368 return MIN(tvb_length(tvb),3);
1374 #define PRT_ID_ISO_8073 0x01
1376 static const value_string prt_id_vals[] = {
1377 {PRT_ID_ISO_8073, "ISO 8073 COTP"},
1379 {0x03, "ISO 10732 in conjunction with ISO 8073"},
1380 {0x04, "ISO 10736 in conjunction with ISO 8602"},
1384 static const value_string sharing_strategy_vals[] = {
1385 {0x00, "No sharing"},
1390 dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1392 proto_tree *x25_tree=0, *ti;
1397 void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
1398 gboolean toa; /* TOA/NPI address format */
1402 const guint8 *next_pd;
1405 pinfo->current_proto = "X.25";
1407 if (check_col(pinfo->fd, COL_PROTOCOL))
1408 col_add_str(pinfo->fd, COL_PROTOCOL, "X.25");
1410 bytes0_1 = tvb_get_ntohs(tvb, 0);
1412 modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
1413 vc = (int)(bytes0_1 & 0x0FFF);
1415 if (bytes0_1 & 0x8000) toa = TRUE;
1418 x25_pkt_len = get_x25_pkt_len(tvb);
1419 if (x25_pkt_len < 3) /* packet too short */
1421 if (check_col(pinfo->fd, COL_INFO))
1422 col_add_str(pinfo->fd, COL_INFO, "Invalid/short X.25 packet");
1424 proto_tree_add_protocol_format(tree,
1425 (modulo == 8 ? proto_x25 : proto_ex25), tvb, 0,
1426 tvb_length(tvb), "Invalid/short X.25 packet");
1430 ti = proto_tree_add_protocol_format(tree,
1431 (modulo == 8) ? proto_x25 : proto_ex25, tvb, 0, x25_pkt_len,
1433 x25_tree = proto_item_add_subtree(ti, ett_x25);
1434 if (bytes0_1 & 0x8000)
1435 proto_tree_add_item(x25_tree,
1436 (modulo == 8) ? hf_x25_qbit : hf_ex25_qbit, tvb, 0, 2,
1438 if (bytes0_1 & 0x4000)
1439 proto_tree_add_item(x25_tree,
1440 (modulo == 8) ? hf_x25_dbit : hf_ex25_dbit, tvb, 0, 2,
1442 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_mod : hf_ex25_mod,
1443 tvb, 0, 2, bytes0_1);
1446 pkt_type = tvb_get_guint8(tvb, 2);
1448 case X25_CALL_REQUEST:
1449 if (check_col(pinfo->fd, COL_INFO))
1450 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1451 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Inc. call"
1455 proto_tree_add_item(x25_tree,
1456 (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1458 proto_tree_add_uint_format(x25_tree,
1459 (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
1461 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Incoming call"
1465 if (localoffset < x25_pkt_len) /* calling/called addresses */
1466 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1468 if (localoffset < x25_pkt_len) /* facilities */
1469 dump_facilities(x25_tree, &localoffset, tvb);
1471 if (localoffset < tvb_length(tvb)) /* user data */
1476 /* Compare the first octet of the CALL REQUEST packet with
1477 various ISO 9577 NLPIDs, as per Annex A of ISO 9577. */
1478 spi = tvb_get_guint8(tvb, localoffset);
1481 /* XXX - handle other NLPIDs, e.g. PPP? */
1484 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1485 pinfo->fd->abs_usecs, dissect_ip);
1487 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1488 "X.224 secondary protocol ID: IP");
1493 if ((spi >= 0x03 && spi <= 0x82)
1494 && tvb_get_guint8(tvb, localoffset+1) == 0x01) {
1495 /* ISO 9577 claims that a SPI in that range is a
1496 length field for X.224/ISO 8073 or X.264/ISO 11570;
1497 however, some of them collide with NLPIDs such
1498 as 0x81 for ISO 8473 CLNP or ISO 8542 ESIS, so
1499 I don't know how you run those over X.25, assuming
1502 I'm also not sure what the "or" means there; it
1503 looks as if X.264 specifies the layout of a
1504 "UN TPDU" ("Use of network connection TPDU"),
1505 which specifies the transport protocol to use
1506 over this network connection, and 0x03 0x01 0x01
1507 0x00 is such a TPDU, with a length of 3, a UN
1508 field of 1 (as is required), a PRT-ID ("protocol
1509 identifier") field of 1 (X.224/ISO 8073, a/k/a
1510 COTP service), and a SHARE ("sharing strategy")
1511 field of 0 ("no sharing", which is the only one
1514 So we'll assume that's what it is, as the SPI
1515 is in the right range for a length, and the UN
1517 prt_id = tvb_get_guint8(tvb, localoffset+2);
1519 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1520 "X.264 length indicator: %u",
1522 proto_tree_add_text(x25_tree, tvb, localoffset+1, 1,
1523 "X.264 UN TPDU identifier: 0x%02X",
1524 tvb_get_guint8(tvb, localoffset+1));
1525 proto_tree_add_text(x25_tree, tvb, localoffset+2, 1,
1526 "X.264 protocol identifier: %s",
1527 val_to_str(prt_id, prt_id_vals,
1528 "Unknown (0x%02X)"));
1529 proto_tree_add_text(x25_tree, tvb, localoffset+3, 1,
1530 "X.264 sharing strategy: %s",
1531 val_to_str(tvb_get_guint8(tvb, localoffset+3),
1532 sharing_strategy_vals, "Unknown (0x%02X)"));
1535 /* XXX - dissect the variable part? */
1537 /* The length doesn't include the length octet itself. */
1538 localoffset += spi + 1;
1542 case PRT_ID_ISO_8073:
1544 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1545 pinfo->fd->abs_usecs, dissect_cotp);
1554 proto_tree_add_text(x25_tree, tvb, localoffset,
1555 tvb_length(tvb)-localoffset, "Data");
1557 localoffset = tvb_length(tvb);
1562 case X25_CALL_ACCEPTED:
1563 if(check_col(pinfo->fd, COL_INFO))
1564 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1565 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call conn."
1569 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1570 tvb, 0, 2, bytes0_1);
1571 proto_tree_add_uint_format(x25_tree,
1572 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1573 tvb, 2, 1, X25_CALL_ACCEPTED,
1574 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call connected"
1578 if (localoffset < x25_pkt_len) /* calling/called addresses */
1579 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1581 if (localoffset < x25_pkt_len) /* facilities */
1582 dump_facilities(x25_tree, &localoffset, tvb);
1584 if (localoffset < tvb_length(tvb)) { /* user data */
1586 proto_tree_add_text(x25_tree, tvb, localoffset,
1587 tvb_length(tvb)-localoffset, "Data");
1588 localoffset=tvb_length(tvb);
1591 case X25_CLEAR_REQUEST:
1592 if(check_col(pinfo->fd, COL_INFO)) {
1593 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - %s",
1594 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear ind."
1596 vc, clear_code(tvb_get_guint8(tvb, 3)),
1597 clear_diag(tvb_get_guint8(tvb, 4)));
1599 x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1601 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1603 proto_tree_add_uint_format(x25_tree,
1604 (modulo == 8) ? hf_x25_type : hf_ex25_type,
1605 tvb, localoffset+2, 1, X25_CLEAR_REQUEST,
1606 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear indication"
1608 proto_tree_add_text(x25_tree, tvb, 3, 1,
1609 "Cause : %s", clear_code(tvb_get_guint8(tvb, 3)));
1610 proto_tree_add_text(x25_tree, tvb, 4, 1,
1611 "Diagnostic : %s", clear_diag(tvb_get_guint8(tvb, 4)));
1613 localoffset = x25_pkt_len;
1615 case X25_CLEAR_CONFIRMATION:
1616 if(check_col(pinfo->fd, COL_INFO))
1617 col_add_fstr(pinfo->fd, COL_INFO, "Clear Conf. VC:%d", vc);
1619 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1621 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1622 2, 1, X25_CLEAR_CONFIRMATION);
1624 localoffset = x25_pkt_len;
1626 if (localoffset < tvb_length(tvb)) /* extended clear conf format */
1627 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1629 if (localoffset < tvb_length(tvb)) /* facilities */
1630 dump_facilities(x25_tree, &localoffset, tvb);
1632 case X25_DIAGNOSTIC:
1633 if(check_col(pinfo->fd, COL_INFO)) {
1634 col_add_fstr(pinfo->fd, COL_INFO, "Diag. %d",
1635 (int)tvb_get_guint8(tvb, 3));
1638 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1639 2, 1, X25_DIAGNOSTIC);
1640 proto_tree_add_text(x25_tree, tvb, 3, 1,
1641 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 3));
1643 localoffset = x25_pkt_len;
1646 if(check_col(pinfo->fd, COL_INFO))
1647 col_add_fstr(pinfo->fd, COL_INFO, "Interrupt VC:%d", vc);
1649 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1651 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1652 2, 1, X25_INTERRUPT);
1654 localoffset = x25_pkt_len;
1656 case X25_INTERRUPT_CONFIRMATION:
1657 if(check_col(pinfo->fd, COL_INFO))
1658 col_add_fstr(pinfo->fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
1660 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1662 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1663 2, 1, X25_INTERRUPT_CONFIRMATION);
1665 localoffset = x25_pkt_len;
1667 case X25_RESET_REQUEST:
1668 if(check_col(pinfo->fd, COL_INFO)) {
1669 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
1670 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset ind."
1672 vc, reset_code(tvb_get_guint8(tvb, 3)),
1673 (int)tvb_get_guint8(tvb, 4));
1675 x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1677 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1679 proto_tree_add_uint_format(x25_tree,
1680 (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
1682 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset indication"
1684 proto_tree_add_text(x25_tree, tvb, 3, 1,
1685 "Cause : %s", reset_code(tvb_get_guint8(tvb, 3)));
1686 proto_tree_add_text(x25_tree, tvb, 4, 1,
1687 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1689 localoffset = x25_pkt_len;
1691 case X25_RESET_CONFIRMATION:
1692 if(check_col(pinfo->fd, COL_INFO))
1693 col_add_fstr(pinfo->fd, COL_INFO, "Reset conf. VC:%d", vc);
1695 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn, tvb,
1697 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1698 2, 1, X25_RESET_CONFIRMATION);
1700 localoffset = x25_pkt_len;
1702 case X25_RESTART_REQUEST:
1703 if(check_col(pinfo->fd, COL_INFO)) {
1704 col_add_fstr(pinfo->fd, COL_INFO, "%s %s - Diag.:%d",
1705 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart ind."
1707 restart_code(tvb_get_guint8(tvb, 3)),
1708 (int)tvb_get_guint8(tvb, 3));
1711 proto_tree_add_uint_format(x25_tree,
1712 (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb, 2, 1,
1713 X25_RESTART_REQUEST,
1714 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart indication"
1715 : "Restart request");
1716 proto_tree_add_text(x25_tree, tvb, 3, 1,
1717 "Cause : %s", restart_code(tvb_get_guint8(tvb, 3)));
1718 proto_tree_add_text(x25_tree, tvb, 4, 1,
1719 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1721 localoffset = x25_pkt_len;
1723 case X25_RESTART_CONFIRMATION:
1724 if(check_col(pinfo->fd, COL_INFO))
1725 col_add_str(pinfo->fd, COL_INFO, "Restart conf.");
1727 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1728 2, 1, X25_RESTART_CONFIRMATION);
1729 localoffset = x25_pkt_len;
1731 case X25_REGISTRATION_REQUEST:
1732 if(check_col(pinfo->fd, COL_INFO))
1733 col_add_str(pinfo->fd, COL_INFO, "Registration req.");
1735 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1736 2, 1, X25_REGISTRATION_REQUEST);
1738 if (localoffset < x25_pkt_len)
1739 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, FALSE);
1742 if (localoffset < x25_pkt_len)
1743 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1744 "Registration length: %d",
1745 tvb_get_guint8(tvb, localoffset) & 0x7F);
1746 if (localoffset+1 < x25_pkt_len)
1747 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1748 tvb_get_guint8(tvb, localoffset) & 0x7F,
1751 localoffset = tvb_length(tvb);
1753 case X25_REGISTRATION_CONFIRMATION:
1754 if(check_col(pinfo->fd, COL_INFO))
1755 col_add_str(pinfo->fd, COL_INFO, "Registration conf.");
1757 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type, tvb,
1758 2, 1, X25_REGISTRATION_CONFIRMATION);
1759 proto_tree_add_text(x25_tree, tvb, 3, 1,
1760 "Cause: %s", registration_code(tvb_get_guint8(tvb, 3)));
1761 proto_tree_add_text(x25_tree, tvb, 4, 1,
1762 "Diagnostic: %s", registration_code(tvb_get_guint8(tvb, 4)));
1765 if (localoffset < x25_pkt_len)
1766 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, TRUE);
1769 if (localoffset < x25_pkt_len)
1770 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1771 "Registration length: %d",
1772 tvb_get_guint8(tvb, localoffset) & 0x7F);
1773 if (localoffset+1 < x25_pkt_len)
1774 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1775 tvb_get_guint8(tvb, localoffset) & 0x7F,
1778 localoffset = tvb_length(tvb);
1782 if ((pkt_type & 0x01) == X25_DATA)
1784 if(check_col(pinfo->fd, COL_INFO)) {
1786 col_add_fstr(pinfo->fd, COL_INFO,
1787 "Data VC:%d P(S):%d P(R):%d %s", vc,
1788 (pkt_type >> 1) & 0x07,
1789 (pkt_type >> 5) & 0x07,
1790 ((pkt_type >> 4) & 0x01) ? " M" : "");
1792 col_add_fstr(pinfo->fd, COL_INFO,
1793 "Data VC:%d P(S):%d P(R):%d %s", vc,
1794 tvb_get_guint8(tvb, localoffset+1) >> 1,
1796 (tvb_get_guint8(tvb, localoffset+1) & 0x01) ? " M" : "");
1799 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1800 tvb, localoffset-2, 2, bytes0_1);
1802 proto_tree_add_item_hidden(x25_tree, hf_x25_type, tvb,
1803 localoffset, 1, X25_DATA);
1804 proto_tree_add_item(x25_tree, hf_x25_p_r, tvb,
1805 localoffset, 1, pkt_type);
1806 if (pkt_type & 0x10)
1807 proto_tree_add_item(x25_tree, hf_x25_mbit, tvb, localoffset, 1,
1809 proto_tree_add_item(x25_tree, hf_x25_p_s, tvb, localoffset, 1,
1811 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1812 decode_boolean_bitfield(pkt_type, 0x01, 1*8,
1816 proto_tree_add_item_hidden(x25_tree, hf_ex25_type, tvb,
1817 localoffset, 1, X25_DATA);
1818 proto_tree_add_item(x25_tree, hf_x25_p_r, tvb,
1819 localoffset, 1, pkt_type);
1820 proto_tree_add_item(x25_tree, hf_x25_p_s, tvb,
1821 localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
1822 if (tvb_get_guint8(tvb, localoffset+1) & 0x01)
1823 proto_tree_add_item(x25_tree, hf_ex25_mbit, tvb,
1824 localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
1827 localoffset += (modulo == 8) ? 1 : 2;
1830 switch (pkt_type & 0x1F)
1833 if(check_col(pinfo->fd, COL_INFO)) {
1835 col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
1836 vc, (pkt_type >> 5) & 0x07);
1838 col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
1839 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1842 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1843 tvb, localoffset-2, 2, bytes0_1);
1845 proto_tree_add_item(x25_tree, hf_x25_p_r, tvb,
1846 localoffset, 1, pkt_type);
1847 proto_tree_add_item(x25_tree, hf_x25_type, tvb,
1848 localoffset, 1, X25_RR);
1851 proto_tree_add_item(x25_tree, hf_ex25_type, tvb,
1852 localoffset, 1, X25_RR);
1853 proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
1854 localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
1860 if(check_col(pinfo->fd, COL_INFO)) {
1862 col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
1863 vc, (pkt_type >> 5) & 0x07);
1865 col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
1866 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1869 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1870 tvb, localoffset-2, 2, bytes0_1);
1872 proto_tree_add_item(x25_tree, hf_x25_p_r, tvb,
1873 localoffset, 1, pkt_type);
1874 proto_tree_add_item(x25_tree, hf_x25_type, tvb,
1875 localoffset, 1, X25_RNR);
1878 proto_tree_add_item(x25_tree, hf_ex25_type, tvb,
1879 localoffset, 1, X25_RNR);
1880 proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
1881 localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
1887 if(check_col(pinfo->fd, COL_INFO)) {
1889 col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
1890 vc, (pkt_type >> 5) & 0x07);
1892 col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
1893 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1896 proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
1897 tvb, localoffset-2, 2, bytes0_1);
1899 proto_tree_add_item(x25_tree, hf_x25_p_r, tvb,
1900 localoffset, 1, pkt_type);
1901 proto_tree_add_item(x25_tree, hf_x25_type, tvb,
1902 localoffset, 1, X25_REJ);
1905 proto_tree_add_item(x25_tree, hf_ex25_type, tvb,
1906 localoffset, 1, X25_REJ);
1907 proto_tree_add_item(x25_tree, hf_ex25_p_r, tvb,
1908 localoffset+1, 1, tvb_get_guint8(tvb, localoffset+1));
1912 localoffset += (modulo == 8) ? 1 : 2;
1915 if (localoffset >= tvb_length(tvb)) return;
1917 next_tvb = tvb_new_subset(tvb, localoffset, -1, -1);
1918 tvb_compat(next_tvb, &next_pd, &next_offset);
1919 /* search the dissector in the hash table */
1920 if ((dissect = x25_hash_get_dissect(pinfo->fd->abs_secs, pinfo->fd->abs_usecs, vc)))
1921 (*dissect)(next_pd, next_offset, pinfo->fd, tree);
1923 /* If the Call Req. has not been captured, assume these packets carry IP */
1924 if (tvb_get_guint8(tvb, localoffset) == 0x45) {
1925 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1926 pinfo->fd->abs_usecs, dissect_ip);
1927 dissect_ip(next_pd, next_offset, pinfo->fd, tree);
1930 dissect_data(next_pd, next_offset, pinfo->fd, tree);
1936 proto_register_x25(void)
1938 static hf_register_info hf8[] = {
1940 { "Q Bit", "x25.q", FT_BOOLEAN, 2, NULL, 0x8000,
1941 "Qualifier Bit" } },
1943 { "D Bit", "x25.d", FT_BOOLEAN, 2, NULL, 0x4000,
1944 "Delivery Confirmation Bit" } },
1946 { "Modulo", "x25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1947 "Specifies whether the frame is modulo 8 or 128" } },
1949 { "Logical Channel", "x25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
1950 "Logical Channel Number" } },
1952 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1955 { "P(R)", "x25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
1956 "Packet Receive Sequence Number" } },
1958 { "M Bit", "x25.m", FT_BOOLEAN, 1, NULL, 0x10,
1961 { "P(S)", "x25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
1962 "Packet Send Sequence Number" } },
1965 static hf_register_info hf128[] = {
1967 { "Q Bit", "ex25.q", FT_BOOLEAN, 2, NULL, 0x8000,
1968 "Qualifier Bit" } },
1970 { "D Bit", "ex25.d", FT_BOOLEAN, 2, NULL, 0x4000,
1971 "Delivery Confirmation Bit" } },
1973 { "Modulo", "ex25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1974 "Specifies whether the frame is modulo 8 or 128" } },
1976 { "Logical Channel", "ex25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
1977 "Logical Channel Number" } },
1979 { "Packet Type", "ex25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1982 { "P(R)", "ex25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
1983 "Packet Receive Sequence Number" } },
1985 { "M Bit", "ex25.m", FT_BOOLEAN, 1, NULL, 0x01,
1988 { "P(S)", "ex25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
1989 "Packet Send Sequence Number" } },
1991 static gint *ett[] = {
1994 &ett_x25_fac_unknown,
1996 &ett_x25_fac_reverse,
1997 &ett_x25_fac_throughput,
1999 &ett_x25_fac_called_modif,
2000 &ett_x25_fac_cug_outgoing_acc,
2001 &ett_x25_fac_throughput_min,
2002 &ett_x25_fac_express_data,
2003 &ett_x25_fac_bilateral_cug,
2004 &ett_x25_fac_packet_size,
2005 &ett_x25_fac_window_size,
2006 &ett_x25_fac_rpoa_selection,
2007 &ett_x25_fac_transit_delay,
2008 &ett_x25_fac_call_transfer,
2009 &ett_x25_fac_called_addr_ext,
2010 &ett_x25_fac_ete_transit_delay,
2011 &ett_x25_fac_calling_addr_ext,
2012 &ett_x25_fac_call_deflect,
2013 &ett_x25_fac_priority
2016 proto_x25 = proto_register_protocol ("X.25", "x25");
2017 proto_ex25 = proto_register_protocol ("Extended X.25 (modulo 128)", "ex25");
2018 proto_register_field_array (proto_x25, hf8, array_length(hf8));
2019 proto_register_field_array (proto_ex25, hf128, array_length(hf128));
2020 proto_register_subtree_array(ett, array_length(ett));
2021 register_init_routine(&reinit_x25_hashtable);