2 * Routines for X.25 packet disassembly
3 * Olivier Abad <oabad@noos.fr>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <epan/packet.h>
33 #include <epan/ax25_pids.h>
34 #include <epan/llcsaps.h>
35 #include <epan/circuit.h>
36 #include <epan/reassemble.h>
37 #include <epan/prefs.h>
38 #include <epan/wmem/wmem.h>
39 #include <epan/expert.h>
40 #include <epan/nlpid.h>
41 #include <epan/x264_prt_id.h>
42 #include <epan/lapd_sapi.h>
45 * Direction of packet.
48 X25_FROM_DCE, /* DCE->DTE */
49 X25_FROM_DTE, /* DTE->DCE */
50 X25_UNKNOWN /* direction unknown */
54 * 0 for data packets, 1 for non-data packets.
56 #define X25_NONDATA_BIT 0x01
58 #define X25_CALL_REQUEST 0x0B
59 #define X25_CALL_ACCEPTED 0x0F
60 #define X25_CLEAR_REQUEST 0x13
61 #define X25_CLEAR_CONFIRMATION 0x17
62 #define X25_INTERRUPT 0x23
63 #define X25_INTERRUPT_CONFIRMATION 0x27
64 #define X25_RESET_REQUEST 0x1B
65 #define X25_RESET_CONFIRMATION 0x1F
66 #define X25_RESTART_REQUEST 0xFB
67 #define X25_RESTART_CONFIRMATION 0xFF
68 #define X25_REGISTRATION_REQUEST 0xF3
69 #define X25_REGISTRATION_CONFIRMATION 0xF7
70 #define X25_DIAGNOSTIC 0xF1
76 #define PACKET_IS_DATA(type) (!(type & X25_NONDATA_BIT))
77 #define PACKET_TYPE_FC(type) (type & 0x1F)
79 #define X25_MBIT_MOD8 0x10
80 #define X25_MBIT_MOD128 0x01
82 #define X25_ABIT 0x8000
84 #define X25_QBIT 0x8000
85 #define X25_DBIT 0x4000
87 #define X25_FAC_CLASS_MASK 0xC0
89 #define X25_FAC_CLASS_A 0x00
90 #define X25_FAC_CLASS_B 0x40
91 #define X25_FAC_CLASS_C 0x80
92 #define X25_FAC_CLASS_D 0xC0
94 #define X25_FAC_COMP_MARK 0x00
95 #define X25_FAC_REVERSE 0x01
96 #define X25_FAC_THROUGHPUT 0x02
97 #define X25_FAC_CUG 0x03
98 #define X25_FAC_CHARGING_INFO 0x04
99 #define X25_FAC_CALLED_MODIF 0x08
100 #define X25_FAC_CUG_OUTGOING_ACC 0x09
101 #define X25_FAC_THROUGHPUT_MIN 0x0A
102 #define X25_FAC_EXPRESS_DATA 0x0B
103 #define X25_FAC_BILATERAL_CUG 0x41
104 #define X25_FAC_PACKET_SIZE 0x42
105 #define X25_FAC_WINDOW_SIZE 0x43
106 #define X25_FAC_RPOA_SELECTION 0x44
107 #define X25_FAC_CUG_EXT 0x47
108 #define X25_FAC_CUG_OUTGOING_ACC_EXT 0x48
109 #define X25_FAC_TRANSIT_DELAY 0x49
110 #define X25_FAC_CALL_DURATION 0xC1
111 #define X25_FAC_SEGMENT_COUNT 0xC2
112 #define X25_FAC_CALL_TRANSFER 0xC3
113 #define X25_FAC_RPOA_SELECTION_EXT 0xC4
114 #define X25_FAC_MONETARY_UNIT 0xC5
115 #define X25_FAC_NUI 0xC6
116 #define X25_FAC_CALLED_ADDR_EXT 0xC9
117 #define X25_FAC_ETE_TRANSIT_DELAY 0xCA
118 #define X25_FAC_CALLING_ADDR_EXT 0xCB
119 #define X25_FAC_CALL_DEFLECT 0xD1
120 #define X25_FAC_PRIORITY 0xD2
122 static int proto_x25 = -1;
123 static int hf_x25_facility = -1;
124 static int hf_x25_facilities_length = -1;
125 static int hf_x25_facility_length = -1;
126 static int hf_x25_facility_class = -1;
127 static int hf_x25_facility_classA = -1;
128 static int hf_x25_facility_classA_comp_mark = -1;
129 static int hf_x25_facility_classA_reverse = -1;
130 static int hf_x25_facility_classA_charging_info = -1;
131 static int hf_x25_facility_reverse_charging = -1;
132 static int hf_x25_facility_charging_info = -1;
133 static int hf_x25_facility_throughput_called_dte = -1;
134 static int hf_x25_throughput_called_dte = -1;
135 static int hf_x25_facility_classA_cug = -1;
136 static int hf_x25_facility_classA_called_motif = -1;
137 static int hf_x25_facility_classA_cug_outgoing_acc = -1;
138 static int hf_x25_facility_classA_throughput_min = -1;
139 static int hf_x25_facility_classA_express_data = -1;
140 static int hf_x25_facility_classA_unknown = -1;
141 static int hf_x25_facility_classB = -1;
142 static int hf_x25_facility_classB_bilateral_cug = -1;
143 static int hf_x25_facility_packet_size_called_dte = -1;
144 static int hf_x25_facility_packet_size_calling_dte = -1;
145 static int hf_x25_facility_data_network_id_code = -1;
146 static int hf_x25_facility_cug_ext = -1;
147 static int hf_x25_facility_cug_outgoing_acc_ext = -1;
148 static int hf_x25_facility_transit_delay = -1;
149 static int hf_x25_facility_classB_unknown = -1;
150 static int hf_x25_facility_classC = -1;
151 static int hf_x25_facility_classC_unknown = -1;
152 static int hf_x25_facility_classD = -1;
153 static int hf_x25_gfi = -1;
154 static int hf_x25_abit = -1;
155 static int hf_x25_qbit = -1;
156 static int hf_x25_dbit = -1;
157 static int hf_x25_mod = -1;
158 static int hf_x25_lcn = -1;
159 static int hf_x25_type = -1;
160 static int hf_x25_type_fc_mod8 = -1;
161 static int hf_x25_type_data = -1;
162 static int hf_x25_diagnostic = -1;
163 static int hf_x25_p_r_mod8 = -1;
164 static int hf_x25_p_r_mod128 = -1;
165 static int hf_x25_mbit_mod8 = -1;
166 static int hf_x25_mbit_mod128 = -1;
167 static int hf_x25_p_s_mod8 = -1;
168 static int hf_x25_p_s_mod128 = -1;
169 static int hf_x25_window_size_called_dte = -1;
170 static int hf_x25_window_size_calling_dte = -1;
171 static int hf_x25_dte_address_length = -1;
172 static int hf_x25_dce_address_length = -1;
173 static int hf_x25_calling_address_length = -1;
174 static int hf_x25_called_address_length = -1;
175 static int hf_x25_facility_call_transfer_reason = -1;
176 static int hf_x25_facility_monetary_unit = -1;
177 static int hf_x25_facility_nui = -1;
178 static int hf_x25_facility_cumulative_ete_transit_delay = -1;
179 static int hf_x25_facility_requested_ete_transit_delay = -1;
180 static int hf_x25_facility_max_acceptable_ete_transit_delay = -1;
181 static int hf_x25_facility_priority_data = -1;
182 static int hf_x25_facility_priority_estab_conn = -1;
183 static int hf_x25_facility_priority_keep_conn = -1;
184 static int hf_x25_facility_min_acceptable_priority_data = -1;
185 static int hf_x25_facility_min_acceptable_priority_estab_conn = -1;
186 static int hf_x25_facility_min_acceptable_priority_keep_conn = -1;
187 static int hf_x25_facility_classD_unknown = -1;
188 static int hf_x25_facility_call_transfer_num_semi_octets = -1;
189 static int hf_x25_facility_calling_addr_ext_num_semi_octets = -1;
190 static int hf_x25_facility_called_addr_ext_num_semi_octets = -1;
191 static int hf_x25_facility_call_deflect_num_semi_octets = -1;
192 static int hf_x264_length_indicator = -1;
193 static int hf_x264_un_tpdu_id = -1;
194 static int hf_x264_protocol_id = -1;
195 static int hf_x264_sharing_strategy = -1;
196 static int hf_x263_sec_protocol_id = -1;
197 static int hf_x25_reg_request_length = -1;
198 static int hf_x25_reg_confirm_length = -1;
201 static gint ett_x25 = -1;
202 static gint ett_x25_gfi = -1;
203 static gint ett_x25_facilities = -1;
204 static gint ett_x25_facility = -1;
205 static gint ett_x25_user_data = -1;
207 static gint ett_x25_segment = -1;
208 static gint ett_x25_segments = -1;
209 static gint hf_x25_segments = -1;
210 static gint hf_x25_segment = -1;
211 static gint hf_x25_segment_overlap = -1;
212 static gint hf_x25_segment_overlap_conflict = -1;
213 static gint hf_x25_segment_multiple_tails = -1;
214 static gint hf_x25_segment_too_long_segment = -1;
215 static gint hf_x25_segment_error = -1;
216 static gint hf_x25_segment_count = -1;
217 static gint hf_x25_reassembled_length = -1;
218 static gint hf_x25_fast_select = -1;
219 static gint hf_x25_icrd = -1;
220 static gint hf_x25_reg_confirm_cause = -1;
221 static gint hf_x25_reg_confirm_diagnostic = -1;
223 static expert_field ei_x25_facility_length = EI_INIT;
225 static const value_string vals_modulo[] = {
231 static const value_string vals_x25_type[] = {
232 { X25_CALL_REQUEST, "Call" },
233 { X25_CALL_ACCEPTED, "Call Accepted" },
234 { X25_CLEAR_REQUEST, "Clear" },
235 { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
236 { X25_INTERRUPT, "Interrupt" },
237 { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
238 { X25_RESET_REQUEST, "Reset" },
239 { X25_RESET_CONFIRMATION, "Reset Confirmation" },
240 { X25_RESTART_REQUEST, "Restart" },
241 { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
242 { X25_REGISTRATION_REQUEST, "Registration" },
243 { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
244 { X25_DIAGNOSTIC, "Diagnostic" },
248 { X25_DATA, "Data" },
252 static struct true_false_string m_bit_tfs = {
257 static const value_string x25_fast_select_vals[] = {
258 { 0, "Not requested" },
259 { 1, "Not requested" },
260 { 2, "No restriction on response" },
261 { 3, "Restriction on response" },
265 static const value_string x25_icrd_vals[] = {
266 { 0, "Status not selected" },
267 { 1, "Prevention requested" },
268 { 2, "Allowance requested" },
269 { 3, "Not allowed" },
273 static const value_string x25_clear_diag_vals[] = {
274 { 0, "No additional information" },
275 { 1, "Invalid P(S)" },
276 { 2, "Invalid P(R)" },
277 { 16, "Packet type invalid" },
278 { 17, "Packet type invalid for state r1" },
279 { 18, "Packet type invalid for state r2" },
280 { 19, "Packet type invalid for state r3" },
281 { 20, "Packet type invalid for state p1" },
282 { 21, "Packet type invalid for state p2" },
283 { 22, "Packet type invalid for state p3" },
284 { 23, "Packet type invalid for state p4" },
285 { 24, "Packet type invalid for state p5" },
286 { 25, "Packet type invalid for state p6" },
287 { 26, "Packet type invalid for state p7" },
288 { 27, "Packet type invalid for state d1" },
289 { 28, "Packet type invalid for state d2" },
290 { 29, "Packet type invalid for state d3" },
291 { 32, "Packet not allowed" },
292 { 33, "Unidentifiable packet" },
293 { 34, "Call on one-way logical channel" },
294 { 35, "Invalid packet type on a PVC" },
295 { 36, "Packet on unassigned LC" },
296 { 37, "Reject not subscribed to" },
297 { 38, "Packet too short" },
298 { 39, "Packet too long" },
299 { 40, "Invalid general format identifier" },
300 { 41, "Restart/registration packet with nonzero bits" },
301 { 42, "Packet type not compatible with facility" },
302 { 43, "Unauthorised interrupt confirmation" },
303 { 44, "Unauthorised interrupt" },
304 { 45, "Unauthorised reject" },
305 { 48, "Time expired" },
306 { 49, "Time expired for incoming call" },
307 { 50, "Time expired for clear indication" },
308 { 51, "Time expired for reset indication" },
309 { 52, "Time expired for restart indication" },
310 { 53, "Time expired for call deflection" },
311 { 64, "Call set-up/clearing or registration pb." },
312 { 65, "Facility/registration code not allowed" },
313 { 66, "Facility parameter not allowed" },
314 { 67, "Invalid called DTE address" },
315 { 68, "Invalid calling DTE address" },
316 { 69, "Invalid facility/registration length" },
317 { 70, "Incoming call barred" },
318 { 71, "No logical channel available" },
319 { 72, "Call collision" },
320 { 73, "Duplicate facility requested" },
321 { 74, "Non zero address length" },
322 { 75, "Non zero facility length" },
323 { 76, "Facility not provided when expected" },
324 { 77, "Invalid CCITT-specified DTE facility" },
325 { 78, "Max. nb of call redir/defl. exceeded" },
326 { 80, "Miscellaneous" },
327 { 81, "Improper cause code from DTE" },
328 { 82, "Not aligned octet" },
329 { 83, "Inconsistent Q bit setting" },
330 { 84, "NUI problem" },
331 { 112, "International problem" },
332 { 113, "Remote network problem" },
333 { 114, "International protocol problem" },
334 { 115, "International link out of order" },
335 { 116, "International link busy" },
336 { 117, "Transit network facility problem" },
337 { 118, "Remote network facility problem" },
338 { 119, "International routing problem" },
339 { 120, "Temporary routing problem" },
340 { 121, "Unknown called DNIC" },
341 { 122, "Maintenance action" },
342 { 144, "Timer expired or retransmission count surpassed" },
343 { 145, "Timer expired or retransmission count surpassed for INTERRUPT" },
344 { 146, "Timer expired or retransmission count surpassed for DATA packet transmission" },
345 { 147, "Timer expired or retransmission count surpassed for REJECT" },
346 { 160, "DTE-specific signals" },
347 { 161, "DTE operational" },
348 { 162, "DTE not operational" },
349 { 163, "DTE resource constraint" },
350 { 164, "Fast select not subscribed" },
351 { 165, "Invalid partially full DATA packet" },
352 { 166, "D-bit procedure not supported" },
353 { 167, "Registration/Cancellation confirmed" },
354 { 224, "OSI network service problem" },
355 { 225, "Disconnection (transient condition)" },
356 { 226, "Disconnection (permanent condition)" },
357 { 227, "Connection rejection - reason unspecified (transient condition)" },
358 { 228, "Connection rejection - reason unspecified (permanent condition)" },
359 { 229, "Connection rejection - quality of service not available (transient condition)" },
360 { 230, "Connection rejection - quality of service not available (permanent condition)" },
361 { 231, "Connection rejection - NSAP unreachable (transient condition)" },
362 { 232, "Connection rejection - NSAP unreachable (permanent condition)" },
363 { 233, "reset - reason unspecified" },
364 { 234, "reset - congestion" },
365 { 235, "Connection rejection - NSAP address unknown (permanent condition)" },
366 { 240, "Higher layer initiated" },
367 { 241, "Disconnection - normal" },
368 { 242, "Disconnection - abnormal" },
369 { 243, "Disconnection - incompatible information in user data" },
370 { 244, "Connection rejection - reason unspecified (transient condition)" },
371 { 245, "Connection rejection - reason unspecified (permanent condition)" },
372 { 246, "Connection rejection - quality of service not available (transient condition)" },
373 { 247, "Connection rejection - quality of service not available (permanent condition)" },
374 { 248, "Connection rejection - incompatible information in user data" },
375 { 249, "Connection rejection - unrecognizable protocol identifier in user data" },
376 { 250, "Reset - user resynchronization" },
380 value_string_ext x25_clear_diag_vals_ext = VALUE_STRING_EXT_INIT(x25_clear_diag_vals);
382 static const value_string x25_registration_code_vals[] = {
383 { 0x03, "Invalid facility request" },
384 { 0x05, "Network congestion" },
385 { 0x13, "Local procedure error" },
386 { 0x7F, "Registration/cancellation confirmed" },
390 static const value_string x25_facilities_class_vals[] = {
391 { X25_FAC_CLASS_A>>6, "A" },
392 { X25_FAC_CLASS_B>>6, "B" },
393 { X25_FAC_CLASS_C>>6, "C" },
394 { X25_FAC_CLASS_D>>6, "D" },
398 static const value_string x25_facilities_classA_vals[] = {
399 { X25_FAC_COMP_MARK, "Marker" },
400 { X25_FAC_REVERSE, "Reverse charging / Fast select" },
401 { X25_FAC_CHARGING_INFO, "Charging information" },
402 { X25_FAC_THROUGHPUT, "Throughput class negotiation" },
403 { X25_FAC_CUG, "Closed user group selection" },
404 { X25_FAC_CALLED_MODIF, "Called address modified" },
405 { X25_FAC_CUG_OUTGOING_ACC, "Closed user group with outgoing access selection" },
406 { X25_FAC_THROUGHPUT_MIN, "Minimum throughput class" },
407 { X25_FAC_EXPRESS_DATA, "Negotiation of express data" },
411 static const value_string x25_facilities_classA_comp_mark_vals[] = {
412 { 0x00, "Network complementary services - calling DTE" },
413 { 0x0F, "DTE complementary services" },
414 { 0xFF, "Network complementary services - called DTE" },
418 static const value_string x25_facilities_classA_throughput_vals[] = {
433 static const value_string x25_facilities_classB_vals[] = {
434 { X25_FAC_BILATERAL_CUG, "Bilateral closed user group selection" },
435 { X25_FAC_PACKET_SIZE, "Packet size" },
436 { X25_FAC_WINDOW_SIZE, "Window size" },
437 { X25_FAC_RPOA_SELECTION, "RPOA selection" },
438 { X25_FAC_CUG_EXT, "Extended closed user group selection" },
439 { X25_FAC_CUG_OUTGOING_ACC_EXT, "Extended closed user group with outgoing access selection" },
440 { X25_FAC_TRANSIT_DELAY, "Transit delay selection and indication" },
444 static const value_string x25_facilities_classB_packet_size_vals[] = {
457 static const value_string x25_facilities_classC_vals[] = {
461 static const value_string x25_facilities_classD_vals[] = {
462 { X25_FAC_CALL_DURATION, "Call duration" },
463 { X25_FAC_SEGMENT_COUNT, "Segment count" },
464 { X25_FAC_CALL_TRANSFER, "Call redirection or deflection notification" },
465 { X25_FAC_RPOA_SELECTION_EXT, "Extended RPOA selection" },
466 { X25_FAC_CALLING_ADDR_EXT, "Calling address extension" },
467 { X25_FAC_MONETARY_UNIT, "Monetary Unit" },
468 { X25_FAC_NUI, "Network User Identification selection" },
469 { X25_FAC_CALLED_ADDR_EXT, "Called address extension" },
470 { X25_FAC_ETE_TRANSIT_DELAY, "End to end transit delay" },
471 { X25_FAC_CALL_DEFLECT, "Call deflection selection" },
472 { X25_FAC_PRIORITY, "Priority" },
476 static struct true_false_string x25_reverse_charging_val = {
481 static const value_string x25_facilities_call_transfer_reason_vals[] = {
482 { 0x01, "originally called DTE busy" },
483 { 0x07, "call dist. within a hunt group" },
484 { 0x09, "originally called DTE out of order" },
485 { 0x0F, "systematic call redirection" },
489 static const fragment_items x25_frag_items = {
494 &hf_x25_segment_overlap,
495 &hf_x25_segment_overlap_conflict,
496 &hf_x25_segment_multiple_tails,
497 &hf_x25_segment_too_long_segment,
498 &hf_x25_segment_error,
499 &hf_x25_segment_count,
501 &hf_x25_reassembled_length,
502 /* Reassembled data field */
507 static dissector_handle_t ip_handle;
508 static dissector_handle_t clnp_handle;
509 static dissector_handle_t ositp_handle;
510 static dissector_handle_t qllc_handle;
511 static dissector_handle_t data_handle;
514 static gboolean payload_is_qllc_sna = FALSE;
515 static gboolean call_request_nodata_is_cotp = FALSE;
516 static gboolean payload_check_data = FALSE;
517 static gboolean reassemble_x25 = TRUE;
519 /* Reassembly of X.25 */
521 static reassembly_table x25_reassembly_table;
523 static dissector_table_t x25_subdissector_table;
524 static heur_dissector_list_t x25_heur_subdissector_list;
527 x25_hash_add_proto_start(guint16 vc, guint32 frame, dissector_handle_t dissect)
532 * Is there already a circuit with this VC number?
534 circuit = find_circuit(CT_X25, vc, frame);
535 if (circuit != NULL) {
537 * Yes - close it, as we're creating a new one.
539 close_circuit(circuit, frame - 1);
543 * Set up a new circuit.
545 circuit = circuit_new(CT_X25, vc, frame);
550 circuit_set_dissector(circuit, dissect);
554 x25_hash_add_proto_end(guint16 vc, guint32 frame)
559 * Try to find the circuit.
561 circuit = find_circuit(CT_X25, vc, frame);
564 * If we succeeded, close it.
567 close_circuit(circuit, frame);
570 static const char *clear_code(unsigned char code)
572 if (code == 0x00 || (code & 0x80) == 0x80)
573 return "DTE Originated";
578 return "Number Busy";
580 return "Invalid Facility Requested";
582 return "Network Congestion";
584 return "Out Of Order";
586 return "Access Barred";
588 return "Not Obtainable";
590 return "Remote Procedure Error";
592 return "Local Procedure Error";
594 return "RPOA Out Of Order";
596 return "Reverse Charging Acceptance Not Subscribed";
598 return "Incompatible Destination";
600 return "Fast Select Acceptance Not Subscribed";
602 return "Destination Absent";
605 return wmem_strdup_printf(wmem_packet_scope(),"Unknown %02X", code);
608 static const char *reset_code(unsigned char code)
610 if (code == 0x00 || (code & 0x80) == 0x80)
611 return "DTE Originated";
616 return "Out of order";
618 return "Remote Procedure Error";
620 return "Local Procedure Error";
622 return "Network Congestion";
624 return "Remote DTE operational";
626 return "Network operational";
628 return "Incompatible Destination";
630 return "Network out of order";
633 return wmem_strdup_printf(wmem_packet_scope(),"Unknown %02X", code);
636 static const char *restart_code(unsigned char code)
638 if (code == 0x00 || (code & 0x80) == 0x80)
639 return "DTE Originated";
644 return "Local Procedure Error";
646 return "Network Congestion";
648 return "Network Operational";
650 return "Registration/cancellation confirmed";
653 return wmem_strdup_printf(wmem_packet_scope(),"Unknown %02X", code);
657 dte_address_util(tvbuff_t *tvb, int offset, guint8 len)
660 char *tmpbuf = (char *)wmem_alloc(wmem_packet_scope(), 258);
662 for (i = 0; (i<len)&&(i<256); i++) {
664 tmpbuf[i] = ((tvb_get_guint8(tvb, offset+i/2) >> 4) & 0x0F) + '0';
665 /* if > 9, convert to the right hexadecimal letter */
667 tmpbuf[i] += ('A' - '0' - 10);
669 tmpbuf[i] = (tvb_get_guint8(tvb, offset+i/2) & 0x0F) + '0';
670 /* if > 9, convert to the right hexadecimal letter */
672 tmpbuf[i] += ('A' - '0' - 10);
682 add_priority(proto_tree *tree, int hf, tvbuff_t *tvb, int offset)
686 priority = tvb_get_guint8(tvb, offset);
688 proto_tree_add_uint_format_value(tree, hf, tvb, offset, 1, priority,
689 "Unspecified (255)");
691 proto_tree_add_uint(tree, hf, tvb, offset, 1, priority);
695 dump_facilities(proto_tree *tree, int *offset, tvbuff_t *tvb, packet_info *pinfo)
697 guint8 fac, byte1, byte2, byte3;
698 guint32 len; /* facilities length */
699 proto_item *ti = NULL;
700 proto_tree *facilities_tree = NULL, *facility_tree = NULL;
702 len = tvb_get_guint8(tvb, *offset);
704 ti = proto_tree_add_text(tree, tvb, *offset, len + 1,
706 facilities_tree = proto_item_add_subtree(ti, ett_x25_facilities);
707 proto_tree_add_item(facilities_tree, hf_x25_facilities_length, tvb, *offset, 1, ENC_NA);
712 ti = proto_tree_add_item(facilities_tree, hf_x25_facility, tvb, *offset, -1, ENC_NA);
713 fac = tvb_get_guint8(tvb, *offset);
714 switch(fac & X25_FAC_CLASS_MASK) {
715 case X25_FAC_CLASS_A:
716 proto_item_set_len(ti, 2);
717 proto_item_append_text(ti, ": %s",
718 val_to_str(fac, x25_facilities_classA_vals, "Unknown (0x%02X)"));
719 facility_tree = proto_item_add_subtree(ti, ett_x25_facility);
720 proto_tree_add_item(facility_tree, hf_x25_facility_class, tvb, *offset, 1, ENC_NA);
721 proto_tree_add_item(facility_tree, hf_x25_facility_classA, tvb, *offset, 1, ENC_NA);
724 case X25_FAC_COMP_MARK:
725 proto_tree_add_item(facility_tree, hf_x25_facility_classA_comp_mark, tvb, *offset+1, 1, ENC_NA);
727 case X25_FAC_REVERSE:
728 proto_tree_add_item(facility_tree, hf_x25_facility_classA_reverse, tvb, *offset+1, 1, ENC_NA);
729 proto_tree_add_item(facility_tree, hf_x25_fast_select, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
730 proto_tree_add_item(facility_tree, hf_x25_icrd, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
731 proto_tree_add_item(facility_tree, hf_x25_facility_reverse_charging, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
733 case X25_FAC_CHARGING_INFO:
734 proto_tree_add_item(facility_tree, hf_x25_facility_classA_charging_info, tvb, *offset+1, 1, ENC_NA);
735 proto_tree_add_item(facility_tree, hf_x25_facility_charging_info, tvb, *offset+1, 1, ENC_NA);
737 case X25_FAC_THROUGHPUT:
738 proto_tree_add_item(facility_tree, hf_x25_facility_throughput_called_dte, tvb, *offset+1, 1, ENC_NA);
739 proto_tree_add_item(facility_tree, hf_x25_throughput_called_dte, tvb, *offset+1, 1, ENC_NA);
742 proto_tree_add_item(facility_tree, hf_x25_facility_classA_cug, tvb, *offset+1, 1, ENC_NA);
744 case X25_FAC_CALLED_MODIF:
745 proto_tree_add_item(facility_tree, hf_x25_facility_classA_called_motif, tvb, *offset+1, 1, ENC_NA);
747 case X25_FAC_CUG_OUTGOING_ACC:
748 proto_tree_add_item(facility_tree, hf_x25_facility_classA_cug_outgoing_acc, tvb, *offset+1, 1, ENC_NA);
750 case X25_FAC_THROUGHPUT_MIN:
751 proto_tree_add_item(facility_tree, hf_x25_facility_classA_throughput_min, tvb, *offset+1, 1, ENC_NA);
753 case X25_FAC_EXPRESS_DATA:
754 proto_tree_add_item(facility_tree, hf_x25_facility_classA_express_data, tvb, *offset+1, 1, ENC_NA);
757 proto_tree_add_item(facility_tree, hf_x25_facility_classA_unknown, tvb, *offset+1, 1, ENC_NA);
764 case X25_FAC_CLASS_B:
765 proto_item_set_len(ti, 3);
766 proto_item_append_text(ti, ": %s",
767 val_to_str(fac, x25_facilities_classB_vals, "Unknown (0x%02X)"));
768 facility_tree = proto_item_add_subtree(ti, ett_x25_facility);
769 proto_tree_add_item(facility_tree, hf_x25_facility_class, tvb, *offset, 1, ENC_NA);
770 proto_tree_add_item(facility_tree, hf_x25_facility_classB, tvb, *offset, 1, ENC_NA);
773 case X25_FAC_BILATERAL_CUG:
774 proto_tree_add_item(facility_tree, hf_x25_facility_classB_bilateral_cug, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
776 case X25_FAC_PACKET_SIZE:
777 proto_tree_add_item(facility_tree, hf_x25_facility_packet_size_called_dte, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
778 proto_tree_add_item(facility_tree, hf_x25_facility_packet_size_calling_dte, tvb, *offset+2, 1, ENC_BIG_ENDIAN);
780 case X25_FAC_WINDOW_SIZE:
781 proto_tree_add_item(facility_tree, hf_x25_window_size_called_dte, tvb, *offset+1, 1, ENC_NA);
782 proto_tree_add_item(facility_tree, hf_x25_window_size_calling_dte, tvb, *offset+2, 1, ENC_NA);
784 case X25_FAC_RPOA_SELECTION:
785 proto_tree_add_item(facility_tree, hf_x25_facility_data_network_id_code, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
787 case X25_FAC_CUG_EXT:
788 proto_tree_add_item(facility_tree, hf_x25_facility_cug_ext, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
790 case X25_FAC_CUG_OUTGOING_ACC_EXT:
791 proto_tree_add_item(facility_tree, hf_x25_facility_cug_outgoing_acc_ext, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
793 case X25_FAC_TRANSIT_DELAY:
794 proto_tree_add_item(facility_tree, hf_x25_facility_transit_delay, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
797 proto_tree_add_item(facility_tree, hf_x25_facility_classB_unknown, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
804 case X25_FAC_CLASS_C:
805 proto_item_set_len(ti, 4);
806 proto_item_append_text(ti, ": %s",
807 val_to_str(fac, x25_facilities_classC_vals, "Unknown (0x%02X)"));
808 facility_tree = proto_item_add_subtree(ti, ett_x25_facility);
809 proto_tree_add_item(facility_tree, hf_x25_facility_class, tvb, *offset, 1, ENC_NA);
810 proto_tree_add_item(facility_tree, hf_x25_facility_classC, tvb, *offset, 1, ENC_NA);
812 proto_tree_add_item(facility_tree, hf_x25_facility_classC_unknown, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
817 case X25_FAC_CLASS_D:
818 proto_item_append_text(ti, ": %s",
819 val_to_str(fac, x25_facilities_classD_vals, "Unknown (0x%02X)"));
820 facility_tree = proto_item_add_subtree(ti, ett_x25_facility);
821 proto_tree_add_item(facility_tree, hf_x25_facility_class, tvb, *offset, 1, ENC_NA);
822 byte1 = tvb_get_guint8(tvb, *offset+1);
823 proto_item_set_len(ti, byte1+2);
824 proto_tree_add_item(facility_tree, hf_x25_facility_classD, tvb, *offset, 1, ENC_NA);
825 proto_tree_add_item(facility_tree, hf_x25_facility_length, tvb, *offset+1, 1, ENC_NA);
828 case X25_FAC_CALL_DURATION:
832 if ((byte1 < 4) || (byte1 % 4)) {
833 expert_add_info(pinfo, ti, &ei_x25_facility_length);
836 for (i = 0; (i<byte1); i+=4) {
837 proto_tree_add_text(facility_tree, tvb, *offset+2+i, 4,
838 "Call duration: %u Day(s) %02X:%02X:%02X Hour(s)",
839 tvb_get_guint8(tvb, *offset+2+i),
840 tvb_get_guint8(tvb, *offset+3+i),
841 tvb_get_guint8(tvb, *offset+4+i),
842 tvb_get_guint8(tvb, *offset+5+i));
846 case X25_FAC_SEGMENT_COUNT:
850 if ((byte1 < 8) || (byte1 % 8)) {
851 expert_add_info(pinfo, ti, &ei_x25_facility_length);
854 for (i = 0; (i<byte1); i+=8) {
855 proto_tree_add_text(facility_tree, tvb, *offset+2+i, 4,
856 "Segments sent to DTE: %02X%02X%02X%02X",
857 tvb_get_guint8(tvb, *offset+2+i),
858 tvb_get_guint8(tvb, *offset+3+i),
859 tvb_get_guint8(tvb, *offset+4+i),
860 tvb_get_guint8(tvb, *offset+5+i));
861 proto_tree_add_text(facility_tree, tvb, *offset+6+i, 4,
862 "Segments received from DTE: %02X%02X%02X%02X",
863 tvb_get_guint8(tvb, *offset+6+i),
864 tvb_get_guint8(tvb, *offset+7+i),
865 tvb_get_guint8(tvb, *offset+8+i),
866 tvb_get_guint8(tvb, *offset+9+i));
870 case X25_FAC_CALL_TRANSFER:
875 expert_add_info(pinfo, ti, &ei_x25_facility_length);
878 byte2 = tvb_get_guint8(tvb, *offset+2);
879 if ((byte2 & 0xC0) == 0xC0) {
880 proto_tree_add_uint_format_value(facility_tree, hf_x25_facility_call_transfer_reason, tvb,
881 *offset+2, 1, byte2, "call deflection by the originally called DTE address");
884 proto_tree_add_uint(facility_tree, hf_x25_facility_call_transfer_reason, tvb, *offset+2, 1, byte2);
886 byte3 = tvb_get_guint8(tvb, *offset+3);
887 proto_tree_add_uint(facility_tree, hf_x25_facility_call_transfer_num_semi_octets, tvb, *offset+4, 1, byte3);
888 tmpbuf = dte_address_util(tvb, *offset + 4, byte3);
890 proto_tree_add_text(facility_tree, tvb, *offset+4, byte1 - 2,
891 "DTE address: %s", tmpbuf);
894 case X25_FAC_RPOA_SELECTION_EXT:
898 if ((byte1 < 2) || (byte1 % 2)) {
899 expert_add_info(pinfo, ti, &ei_x25_facility_length);
902 for (i = 0; (i<byte1); i+=2) {
903 proto_tree_add_text(facility_tree, tvb, *offset+2+i, 2,
904 "Data network identification code: %04X",
905 tvb_get_ntohs(tvb, *offset+2+i));
909 case X25_FAC_CALLING_ADDR_EXT:
914 expert_add_info(pinfo, ti, &ei_x25_facility_length);
917 byte2 = tvb_get_guint8(tvb, *offset+2) & 0x3F;
918 proto_tree_add_uint(facility_tree, hf_x25_facility_calling_addr_ext_num_semi_octets, tvb, *offset+2, 1, byte2);
919 tmpbuf = dte_address_util(tvb, *offset + 3, byte2);
920 proto_tree_add_text(facility_tree, tvb, *offset+3, byte1 - 1,
921 "DTE address: %s", tmpbuf);
924 case X25_FAC_MONETARY_UNIT:
925 proto_tree_add_item(facility_tree, hf_x25_facility_monetary_unit, tvb, *offset+2, byte1, ENC_NA);
928 proto_tree_add_item(facility_tree, hf_x25_facility_nui, tvb, *offset+2, byte1, ENC_NA);
930 case X25_FAC_CALLED_ADDR_EXT:
935 expert_add_info(pinfo, ti, &ei_x25_facility_length);
938 byte2 = tvb_get_guint8(tvb, *offset+2) & 0x3F;
939 proto_tree_add_uint(facility_tree, hf_x25_facility_called_addr_ext_num_semi_octets, tvb, *offset+2, 1, byte2);
940 tmpbuf = dte_address_util(tvb, *offset+3, byte2);
942 proto_tree_add_text(facility_tree, tvb, *offset+3, byte1 - 1,
943 "DTE address: %s", tmpbuf);
946 case X25_FAC_ETE_TRANSIT_DELAY:
949 proto_tree_add_item(facility_tree, hf_x25_facility_cumulative_ete_transit_delay, tvb, *offset+2, 2, ENC_BIG_ENDIAN);
952 proto_tree_add_item(facility_tree, hf_x25_facility_requested_ete_transit_delay, tvb, *offset+4, 2, ENC_BIG_ENDIAN);
955 proto_tree_add_item(facility_tree, hf_x25_facility_max_acceptable_ete_transit_delay, tvb, *offset+6, 2, ENC_BIG_ENDIAN);
957 case X25_FAC_CALL_DEFLECT:
962 expert_add_info(pinfo, ti, &ei_x25_facility_length);
965 byte2 = tvb_get_guint8(tvb, *offset+2);
966 if ((byte2 & 0xC0) == 0xC0)
967 proto_tree_add_text(facility_tree, tvb, *offset+2, 1,
968 "Reason: call DTE originated");
970 proto_tree_add_text(facility_tree, tvb, *offset+2, 1,
972 byte3 = tvb_get_guint8(tvb, *offset+3);
973 proto_tree_add_uint(facility_tree, hf_x25_facility_call_deflect_num_semi_octets, tvb, *offset+3, 1, byte3);
974 tmpbuf = dte_address_util(tvb, *offset+4, byte3);
976 proto_tree_add_text(facility_tree, tvb, *offset+4, byte1 - 2,
977 "Alternative DTE address: %s", tmpbuf);
980 case X25_FAC_PRIORITY:
983 add_priority(facility_tree, hf_x25_facility_priority_data, tvb, *offset+2);
986 add_priority(facility_tree, hf_x25_facility_priority_estab_conn, tvb, *offset+3);
989 add_priority(facility_tree, hf_x25_facility_priority_keep_conn, tvb, *offset+4);
992 add_priority(facility_tree, hf_x25_facility_min_acceptable_priority_data, tvb, *offset+5);
995 add_priority(facility_tree, hf_x25_facility_min_acceptable_priority_estab_conn, tvb, *offset+6);
998 add_priority(facility_tree, hf_x25_facility_min_acceptable_priority_keep_conn, tvb, *offset+7);
1001 proto_tree_add_item(facility_tree, hf_x25_facility_classD_unknown, tvb, *offset+2, byte1, ENC_NA);
1004 byte1 = tvb_get_guint8(tvb, *offset+1);
1005 (*offset) += byte1+2;
1013 x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1014 packet_info *pinfo, gboolean is_registration)
1018 char *addr1, *addr2;
1019 char *first, *second;
1023 addr1=(char *)wmem_alloc(wmem_packet_scope(), 16);
1024 addr2=(char *)wmem_alloc(wmem_packet_scope(), 16);
1026 byte = tvb_get_guint8(tvb, *offset);
1027 len1 = (byte >> 0) & 0x0F;
1028 len2 = (byte >> 4) & 0x0F;
1031 if (is_registration) {
1032 proto_tree_add_item(tree, hf_x25_dte_address_length, tvb, *offset, 1, ENC_NA);
1033 proto_tree_add_item(tree, hf_x25_dce_address_length, tvb, *offset, 1, ENC_NA);
1036 proto_tree_add_item(tree, hf_x25_calling_address_length, tvb, *offset, 1, ENC_NA);
1037 proto_tree_add_item(tree, hf_x25_called_address_length, tvb, *offset, 1, ENC_NA);
1042 localoffset = *offset;
1043 byte = tvb_get_guint8(tvb, localoffset);
1047 for (i = 0; i < (len1 + len2); i++) {
1050 *first++ = ((byte >> 0) & 0x0F) + '0';
1052 byte = tvb_get_guint8(tvb, localoffset);
1054 *first++ = ((byte >> 4) & 0x0F) + '0';
1058 *second++ = ((byte >> 0) & 0x0F) + '0';
1060 byte = tvb_get_guint8(tvb, localoffset);
1062 *second++ = ((byte >> 4) & 0x0F) + '0';
1071 col_add_str(pinfo->cinfo, COL_RES_DL_DST, addr1);
1073 proto_tree_add_text(tree, tvb, *offset,
1077 "Called address: %s",
1081 col_add_str(pinfo->cinfo, COL_RES_DL_SRC, addr2);
1083 proto_tree_add_text(tree, tvb, *offset + len1/2,
1084 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1087 "Calling address: %s",
1090 (*offset) += ((len1 + len2 + 1) / 2);
1094 x25_toa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1099 char *addr1, *addr2;
1100 char *first, *second;
1104 addr1=(char *)wmem_alloc(wmem_packet_scope(), 256);
1105 addr2=(char *)wmem_alloc(wmem_packet_scope(), 256);
1107 len1 = tvb_get_guint8(tvb, *offset);
1109 proto_tree_add_text(tree, tvb, *offset, 1,
1110 "Called address length: %u",
1115 len2 = tvb_get_guint8(tvb, *offset);
1117 proto_tree_add_text(tree, tvb, *offset, 1,
1118 "Calling address length: %u",
1123 localoffset = *offset;
1124 byte = tvb_get_guint8(tvb, localoffset);
1127 * XXX - the first two half-octets of the address are the TOA and
1128 * NPI; process them as such and, if the TOA says an address is
1129 * an alternative address, process it correctly (i.e., not as a
1130 * sequence of half-octets containing digit values).
1134 for (i = 0; i < (len1 + len2); i++) {
1137 *first++ = ((byte >> 0) & 0x0F) + '0';
1139 byte = tvb_get_guint8(tvb, localoffset);
1141 *first++ = ((byte >> 4) & 0x0F) + '0';
1145 *second++ = ((byte >> 0) & 0x0F) + '0';
1147 byte = tvb_get_guint8(tvb, localoffset);
1149 *second++ = ((byte >> 4) & 0x0F) + '0';
1158 col_add_str(pinfo->cinfo, COL_RES_DL_DST, addr1);
1160 proto_tree_add_text(tree, tvb, *offset,
1162 "Called address: %s",
1166 col_add_str(pinfo->cinfo, COL_RES_DL_SRC, addr2);
1168 proto_tree_add_text(tree, tvb, *offset + len1/2,
1169 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1170 "Calling address: %s",
1173 (*offset) += ((len1 + len2 + 1) / 2);
1177 get_x25_pkt_len(tvbuff_t *tvb)
1179 guint length, called_len, calling_len, dte_len, dce_len;
1180 guint8 byte2, bytex;
1182 byte2 = tvb_get_guint8(tvb, 2);
1185 case X25_CALL_REQUEST:
1186 bytex = tvb_get_guint8(tvb, 3);
1187 called_len = (bytex >> 0) & 0x0F;
1188 calling_len = (bytex >> 4) & 0x0F;
1189 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1190 if (length < tvb_reported_length(tvb))
1191 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1193 return MIN(tvb_reported_length(tvb),length);
1195 case X25_CALL_ACCEPTED:
1196 /* The calling/called address length byte (following the packet type)
1197 * is not mandatory, so we must check the packet length before trying
1199 if (tvb_reported_length(tvb) == 3)
1201 bytex = tvb_get_guint8(tvb, 3);
1202 called_len = (bytex >> 0) & 0x0F;
1203 calling_len = (bytex >> 4) & 0x0F;
1204 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1205 if (length < tvb_reported_length(tvb))
1206 length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1208 return MIN(tvb_reported_length(tvb),length);
1210 case X25_CLEAR_REQUEST:
1211 case X25_RESET_REQUEST:
1212 case X25_RESTART_REQUEST:
1213 return MIN(tvb_reported_length(tvb),5);
1215 case X25_DIAGNOSTIC:
1216 return MIN(tvb_reported_length(tvb),4);
1218 case X25_CLEAR_CONFIRMATION:
1220 case X25_INTERRUPT_CONFIRMATION:
1221 case X25_RESET_CONFIRMATION:
1222 case X25_RESTART_CONFIRMATION:
1223 return MIN(tvb_reported_length(tvb),3);
1225 case X25_REGISTRATION_REQUEST:
1226 bytex = tvb_get_guint8(tvb, 3);
1227 dce_len = (bytex >> 0) & 0x0F;
1228 dte_len = (bytex >> 4) & 0x0F;
1229 length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1230 if (length < tvb_reported_length(tvb))
1231 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1233 return MIN(tvb_reported_length(tvb),length);
1235 case X25_REGISTRATION_CONFIRMATION:
1236 bytex = tvb_get_guint8(tvb, 5);
1237 dce_len = (bytex >> 0) & 0x0F;
1238 dte_len = (bytex >> 4) & 0x0F;
1239 length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1240 if (length < tvb_reported_length(tvb))
1241 length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1243 return MIN(tvb_reported_length(tvb),length);
1246 if (PACKET_IS_DATA(byte2))
1247 return MIN(tvb_reported_length(tvb),3);
1249 switch (PACKET_TYPE_FC(byte2))
1252 return MIN(tvb_reported_length(tvb),3);
1255 return MIN(tvb_reported_length(tvb),3);
1258 return MIN(tvb_reported_length(tvb),3);
1264 static const value_string prt_id_vals[] = {
1265 {PRT_ID_ISO_8073, "ISO 8073 COTP"},
1266 {PRT_ID_ISO_8602, "ISO 8602 CLTP"},
1267 {PRT_ID_ISO_10736_ISO_8073, "ISO 10736 in conjunction with ISO 8073 COTP"},
1268 {PRT_ID_ISO_10736_ISO_8602, "ISO 10736 in conjunction with ISO 8602 CLTP"},
1272 static const value_string sharing_strategy_vals[] = {
1273 {0x00, "No sharing"},
1278 dissect_x25_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1279 x25_dir_t dir, gboolean side)
1281 proto_tree *x25_tree=0, *gfi_tree=0, *userdata_tree=0;
1283 guint localoffset=0;
1287 dissector_handle_t dissect = NULL;
1288 gboolean toa; /* TOA/NPI address format */
1291 const char *short_name = NULL, *long_name = NULL;
1292 tvbuff_t *next_tvb = NULL;
1293 gboolean q_bit_set = FALSE;
1297 void *saved_private_data;
1298 fragment_head *fd_head;
1304 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X.25");
1305 col_clear(pinfo->cinfo, COL_INFO);
1307 bytes0_1 = tvb_get_ntohs(tvb, 0);
1309 modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
1310 vc = (int)(bytes0_1 & 0x0FFF);
1312 pinfo->ctype = CT_X25;
1313 pinfo->circuit_id = vc;
1315 if (bytes0_1 & X25_ABIT) toa = TRUE;
1318 x25_pkt_len = get_x25_pkt_len(tvb);
1319 if (x25_pkt_len < 3) /* packet too short */
1321 col_set_str(pinfo->cinfo, COL_INFO, "Invalid/short X.25 packet");
1323 proto_tree_add_protocol_format(tree, proto_x25, tvb, 0, -1,
1324 "Invalid/short X.25 packet");
1328 pkt_type = tvb_get_guint8(tvb, 2);
1329 if (PACKET_IS_DATA(pkt_type)) {
1330 if (bytes0_1 & X25_QBIT)
1335 ti = proto_tree_add_item(tree, proto_x25, tvb, 0, x25_pkt_len, ENC_NA);
1336 x25_tree = proto_item_add_subtree(ti, ett_x25);
1337 ti = proto_tree_add_item(x25_tree, hf_x25_gfi, tvb, 0, 2, ENC_BIG_ENDIAN);
1338 gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
1340 if (PACKET_IS_DATA(pkt_type)) {
1341 proto_tree_add_boolean(gfi_tree, hf_x25_qbit, tvb, 0, 2,
1344 else if (pkt_type == X25_CALL_REQUEST ||
1345 pkt_type == X25_CALL_ACCEPTED ||
1346 pkt_type == X25_CLEAR_REQUEST ||
1347 pkt_type == X25_CLEAR_CONFIRMATION) {
1348 proto_tree_add_boolean(gfi_tree, hf_x25_abit, tvb, 0, 2,
1352 if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
1353 PACKET_IS_DATA(pkt_type)) {
1354 proto_tree_add_boolean(gfi_tree, hf_x25_dbit, tvb, 0, 2,
1357 proto_tree_add_uint(gfi_tree, hf_x25_mod, tvb, 0, 2, bytes0_1);
1361 case X25_CALL_REQUEST:
1365 short_name = "Inc. call";
1366 long_name = "Incoming call";
1370 short_name = "Call req.";
1371 long_name = "Call request";
1375 short_name = "Inc. call/Call req.";
1376 long_name = "Incoming call/Call request";
1379 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d", short_name, vc);
1381 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb,
1383 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1384 X25_CALL_REQUEST, "%s", long_name);
1387 if (localoffset < x25_pkt_len) { /* calling/called addresses */
1389 x25_toa(x25_tree, (gint*)&localoffset, tvb, pinfo);
1391 x25_ntoa(x25_tree, (gint*)&localoffset, tvb, pinfo, FALSE);
1394 if (localoffset < x25_pkt_len) /* facilities */
1395 dump_facilities(x25_tree, (gint*)&localoffset, tvb, pinfo);
1397 if (localoffset < tvb_reported_length(tvb)) /* user data */
1401 ti = proto_tree_add_text(x25_tree, tvb, localoffset, -1,
1403 userdata_tree = proto_item_add_subtree(ti, ett_x25_user_data);
1406 /* X.263/ISO 9577 says that:
1408 When CLNP or ESIS are run over X.25, the SPI
1409 is 0x81 or 0x82, respectively; those are the
1410 NLPIDs for those protocol.
1412 When X.224/ISO 8073 COTP is run over X.25, and
1413 when ISO 11570 explicit identification is being
1414 used, the first octet of the user data field is
1415 a TPDU length field, and the rest is "as defined
1416 in ITU-T Rec. X.225 | ISO/IEC 8073, Annex B,
1417 or ITU-T Rec. X.264 and ISO/IEC 11570".
1419 When X.264/ISO 11570 default identification is
1420 being used, there is no user data field in the
1421 CALL REQUEST packet. This is for X.225/ISO 8073
1424 It also says that SPI values from 0x03 through 0x3f are
1425 reserved and are in use by X.224/ISO 8073 Annex B and
1426 X.264/ISO 11570. The note says that those values are
1427 not NLPIDs, they're "used by the respective higher layer
1428 protocol" and "not used for higher layer protocol
1429 identification". I infer from this and from what
1430 X.264/ISO 11570 says that this means that values in those
1431 range are valid values for the first octet of an
1432 X.224/ISO 8073 packet or for X.264/ISO 11570.
1434 Annex B of X.225/ISO 8073 mentions some additional TPDU
1435 types that can be put in what I presume is the user
1436 data of connect requests. It says that:
1438 The sending transport entity shall:
1440 a) either not transmit any TPDU in the NS-user data
1441 parameter of the N-CONNECT request primitive; or
1443 b) transmit the UN-TPDU (see ITU-T Rec. X.264 and
1444 ISO/IEC 11570) followed by the NCM-TPDU in the
1445 NS-user data parameter of the N-CONNECT request
1448 I don't know if this means that the user data field
1449 will contain a UN TPDU followed by an NCM TPDU or not.
1451 X.264/ISO 11570 says that:
1453 When default identification is being used,
1454 X.225/ISO 8073 COTP is identified. No user data
1455 is sent in the network-layer connection request.
1457 When explicit identification is being used,
1458 the user data is a UN TPDU ("Use of network
1459 connection TPDU"), which specifies the transport
1460 protocol to use over this network connection.
1461 It also says that the length of a UN TPDU shall
1462 not exceed 32 octets, i.e. shall not exceed 0x20;
1463 it says this is "due to the desire not to conflict
1464 with the protocol identifier field carried by X.25
1465 CALL REQUEST/INCOMING CALL packets", and says that
1466 field has values specified in X.244. X.244 has been
1467 superseded by X.263/ISO 9577, so that presumably
1468 means the goal is to allow a UN TPDU's length
1469 field to be distinguished from an NLPID, allowing
1470 you to tell whether X.264/ISO 11570 explicit
1471 identification is being used or an NLPID is
1472 being used as the SPI.
1474 I read this as meaning that, if the ISO mechanisms are
1475 used to identify the protocol being carried over X.25:
1477 if there's no user data in the CALL REQUEST/
1478 INCOMING CALL packet, it's COTP;
1480 if there is user data, then:
1482 if the first octet is less than or equal to
1483 32, it might be a UN TPDU, and that identifies
1484 the transport protocol being used, and
1485 it may be followed by more data, such
1486 as a COTP NCM TPDU if it's COTP;
1488 if the first octet is greater than 32, it's
1489 an NLPID, *not* a TPDU length, and the
1490 stuff following it is *not* a TPDU.
1492 Figure A.2 of X.263/ISO 9577 seems to say that the
1493 first octet of the user data is a TPDU length field,
1494 in the range 0x03 through 0x82, and says they are
1495 for X.225/ISO 8073 Annex B or X.264/ISO 11570.
1497 However, X.264/ISO 11570 seems to imply that the length
1498 field would be that of a UN TPDU, which must be less
1499 than or equal to 0x20, and X.225/ISO 8073 Annex B seems
1500 to indicate that the user data must begin with
1501 an X.264/ISO 11570 UN TPDU, so I'd say that A.2 should
1502 have said "in the range 0x03 through 0x20", instead
1503 (the length value doesn't include the length field,
1504 and the minimum UN TPDU has length, type, PRT-ID,
1505 and SHARE, so that's 3 bytes without the length). */
1506 spi = tvb_get_guint8(tvb, localoffset);
1507 if (spi > 32 || spi < 3) {
1508 /* First octet is > 32, or < 3, so the user data isn't an
1509 X.264/ISO 11570 UN TPDU */
1512 /* First octet is >= 3 and <= 32, so the user data *might*
1513 be an X.264/ISO 11570 UN TPDU. Check whether we have
1514 enough data to see if it is. */
1515 if (tvb_bytes_exist(tvb, localoffset+1, 1)) {
1516 /* We do; check whether the second octet is 1. */
1517 if (tvb_get_guint8(tvb, localoffset+1) == 0x01) {
1518 /* Yes, the second byte is 1, so it looks like
1522 /* No, the second byte is not 1, so it's not a
1527 /* We can't see the second byte of the putative UN
1528 TPDU, so we don't know if that's what it is. */
1532 if (is_x_264 == -1) {
1534 * We don't know what it is; just skip it.
1536 localoffset = tvb_length(tvb);
1537 } else if (is_x_264) {
1538 /* It looks like an X.264 UN TPDU, so show it as such. */
1539 if (userdata_tree) {
1540 proto_tree_add_item( userdata_tree, hf_x264_length_indicator, tvb, localoffset, 1, ENC_NA);
1541 proto_tree_add_item( userdata_tree, hf_x264_un_tpdu_id, tvb, localoffset+1, 1, ENC_NA);
1543 prt_id = tvb_get_guint8(tvb, localoffset+2);
1544 if (userdata_tree) {
1545 proto_tree_add_item( userdata_tree, hf_x264_protocol_id, tvb, localoffset+2, 1, ENC_NA);
1546 proto_tree_add_item( userdata_tree, hf_x264_sharing_strategy, tvb, localoffset+3, 1, ENC_NA);
1549 /* XXX - dissect the variable part? */
1551 /* The length doesn't include the length octet itself. */
1552 localoffset += spi + 1;
1556 case PRT_ID_ISO_8073:
1558 if (!pinfo->fd->flags.visited)
1559 x25_hash_add_proto_start(vc, pinfo->fd->num, ositp_handle);
1560 /* XXX - dissect the rest of the user data as COTP?
1561 That needs support for NCM TPDUs, etc. */
1564 case PRT_ID_ISO_8602:
1566 if (!pinfo->fd->flags.visited)
1567 x25_hash_add_proto_start(vc, pinfo->fd->num, ositp_handle);
1570 } else if (is_x_264 == 0) {
1571 /* It doesn't look like a UN TPDU, so compare the first
1572 octet of the CALL REQUEST packet with various X.263/
1573 ISO 9577 NLPIDs, as per Annex A of X.263/ISO 9577. */
1575 if (userdata_tree) {
1576 proto_tree_add_item( userdata_tree, hf_x263_sec_protocol_id, tvb, localoffset, 1, ENC_NA);
1579 if (!pinfo->fd->flags.visited) {
1581 * Is there a dissector handle for this SPI?
1582 * If so, assign it to this virtual circuit.
1584 dissect = dissector_get_uint_handle(x25_subdissector_table, spi);
1585 if (dissect != NULL)
1586 x25_hash_add_proto_start(vc, pinfo->fd->num, dissect);
1590 * If there's only one octet of user data, it's just
1591 * an NLPID; don't try to dissect it.
1593 if (localoffset + 1 == tvb_reported_length(tvb))
1597 * There's more than one octet of user data, so we'll
1598 * dissect it; for some protocols, the NLPID is considered
1599 * to be part of the PDU, so, for those cases, we don't
1600 * skip past it. For other protocols, we skip the NLPID.
1604 case NLPID_ISO8473_CLNP:
1605 case NLPID_ISO9542_ESIS:
1606 case NLPID_ISO10589_ISIS:
1607 case NLPID_ISO10747_IDRP:
1610 * The NLPID is part of the PDU. Don't skip it.
1611 * But if it's all there is to the PDU, don't
1612 * bother dissecting it.
1616 case NLPID_SPI_X_29:
1618 * The first 4 bytes of the call user data are
1619 * the SPI plus 3 reserved bytes; they are not
1620 * part of the data to be dissected as X.29 data.
1627 * The NLPID isn't part of the PDU - skip it.
1628 * If that means there's nothing to dissect
1634 /* if there's no user data in the CALL REQUEST/
1635 INCOMING CALL packet, it's COTP; */
1637 if (call_request_nodata_is_cotp){
1638 x25_hash_add_proto_start(vc, pinfo->fd->num, ositp_handle);
1642 case X25_CALL_ACCEPTED:
1646 short_name = "Call conn.";
1647 long_name = "Call connected";
1651 short_name = "Call acc.";
1652 long_name = "Call accepted";
1656 short_name = "Call conn./Call acc.";
1657 long_name = "Call connected/Call accepted";
1660 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d", short_name, vc);
1662 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1663 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1664 X25_CALL_ACCEPTED, "%s", long_name);
1667 if (localoffset < x25_pkt_len) { /* calling/called addresses */
1669 x25_toa(x25_tree, (gint*)&localoffset, tvb, pinfo);
1671 x25_ntoa(x25_tree, (gint*)&localoffset, tvb, pinfo, FALSE);
1674 if (localoffset < x25_pkt_len) /* facilities */
1675 dump_facilities(x25_tree, (gint*)&localoffset, tvb, pinfo);
1677 case X25_CLEAR_REQUEST:
1681 short_name = "Clear ind.";
1682 long_name = "Clear indication";
1686 short_name = "Clear req.";
1687 long_name = "Clear request";
1691 short_name = "Clear ind./Clear req.";
1692 long_name = "Clear indication/Clear request";
1695 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d %s - %s", short_name,
1696 vc, clear_code(tvb_get_guint8(tvb, 3)),
1697 val_to_str_ext(tvb_get_guint8(tvb, 4), &x25_clear_diag_vals_ext, "Unknown (0x%02x)"));
1698 x25_hash_add_proto_end(vc, pinfo->fd->num);
1700 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1701 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb,
1702 localoffset+2, 1, X25_CLEAR_REQUEST, "%s",
1704 proto_tree_add_text(x25_tree, tvb, 3, 1,
1705 "Cause: %s", clear_code(tvb_get_guint8(tvb, 3)));
1706 proto_tree_add_item(x25_tree, hf_x25_diagnostic, tvb, 4, 1, ENC_NA);
1708 localoffset = x25_pkt_len;
1710 case X25_CLEAR_CONFIRMATION:
1711 col_add_fstr(pinfo->cinfo, COL_INFO, "Clear Conf. VC:%d", vc);
1713 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1714 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1715 X25_CLEAR_CONFIRMATION);
1717 localoffset = x25_pkt_len;
1719 if (localoffset < tvb_reported_length(tvb)) { /* extended clear conf format */
1721 x25_toa(x25_tree, (gint*)&localoffset, tvb, pinfo);
1723 x25_ntoa(x25_tree,(gint*)&localoffset, tvb, pinfo, FALSE);
1726 if (localoffset < tvb_reported_length(tvb)) /* facilities */
1727 dump_facilities(x25_tree, (gint*)&localoffset, tvb, pinfo);
1729 case X25_DIAGNOSTIC:
1730 col_add_fstr(pinfo->cinfo, COL_INFO, "Diag. %d",
1731 (int)tvb_get_guint8(tvb, 3));
1733 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1735 proto_tree_add_text(x25_tree, tvb, 3, 1,
1736 "Diagnostic: %d", (int)tvb_get_guint8(tvb, 3));
1738 localoffset = x25_pkt_len;
1741 col_add_fstr(pinfo->cinfo, COL_INFO, "Interrupt VC:%d", vc);
1743 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1744 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1747 localoffset = x25_pkt_len;
1749 case X25_INTERRUPT_CONFIRMATION:
1750 col_add_fstr(pinfo->cinfo, COL_INFO, "Interrupt Conf. VC:%d", vc);
1752 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1753 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1754 X25_INTERRUPT_CONFIRMATION);
1756 localoffset = x25_pkt_len;
1758 case X25_RESET_REQUEST:
1762 short_name = "Reset ind.";
1763 long_name = "Reset indication";
1767 short_name = "Reset req.";
1768 long_name = "Reset request";
1772 short_name = "Reset ind./Reset req.";
1773 long_name = "Reset indication/Reset request";
1776 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d %s - Diag.:%d",
1777 short_name, vc, reset_code(tvb_get_guint8(tvb, 3)),
1778 (int)tvb_get_guint8(tvb, 4));
1779 x25_hash_add_proto_end(vc, pinfo->fd->num);
1781 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1782 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1783 X25_RESET_REQUEST, "%s", long_name);
1784 proto_tree_add_text(x25_tree, tvb, 3, 1,
1785 "Cause: %s", reset_code(tvb_get_guint8(tvb, 3)));
1786 proto_tree_add_text(x25_tree, tvb, 4, 1,
1787 "Diagnostic: %d", (int)tvb_get_guint8(tvb, 4));
1789 localoffset = x25_pkt_len;
1791 case X25_RESET_CONFIRMATION:
1792 col_add_fstr(pinfo->cinfo, COL_INFO, "Reset conf. VC:%d", vc);
1794 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1795 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1796 X25_RESET_CONFIRMATION);
1798 localoffset = x25_pkt_len;
1800 case X25_RESTART_REQUEST:
1804 short_name = "Restart ind.";
1805 long_name = "Restart indication";
1809 short_name = "Restart req.";
1810 long_name = "Restart request";
1814 short_name = "Restart ind./Restart req.";
1815 long_name = "Restart indication/Restart request";
1818 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s - Diag.:%d",
1820 restart_code(tvb_get_guint8(tvb, 3)),
1821 (int)tvb_get_guint8(tvb, 4));
1823 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1824 X25_RESTART_REQUEST, "%s", long_name);
1825 proto_tree_add_text(x25_tree, tvb, 3, 1,
1826 "Cause: %s", restart_code(tvb_get_guint8(tvb, 3)));
1827 proto_tree_add_text(x25_tree, tvb, 4, 1,
1828 "Diagnostic: %d", (int)tvb_get_guint8(tvb, 4));
1830 localoffset = x25_pkt_len;
1832 case X25_RESTART_CONFIRMATION:
1833 col_set_str(pinfo->cinfo, COL_INFO, "Restart conf.");
1835 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1836 X25_RESTART_CONFIRMATION);
1837 localoffset = x25_pkt_len;
1839 case X25_REGISTRATION_REQUEST:
1840 col_set_str(pinfo->cinfo, COL_INFO, "Registration req.");
1842 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1843 X25_REGISTRATION_REQUEST);
1845 if (localoffset < x25_pkt_len)
1846 x25_ntoa(x25_tree, (gint*)&localoffset, tvb, pinfo, TRUE);
1849 if (localoffset < x25_pkt_len)
1850 proto_tree_add_item( x25_tree, hf_x25_reg_request_length, tvb, localoffset, 1, ENC_NA);
1851 if (localoffset+1 < x25_pkt_len)
1852 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1853 tvb_get_guint8(tvb, localoffset) & 0x7F,
1856 localoffset = tvb_reported_length(tvb);
1858 case X25_REGISTRATION_CONFIRMATION:
1859 col_set_str(pinfo->cinfo, COL_INFO, "Registration conf.");
1861 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1862 X25_REGISTRATION_CONFIRMATION);
1863 proto_tree_add_item(x25_tree, hf_x25_reg_confirm_cause, tvb, 3, 1, ENC_NA);
1864 proto_tree_add_item(x25_tree, hf_x25_reg_confirm_diagnostic, tvb, 4, 1, ENC_NA);
1867 if (localoffset < x25_pkt_len)
1868 x25_ntoa(x25_tree, (gint*)&localoffset, tvb, pinfo, TRUE);
1871 if (localoffset < x25_pkt_len)
1872 proto_tree_add_item( x25_tree, hf_x25_reg_confirm_length, tvb, localoffset, 1, ENC_NA);
1873 if (localoffset+1 < x25_pkt_len)
1874 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1875 tvb_get_guint8(tvb, localoffset) & 0x7F,
1878 localoffset = tvb_reported_length(tvb);
1883 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1886 if (PACKET_IS_DATA(pkt_type)) {
1888 col_add_fstr(pinfo->cinfo, COL_INFO,
1889 "Data VC:%d P(S):%d P(R):%d %s", vc,
1890 (pkt_type >> 1) & 0x07,
1891 (pkt_type >> 5) & 0x07,
1892 (pkt_type & X25_MBIT_MOD8) ? " M" : "");
1894 col_add_fstr(pinfo->cinfo, COL_INFO,
1895 "Data VC:%d P(S):%d P(R):%d %s", vc,
1896 tvb_get_guint8(tvb, localoffset+1) >> 1,
1898 (tvb_get_guint8(tvb, localoffset+1) & X25_MBIT_MOD128) ? " M" : "");
1901 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1902 localoffset, 1, pkt_type);
1903 proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod8, tvb,
1904 localoffset, 1, pkt_type);
1905 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod8, tvb,
1906 localoffset, 1, pkt_type);
1907 proto_tree_add_uint(x25_tree, hf_x25_type_data, tvb,
1908 localoffset, 1, pkt_type);
1911 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod128, tvb,
1912 localoffset, 1, pkt_type);
1913 proto_tree_add_uint(x25_tree, hf_x25_type_data, tvb,
1914 localoffset, 1, pkt_type);
1915 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod128, tvb,
1917 tvb_get_guint8(tvb, localoffset+1));
1918 proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod128, tvb,
1920 tvb_get_guint8(tvb, localoffset+1));
1924 m_bit_set = pkt_type & X25_MBIT_MOD8;
1927 m_bit_set = tvb_get_guint8(tvb, localoffset+1) & X25_MBIT_MOD128;
1930 payload_len = tvb_reported_length_remaining(tvb, localoffset);
1931 if (reassemble_x25) {
1933 * Reassemble received and sent traffic separately.
1934 * We don't reassemble traffic with an unknown direction
1940 * OR in an extra bit to distinguish from traffic
1941 * in the other direction.
1943 frag_key |= 0x10000;
1945 fd_head = fragment_add_seq_next(&x25_reassembly_table,
1947 pinfo, frag_key, NULL,
1948 payload_len, m_bit_set);
1949 pinfo->fragmented = m_bit_set;
1951 /* Fragment handling is not adapted to handle several x25
1952 * packets in the same frame. This is common with XOT and
1953 * shorter packet sizes.
1954 * Therefore, fragment_add_seq_next seem to always return fd_head
1955 * A fix to use m_bit_set to only show fragments for last pkt
1957 if (!m_bit_set && fd_head) {
1958 if (fd_head->next) {
1959 proto_item *frag_tree_item;
1961 /* This is the last packet */
1962 next_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
1963 add_new_data_source(pinfo, next_tvb, "Reassembled X.25");
1965 show_fragment_seq_tree(fd_head,
1968 pinfo, next_tvb, &frag_tree_item);
1973 if (m_bit_set && next_tvb == NULL) {
1975 * This isn't the last packet, so just
1976 * show it as X.25 user data.
1978 proto_tree_add_text(x25_tree, tvb, localoffset, -1,
1979 "User data (%u byte%s)", payload_len,
1980 plurality(payload_len, "", "s"));
1986 * Non-data packets (RR, RNR, REJ).
1990 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1991 localoffset, 1, pkt_type);
1992 proto_tree_add_item(x25_tree, hf_x25_type_fc_mod8, tvb,
1993 localoffset, 1, ENC_NA);
1995 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d P(R):%d",
1996 val_to_str(PACKET_TYPE_FC(pkt_type), vals_x25_type, "Unknown (0x%02X)"),
1997 vc, (pkt_type >> 5) & 0x07);
2001 proto_tree_add_item(x25_tree, hf_x25_type, tvb,
2002 localoffset, 1, ENC_NA);
2003 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
2004 localoffset+1, 1, ENC_NA);
2006 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d P(R):%d",
2007 val_to_str(PACKET_TYPE_FC(pkt_type), vals_x25_type, "Unknown (0x%02X)"),
2008 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
2015 if (localoffset >= tvb_reported_length(tvb))
2017 if (pinfo->fragmented)
2021 next_tvb = tvb_new_subset_remaining(tvb, localoffset);
2023 saved_private_data = pinfo->private_data;
2024 pinfo->private_data = &q_bit_set;
2026 /* See if there's already a dissector for this circuit. */
2027 if (try_circuit_dissector(CT_X25, vc, pinfo->fd->num, next_tvb, pinfo,
2029 pinfo->private_data = saved_private_data;
2030 return; /* found it and dissected it */
2033 /* Did the user suggest QLLC/SNA? */
2034 if (payload_is_qllc_sna) {
2035 /* Yes - dissect it as QLLC/SNA. */
2036 if (!pinfo->fd->flags.visited)
2037 x25_hash_add_proto_start(vc, pinfo->fd->num, qllc_handle);
2038 call_dissector(qllc_handle, next_tvb, pinfo, tree);
2039 pinfo->private_data = saved_private_data;
2043 if (payload_check_data){
2044 /* If the Call Req. has not been captured, let's look at the first
2045 two bytes of the payload to see if this looks like COTP. */
2046 if (tvb_get_guint8(tvb, localoffset) == tvb_length(next_tvb)-1) {
2047 /* First byte contains the length of the remaining buffer */
2048 if ((tvb_get_guint8(tvb, localoffset+1) & 0x0F) == 0) {
2049 /* Second byte contains a valid COTP TPDU */
2050 if (!pinfo->fd->flags.visited)
2051 x25_hash_add_proto_start(vc, pinfo->fd->num, ositp_handle);
2052 call_dissector(ositp_handle, next_tvb, pinfo, tree);
2053 pinfo->private_data = saved_private_data;
2058 /* Then let's look at the first byte of the payload to see if this
2059 looks like IP or CLNP. */
2060 switch (tvb_get_guint8(tvb, localoffset)) {
2063 /* Looks like an IP header */
2064 if (!pinfo->fd->flags.visited)
2065 x25_hash_add_proto_start(vc, pinfo->fd->num, ip_handle);
2066 call_dissector(ip_handle, next_tvb, pinfo, tree);
2067 pinfo->private_data = saved_private_data;
2070 case NLPID_ISO8473_CLNP:
2071 if (!pinfo->fd->flags.visited)
2072 x25_hash_add_proto_start(vc, pinfo->fd->num, clnp_handle);
2073 call_dissector(clnp_handle, next_tvb, pinfo, tree);
2074 pinfo->private_data = saved_private_data;
2079 /* Try the heuristic dissectors. */
2080 if (dissector_try_heuristic(x25_heur_subdissector_list, next_tvb, pinfo,
2082 pinfo->private_data = saved_private_data;
2086 /* All else failed; dissect it as raw data */
2087 call_dissector(data_handle, next_tvb, pinfo, tree);
2088 pinfo->private_data = saved_private_data;
2092 * X.25 dissector for use when "pinfo->pseudo_header" points to a
2093 * "struct x25_phdr".
2096 dissect_x25_dir(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2098 dissect_x25_common(tvb, pinfo, tree,
2099 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? X25_FROM_DCE :
2101 pinfo->pseudo_header->x25.flags & FROM_DCE);
2105 * X.25 dissector for use when "pinfo->pseudo_header" doesn't point to a
2106 * "struct x25_phdr".
2109 dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2114 * We don't know if this packet is DTE->DCE or DCE->DCE.
2115 * However, we can, at least, distinguish between the two
2116 * sides of the conversation, based on the addresses and
2119 direction = CMP_ADDRESS(&pinfo->src, &pinfo->dst);
2121 direction = (pinfo->srcport > pinfo->destport)*2 - 1;
2122 dissect_x25_common(tvb, pinfo, tree, X25_UNKNOWN, direction > 0);
2126 x25_reassemble_init(void)
2128 reassembly_table_init(&x25_reassembly_table,
2129 &addresses_reassembly_table_functions);
2133 proto_register_x25(void)
2135 static hf_register_info hf[] = {
2137 { "Facility", "x25.facility", FT_NONE, BASE_NONE, NULL, 0,
2139 { &hf_x25_facilities_length,
2140 { "Facilities Length", "x25.facilities_length", FT_UINT8, BASE_DEC, NULL, 0,
2142 { &hf_x25_facility_length,
2143 { "Length", "x25.facility_length", FT_UINT8, BASE_DEC, NULL, 0,
2145 { &hf_x25_facility_class,
2146 { "Facility Class", "x25.facility.class", FT_UINT8, BASE_HEX, VALS(x25_facilities_class_vals), X25_FAC_CLASS_MASK,
2148 { &hf_x25_facility_classA,
2149 { "Code", "x25.facility.classA", FT_UINT8, BASE_HEX, VALS(x25_facilities_classA_vals), 0,
2150 "Facility ClassA Code", HFILL }},
2151 { &hf_x25_facility_classA_comp_mark,
2152 { "Parameter", "x25.facility.comp_mark", FT_UINT8, BASE_DEC, VALS(x25_facilities_classA_comp_mark_vals), 0,
2153 "Facility Marker Parameter", HFILL }},
2154 { &hf_x25_facility_classA_reverse,
2155 { "Parameter", "x25.facility.reverse", FT_UINT8, BASE_HEX, NULL, 0,
2156 "Facility Reverse Charging Parameter", HFILL }},
2157 { &hf_x25_facility_classA_charging_info,
2158 { "Parameter", "x25.facility.charging_info", FT_UINT8, BASE_HEX, NULL, 0,
2159 "Facility Charging Information Parameter", HFILL }},
2160 { &hf_x25_facility_reverse_charging,
2161 { "Reverse charging", "x25.reverse_charging", FT_BOOLEAN, 8, TFS(&x25_reverse_charging_val), 0x01,
2163 { &hf_x25_facility_charging_info,
2164 { "Charging information", "x25.charging_info", FT_BOOLEAN, 8, TFS(&tfs_requested_not_requested), 0x01,
2166 { &hf_x25_facility_throughput_called_dte,
2167 { "From the called DTE", "x25.facility.throughput.called_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classA_throughput_vals), 0xF0,
2168 "Facility Throughput called DTE", HFILL }},
2169 { &hf_x25_throughput_called_dte,
2170 { "From the calling DTE", "x25.facility.throughput.called_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classA_throughput_vals), 0x0F,
2171 "Facility Throughput called DTE", HFILL }},
2172 { &hf_x25_facility_classA_cug,
2173 { "Closed user group", "x25.facility.cug", FT_UINT8, BASE_HEX, NULL, 0,
2174 "Facility Closed user group", HFILL }},
2175 { &hf_x25_facility_classA_called_motif,
2176 { "Parameter", "x25.facility.called_motif", FT_UINT8, BASE_HEX, NULL, 0,
2177 "Facility Called address modified parameter", HFILL }},
2178 { &hf_x25_facility_classA_cug_outgoing_acc,
2179 { "Closed user group", "x25.facility.cug_outgoing_acc", FT_UINT8, BASE_HEX, NULL, 0,
2180 "Facility Closed user group with outgoing access selection", HFILL }},
2181 { &hf_x25_facility_classA_throughput_min,
2182 { "Parameter", "x25.facility.throughput_min", FT_UINT8, BASE_HEX, NULL, 0,
2183 "Facility Minimum throughput class parameter", HFILL }},
2184 { &hf_x25_facility_classA_express_data,
2185 { "Parameter", "x25.facility.express_data", FT_UINT8, BASE_HEX, NULL, 0,
2186 "Facility Negotiation of express data parameter", HFILL }},
2187 { &hf_x25_facility_classA_unknown,
2188 { "Parameter", "x25.facility.classA_unknown", FT_UINT8, BASE_HEX, NULL, 0,
2189 "Facility Class A unknown parameter", HFILL }},
2190 { &hf_x25_facility_classB,
2191 { "Code", "x25.facility.classB", FT_UINT8, BASE_HEX, VALS(x25_facilities_classB_vals), 0,
2192 "Facility ClassB Code", HFILL }},
2193 { &hf_x25_facility_classB_bilateral_cug,
2194 { "Bilateral CUG", "x25.facility.bilateral_cug", FT_UINT16, BASE_HEX, NULL, 0,
2195 "Facility Bilateral CUG", HFILL }},
2196 { &hf_x25_facility_packet_size_called_dte,
2197 { "From the called DTE", "x25.facility.packet_size.called_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classB_packet_size_vals), 0,
2198 "Facility Packet size from the called DTE", HFILL }},
2199 { &hf_x25_facility_packet_size_calling_dte,
2200 { "From the calling DTE", "x25.facility.packet_size.calling_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classB_packet_size_vals), 0,
2201 "Facility Packet size from the calling DTE", HFILL }},
2202 { &hf_x25_facility_data_network_id_code,
2203 { "Data network identification code", "x25.facility.data_network_id_code", FT_UINT16, BASE_HEX, NULL, 0,
2204 "Facility RPOA selection data network identification code", HFILL }},
2205 { &hf_x25_facility_cug_ext,
2206 { "Closed user group", "x25.facility.cug_ext", FT_UINT16, BASE_HEX, NULL, 0,
2207 "Facility Extended closed user group selection", HFILL }},
2208 { &hf_x25_facility_cug_outgoing_acc_ext,
2209 { "Closed user group", "x25.facility.cug_outgoing_acc_ext", FT_UINT16, BASE_HEX, NULL, 0,
2210 "Facility Extended closed user group with outgoing access selection", HFILL }},
2211 { &hf_x25_facility_transit_delay,
2212 { "Transit delay (ms)", "x25.facility.transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2213 "Facility Transit delay selection and indication", HFILL }},
2214 { &hf_x25_facility_classB_unknown,
2215 { "Parameter", "x25.facility.classB_unknown", FT_UINT16, BASE_HEX, NULL, 0,
2216 "Facility Class B unknown parameter", HFILL }},
2217 { &hf_x25_facility_classC_unknown,
2218 { "Parameter", "x25.facility.classC_unknown", FT_UINT24, BASE_HEX, NULL, 0,
2219 "Facility Class C unknown parameter", HFILL }},
2220 { &hf_x25_facility_classC,
2221 { "Code", "x25.facility.classC", FT_UINT8, BASE_HEX, VALS(x25_facilities_classC_vals), 0,
2222 "Facility ClassC Code", HFILL }},
2223 { &hf_x25_facility_classD,
2224 { "Code", "x25.facility.classD", FT_UINT8, BASE_HEX, VALS(x25_facilities_classD_vals), 0,
2225 "Facility ClassD Code", HFILL }},
2227 { "GFI", "x25.gfi", FT_UINT16, BASE_DEC, NULL, 0xF000,
2228 "General format identifier", HFILL }},
2230 { "A Bit", "x25.a", FT_BOOLEAN, 16, NULL, X25_ABIT,
2231 "Address Bit", HFILL }},
2233 { "Q Bit", "x25.q", FT_BOOLEAN, 16, NULL, X25_QBIT,
2234 "Qualifier Bit", HFILL }},
2236 { "D Bit", "x25.d", FT_BOOLEAN, 16, NULL, X25_DBIT,
2237 "Delivery Confirmation Bit", HFILL }},
2239 { "Modulo", "x25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
2240 "Specifies whether the frame is modulo 8 or 128", HFILL }},
2242 { "Logical Channel", "x25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
2243 "Logical Channel Number", HFILL }},
2245 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
2247 { &hf_x25_type_fc_mod8,
2248 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x1F,
2250 { &hf_x25_type_data,
2251 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x01,
2253 { &hf_x25_diagnostic,
2254 { "Diagnostic", "x25.diagnostic", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &x25_clear_diag_vals_ext, 0,
2257 { "P(R)", "x25.p_r", FT_UINT8, BASE_DEC, NULL, 0xE0,
2258 "Packet Receive Sequence Number", HFILL }},
2259 { &hf_x25_p_r_mod128,
2260 { "P(R)", "x25.p_r", FT_UINT8, BASE_DEC, NULL, 0xFE,
2261 "Packet Receive Sequence Number", HFILL }},
2262 { &hf_x25_mbit_mod8,
2263 { "M Bit", "x25.m", FT_BOOLEAN, 8, TFS(&m_bit_tfs), X25_MBIT_MOD8,
2264 "More Bit", HFILL }},
2265 { &hf_x25_mbit_mod128,
2266 { "M Bit", "x25.m", FT_BOOLEAN, 8, TFS(&m_bit_tfs), X25_MBIT_MOD128,
2267 "More Bit", HFILL }},
2269 { "P(S)", "x25.p_s", FT_UINT8, BASE_DEC, NULL, 0x0E,
2270 "Packet Send Sequence Number", HFILL }},
2271 { &hf_x25_p_s_mod128,
2272 { "P(S)", "x25.p_s", FT_UINT8, BASE_DEC, NULL, 0xFE,
2273 "Packet Send Sequence Number", HFILL }},
2274 { &hf_x25_window_size_called_dte,
2275 { "From the called DTE", "x25.window_size.called_dte", FT_UINT8, BASE_DEC, NULL, 0x7F,
2277 { &hf_x25_window_size_calling_dte,
2278 { "From the calling DTE", "x25.window_size.calling_dte", FT_UINT8, BASE_DEC, NULL, 0x7F,
2280 { &hf_x25_dte_address_length,
2281 { "DTE address length", "x25.dte_address_length", FT_UINT8, BASE_DEC, NULL, 0xF0,
2283 { &hf_x25_dce_address_length,
2284 { "DCE address length", "x25.dce_address_length", FT_UINT8, BASE_DEC, NULL, 0x0F,
2286 { &hf_x25_calling_address_length,
2287 { "Calling address length", "x25.calling_address_length", FT_UINT8, BASE_DEC, NULL, 0xF0,
2289 { &hf_x25_called_address_length,
2290 { "Called address length", "x25.called_address_length", FT_UINT8, BASE_DEC, NULL, 0x0F,
2292 { &hf_x25_facility_call_transfer_reason,
2293 { "Reason", "x25.facility.call_transfer_reason", FT_UINT8, BASE_DEC, VALS(x25_facilities_call_transfer_reason_vals), 0,
2295 { &hf_x25_facility_monetary_unit,
2296 { "Monetary unit", "x25.facility.monetary_unit", FT_BYTES, BASE_NONE, NULL, 0,
2298 { &hf_x25_facility_nui,
2299 { "NUI", "x25.facility.nui", FT_BYTES, BASE_NONE, NULL, 0,
2301 { &hf_x25_facility_cumulative_ete_transit_delay,
2302 { "Cumulative end-to-end transit delay (ms)", "x25.facility.cumulative_ete_transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2304 { &hf_x25_facility_requested_ete_transit_delay,
2305 { "Requested end-to-end transit delay (ms)", "x25.facility.requested_ete_transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2307 { &hf_x25_facility_max_acceptable_ete_transit_delay,
2308 { "Maximum acceptable end-to-end transit delay (ms)", "x25.facility.mac_acceptable_ete_transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2310 { &hf_x25_facility_priority_data,
2311 { "Priority for data", "x25.facility.priority_data", FT_UINT8, BASE_DEC, NULL, 0,
2313 { &hf_x25_facility_priority_estab_conn,
2314 { "Priority for establishing connection", "x25.facility.priority_estab_conn", FT_UINT8, BASE_DEC, NULL, 0,
2316 { &hf_x25_facility_priority_keep_conn,
2317 { "Priority for keeping connection", "x25.facility.priority_keep_conn", FT_UINT8, BASE_DEC, NULL, 0,
2319 { &hf_x25_facility_min_acceptable_priority_data,
2320 { "Minimum acceptable priority for data", "x25.facility.min_acceptable_priority_data", FT_UINT8, BASE_DEC, NULL, 0,
2322 { &hf_x25_facility_min_acceptable_priority_estab_conn,
2323 { "Minimum acceptable priority for establishing connection", "x25.facility.min_acceptable_priority_estab_conn", FT_UINT8, BASE_DEC, NULL, 0,
2325 { &hf_x25_facility_min_acceptable_priority_keep_conn,
2326 { "Minimum acceptable priority for keeping connection", "x25.facility.min_acceptable_priority_keep_conn", FT_UINT8, BASE_DEC, NULL, 0,
2328 { &hf_x25_facility_classD_unknown,
2329 { "Parameter", "x25.facility.classD_unknown", FT_BYTES, BASE_NONE, NULL, 0,
2330 "Facility Class D unknown parameter", HFILL }},
2331 { &hf_x25_facility_call_transfer_num_semi_octets,
2332 { "Number of semi-octets in DTE address", "x25.facility.call_transfer_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2334 { &hf_x25_facility_calling_addr_ext_num_semi_octets,
2335 { "Number of semi-octets in DTE address", "x25.facility.calling_addr_ext_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2337 { &hf_x25_facility_called_addr_ext_num_semi_octets,
2338 { "Number of semi-octets in DTE address", "x25.facility.called_addr_ext_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2340 { &hf_x25_facility_call_deflect_num_semi_octets,
2341 { "Number of semi-octets in the alternative DTE address", "x25.facility.call_deflect_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2343 { &hf_x264_length_indicator,
2344 { "X.264 length indicator", "x25.x264_length_indicator", FT_UINT8, BASE_DEC, NULL, 0,
2346 { &hf_x264_un_tpdu_id,
2347 { "X.264 UN TPDU identifier", "x25.x264_un_tpdu_id", FT_UINT8, BASE_HEX, NULL, 0,
2349 { &hf_x264_protocol_id,
2350 { "X.264 protocol identifier", "x25.x264_protocol_id", FT_UINT8, BASE_HEX, VALS(prt_id_vals), 0,
2352 { &hf_x264_sharing_strategy,
2353 { "X.264 sharing strategy", "x25.x264_sharing_strategy", FT_UINT8, BASE_HEX, VALS(sharing_strategy_vals), 0,
2355 { &hf_x263_sec_protocol_id,
2356 { "X.263 secondary protocol ID", "x25.x263_sec_protocol_id", FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0,
2358 { &hf_x25_reg_request_length,
2359 { "Registration length", "x25.reg_request_length", FT_UINT8, BASE_DEC, NULL, 0x7F,
2361 { &hf_x25_reg_confirm_length,
2362 { "Registration length", "x25.reg_confirm_length", FT_UINT8, BASE_DEC, NULL, 0x7F,
2365 { &hf_x25_segment_overlap,
2366 { "Fragment overlap", "x25.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2367 "Fragment overlaps with other fragments", HFILL }},
2369 { &hf_x25_segment_overlap_conflict,
2370 { "Conflicting data in fragment overlap", "x25.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2371 "Overlapping fragments contained conflicting data", HFILL }},
2373 { &hf_x25_segment_multiple_tails,
2374 { "Multiple tail fragments found", "x25.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2375 "Several tails were found when defragmenting the packet", HFILL }},
2377 { &hf_x25_segment_too_long_segment,
2378 { "Fragment too long", "x25.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2379 "Fragment contained data past end of packet", HFILL }},
2381 { &hf_x25_segment_error,
2382 { "Defragmentation error", "x25.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2383 "Defragmentation error due to illegal fragments", HFILL }},
2385 { &hf_x25_segment_count,
2386 { "Fragment count", "x25.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2389 { &hf_x25_reassembled_length,
2390 { "Reassembled X.25 length", "x25.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
2391 "The total length of the reassembled payload", HFILL }},
2394 { "X.25 Fragment", "x25.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2395 "X25 Fragment", HFILL }},
2398 { "X.25 Fragments", "x25.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2401 { &hf_x25_fast_select,
2402 { "Fast select", "x25.fast_select", FT_UINT8, BASE_DEC, VALS(x25_fast_select_vals), 0xC0,
2406 { "ICRD", "x25.icrd", FT_UINT8, BASE_DEC, VALS(x25_icrd_vals), 0x30,
2409 { &hf_x25_reg_confirm_cause,
2410 { "Cause", "x25.reg_confirm.cause", FT_UINT8, BASE_DEC, VALS(x25_registration_code_vals), 0,
2413 { &hf_x25_reg_confirm_diagnostic,
2414 { "Diagnostic", "x25.reg_confirm.diagnostic", FT_UINT8, BASE_DEC, VALS(x25_registration_code_vals), 0,
2418 static gint *ett[] = {
2421 &ett_x25_facilities,
2428 static ei_register_info ei[] = {
2429 { &ei_x25_facility_length, { "x25.facility_length.bogus", PI_PROTOCOL, PI_WARN, "Bogus length", EXPFILL }},
2432 module_t *x25_module;
2433 expert_module_t* expert_x25;
2435 proto_x25 = proto_register_protocol ("X.25", "X.25", "x25");
2436 proto_register_field_array (proto_x25, hf, array_length(hf));
2437 proto_register_subtree_array(ett, array_length(ett));
2438 expert_x25 = expert_register_protocol(proto_x25);
2439 expert_register_field_array(expert_x25, ei, array_length(ei));
2441 x25_subdissector_table = register_dissector_table("x.25.spi",
2442 "X.25 secondary protocol identifier", FT_UINT8, BASE_HEX);
2443 register_heur_dissector_list("x.25", &x25_heur_subdissector_list);
2445 register_dissector("x.25_dir", dissect_x25_dir, proto_x25);
2446 register_dissector("x.25", dissect_x25, proto_x25);
2449 x25_module = prefs_register_protocol(proto_x25, NULL);
2450 prefs_register_obsolete_preference(x25_module, "non_q_bit_is_sna");
2451 prefs_register_bool_preference(x25_module, "payload_is_qllc_sna",
2452 "Default to QLLC/SNA",
2453 "If CALL REQUEST not seen or didn't specify protocol, dissect as QLLC/SNA",
2454 &payload_is_qllc_sna);
2455 prefs_register_bool_preference(x25_module, "call_request_nodata_is_cotp",
2456 "Assume COTP for Call Request without data",
2457 "If CALL REQUEST has no data, assume the protocol handled is COTP",
2458 &call_request_nodata_is_cotp);
2459 prefs_register_bool_preference(x25_module, "payload_check_data",
2460 "Check data for COTP/IP/CLNP",
2461 "If CALL REQUEST not seen or didn't specify protocol, check user data before checking heuristic dissectors",
2462 &payload_check_data);
2463 prefs_register_bool_preference(x25_module, "reassemble",
2464 "Reassemble fragmented X.25 packets",
2465 "Reassemble fragmented X.25 packets",
2467 register_init_routine(&x25_reassemble_init);
2471 proto_reg_handoff_x25(void)
2473 dissector_handle_t x25_handle;
2476 * Get handles for various dissectors.
2478 ip_handle = find_dissector("ip");
2479 clnp_handle = find_dissector("clnp");
2480 ositp_handle = find_dissector("ositp");
2481 qllc_handle = find_dissector("qllc");
2482 data_handle = find_dissector("data");
2484 x25_handle = find_dissector("x.25");
2485 dissector_add_uint("llc.dsap", SAP_X25, x25_handle);
2486 dissector_add_uint("lapd.sapi", LAPD_SAPI_X25, x25_handle);
2487 dissector_add_uint("ax25.pid", AX25_P_ROSE, x25_handle);