2 * Routines for x25 packet disassembly
3 * Olivier Abad <oabad@cybercable.fr>
5 * $Id: packet-x25.c,v 1.59 2001/12/03 05:07:16 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
42 #include "x264_prt_id.h"
46 #define X25_CALL_REQUEST 0x0B
47 #define X25_CALL_ACCEPTED 0x0F
48 #define X25_CLEAR_REQUEST 0x13
49 #define X25_CLEAR_CONFIRMATION 0x17
50 #define X25_INTERRUPT 0x23
51 #define X25_INTERRUPT_CONFIRMATION 0x27
52 #define X25_RESET_REQUEST 0x1B
53 #define X25_RESET_CONFIRMATION 0x1F
54 #define X25_RESTART_REQUEST 0xFB
55 #define X25_RESTART_CONFIRMATION 0xFF
56 #define X25_REGISTRATION_REQUEST 0xF3
57 #define X25_REGISTRATION_CONFIRMATION 0xF7
58 #define X25_DIAGNOSTIC 0xF1
64 #define X25_FAC_CLASS_MASK 0xC0
66 #define X25_FAC_CLASS_A 0x00
67 #define X25_FAC_CLASS_B 0x40
68 #define X25_FAC_CLASS_C 0x80
69 #define X25_FAC_CLASS_D 0xC0
71 #define X25_FAC_COMP_MARK 0x00
72 #define X25_FAC_REVERSE 0x01
73 #define X25_FAC_THROUGHPUT 0x02
74 #define X25_FAC_CUG 0x03
75 #define X25_FAC_CALLED_MODIF 0x08
76 #define X25_FAC_CUG_OUTGOING_ACC 0x09
77 #define X25_FAC_THROUGHPUT_MIN 0x0A
78 #define X25_FAC_EXPRESS_DATA 0x0B
79 #define X25_FAC_BILATERAL_CUG 0x41
80 #define X25_FAC_PACKET_SIZE 0x42
81 #define X25_FAC_WINDOW_SIZE 0x43
82 #define X25_FAC_RPOA_SELECTION 0x44
83 #define X25_FAC_TRANSIT_DELAY 0x49
84 #define X25_FAC_CALL_TRANSFER 0xC3
85 #define X25_FAC_CALLED_ADDR_EXT 0xC9
86 #define X25_FAC_ETE_TRANSIT_DELAY 0xCA
87 #define X25_FAC_CALLING_ADDR_EXT 0xCB
88 #define X25_FAC_CALL_DEFLECT 0xD1
89 #define X25_FAC_PRIORITY 0xD2
91 static int proto_x25 = -1;
92 static int hf_x25_gfi = -1;
93 static int hf_x25_abit = -1;
94 static int hf_x25_qbit = -1;
95 static int hf_x25_dbit = -1;
96 static int hf_x25_mod = -1;
97 static int hf_x25_lcn = -1;
98 static int hf_x25_type = -1;
99 static int hf_x25_p_r_mod8 = -1;
100 static int hf_x25_p_r_mod128 = -1;
101 static int hf_x25_mbit_mod8 = -1;
102 static int hf_x25_mbit_mod128 = -1;
103 static int hf_x25_p_s_mod8 = -1;
104 static int hf_x25_p_s_mod128 = -1;
106 static gint ett_x25 = -1;
107 static gint ett_x25_gfi = -1;
108 static gint ett_x25_fac = -1;
109 static gint ett_x25_fac_unknown = -1;
110 static gint ett_x25_fac_mark = -1;
111 static gint ett_x25_fac_reverse = -1;
112 static gint ett_x25_fac_throughput = -1;
113 static gint ett_x25_fac_cug = -1;
114 static gint ett_x25_fac_called_modif = -1;
115 static gint ett_x25_fac_cug_outgoing_acc = -1;
116 static gint ett_x25_fac_throughput_min = -1;
117 static gint ett_x25_fac_express_data = -1;
118 static gint ett_x25_fac_bilateral_cug = -1;
119 static gint ett_x25_fac_packet_size = -1;
120 static gint ett_x25_fac_window_size = -1;
121 static gint ett_x25_fac_rpoa_selection = -1;
122 static gint ett_x25_fac_transit_delay = -1;
123 static gint ett_x25_fac_call_transfer = -1;
124 static gint ett_x25_fac_called_addr_ext = -1;
125 static gint ett_x25_fac_ete_transit_delay = -1;
126 static gint ett_x25_fac_calling_addr_ext = -1;
127 static gint ett_x25_fac_call_deflect = -1;
128 static gint ett_x25_fac_priority = -1;
129 static gint ett_x25_user_data = -1;
131 static const value_string vals_modulo[] = {
137 static const value_string vals_x25_type[] = {
138 { X25_CALL_REQUEST, "Call" },
139 { X25_CALL_ACCEPTED, "Call Accepted" },
140 { X25_CLEAR_REQUEST, "Clear" },
141 { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
142 { X25_INTERRUPT, "Interrupt" },
143 { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
144 { X25_RESET_REQUEST, "Reset" },
145 { X25_RESET_CONFIRMATION, "Reset Confirmation" },
146 { X25_RESTART_REQUEST, "Restart" },
147 { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
148 { X25_REGISTRATION_REQUEST, "Registration" },
149 { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
150 { X25_DIAGNOSTIC, "Diagnostic" },
154 { X25_DATA, "DATA" },
158 static dissector_handle_t ip_handle;
159 static dissector_handle_t ositp_handle;
160 static dissector_handle_t sna_handle;
161 static dissector_handle_t qllc_handle;
162 static dissector_handle_t data_handle;
165 static gboolean non_q_bit_is_sna = FALSE;
167 static dissector_table_t x25_subdissector_table;
170 * each vc_info node contains :
171 * the time of the first frame using this dissector (secs and usecs)
172 * the time of the last frame using this dissector (0 if it is unknown)
173 * a handle for the dissector
175 * the "time of first frame" is initialized when a Call Req. is received
176 * the "time of last frame" is initialized when a Clear, Reset, or Restart
179 typedef struct _vc_info {
180 guint32 first_frame_secs, first_frame_usecs;
181 guint32 last_frame_secs, last_frame_usecs;
182 dissector_handle_t dissect;
183 struct _vc_info *next;
187 * the hash table will contain linked lists of global_vc_info
188 * each global_vc_info struct contains :
189 * the VC number (the hash table is indexed with VC % 64)
190 * a linked list of vc_info
192 typedef struct _global_vc_info {
195 struct _global_vc_info *next;
198 static global_vc_info *hash_table[64];
201 free_vc_info(vc_info *pt)
213 reinit_x25_hashtable(void)
217 for (i=0; i<64; i++) {
218 if (hash_table[i]) /* not NULL ==> free */
220 global_vc_info *hash_ent, *hash_ent2;
221 hash_ent2 = hash_ent = hash_table[i];
224 hash_ent2 = hash_ent;
225 hash_ent = hash_ent->next;
226 free_vc_info(hash_ent2->info);
235 x25_hash_add_proto_start(guint16 vc, guint32 frame_secs, guint32 frame_usecs,
236 dissector_handle_t dissect)
239 global_vc_info *hash_ent;
240 global_vc_info *hash_ent2;
242 if (hash_table[idx] == 0)
244 hash_ent = (global_vc_info *)g_malloc(sizeof(global_vc_info));
246 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
249 hash_ent->vc_num = vc;
251 hash_ent->info = (vc_info *)g_malloc(sizeof(vc_info));
252 if (!hash_ent->info) {
253 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
256 hash_ent->info->first_frame_secs = frame_secs;
257 hash_ent->info->first_frame_usecs = frame_usecs;
258 hash_ent->info->last_frame_secs = 0;
259 hash_ent->info->last_frame_usecs = 0;
260 hash_ent->info->dissect = dissect;
261 hash_ent->info->next = 0;
262 hash_table[idx] = hash_ent;
266 hash_ent2 = hash_ent = hash_table[idx];
267 /* search an entry with the same VC number */
268 while (hash_ent != NULL && hash_ent->vc_num != vc) {
269 hash_ent2 = hash_ent;
270 hash_ent = hash_ent->next;
272 if (hash_ent != NULL) /* hash_ent->vc_num == vc */
274 vc_info *vci = hash_ent->info;
275 while (vci->next) vci = vci->next; /* last element */
276 if (vci->dissect == dissect) {
277 vci->last_frame_secs = 0;
278 vci->last_frame_usecs = 0;
281 vci->next = (vc_info *)g_malloc(sizeof(vc_info));
282 if (vci->next == 0) {
283 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
286 vci->next->first_frame_secs = frame_secs;
287 vci->next->first_frame_usecs = frame_usecs;
288 vci->next->last_frame_secs = 0;
289 vci->next->last_frame_usecs = 0;
290 vci->next->dissect = dissect;
294 else /* new vc number */
296 hash_ent2->next = (global_vc_info *)g_malloc(sizeof(global_vc_info));
297 if (!hash_ent2->next) {
298 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
301 hash_ent2->next->info = (vc_info *)g_malloc(sizeof(vc_info));
302 if (!hash_ent2->next->info) {
303 fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
306 hash_ent2->next->info->first_frame_secs = frame_secs;
307 hash_ent2->next->info->first_frame_usecs = frame_usecs;
308 hash_ent2->next->info->last_frame_secs = 0;
309 hash_ent2->next->info->last_frame_usecs = 0;
310 hash_ent2->next->info->dissect = dissect;
311 hash_ent2->next->info->next = 0;
317 x25_hash_add_proto_end(guint16 vc, guint32 frame_secs, guint32 frame_usecs)
319 global_vc_info *hash_ent = hash_table[vc%64];
322 if (!hash_ent) return;
323 while(hash_ent->vc_num != vc) hash_ent = hash_ent->next;
324 if (!hash_ent) return;
326 vci = hash_ent->info;
327 while (vci->next) vci = vci->next;
328 vci->last_frame_secs = frame_secs;
329 vci->last_frame_usecs = frame_usecs;
332 static dissector_handle_t
333 x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc)
335 global_vc_info *hash_ent = hash_table[vc%64];
342 while (hash_ent && hash_ent->vc_num != vc)
343 hash_ent = hash_ent->next;
347 /* a hash_ent was found for this VC number */
348 vci2 = vci = hash_ent->info;
350 /* looking for an entry matching our frame time */
351 while (vci && (vci->last_frame_secs < frame_secs ||
352 (vci->last_frame_secs == frame_secs &&
353 vci->last_frame_usecs < frame_usecs))) {
357 /* we reached last record, and previous record has a non zero
358 * last frame time ==> no dissector */
359 if (!vci && (vci2->last_frame_secs || vci2->last_frame_usecs))
362 /* we reached last record, and previous record has a zero last frame time
363 * ==> dissector for previous frame has not been "stopped" by a Clear, etc */
365 /* if the start time for vci2 is greater than our frame time
366 * ==> no dissector */
367 if (frame_secs < vci2->first_frame_secs ||
368 (frame_secs == vci2->first_frame_secs &&
369 frame_usecs < vci2->first_frame_usecs))
372 return vci2->dissect;
375 /* our frame time is before vci's end. Check if it is after vci's start */
376 if (frame_secs < vci->first_frame_secs ||
377 (frame_secs == vci->first_frame_secs &&
378 frame_usecs < vci->first_frame_usecs))
384 static char *clear_code(unsigned char code)
386 static char buffer[25];
388 if (code == 0x00 || (code & 0x80) == 0x80)
389 return "DTE Originated";
391 return "Number Busy";
393 return "Invalid Facility Requested";
395 return "Network Congestion";
397 return "Out Of Order";
399 return "Access Barred";
401 return "Not Obtainable";
403 return "Remote Procedure Error";
405 return "Local Procedure Error";
407 return "RPOA Out Of Order";
409 return "Reverse Charging Acceptance Not Subscribed";
411 return "Incompatible Destination";
413 return "Fast Select Acceptance Not Subscribed";
415 return "Destination Absent";
417 sprintf(buffer, "Unknown %02X", code);
422 static char *clear_diag(unsigned char code)
424 static char buffer[25];
427 return "No additional information";
429 return "Invalid P(S)";
431 return "Invalid P(R)";
433 return "Packet type invalid";
435 return "Packet type invalid for state r1";
437 return "Packet type invalid for state r2";
439 return "Packet type invalid for state r3";
441 return "Packet type invalid for state p1";
443 return "Packet type invalid for state p2";
445 return "Packet type invalid for state p3";
447 return "Packet type invalid for state p4";
449 return "Packet type invalid for state p5";
451 return "Packet type invalid for state p6";
453 return "Packet type invalid for state p7";
455 return "Packet type invalid for state d1";
457 return "Packet type invalid for state d2";
459 return "Packet type invalid for state d3";
461 return "Packet not allowed";
463 return "Unidentifiable packet";
465 return "Call on one-way logical channel";
467 return "Invalid packet type on a PVC";
469 return "Packet on unassigned LC";
471 return "Reject not subscribed to";
473 return "Packet too short";
475 return "Packet too long";
477 return "Invalid general format identifier";
479 return "Restart/registration packet with nonzero bits";
481 return "Packet type not compatible with facility";
483 return "Unauthorised interrupt confirmation";
485 return "Unauthorised interrupt";
487 return "Unauthorised reject";
489 return "Time expired";
491 return "Time expired for incoming call";
493 return "Time expired for clear indication";
495 return "Time expired for reset indication";
497 return "Time expired for restart indication";
499 return "Time expired for call deflection";
501 return "Call set-up/clearing or registration pb.";
503 return "Facility/registration code not allowed";
505 return "Facility parameter not allowed";
507 return "Invalid called DTE address";
509 return "Invalid calling DTE address";
511 return "Invalid facility/registration length";
513 return "Incoming call barred";
515 return "No logical channel available";
517 return "Call collision";
519 return "Duplicate facility requested";
521 return "Non zero address length";
523 return "Non zero facility length";
525 return "Facility not provided when expected";
527 return "Invalid CCITT-specified DTE facility";
529 return "Max. nb of call redir/defl. exceeded";
531 return "Miscellaneous";
533 return "Improper cause code from DTE";
535 return "Not aligned octet";
537 return "Inconsistent Q bit setting";
539 return "NUI problem";
541 return "International problem";
543 return "Remote network problem";
545 return "International protocol problem";
547 return "International link out of order";
549 return "International link busy";
551 return "Transit network facility problem";
553 return "Remote network facility problem";
555 return "International routing problem";
557 return "Temporary routing problem";
559 return "Unknown called DNIC";
561 return "Maintenance action";
563 return "Timer expired or retransmission count surpassed";
565 return "Timer expired or retransmission count surpassed for INTERRUPT";
567 return "Timer expired or retransmission count surpassed for DATA "
568 "packet transmission";
570 return "Timer expired or retransmission count surpassed for REJECT";
572 return "DTE-specific signals";
574 return "DTE operational";
576 return "DTE not operational";
578 return "DTE resource constraint";
580 return "Fast select not subscribed";
582 return "Invalid partially full DATA packet";
584 return "D-bit procedure not supported";
586 return "Registration/Cancellation confirmed";
588 return "OSI network service problem";
590 return "Disconnection (transient condition)";
592 return "Disconnection (permanent condition)";
594 return "Connection rejection - reason unspecified (transient "
597 return "Connection rejection - reason unspecified (permanent "
600 return "Connection rejection - quality of service not available "
601 "transient condition)";
603 return "Connection rejection - quality of service not available "
604 "permanent condition)";
606 return "Connection rejection - NSAP unreachable (transient condition)";
608 return "Connection rejection - NSAP unreachable (permanent condition)";
610 return "reset - reason unspecified";
612 return "reset - congestion";
614 return "Connection rejection - NSAP address unknown (permanent "
617 return "Higher layer initiated";
619 return "Disconnection - normal";
621 return "Disconnection - abnormal";
623 return "Disconnection - incompatible information in user data";
625 return "Connection rejection - reason unspecified (transient "
628 return "Connection rejection - reason unspecified (permanent "
631 return "Connection rejection - quality of service not available "
632 "(transient condition)";
634 return "Connection rejection - quality of service not available "
635 "(permanent condition)";
637 return "Connection rejection - incompatible information in user data";
639 return "Connection rejection - unrecognizable protocol indentifier "
642 return "Reset - user resynchronization";
644 sprintf(buffer, "Unknown %d", code);
649 static char *reset_code(unsigned char code)
651 static char buffer[25];
653 if (code == 0x00 || (code & 0x80) == 0x80)
654 return "DTE Originated";
656 return "Out of order";
658 return "Remote Procedure Error";
660 return "Local Procedure Error";
662 return "Network Congestion";
664 return "Remote DTE operational";
666 return "Network operational";
668 return "Incompatible Destination";
670 return "Network out of order";
672 sprintf(buffer, "Unknown %02X", code);
677 static char *restart_code(unsigned char code)
679 static char buffer[25];
681 if (code == 0x00 || (code & 0x80) == 0x80)
682 return "DTE Originated";
684 return "Local Procedure Error";
686 return "Network Congestion";
688 return "Network Operational";
690 return "Registration/cancellation confirmed";
692 sprintf(buffer, "Unknown %02X", code);
697 static char *registration_code(unsigned char code)
699 static char buffer[25];
702 return "Invalid facility request";
704 return "Network congestion";
706 return "Local procedure error";
708 return "Registration/cancellation confirmed";
710 sprintf(buffer, "Unknown %02X", code);
716 dump_facilities(proto_tree *tree, int *offset, tvbuff_t *tvb)
718 guint8 fac, byte1, byte2, byte3;
719 guint32 len; /* facilities length */
721 proto_tree *fac_tree = 0;
722 proto_tree *fac_subtree;
724 len = tvb_get_guint8(tvb, *offset);
726 ti = proto_tree_add_text(tree, tvb, *offset, len + 1,
728 fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
729 proto_tree_add_text(fac_tree, tvb, *offset, 1,
730 "Facilities length: %d", len);
735 fac = tvb_get_guint8(tvb, *offset);
736 switch(fac & X25_FAC_CLASS_MASK) {
737 case X25_FAC_CLASS_A:
739 case X25_FAC_COMP_MARK:
741 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
742 "Code : 00 (Marker)");
743 switch (tvb_get_guint8(tvb, *offset + 1)) {
746 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
747 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
748 "Parameter : 00 (Network complementary "
749 "services - calling DTE)");
754 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
755 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
756 "Parameter : FF (Network complementary "
757 "services - called DTE)");
762 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
763 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
764 "Parameter : 0F (DTE complementary "
770 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
771 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
772 "Parameter : %02X (Unknown marker)",
773 tvb_get_guint8(tvb, *offset+1));
778 case X25_FAC_REVERSE:
780 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
781 "(Reverse charging / Fast select)", fac);
782 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
783 byte1 = tvb_get_guint8(tvb, *offset + 1);
784 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
785 "Parameter : %02X", byte1);
787 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
788 "11.. .... = Fast select with restriction");
789 else if (byte1 & 0x80)
790 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
791 "10.. .... = Fast select - no restriction");
793 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
794 "00.. .... = Fast select not requested");
795 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
796 decode_boolean_bitfield(byte1, 0x01, 1*8,
797 "Reverse charging requested",
798 "Reverse charging not requested"));
801 case X25_FAC_THROUGHPUT:
805 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
806 "(Throughput class negociation)", fac);
807 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
808 byte1 = tvb_get_guint8(tvb, *offset + 1);
820 sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
821 75*(1<<((byte1 >> 4)-3)));
824 sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
827 sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
830 sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
832 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
833 decode_numeric_bitfield(byte1, 0xF0, 1*8, tmpbuf));
834 switch (byte1 & 0x0F)
845 sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
846 75*(1<<((byte1 & 0x0F)-3)));
849 sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
852 sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
855 sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
857 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
858 decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
863 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
864 "(Closed user group selection)", fac);
865 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
866 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
867 "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
870 case X25_FAC_CALLED_MODIF:
872 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
873 "(Called address modified)", fac);
874 fac_subtree = proto_item_add_subtree(ti,
875 ett_x25_fac_called_modif);
876 proto_tree_add_text(fac_tree, tvb, *offset+1, 1,
877 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
880 case X25_FAC_CUG_OUTGOING_ACC:
882 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
883 "(Closed user group with outgoing access selection)",
885 fac_subtree = proto_item_add_subtree(ti,
886 ett_x25_fac_cug_outgoing_acc);
887 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
888 "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
891 case X25_FAC_THROUGHPUT_MIN:
893 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
894 "(Minimum throughput class)", fac);
895 fac_subtree = proto_item_add_subtree(ti,
896 ett_x25_fac_throughput_min);
897 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
898 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
901 case X25_FAC_EXPRESS_DATA:
903 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
904 "(Negociation of express data)", fac);
905 fac_subtree = proto_item_add_subtree(ti,
906 ett_x25_fac_express_data);
907 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
908 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
913 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
914 "Code : %02X (Unknown class A)", fac);
915 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
916 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
917 "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
924 case X25_FAC_CLASS_B:
926 case X25_FAC_BILATERAL_CUG:
928 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
929 "(Bilateral closed user group selection)", fac);
930 fac_subtree = proto_item_add_subtree(ti,
931 ett_x25_fac_bilateral_cug);
932 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
933 "Bilateral CUG: %04X",
934 tvb_get_ntohs(tvb, *offset+1));
937 case X25_FAC_PACKET_SIZE:
942 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
943 "(Packet size)", fac);
944 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
945 byte1 = tvb_get_guint8(tvb, *offset + 1);
949 sprintf(tmpbuf, "From the called DTE : %%u (16)");
952 sprintf(tmpbuf, "From the called DTE : %%u (32)");
955 sprintf(tmpbuf, "From the called DTE : %%u (64)");
958 sprintf(tmpbuf, "From the called DTE : %%u (128)");
961 sprintf(tmpbuf, "From the called DTE : %%u (256)");
964 sprintf(tmpbuf, "From the called DTE : %%u (512)");
967 sprintf(tmpbuf, "From the called DTE : %%u (1024)");
970 sprintf(tmpbuf, "From the called DTE : %%u (2048)");
973 sprintf(tmpbuf, "From the called DTE : %%u (4096)");
976 sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
979 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
980 decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
982 byte2 = tvb_get_guint8(tvb, *offset + 1);
986 sprintf(tmpbuf, "From the calling DTE : %%u (16)");
989 sprintf(tmpbuf, "From the calling DTE : %%u (32)");
992 sprintf(tmpbuf, "From the calling DTE : %%u (64)");
995 sprintf(tmpbuf, "From the calling DTE : %%u (128)");
998 sprintf(tmpbuf, "From the calling DTE : %%u (256)");
1001 sprintf(tmpbuf, "From the calling DTE : %%u (512)");
1004 sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
1007 sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
1010 sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
1013 sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
1016 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1017 decode_numeric_bitfield(byte2, 0x0F, 1*8, tmpbuf));
1020 case X25_FAC_WINDOW_SIZE:
1022 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1023 "(Window size)", fac);
1024 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
1025 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1026 decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+1),
1027 0x7F, 1*8, "From the called DTE: %u"));
1028 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1029 decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+2),
1030 0x7F, 1*8, "From the calling DTE: %u"));
1033 case X25_FAC_RPOA_SELECTION:
1035 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1036 "(RPOA selection)", fac);
1037 fac_subtree = proto_item_add_subtree(ti,
1038 ett_x25_fac_rpoa_selection);
1039 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
1040 "Data network identification code : %04X",
1041 tvb_get_ntohs(tvb, *offset+1));
1044 case X25_FAC_TRANSIT_DELAY:
1046 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1047 "(Transit delay selection and indication)", fac);
1048 fac_subtree = proto_item_add_subtree(ti,
1049 ett_x25_fac_transit_delay);
1050 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
1051 "Transit delay: %d ms",
1052 tvb_get_ntohs(tvb, *offset+1));
1057 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1058 "Code : %02X (Unknown class B)", fac);
1059 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1060 proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
1061 "Parameter %04X", tvb_get_ntohs(tvb, *offset+1));
1068 case X25_FAC_CLASS_C:
1070 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1071 "Code : %02X (Unknown class C)", fac);
1072 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1073 proto_tree_add_text(fac_subtree, tvb, *offset+1, 3,
1075 tvb_get_ntoh24(tvb, *offset+1));
1080 case X25_FAC_CLASS_D:
1082 case X25_FAC_CALL_TRANSFER:
1087 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1088 "(Call redirection or deflection notification)", fac);
1089 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
1090 byte1 = tvb_get_guint8(tvb, *offset+1);
1091 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1092 "Length : %u", byte1);
1093 byte2 = tvb_get_guint8(tvb, *offset+2);
1094 if ((byte2 & 0xC0) == 0xC0) {
1095 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1096 "Reason : call deflection by the originally "
1097 "called DTE address");
1102 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1103 "Reason : originally called DTE busy");
1106 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1107 "Reason : call dist. within a hunt group");
1110 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1111 "Reason : originally called DTE out of order");
1114 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1115 "Reason : systematic call redirection");
1118 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1119 "Reason : unknown");
1123 byte3 = tvb_get_guint8(tvb, *offset+3);
1124 proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1125 "Number of semi-octets in DTE address : %u",
1127 for (i = 0; i < byte3; i++) {
1129 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1131 /* if > 9, convert to the right hexadecimal letter */
1132 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1134 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1136 /* if > 9, convert to the right hexadecimal letter */
1137 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1141 proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1142 "DTE address : %s", tmpbuf);
1145 case X25_FAC_CALLING_ADDR_EXT:
1150 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1151 "(Calling address extension)", fac);
1152 fac_subtree = proto_item_add_subtree(ti,
1153 ett_x25_fac_calling_addr_ext);
1154 byte1 = tvb_get_guint8(tvb, *offset+1);
1155 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1156 "Length : %u", byte1);
1157 byte2 = tvb_get_guint8(tvb, *offset+2);
1158 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1159 "Number of semi-octets in DTE address : %u", byte2);
1160 for (i = 0; i < byte2; i++) {
1162 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1164 /* if > 9, convert to the right hexadecimal letter */
1165 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1167 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1169 /* if > 9, convert to the right hexadecimal letter */
1170 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1174 proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1175 "DTE address : %s", tmpbuf);
1178 case X25_FAC_CALLED_ADDR_EXT:
1183 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1184 "(Called address extension)", fac);
1185 fac_subtree = proto_item_add_subtree(ti,
1186 ett_x25_fac_called_addr_ext);
1187 byte1 = tvb_get_guint8(tvb, *offset+1);
1188 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1189 "Length : %u", byte1);
1190 byte2 = tvb_get_guint8(tvb, *offset+2);
1191 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1192 "Number of semi-octets in DTE address : %u", byte2);
1193 for (i = 0; i < byte2; i++) {
1195 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1197 /* if > 9, convert to the right hexadecimal letter */
1198 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1200 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1202 /* if > 9, convert to the right hexadecimal letter */
1203 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1207 proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1208 "DTE address : %s", tmpbuf);
1211 case X25_FAC_ETE_TRANSIT_DELAY:
1213 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1214 "(End to end transit delay)", fac);
1215 fac_subtree = proto_item_add_subtree(ti,
1216 ett_x25_fac_ete_transit_delay);
1217 byte1 = tvb_get_guint8(tvb, *offset+1);
1218 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1219 "Length : %u", byte1);
1220 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1223 case X25_FAC_CALL_DEFLECT:
1228 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1229 "(Call deflection selection)", fac);
1230 fac_subtree = proto_item_add_subtree(ti,
1231 ett_x25_fac_call_deflect);
1232 byte1 = tvb_get_guint8(tvb, *offset+1);
1233 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1234 "Length : %u", byte1);
1235 byte2 = tvb_get_guint8(tvb, *offset+2);
1236 if ((byte2 & 0xC0) == 0xC0)
1237 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1238 "Reason : call DTE originated");
1240 proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1241 "Reason : unknown");
1242 byte3 = tvb_get_guint8(tvb, *offset+3);
1243 proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1244 "Number of semi-octets in the alternative DTE address : %u",
1246 for (i = 0; i < byte3; i++) {
1248 tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1250 /* if > 9, convert to the right hexadecimal letter */
1251 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1253 tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1255 /* if > 9, convert to the right hexadecimal letter */
1256 if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1260 proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1261 "Alternative DTE address : %s", tmpbuf);
1264 case X25_FAC_PRIORITY:
1266 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1267 "Code : %02X (Priority)", fac);
1268 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
1269 byte1 = tvb_get_guint8(tvb, *offset+1);
1270 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1271 "Length : %u", byte1);
1272 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1277 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1278 "Code : %02X (Unknown class D)", fac);
1279 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1280 byte1 = tvb_get_guint8(tvb, *offset+1);
1281 proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1282 "Length : %u", byte1);
1283 proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1286 byte1 = tvb_get_guint8(tvb, *offset+1);
1287 (*offset) += byte1+2;
1295 x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1296 frame_data *fd, gboolean toa)
1300 char addr1[16], addr2[16];
1301 char *first, *second;
1305 byte = tvb_get_guint8(tvb, *offset);
1306 len1 = (byte >> 4) & 0x0F;
1307 len2 = (byte >> 0) & 0x0F;
1309 proto_tree_add_text(tree, tvb, *offset, 1,
1310 decode_numeric_bitfield(byte, 0xF0, 1*8,
1311 toa ? "Called address length : %u" :
1312 "Calling address length : %u"));
1313 proto_tree_add_text(tree, tvb, *offset, 1,
1314 decode_numeric_bitfield(byte, 0x0F, 1*8,
1315 toa ? "Calling address length : %u" :
1316 "Called address length : %u"));
1320 localoffset = *offset;
1321 byte = tvb_get_guint8(tvb, localoffset);
1325 for (i = 0; i < (len1 + len2); i++) {
1328 *first++ = ((byte >> 0) & 0x0F) + '0';
1330 byte = tvb_get_guint8(tvb, localoffset);
1332 *first++ = ((byte >> 4) & 0x0F) + '0';
1336 *second++ = ((byte >> 0) & 0x0F) + '0';
1338 byte = tvb_get_guint8(tvb, localoffset);
1340 *second++ = ((byte >> 4) & 0x0F) + '0';
1350 if (check_col(fd, COL_RES_DL_DST))
1351 col_add_str(fd, COL_RES_DL_DST, addr1);
1354 if(check_col(fd, COL_RES_DL_SRC))
1355 col_add_str(fd, COL_RES_DL_SRC, addr1);
1358 proto_tree_add_text(tree, tvb, *offset,
1361 toa ? "Called" : "Calling",
1366 if (check_col(fd, COL_RES_DL_SRC))
1367 col_add_str(fd, COL_RES_DL_SRC, addr2);
1370 if(check_col(fd, COL_RES_DL_DST))
1371 col_add_str(fd, COL_RES_DL_DST, addr2);
1374 proto_tree_add_text(tree, tvb, *offset + len1/2,
1375 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1377 toa ? "Calling" : "Called",
1380 (*offset) += ((len1 + len2 + 1) / 2);
1384 get_x25_pkt_len(tvbuff_t *tvb)
1386 guint length, called_len, calling_len, dte_len, dce_len;
1387 guint8 byte2, bytex;
1389 byte2 = tvb_get_guint8(tvb, 2);
1392 case X25_CALL_REQUEST:
1393 bytex = tvb_get_guint8(tvb, 3);
1394 called_len = (bytex >> 0) & 0x0F;
1395 calling_len = (bytex >> 4) & 0x0F;
1396 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1397 if (length < tvb_reported_length(tvb))
1398 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1400 return MIN(tvb_reported_length(tvb),length);
1402 case X25_CALL_ACCEPTED:
1403 /* The calling/called address length byte (following the packet type)
1404 * is not mandatory, so we must check the packet length before trying
1406 if (tvb_reported_length(tvb) == 3)
1408 bytex = tvb_get_guint8(tvb, 3);
1409 called_len = (bytex >> 0) & 0x0F;
1410 calling_len = (bytex >> 4) & 0x0F;
1411 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1412 if (length < tvb_reported_length(tvb))
1413 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1415 return MIN(tvb_reported_length(tvb),length);
1417 case X25_CLEAR_REQUEST:
1418 case X25_RESET_REQUEST:
1419 case X25_RESTART_REQUEST:
1420 return MIN(tvb_reported_length(tvb),5);
1422 case X25_DIAGNOSTIC:
1423 return MIN(tvb_reported_length(tvb),4);
1425 case X25_CLEAR_CONFIRMATION:
1427 case X25_INTERRUPT_CONFIRMATION:
1428 case X25_RESET_CONFIRMATION:
1429 case X25_RESTART_CONFIRMATION:
1430 return MIN(tvb_reported_length(tvb),3);
1432 case X25_REGISTRATION_REQUEST:
1433 bytex = tvb_get_guint8(tvb, 3);
1434 dce_len = (bytex >> 0) & 0x0F;
1435 dte_len = (bytex >> 4) & 0x0F;
1436 length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1437 if (length < tvb_reported_length(tvb))
1438 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1440 return MIN(tvb_reported_length(tvb),length);
1442 case X25_REGISTRATION_CONFIRMATION:
1443 bytex = tvb_get_guint8(tvb, 5);
1444 dce_len = (bytex >> 0) & 0x0F;
1445 dte_len = (bytex >> 4) & 0x0F;
1446 length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1447 if (length < tvb_reported_length(tvb))
1448 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1450 return MIN(tvb_reported_length(tvb),length);
1453 if ((byte2 & 0x01) == X25_DATA) return MIN(tvb_reported_length(tvb),3);
1455 switch (byte2 & 0x1F)
1458 return MIN(tvb_reported_length(tvb),3);
1461 return MIN(tvb_reported_length(tvb),3);
1464 return MIN(tvb_reported_length(tvb),3);
1470 static const value_string prt_id_vals[] = {
1471 {PRT_ID_ISO_8073, "ISO 8073 COTP"},
1472 {PRT_ID_ISO_8602, "ISO 8602 CLTP"},
1473 {PRT_ID_ISO_10736_ISO_8073, "ISO 10736 in conjunction with ISO 8073 COTP"},
1474 {PRT_ID_ISO_10736_ISO_8602, "ISO 10736 in conjunction with ISO 8602 CLTP"},
1478 static const value_string sharing_strategy_vals[] = {
1479 {0x00, "No sharing"},
1484 dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1486 proto_tree *x25_tree=0, *gfi_tree=0, *userdata_tree=0;
1488 guint localoffset=0;
1492 dissector_handle_t dissect;
1493 gboolean toa; /* TOA/NPI address format */
1497 gboolean q_bit_set = FALSE;
1499 if (check_col(pinfo->fd, COL_PROTOCOL))
1500 col_set_str(pinfo->fd, COL_PROTOCOL, "X.25");
1502 bytes0_1 = tvb_get_ntohs(tvb, 0);
1504 modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
1505 vc = (int)(bytes0_1 & 0x0FFF);
1507 if (bytes0_1 & 0x8000) toa = TRUE;
1510 x25_pkt_len = get_x25_pkt_len(tvb);
1511 if (x25_pkt_len < 3) /* packet too short */
1513 if (check_col(pinfo->fd, COL_INFO))
1514 col_set_str(pinfo->fd, COL_INFO, "Invalid/short X.25 packet");
1516 proto_tree_add_protocol_format(tree, proto_x25, tvb, 0,
1517 tvb_length(tvb), "Invalid/short X.25 packet");
1521 pkt_type = tvb_get_guint8(tvb, 2);
1524 ti = proto_tree_add_item(tree, proto_x25, tvb, 0, x25_pkt_len, FALSE);
1525 x25_tree = proto_item_add_subtree(ti, ett_x25);
1526 ti = proto_tree_add_item(x25_tree, hf_x25_gfi, tvb, 0, 2, FALSE);
1527 gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
1529 if ((pkt_type & 0x01) == X25_DATA) {
1530 proto_tree_add_boolean(gfi_tree, hf_x25_qbit, tvb, 0, 2,
1532 if (bytes0_1 & 0x8000) {
1536 else if (pkt_type == X25_CALL_REQUEST ||
1537 pkt_type == X25_CALL_ACCEPTED ||
1538 pkt_type == X25_CLEAR_REQUEST ||
1539 pkt_type == X25_CLEAR_CONFIRMATION) {
1540 proto_tree_add_boolean(gfi_tree, hf_x25_abit, tvb, 0, 2,
1544 if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
1545 (pkt_type & 0x01) == X25_DATA) {
1546 proto_tree_add_boolean(gfi_tree, hf_x25_dbit, tvb, 0, 2,
1549 proto_tree_add_uint(gfi_tree, hf_x25_mod, tvb, 0, 2, bytes0_1);
1553 case X25_CALL_REQUEST:
1554 if (check_col(pinfo->fd, COL_INFO))
1555 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1556 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Inc. call"
1560 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb,
1562 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1564 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Incoming call"
1568 if (localoffset < x25_pkt_len) /* calling/called addresses */
1569 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1571 if (localoffset < x25_pkt_len) /* facilities */
1572 dump_facilities(x25_tree, &localoffset, tvb);
1574 if (localoffset < tvb_reported_length(tvb)) /* user data */
1581 ti = proto_tree_add_text(x25_tree, tvb, localoffset,
1582 tvb_length_remaining(tvb, localoffset),
1584 userdata_tree = proto_item_add_subtree(ti, ett_x25_user_data);
1587 /* X.263/ISO 9577 says that:
1589 When CLNP or ESIS are run over X.25, the SPI
1590 is 0x81 or 0x82, respectively; those are the
1591 NLPIDs for those protocol.
1593 When X.224/ISO 8073 COTP is run over X.25, and
1594 when ISO 11570 explicit identification is being
1595 used, the first octet of the user data field is
1596 a TPDU length field, and the rest is "as defined
1597 in ITU-T Rec. X.225 | ISO/IEC 8073, Annex B,
1598 or ITU-T Rec. X.264 and ISO/IEC 11570".
1600 When X.264/ISO 11570 default identification is
1601 being used, there is no user data field in the
1602 CALL REQUEST packet. This is for X.225/ISO 8073
1605 It also says that SPI values from 0x03 through 0x3f are
1606 reserved and are in use by X.224/ISO 8073 Annex B and
1607 X.264/ISO 11570. The note says that those values are
1608 not NLPIDs, they're "used by the respective higher layer
1609 protocol" and "not used for higher layer protocol
1610 identification". I infer from this and from what
1611 X.264/ISO 11570 says that this means that values in those
1612 range are valid values for the first octet of an
1613 X.224/ISO 8073 packet or for X.264/ISO 11570.
1615 Annex B of X.225/ISO 8073 mentions some additional TPDU
1616 types that can be put in what I presume is the user
1617 data of connect requests. It says that:
1619 The sending transport entity shall:
1621 a) either not transmit any TPDU in the NS-user data
1622 parameter of the N-CONNECT request primitive; or
1624 b) transmit the UN-TPDU (see ITU-T Rec. X.264 and
1625 ISO/IEC 11570) followed by the NCM-TPDU in the
1626 NS-user data parameter of the N-CONNECT request
1629 I don't know if this means that the user data field
1630 will contain a UN TPDU followed by an NCM TPDU or not.
1632 X.264/ISO 11570 says that:
1634 When default identification is being used,
1635 X.225/ISO 8073 COTP is identified. No user data
1636 is sent in the network-layer connection request.
1638 When explicit identification is being used,
1639 the user data is a UN TPDU ("Use of network
1640 connection TPDU"), which specifies the transport
1641 protocol to use over this network connection.
1642 It also says that the length of a UN TPDU shall
1643 not exceed 32 octets, i.e. shall not exceed 0x20;
1644 it says this is "due to the desire not to conflict
1645 with the protocol identifier field carried by X.25
1646 CALL REQUEST/INCOMING CALL packets", and says that
1647 field has values specified in X.244. X.244 has been
1648 superseded by X.263/ISO 9577, so that presumably
1649 means the goal is to allow a UN TPDU's length
1650 field to be distinguished from an NLPID, allowing
1651 you to tell whether X.264/ISO 11570 explicit
1652 identification is being used or an NLPID is
1653 being used as the SPI.
1655 I read this as meaning that, if the ISO mechanisms are
1656 used to identify the protocol being carried over X.25:
1658 if there's no user data in the CALL REQUEST/
1659 INCOMING CALL packet, it's COTP;
1661 if there is user data, then:
1663 if the first octet is less than or equal to
1664 32, it might be a UN TPDU, and that identifies
1665 the transport protocol being used, and
1666 it may be followed by more data, such
1667 as a COTP NCM TPDU if it's COTP;
1669 if the first octet is greater than 32, it's
1670 an NLPID, *not* a TPDU length, and the
1671 stuff following it is *not* a TPDU.
1673 Figure A.2 of X.263/ISO 9577 seems to say that the
1674 first octet of the user data is a TPDU length field,
1675 in the range 0x03 through 0x82, and says they are
1676 for X.225/ISO 8073 Annex B or X.264/ISO 11570.
1678 However, X.264/ISO 11570 seems to imply that the length
1679 field would be that of a UN TPDU, which must be less
1680 than or equal to 0x20, and X.225/ISO 8073 Annex B seems
1681 to indicate that the user data must begin with
1682 an X.264/ISO 11570 UN TPDU, so I'd say that A.2 should
1683 have said "in the range 0x03 through 0x20", instead
1684 (the length value doesn't include the length field,
1685 and the minimum UN TPDU has length, type, PRT-ID,
1686 and SHARE, so that's 3 bytes without the length). */
1687 spi = tvb_get_guint8(tvb, localoffset);
1688 if (spi > 32 || spi < 3) {
1689 /* First octet is > 32, or < 3, so the user data isn't an
1690 X.264/ISO 11570 UN TPDU */
1693 /* First octet is >= 3 and <= 32, so the user data *might*
1694 be an X.264/ISO 11570 UN TPDU. Check whether we have
1695 enough data to see if it is. */
1696 if (tvb_bytes_exist(tvb, localoffset+1, 1)) {
1697 /* We do; check whether the second octet is 1. */
1698 if (tvb_get_guint8(tvb, localoffset+1) == 0x01) {
1699 /* Yes, the second byte is 1, so it looks like
1703 /* No, the second byte is not 1, so it's not a
1708 /* We can't see the second byte of the putative UN
1709 TPDU, so we don't know if that's what it is. */
1713 if (is_x_264 == -1) {
1715 * We don't know what it is; just skip it.
1717 localoffset = tvb_length(tvb);
1718 } else if (is_x_264) {
1719 /* It looks like an X.264 UN TPDU, so show it as such. */
1720 if (userdata_tree) {
1721 proto_tree_add_text(userdata_tree, tvb, localoffset, 1,
1722 "X.264 length indicator: %u",
1724 proto_tree_add_text(userdata_tree, tvb, localoffset+1, 1,
1725 "X.264 UN TPDU identifier: 0x%02X",
1726 tvb_get_guint8(tvb, localoffset+1));
1728 prt_id = tvb_get_guint8(tvb, localoffset+2);
1729 if (userdata_tree) {
1730 proto_tree_add_text(x25_tree, tvb, localoffset+2, 1,
1731 "X.264 protocol identifier: %s",
1732 val_to_str(prt_id, prt_id_vals,
1733 "Unknown (0x%02X)"));
1734 proto_tree_add_text(x25_tree, tvb, localoffset+3, 1,
1735 "X.264 sharing strategy: %s",
1736 val_to_str(tvb_get_guint8(tvb, localoffset+3),
1737 sharing_strategy_vals, "Unknown (0x%02X)"));
1740 /* XXX - dissect the variable part? */
1742 /* The length doesn't include the length octet itself. */
1743 localoffset += spi + 1;
1747 case PRT_ID_ISO_8073:
1749 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1750 pinfo->fd->abs_usecs,
1752 /* XXX - disssect the rest of the user data as COTP?
1753 That needs support for NCM TPDUs, etc. */
1756 case PRT_ID_ISO_8602:
1758 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1759 pinfo->fd->abs_usecs,
1763 } else if (is_x_264 == 0) {
1764 /* It doesn't look like a UN TPDU, so compare the first
1765 octet of the CALL REQUEST packet with various X.263/
1766 ISO 9577 NLPIDs, as per Annex A of X.263/ISO 9577. */
1768 if (userdata_tree) {
1769 proto_tree_add_text(userdata_tree, tvb, localoffset, 1,
1770 "X.263 secondary protocol ID: %s",
1771 val_to_str(spi, nlpid_vals, "Unknown (0x%02x)"));
1776 * What's the dissector handle for this SPI?
1778 dissect = dissector_get_port_handle(x25_subdissector_table, spi);
1779 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1780 pinfo->fd->abs_usecs, dissect);
1782 if (localoffset < tvb_length(tvb)) {
1783 if (userdata_tree) {
1784 proto_tree_add_text(userdata_tree, tvb, localoffset,
1785 tvb_length(tvb)-localoffset, "Data");
1787 localoffset = tvb_length(tvb);
1791 case X25_CALL_ACCEPTED:
1792 if(check_col(pinfo->fd, COL_INFO))
1793 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1794 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call conn."
1798 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1799 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1801 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call connected"
1805 if (localoffset < x25_pkt_len) /* calling/called addresses */
1806 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1808 if (localoffset < x25_pkt_len) /* facilities */
1809 dump_facilities(x25_tree, &localoffset, tvb);
1811 if (localoffset < tvb_reported_length(tvb)) { /* user data */
1813 proto_tree_add_text(x25_tree, tvb, localoffset,
1814 tvb_reported_length(tvb)-localoffset, "Data");
1815 localoffset=tvb_reported_length(tvb);
1818 case X25_CLEAR_REQUEST:
1819 if(check_col(pinfo->fd, COL_INFO)) {
1820 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - %s",
1821 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear ind."
1823 vc, clear_code(tvb_get_guint8(tvb, 3)),
1824 clear_diag(tvb_get_guint8(tvb, 4)));
1826 x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1828 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1829 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb,
1830 localoffset+2, 1, X25_CLEAR_REQUEST,
1831 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear indication"
1833 proto_tree_add_text(x25_tree, tvb, 3, 1,
1834 "Cause : %s", clear_code(tvb_get_guint8(tvb, 3)));
1835 proto_tree_add_text(x25_tree, tvb, 4, 1,
1836 "Diagnostic : %s", clear_diag(tvb_get_guint8(tvb, 4)));
1838 localoffset = x25_pkt_len;
1840 case X25_CLEAR_CONFIRMATION:
1841 if(check_col(pinfo->fd, COL_INFO))
1842 col_add_fstr(pinfo->fd, COL_INFO, "Clear Conf. VC:%d", vc);
1844 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1845 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1846 X25_CLEAR_CONFIRMATION);
1848 localoffset = x25_pkt_len;
1850 if (localoffset < tvb_reported_length(tvb)) /* extended clear conf format */
1851 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1853 if (localoffset < tvb_reported_length(tvb)) /* facilities */
1854 dump_facilities(x25_tree, &localoffset, tvb);
1856 case X25_DIAGNOSTIC:
1857 if(check_col(pinfo->fd, COL_INFO)) {
1858 col_add_fstr(pinfo->fd, COL_INFO, "Diag. %d",
1859 (int)tvb_get_guint8(tvb, 3));
1862 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1864 proto_tree_add_text(x25_tree, tvb, 3, 1,
1865 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 3));
1867 localoffset = x25_pkt_len;
1870 if(check_col(pinfo->fd, COL_INFO))
1871 col_add_fstr(pinfo->fd, COL_INFO, "Interrupt VC:%d", vc);
1873 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1874 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1877 localoffset = x25_pkt_len;
1879 case X25_INTERRUPT_CONFIRMATION:
1880 if(check_col(pinfo->fd, COL_INFO))
1881 col_add_fstr(pinfo->fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
1883 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1884 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1885 X25_INTERRUPT_CONFIRMATION);
1887 localoffset = x25_pkt_len;
1889 case X25_RESET_REQUEST:
1890 if(check_col(pinfo->fd, COL_INFO)) {
1891 col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
1892 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset ind."
1894 vc, reset_code(tvb_get_guint8(tvb, 3)),
1895 (int)tvb_get_guint8(tvb, 4));
1897 x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1899 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1900 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1902 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset indication"
1904 proto_tree_add_text(x25_tree, tvb, 3, 1,
1905 "Cause : %s", reset_code(tvb_get_guint8(tvb, 3)));
1906 proto_tree_add_text(x25_tree, tvb, 4, 1,
1907 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1909 localoffset = x25_pkt_len;
1911 case X25_RESET_CONFIRMATION:
1912 if(check_col(pinfo->fd, COL_INFO))
1913 col_add_fstr(pinfo->fd, COL_INFO, "Reset conf. VC:%d", vc);
1915 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1916 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1917 X25_RESET_CONFIRMATION);
1919 localoffset = x25_pkt_len;
1921 case X25_RESTART_REQUEST:
1922 if(check_col(pinfo->fd, COL_INFO)) {
1923 col_add_fstr(pinfo->fd, COL_INFO, "%s %s - Diag.:%d",
1924 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart ind."
1926 restart_code(tvb_get_guint8(tvb, 3)),
1927 (int)tvb_get_guint8(tvb, 3));
1930 proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1931 X25_RESTART_REQUEST,
1932 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart indication"
1933 : "Restart request");
1934 proto_tree_add_text(x25_tree, tvb, 3, 1,
1935 "Cause : %s", restart_code(tvb_get_guint8(tvb, 3)));
1936 proto_tree_add_text(x25_tree, tvb, 4, 1,
1937 "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1939 localoffset = x25_pkt_len;
1941 case X25_RESTART_CONFIRMATION:
1942 if(check_col(pinfo->fd, COL_INFO))
1943 col_set_str(pinfo->fd, COL_INFO, "Restart conf.");
1945 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1946 X25_RESTART_CONFIRMATION);
1947 localoffset = x25_pkt_len;
1949 case X25_REGISTRATION_REQUEST:
1950 if(check_col(pinfo->fd, COL_INFO))
1951 col_set_str(pinfo->fd, COL_INFO, "Registration req.");
1953 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1954 X25_REGISTRATION_REQUEST);
1956 if (localoffset < x25_pkt_len)
1957 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, FALSE);
1960 if (localoffset < x25_pkt_len)
1961 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1962 "Registration length: %d",
1963 tvb_get_guint8(tvb, localoffset) & 0x7F);
1964 if (localoffset+1 < x25_pkt_len)
1965 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1966 tvb_get_guint8(tvb, localoffset) & 0x7F,
1969 localoffset = tvb_reported_length(tvb);
1971 case X25_REGISTRATION_CONFIRMATION:
1972 if(check_col(pinfo->fd, COL_INFO))
1973 col_set_str(pinfo->fd, COL_INFO, "Registration conf.");
1975 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1976 X25_REGISTRATION_CONFIRMATION);
1977 proto_tree_add_text(x25_tree, tvb, 3, 1,
1978 "Cause: %s", registration_code(tvb_get_guint8(tvb, 3)));
1979 proto_tree_add_text(x25_tree, tvb, 4, 1,
1980 "Diagnostic: %s", registration_code(tvb_get_guint8(tvb, 4)));
1983 if (localoffset < x25_pkt_len)
1984 x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, TRUE);
1987 if (localoffset < x25_pkt_len)
1988 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1989 "Registration length: %d",
1990 tvb_get_guint8(tvb, localoffset) & 0x7F);
1991 if (localoffset+1 < x25_pkt_len)
1992 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1993 tvb_get_guint8(tvb, localoffset) & 0x7F,
1996 localoffset = tvb_reported_length(tvb);
2000 if ((pkt_type & 0x01) == X25_DATA)
2002 if(check_col(pinfo->fd, COL_INFO)) {
2004 col_add_fstr(pinfo->fd, COL_INFO,
2005 "Data VC:%d P(S):%d P(R):%d %s", vc,
2006 (pkt_type >> 1) & 0x07,
2007 (pkt_type >> 5) & 0x07,
2008 ((pkt_type >> 4) & 0x01) ? " M" : "");
2010 col_add_fstr(pinfo->fd, COL_INFO,
2011 "Data VC:%d P(S):%d P(R):%d %s", vc,
2012 tvb_get_guint8(tvb, localoffset+1) >> 1,
2014 (tvb_get_guint8(tvb, localoffset+1) & 0x01) ? " M" : "");
2017 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
2019 proto_tree_add_uint_hidden(x25_tree, hf_x25_type, tvb,
2020 localoffset, 1, X25_DATA);
2022 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
2023 localoffset, 1, pkt_type);
2024 if (pkt_type & 0x10)
2025 proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod8, tvb,
2026 localoffset, 1, pkt_type);
2027 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod8, tvb,
2028 localoffset, 1, pkt_type);
2029 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
2030 decode_boolean_bitfield(pkt_type, 0x01, 1*8,
2034 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod128, tvb,
2035 localoffset, 1, pkt_type);
2036 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod128, tvb,
2038 tvb_get_guint8(tvb, localoffset+1));
2039 if (tvb_get_guint8(tvb, localoffset+1) & 0x01)
2040 proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod128, tvb,
2042 tvb_get_guint8(tvb, localoffset+1));
2045 localoffset += (modulo == 8) ? 1 : 2;
2048 switch (pkt_type & 0x1F)
2051 if(check_col(pinfo->fd, COL_INFO)) {
2053 col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
2054 vc, (pkt_type >> 5) & 0x07);
2056 col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
2057 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
2060 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
2063 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
2064 localoffset, 1, pkt_type);
2065 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2066 localoffset, 1, X25_RR);
2069 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2070 localoffset, 1, X25_RR);
2071 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
2072 localoffset+1, 1, FALSE);
2078 if(check_col(pinfo->fd, COL_INFO)) {
2080 col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
2081 vc, (pkt_type >> 5) & 0x07);
2083 col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
2084 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
2087 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
2090 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
2091 localoffset, 1, pkt_type);
2092 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2093 localoffset, 1, X25_RNR);
2096 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2097 localoffset, 1, X25_RNR);
2098 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
2099 localoffset+1, 1, FALSE);
2105 if(check_col(pinfo->fd, COL_INFO)) {
2107 col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
2108 vc, (pkt_type >> 5) & 0x07);
2110 col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
2111 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
2114 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
2117 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
2118 localoffset, 1, pkt_type);
2119 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2120 localoffset, 1, X25_REJ);
2123 proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2124 localoffset, 1, X25_REJ);
2125 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
2126 localoffset+1, 1, FALSE);
2130 localoffset += (modulo == 8) ? 1 : 2;
2133 if (localoffset >= tvb_reported_length(tvb)) return;
2135 next_tvb = tvb_new_subset(tvb, localoffset, -1, -1);
2139 call_dissector(qllc_handle, next_tvb, pinfo, tree);
2143 /* search the dissector in the hash table */
2144 if ((dissect = x25_hash_get_dissect(pinfo->fd->abs_secs, pinfo->fd->abs_usecs, vc))) {
2145 call_dissector(dissect, next_tvb, pinfo, tree);
2148 /* Did the user suggest SNA-over-X.25? */
2149 if (non_q_bit_is_sna) {
2150 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
2151 pinfo->fd->abs_usecs, sna_handle);
2152 call_dissector(sna_handle, next_tvb, pinfo, tree);
2154 /* If the Call Req. has not been captured, and the payload begins
2155 with what appears to be an IP header, assume these packets carry
2157 else if (tvb_get_guint8(tvb, localoffset) == 0x45) {
2158 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
2159 pinfo->fd->abs_usecs, ip_handle);
2160 call_dissector(ip_handle, next_tvb, pinfo, tree);
2163 call_dissector(data_handle,next_tvb, pinfo, tree);
2169 proto_register_x25(void)
2171 static hf_register_info hf[] = {
2173 { "GFI", "x.25.gfi", FT_UINT16, BASE_BIN, NULL, 0xF000,
2174 "General format identifier", HFILL }},
2176 { "A Bit", "x.25.a", FT_BOOLEAN, 16, NULL, 0x8000,
2177 "Address Bit", HFILL }},
2179 { "Q Bit", "x.25.q", FT_BOOLEAN, 16, NULL, 0x8000,
2180 "Qualifier Bit", HFILL }},
2182 { "D Bit", "x.25.d", FT_BOOLEAN, 16, NULL, 0x4000,
2183 "Delivery Confirmation Bit", HFILL }},
2185 { "Modulo", "x.25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
2186 "Specifies whether the frame is modulo 8 or 128", HFILL }},
2188 { "Logical Channel", "x.25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
2189 "Logical Channel Number", HFILL }},
2191 { "Packet Type", "x.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
2192 "Packet Type", HFILL }},
2194 { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
2195 "Packet Receive Sequence Number", HFILL }},
2196 { &hf_x25_p_r_mod128,
2197 { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
2198 "Packet Receive Sequence Number", HFILL }},
2199 { &hf_x25_mbit_mod8,
2200 { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x10,
2201 "More Bit", HFILL }},
2202 { &hf_x25_mbit_mod128,
2203 { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x01,
2204 "More Bit", HFILL }},
2206 { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
2207 "Packet Send Sequence Number", HFILL }},
2208 { &hf_x25_p_s_mod128,
2209 { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
2210 "Packet Send Sequence Number", HFILL }},
2212 static gint *ett[] = {
2216 &ett_x25_fac_unknown,
2218 &ett_x25_fac_reverse,
2219 &ett_x25_fac_throughput,
2221 &ett_x25_fac_called_modif,
2222 &ett_x25_fac_cug_outgoing_acc,
2223 &ett_x25_fac_throughput_min,
2224 &ett_x25_fac_express_data,
2225 &ett_x25_fac_bilateral_cug,
2226 &ett_x25_fac_packet_size,
2227 &ett_x25_fac_window_size,
2228 &ett_x25_fac_rpoa_selection,
2229 &ett_x25_fac_transit_delay,
2230 &ett_x25_fac_call_transfer,
2231 &ett_x25_fac_called_addr_ext,
2232 &ett_x25_fac_ete_transit_delay,
2233 &ett_x25_fac_calling_addr_ext,
2234 &ett_x25_fac_call_deflect,
2235 &ett_x25_fac_priority,
2238 module_t *x25_module;
2240 proto_x25 = proto_register_protocol ("X.25", "X.25", "x.25");
2241 proto_register_field_array (proto_x25, hf, array_length(hf));
2242 proto_register_subtree_array(ett, array_length(ett));
2243 register_init_routine(&reinit_x25_hashtable);
2245 x25_subdissector_table = register_dissector_table("x.25.spi");
2247 register_dissector("x.25", dissect_x25, proto_x25);
2250 x25_module = prefs_register_protocol(proto_x25, NULL);
2251 prefs_register_bool_preference(x25_module, "non_q_bit_is_sna",
2252 "When Q-bit is 0, payload is SNA", "When Q-bit is 0, payload is SNA",
2257 proto_reg_handoff_x25(void)
2259 dissector_handle_t x25_handle;
2262 * Get handles for various dissectors.
2264 ip_handle = find_dissector("ip");
2265 ositp_handle = find_dissector("ositp");
2266 sna_handle = find_dissector("sna");
2267 qllc_handle = find_dissector("qllc");
2268 data_handle = find_dissector("data");
2270 x25_handle = find_dissector("x.25");
2271 dissector_add("llc.dsap", SAP_X25, x25_handle);