Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-x25.c
blob3b5b528f1f6daf4acf6ef5df9b3d2b7a6c1a1a55
1 /* packet-x25.c
2 * Routines for X.25 packet disassembly
3 * Olivier Abad <oabad@noos.fr>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
15 #include <epan/packet.h>
16 #include <epan/ax25_pids.h>
17 #include <epan/llcsaps.h>
18 #include <epan/conversation.h>
19 #include <epan/reassemble.h>
20 #include <epan/prefs.h>
21 #include <epan/expert.h>
22 #include <epan/nlpid.h>
23 #include <epan/x264_prt_id.h>
24 #include <epan/lapd_sapi.h>
25 #include <epan/tfs.h>
26 #include <wiretap/wtap.h>
27 #include "packet-sflow.h"
29 void proto_register_x25(void);
30 void proto_reg_handoff_x25(void);
33 * Direction of packet.
35 typedef enum {
36 X25_FROM_DCE, /* DCE->DTE */
37 X25_FROM_DTE, /* DTE->DCE */
38 X25_UNKNOWN /* direction unknown */
39 } x25_dir_t;
42 * 0 for data packets, 1 for non-data packets.
44 #define X25_NONDATA_BIT 0x01
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
59 #define X25_RR 0x01
60 #define X25_RNR 0x05
61 #define X25_REJ 0x09
62 #define X25_DATA 0x00
64 #define PACKET_IS_DATA(type) (!(type & X25_NONDATA_BIT))
65 #define PACKET_TYPE_FC(type) (type & 0x1F)
67 #define X25_MBIT_MOD8 0x10
68 #define X25_MBIT_MOD128 0x01
70 #define X25_ABIT 0x8000
72 #define X25_QBIT 0x8000
73 #define X25_DBIT 0x4000
75 #define X25_FAC_CLASS_MASK 0xC0
77 #define X25_FAC_CLASS_A 0x00
78 #define X25_FAC_CLASS_B 0x40
79 #define X25_FAC_CLASS_C 0x80
80 #define X25_FAC_CLASS_D 0xC0
82 #define X25_FAC_COMP_MARK 0x00
83 #define X25_FAC_REVERSE 0x01
84 #define X25_FAC_THROUGHPUT 0x02
85 #define X25_FAC_CUG 0x03
86 #define X25_FAC_CHARGING_INFO 0x04
87 #define X25_FAC_CALLED_MODIF 0x08
88 #define X25_FAC_CUG_OUTGOING_ACC 0x09
89 #define X25_FAC_THROUGHPUT_MIN 0x0A
90 #define X25_FAC_EXPRESS_DATA 0x0B
91 #define X25_FAC_BILATERAL_CUG 0x41
92 #define X25_FAC_PACKET_SIZE 0x42
93 #define X25_FAC_WINDOW_SIZE 0x43
94 #define X25_FAC_RPOA_SELECTION 0x44
95 #define X25_FAC_CUG_EXT 0x47
96 #define X25_FAC_CUG_OUTGOING_ACC_EXT 0x48
97 #define X25_FAC_TRANSIT_DELAY 0x49
98 #define X25_FAC_CALL_DURATION 0xC1
99 #define X25_FAC_SEGMENT_COUNT 0xC2
100 #define X25_FAC_CALL_TRANSFER 0xC3
101 #define X25_FAC_RPOA_SELECTION_EXT 0xC4
102 #define X25_FAC_MONETARY_UNIT 0xC5
103 #define X25_FAC_NUI 0xC6
104 #define X25_FAC_CALLED_ADDR_EXT 0xC9
105 #define X25_FAC_ETE_TRANSIT_DELAY 0xCA
106 #define X25_FAC_CALLING_ADDR_EXT 0xCB
107 #define X25_FAC_CALL_DEFLECT 0xD1
108 #define X25_FAC_PRIORITY 0xD2
110 static int proto_x25;
111 static int hf_x25_facility;
112 static int hf_x25_facilities_length;
113 static int hf_x25_facility_length;
114 static int hf_x25_facility_class;
115 static int hf_x25_facility_classA;
116 static int hf_x25_facility_classA_comp_mark;
117 static int hf_x25_facility_classA_reverse;
118 static int hf_x25_facility_classA_charging_info;
119 static int hf_x25_facility_reverse_charging;
120 static int hf_x25_facility_charging_info;
121 static int hf_x25_facility_throughput_called_dte;
122 static int hf_x25_throughput_called_dte;
123 static int hf_x25_facility_classA_cug;
124 static int hf_x25_facility_classA_called_motif;
125 static int hf_x25_facility_classA_cug_outgoing_acc;
126 static int hf_x25_facility_classA_throughput_min;
127 static int hf_x25_facility_classA_express_data;
128 static int hf_x25_facility_classA_unknown;
129 static int hf_x25_facility_classB;
130 static int hf_x25_facility_classB_bilateral_cug;
131 static int hf_x25_facility_packet_size_called_dte;
132 static int hf_x25_facility_packet_size_calling_dte;
133 static int hf_x25_facility_data_network_id_code;
134 static int hf_x25_facility_cug_ext;
135 static int hf_x25_facility_cug_outgoing_acc_ext;
136 static int hf_x25_facility_transit_delay;
137 static int hf_x25_facility_classB_unknown;
138 static int hf_x25_facility_classC;
139 static int hf_x25_facility_classC_unknown;
140 static int hf_x25_facility_classD;
141 static int hf_x25_gfi;
142 static int hf_x25_abit;
143 static int hf_x25_qbit;
144 static int hf_x25_dbit;
145 static int hf_x25_mod;
146 static int hf_x25_lcn;
147 static int hf_x25_type;
148 static int hf_x25_type_fc_mod8;
149 static int hf_x25_type_data;
150 static int hf_x25_diagnostic;
151 static int hf_x25_p_r_mod8;
152 static int hf_x25_p_r_mod128;
153 static int hf_x25_mbit_mod8;
154 static int hf_x25_mbit_mod128;
155 static int hf_x25_p_s_mod8;
156 static int hf_x25_p_s_mod128;
157 static int hf_x25_window_size_called_dte;
158 static int hf_x25_window_size_calling_dte;
159 static int hf_x25_dte_address_length;
160 static int hf_x25_dce_address_length;
161 static int hf_x25_calling_address_length;
162 static int hf_x25_called_address_length;
163 static int hf_x25_facility_call_transfer_reason;
164 static int hf_x25_facility_monetary_unit;
165 static int hf_x25_facility_nui;
166 static int hf_x25_facility_cumulative_ete_transit_delay;
167 static int hf_x25_facility_requested_ete_transit_delay;
168 static int hf_x25_facility_max_acceptable_ete_transit_delay;
169 static int hf_x25_facility_priority_data;
170 static int hf_x25_facility_priority_estab_conn;
171 static int hf_x25_facility_priority_keep_conn;
172 static int hf_x25_facility_min_acceptable_priority_data;
173 static int hf_x25_facility_min_acceptable_priority_estab_conn;
174 static int hf_x25_facility_min_acceptable_priority_keep_conn;
175 static int hf_x25_facility_classD_unknown;
176 static int hf_x25_facility_call_transfer_num_semi_octets;
177 static int hf_x25_facility_calling_addr_ext_num_semi_octets;
178 static int hf_x25_facility_called_addr_ext_num_semi_octets;
179 static int hf_x25_facility_call_deflect_num_semi_octets;
180 static int hf_x264_length_indicator;
181 static int hf_x264_un_tpdu_id;
182 static int hf_x264_protocol_id;
183 static int hf_x264_sharing_strategy;
184 static int hf_x263_sec_protocol_id;
185 static int hf_x25_reg_request_length;
186 static int hf_x25_reg_confirm_length;
188 /* Generated from convert_proto_tree_add_text.pl */
189 static int hf_x25_call_duration;
190 static int hf_x25_segments_to_dte;
191 static int hf_x25_segments_from_dte;
192 static int hf_x25_dte_address;
193 static int hf_x25_data_network_identification_code;
194 static int hf_x25_facility_call_deflect_reason;
195 static int hf_x25_alternative_dte_address;
196 static int hf_x25_dce_address;
197 static int hf_x25_called_address;
198 static int hf_x25_calling_address;
199 static int hf_x25_clear_cause;
200 static int hf_x25_reset_cause;
201 static int hf_x25_restart_cause;
202 static int hf_x25_registration;
203 static int hf_x25_user_data;
205 static int ett_x25;
206 static int ett_x25_gfi;
207 static int ett_x25_facilities;
208 static int ett_x25_facility;
209 static int ett_x25_user_data;
211 static int ett_x25_segment;
212 static int ett_x25_segments;
213 static int hf_x25_segments;
214 static int hf_x25_segment;
215 static int hf_x25_segment_overlap;
216 static int hf_x25_segment_overlap_conflict;
217 static int hf_x25_segment_multiple_tails;
218 static int hf_x25_segment_too_long_segment;
219 static int hf_x25_segment_error;
220 static int hf_x25_segment_count;
221 static int hf_x25_reassembled_length;
222 static int hf_x25_fast_select;
223 static int hf_x25_icrd;
224 static int hf_x25_reg_confirm_cause;
225 static int hf_x25_reg_confirm_diagnostic;
227 static expert_field ei_x25_facility_length;
229 static dissector_handle_t x25_handle;
231 static const value_string vals_modulo[] = {
232 { 1, "8" },
233 { 2, "128" },
234 { 0, NULL}
237 static const value_string vals_x25_type[] = {
238 { X25_CALL_REQUEST, "Call" },
239 { X25_CALL_ACCEPTED, "Call Accepted" },
240 { X25_CLEAR_REQUEST, "Clear" },
241 { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
242 { X25_INTERRUPT, "Interrupt" },
243 { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
244 { X25_RESET_REQUEST, "Reset" },
245 { X25_RESET_CONFIRMATION, "Reset Confirmation" },
246 { X25_RESTART_REQUEST, "Restart" },
247 { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
248 { X25_REGISTRATION_REQUEST, "Registration" },
249 { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
250 { X25_DIAGNOSTIC, "Diagnostic" },
251 { X25_RR, "RR" },
252 { X25_RNR, "RNR" },
253 { X25_REJ, "REJ" },
254 { X25_DATA, "Data" },
255 { 0, NULL}
258 static struct true_false_string m_bit_tfs = {
259 "More data follows",
260 "End of data"
263 static const value_string x25_fast_select_vals[] = {
264 { 0, "Not requested" },
265 { 1, "Not requested" },
266 { 2, "No restriction on response" },
267 { 3, "Restriction on response" },
268 { 0, NULL}
271 static const value_string x25_icrd_vals[] = {
272 { 0, "Status not selected" },
273 { 1, "Prevention requested" },
274 { 2, "Allowance requested" },
275 { 3, "Not allowed" },
276 { 0, NULL}
279 static const value_string x25_clear_diag_vals[] = {
280 { 0, "No additional information" },
281 { 1, "Invalid P(S)" },
282 { 2, "Invalid P(R)" },
283 { 16, "Packet type invalid" },
284 { 17, "Packet type invalid for state r1" },
285 { 18, "Packet type invalid for state r2" },
286 { 19, "Packet type invalid for state r3" },
287 { 20, "Packet type invalid for state p1" },
288 { 21, "Packet type invalid for state p2" },
289 { 22, "Packet type invalid for state p3" },
290 { 23, "Packet type invalid for state p4" },
291 { 24, "Packet type invalid for state p5" },
292 { 25, "Packet type invalid for state p6" },
293 { 26, "Packet type invalid for state p7" },
294 { 27, "Packet type invalid for state d1" },
295 { 28, "Packet type invalid for state d2" },
296 { 29, "Packet type invalid for state d3" },
297 { 32, "Packet not allowed" },
298 { 33, "Unidentifiable packet" },
299 { 34, "Call on one-way logical channel" },
300 { 35, "Invalid packet type on a PVC" },
301 { 36, "Packet on unassigned LC" },
302 { 37, "Reject not subscribed to" },
303 { 38, "Packet too short" },
304 { 39, "Packet too long" },
305 { 40, "Invalid general format identifier" },
306 { 41, "Restart/registration packet with nonzero bits" },
307 { 42, "Packet type not compatible with facility" },
308 { 43, "Unauthorised interrupt confirmation" },
309 { 44, "Unauthorised interrupt" },
310 { 45, "Unauthorised reject" },
311 { 48, "Time expired" },
312 { 49, "Time expired for incoming call" },
313 { 50, "Time expired for clear indication" },
314 { 51, "Time expired for reset indication" },
315 { 52, "Time expired for restart indication" },
316 { 53, "Time expired for call deflection" },
317 { 64, "Call set-up/clearing or registration pb." },
318 { 65, "Facility/registration code not allowed" },
319 { 66, "Facility parameter not allowed" },
320 { 67, "Invalid called DTE address" },
321 { 68, "Invalid calling DTE address" },
322 { 69, "Invalid facility/registration length" },
323 { 70, "Incoming call barred" },
324 { 71, "No logical channel available" },
325 { 72, "Call collision" },
326 { 73, "Duplicate facility requested" },
327 { 74, "Non zero address length" },
328 { 75, "Non zero facility length" },
329 { 76, "Facility not provided when expected" },
330 { 77, "Invalid CCITT-specified DTE facility" },
331 { 78, "Max. nb of call redir/defl. exceeded" },
332 { 80, "Miscellaneous" },
333 { 81, "Improper cause code from DTE" },
334 { 82, "Not aligned octet" },
335 { 83, "Inconsistent Q bit setting" },
336 { 84, "NUI problem" },
337 { 112, "International problem" },
338 { 113, "Remote network problem" },
339 { 114, "International protocol problem" },
340 { 115, "International link out of order" },
341 { 116, "International link busy" },
342 { 117, "Transit network facility problem" },
343 { 118, "Remote network facility problem" },
344 { 119, "International routing problem" },
345 { 120, "Temporary routing problem" },
346 { 121, "Unknown called DNIC" },
347 { 122, "Maintenance action" },
348 { 144, "Timer expired or retransmission count surpassed" },
349 { 145, "Timer expired or retransmission count surpassed for INTERRUPT" },
350 { 146, "Timer expired or retransmission count surpassed for DATA packet transmission" },
351 { 147, "Timer expired or retransmission count surpassed for REJECT" },
352 { 160, "DTE-specific signals" },
353 { 161, "DTE operational" },
354 { 162, "DTE not operational" },
355 { 163, "DTE resource constraint" },
356 { 164, "Fast select not subscribed" },
357 { 165, "Invalid partially full DATA packet" },
358 { 166, "D-bit procedure not supported" },
359 { 167, "Registration/Cancellation confirmed" },
360 { 224, "OSI network service problem" },
361 { 225, "Disconnection (transient condition)" },
362 { 226, "Disconnection (permanent condition)" },
363 { 227, "Connection rejection - reason unspecified (transient condition)" },
364 { 228, "Connection rejection - reason unspecified (permanent condition)" },
365 { 229, "Connection rejection - quality of service not available (transient condition)" },
366 { 230, "Connection rejection - quality of service not available (permanent condition)" },
367 { 231, "Connection rejection - NSAP unreachable (transient condition)" },
368 { 232, "Connection rejection - NSAP unreachable (permanent condition)" },
369 { 233, "Reset - reason unspecified" },
370 { 234, "Reset - congestion" },
371 { 235, "Connection rejection - NSAP address unknown (permanent condition)" },
372 { 240, "Higher layer initiated" },
373 { 241, "Disconnection - normal" },
374 { 242, "Disconnection - abnormal" },
375 { 243, "Disconnection - incompatible information in user data" },
376 { 244, "Connection rejection - reason unspecified (transient condition)" },
377 { 245, "Connection rejection - reason unspecified (permanent condition)" },
378 { 246, "Connection rejection - quality of service not available (transient condition)" },
379 { 247, "Connection rejection - quality of service not available (permanent condition)" },
380 { 248, "Connection rejection - incompatible information in user data" },
381 { 249, "Connection rejection - unrecognizable protocol identifier in user data" },
382 { 250, "Reset - user resynchronization" },
383 { 0, NULL}
386 static value_string_ext x25_clear_diag_vals_ext = VALUE_STRING_EXT_INIT(x25_clear_diag_vals);
388 static const value_string x25_registration_code_vals[] = {
389 { 0x03, "Invalid facility request" },
390 { 0x05, "Network congestion" },
391 { 0x13, "Local procedure error" },
392 { 0x7F, "Registration/cancellation confirmed" },
393 { 0, NULL}
396 static const value_string x25_facilities_class_vals[] = {
397 { X25_FAC_CLASS_A>>6, "A" },
398 { X25_FAC_CLASS_B>>6, "B" },
399 { X25_FAC_CLASS_C>>6, "C" },
400 { X25_FAC_CLASS_D>>6, "D" },
401 { 0, NULL}
404 static const value_string x25_facilities_classA_vals[] = {
405 { X25_FAC_COMP_MARK, "Marker" },
406 { X25_FAC_REVERSE, "Reverse charging / Fast select" },
407 { X25_FAC_CHARGING_INFO, "Charging information" },
408 { X25_FAC_THROUGHPUT, "Throughput class negotiation" },
409 { X25_FAC_CUG, "Closed user group selection" },
410 { X25_FAC_CALLED_MODIF, "Called address modified" },
411 { X25_FAC_CUG_OUTGOING_ACC, "Closed user group with outgoing access selection" },
412 { X25_FAC_THROUGHPUT_MIN, "Minimum throughput class" },
413 { X25_FAC_EXPRESS_DATA, "Negotiation of express data" },
414 { 0, NULL}
417 static const value_string x25_facilities_classA_comp_mark_vals[] = {
418 { 0x00, "Network complementary services - calling DTE" },
419 { 0x0F, "DTE complementary services" },
420 { 0xFF, "Network complementary services - called DTE" },
421 { 0, NULL}
424 static const value_string x25_facilities_classA_throughput_vals[] = {
425 { 3, "75 bps" },
426 { 4, "150 bps" },
427 { 5, "300 bps" },
428 { 6, "600 bps" },
429 { 7, "1200 bps" },
430 { 8, "2400 bps" },
431 { 9, "4800 bps" },
432 { 10, "9600 bps" },
433 { 11, "19200 bps" },
434 { 12, "48000 bps" },
435 { 13, "64000 bps" },
436 { 0, NULL}
439 static const value_string x25_facilities_classB_vals[] = {
440 { X25_FAC_BILATERAL_CUG, "Bilateral closed user group selection" },
441 { X25_FAC_PACKET_SIZE, "Packet size" },
442 { X25_FAC_WINDOW_SIZE, "Window size" },
443 { X25_FAC_RPOA_SELECTION, "RPOA selection" },
444 { X25_FAC_CUG_EXT, "Extended closed user group selection" },
445 { X25_FAC_CUG_OUTGOING_ACC_EXT, "Extended closed user group with outgoing access selection" },
446 { X25_FAC_TRANSIT_DELAY, "Transit delay selection and indication" },
447 { 0, NULL}
450 static const value_string x25_facilities_classB_packet_size_vals[] = {
451 { 0x04, "16" },
452 { 0x05, "32" },
453 { 0x06, "64" },
454 { 0x07, "128" },
455 { 0x08, "256" },
456 { 0x09, "512" },
457 { 0x0A, "1024" },
458 { 0x0B, "2048" },
459 { 0x0C, "4096" },
460 { 0, NULL}
463 static const value_string x25_facilities_classC_vals[] = {
464 { 0, NULL}
467 static const value_string x25_facilities_classD_vals[] = {
468 { X25_FAC_CALL_DURATION, "Call duration" },
469 { X25_FAC_SEGMENT_COUNT, "Segment count" },
470 { X25_FAC_CALL_TRANSFER, "Call redirection or deflection notification" },
471 { X25_FAC_RPOA_SELECTION_EXT, "Extended RPOA selection" },
472 { X25_FAC_CALLING_ADDR_EXT, "Calling address extension" },
473 { X25_FAC_MONETARY_UNIT, "Monetary Unit" },
474 { X25_FAC_NUI, "Network User Identification selection" },
475 { X25_FAC_CALLED_ADDR_EXT, "Called address extension" },
476 { X25_FAC_ETE_TRANSIT_DELAY, "End to end transit delay" },
477 { X25_FAC_CALL_DEFLECT, "Call deflection selection" },
478 { X25_FAC_PRIORITY, "Priority" },
479 { 0, NULL}
482 static struct true_false_string x25_reverse_charging_val = {
483 "Requested",
484 "Not requested"
487 static const value_string x25_facilities_call_transfer_reason_vals[] = {
488 { 0x01, "originally called DTE busy" },
489 { 0x07, "call dist. within a hunt group" },
490 { 0x09, "originally called DTE out of order" },
491 { 0x0F, "systematic call redirection" },
492 { 0, NULL}
495 static const fragment_items x25_frag_items = {
496 &ett_x25_segment,
497 &ett_x25_segments,
498 &hf_x25_segments,
499 &hf_x25_segment,
500 &hf_x25_segment_overlap,
501 &hf_x25_segment_overlap_conflict,
502 &hf_x25_segment_multiple_tails,
503 &hf_x25_segment_too_long_segment,
504 &hf_x25_segment_error,
505 &hf_x25_segment_count,
506 NULL,
507 &hf_x25_reassembled_length,
508 /* Reassembled data field */
509 NULL,
510 "segments"
513 static dissector_handle_t ip_handle;
514 static dissector_handle_t clnp_handle;
515 static dissector_handle_t ositp_handle;
516 static dissector_handle_t qllc_handle;
518 /* Preferences */
519 static bool payload_is_qllc_sna;
520 static bool call_request_nodata_is_cotp;
521 static bool payload_check_data;
522 static bool reassemble_x25 = true;
524 /* Reassembly of X.25 */
526 static reassembly_table x25_reassembly_table;
528 static dissector_table_t x25_subdissector_table;
529 static heur_dissector_list_t x25_heur_subdissector_list;
531 static void
532 x25_hash_add_proto_start(uint16_t vc, uint32_t frame, dissector_handle_t dissect)
534 conversation_t *conv;
537 * Is there already a circuit with this VC number?
539 conv = find_conversation_by_id(frame, CONVERSATION_X25, vc);
540 if (conv != NULL) {
542 * Yes - close it, as we're creating a new one.
544 conv->last_frame = frame - 1;
548 * Set up a new circuit.
550 conv = conversation_new_by_id(frame, CONVERSATION_X25, vc);
553 * Set its dissector.
555 conversation_set_dissector(conv, dissect);
558 static void
559 x25_hash_add_proto_end(uint16_t vc, uint32_t frame)
561 conversation_t *conv;
564 * Try to find the circuit.
566 conv = find_conversation_by_id(frame, CONVERSATION_X25, vc);
569 * If we succeeded, close it.
571 if (conv != NULL)
572 conv->last_frame = frame;
575 static const range_string clear_code_rvals[] = {
576 { 0x00, 0x00, "DTE Originated" },
577 { 0x01, 0x01, "Number Busy" },
578 { 0x03, 0x03, "Invalid Facility Requested" },
579 { 0x05, 0x05, "Network Congestion" },
580 { 0x09, 0x09, "Out Of Order" },
581 { 0x0B, 0x0B, "Access Barred" },
582 { 0x0D, 0x0D, "Not Obtainable" },
583 { 0x11, 0x11, "Remote Procedure Error" },
584 { 0x13, 0x13, "Local Procedure Error" },
585 { 0x15, 0x15, "RPOA Out Of Order" },
586 { 0x19, 0x19, "Reverse Charging Acceptance Not Subscribed" },
587 { 0x21, 0x21, "Incompatible Destination" },
588 { 0x29, 0x29, "Fast Select Acceptance Not Subscribed" },
589 { 0x39, 0x39, "Destination Absent" },
590 { 0x80, 0xff, "DTE Originated" },
591 { 0, 0, NULL }
594 static const range_string reset_code_rvals[] = {
595 { 0x00, 0x00, "DTE Originated" },
596 { 0x01, 0x01, "Out of order" },
597 { 0x03, 0x03, "Remote Procedure Error" },
598 { 0x05, 0x05, "Local Procedure Error" },
599 { 0x07, 0x07, "Network Congestion" },
600 { 0x09, 0x09, "Remote DTE operational" },
601 { 0x0F, 0x0F, "Network operational" },
602 { 0x11, 0x11, "Incompatible Destination" },
603 { 0x1D, 0x1D, "Network out of order" },
604 { 0x80, 0xff, "DTE Originated" },
605 { 0, 0, NULL }
608 static const range_string restart_code_rvals[] = {
609 { 0x00, 0x00, "DTE Originated" },
610 { 0x01, 0x01, "Local Procedure Error" },
611 { 0x03, 0x03, "Network Congestion" },
612 { 0x07, 0x07, "Network Operational" },
613 { 0x7F, 0x7F, "Registration/cancellation confirmed" },
614 { 0x80, 0xff, "DTE Originated" },
615 { 0, 0, NULL }
618 static char *
619 dte_address_util(wmem_allocator_t *pool, tvbuff_t *tvb, int offset, uint8_t len)
621 int i;
622 char *tmpbuf = (char *)wmem_alloc(pool, 258);
624 for (i = 0; (i<len)&&(i<256); i++) {
625 if (i % 2 == 0) {
626 tmpbuf[i] = ((tvb_get_uint8(tvb, offset+i/2) >> 4) & 0x0F) + '0';
627 /* if > 9, convert to the right hexadecimal letter */
628 if (tmpbuf[i] > '9')
629 tmpbuf[i] += ('A' - '0' - 10);
630 } else {
631 tmpbuf[i] = (tvb_get_uint8(tvb, offset+i/2) & 0x0F) + '0';
632 /* if > 9, convert to the right hexadecimal letter */
633 if (tmpbuf[i] > '9')
634 tmpbuf[i] += ('A' - '0' - 10);
638 tmpbuf[i] = '\0';
640 return tmpbuf;
643 static void
644 add_priority(proto_tree *tree, int hf, tvbuff_t *tvb, int offset)
646 uint8_t priority;
648 priority = tvb_get_uint8(tvb, offset);
649 if (priority == 255)
650 proto_tree_add_uint_format_value(tree, hf, tvb, offset, 1, priority,
651 "Unspecified (255)");
652 else
653 proto_tree_add_uint(tree, hf, tvb, offset, 1, priority);
656 static void
657 dump_facilities(proto_tree *tree, int *offset, tvbuff_t *tvb, packet_info *pinfo)
659 uint8_t fac, byte1, byte2, byte3;
660 uint32_t len; /* facilities length */
661 proto_item *ti = NULL;
662 proto_tree *facilities_tree = NULL, *facility_tree = NULL;
664 len = tvb_get_uint8(tvb, *offset);
665 if (len && tree) {
666 facilities_tree = proto_tree_add_subtree(tree, tvb, *offset, len + 1,
667 ett_x25_facilities, NULL, "Facilities");
668 proto_tree_add_item(facilities_tree, hf_x25_facilities_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
670 (*offset)++;
672 while (len > 0) {
673 ti = proto_tree_add_item(facilities_tree, hf_x25_facility, tvb, *offset, -1, ENC_NA);
674 fac = tvb_get_uint8(tvb, *offset);
675 switch(fac & X25_FAC_CLASS_MASK) {
676 case X25_FAC_CLASS_A:
677 proto_item_set_len(ti, 2);
678 proto_item_append_text(ti, ": %s",
679 val_to_str(fac, x25_facilities_classA_vals, "Unknown (0x%02X)"));
680 facility_tree = proto_item_add_subtree(ti, ett_x25_facility);
681 proto_tree_add_item(facility_tree, hf_x25_facility_class, tvb, *offset, 1, ENC_BIG_ENDIAN);
682 proto_tree_add_item(facility_tree, hf_x25_facility_classA, tvb, *offset, 1, ENC_BIG_ENDIAN);
683 if (facility_tree) {
684 switch (fac) {
685 case X25_FAC_COMP_MARK:
686 proto_tree_add_item(facility_tree, hf_x25_facility_classA_comp_mark, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
687 break;
688 case X25_FAC_REVERSE:
689 proto_tree_add_item(facility_tree, hf_x25_facility_classA_reverse, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
690 proto_tree_add_item(facility_tree, hf_x25_fast_select, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
691 proto_tree_add_item(facility_tree, hf_x25_icrd, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
692 proto_tree_add_item(facility_tree, hf_x25_facility_reverse_charging, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
693 break;
694 case X25_FAC_CHARGING_INFO:
695 proto_tree_add_item(facility_tree, hf_x25_facility_classA_charging_info, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
696 proto_tree_add_item(facility_tree, hf_x25_facility_charging_info, tvb, *offset+1, 1, ENC_NA);
697 break;
698 case X25_FAC_THROUGHPUT:
699 proto_tree_add_item(facility_tree, hf_x25_facility_throughput_called_dte, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
700 proto_tree_add_item(facility_tree, hf_x25_throughput_called_dte, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
701 break;
702 case X25_FAC_CUG:
703 proto_tree_add_item(facility_tree, hf_x25_facility_classA_cug, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
704 break;
705 case X25_FAC_CALLED_MODIF:
706 proto_tree_add_item(facility_tree, hf_x25_facility_classA_called_motif, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
707 break;
708 case X25_FAC_CUG_OUTGOING_ACC:
709 proto_tree_add_item(facility_tree, hf_x25_facility_classA_cug_outgoing_acc, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
710 break;
711 case X25_FAC_THROUGHPUT_MIN:
712 proto_tree_add_item(facility_tree, hf_x25_facility_classA_throughput_min, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
713 break;
714 case X25_FAC_EXPRESS_DATA:
715 proto_tree_add_item(facility_tree, hf_x25_facility_classA_express_data, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
716 break;
717 default:
718 proto_tree_add_item(facility_tree, hf_x25_facility_classA_unknown, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
719 break;
722 (*offset) += 2;
723 len -= 2;
724 break;
725 case X25_FAC_CLASS_B:
726 proto_item_set_len(ti, 3);
727 proto_item_append_text(ti, ": %s",
728 val_to_str(fac, x25_facilities_classB_vals, "Unknown (0x%02X)"));
729 facility_tree = proto_item_add_subtree(ti, ett_x25_facility);
730 proto_tree_add_item(facility_tree, hf_x25_facility_class, tvb, *offset, 1, ENC_BIG_ENDIAN);
731 proto_tree_add_item(facility_tree, hf_x25_facility_classB, tvb, *offset, 1, ENC_BIG_ENDIAN);
732 if (facility_tree) {
733 switch (fac) {
734 case X25_FAC_BILATERAL_CUG:
735 proto_tree_add_item(facility_tree, hf_x25_facility_classB_bilateral_cug, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
736 break;
737 case X25_FAC_PACKET_SIZE:
738 proto_tree_add_item(facility_tree, hf_x25_facility_packet_size_called_dte, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
739 proto_tree_add_item(facility_tree, hf_x25_facility_packet_size_calling_dte, tvb, *offset+2, 1, ENC_BIG_ENDIAN);
740 break;
741 case X25_FAC_WINDOW_SIZE:
742 proto_tree_add_item(facility_tree, hf_x25_window_size_called_dte, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
743 proto_tree_add_item(facility_tree, hf_x25_window_size_calling_dte, tvb, *offset+2, 1, ENC_BIG_ENDIAN);
744 break;
745 case X25_FAC_RPOA_SELECTION:
746 proto_tree_add_item(facility_tree, hf_x25_facility_data_network_id_code, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
747 break;
748 case X25_FAC_CUG_EXT:
749 proto_tree_add_item(facility_tree, hf_x25_facility_cug_ext, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
750 break;
751 case X25_FAC_CUG_OUTGOING_ACC_EXT:
752 proto_tree_add_item(facility_tree, hf_x25_facility_cug_outgoing_acc_ext, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
753 break;
754 case X25_FAC_TRANSIT_DELAY:
755 proto_tree_add_item(facility_tree, hf_x25_facility_transit_delay, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
756 break;
757 default:
758 proto_tree_add_item(facility_tree, hf_x25_facility_classB_unknown, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
759 break;
762 (*offset) += 3;
763 len -= 3;
764 break;
765 case X25_FAC_CLASS_C:
766 proto_item_set_len(ti, 4);
767 proto_item_append_text(ti, ": %s",
768 val_to_str(fac, x25_facilities_classC_vals, "Unknown (0x%02X)"));
769 facility_tree = proto_item_add_subtree(ti, ett_x25_facility);
770 proto_tree_add_item(facility_tree, hf_x25_facility_class, tvb, *offset, 1, ENC_BIG_ENDIAN);
771 proto_tree_add_item(facility_tree, hf_x25_facility_classC, tvb, *offset, 1, ENC_BIG_ENDIAN);
772 if (facility_tree) {
773 proto_tree_add_item(facility_tree, hf_x25_facility_classC_unknown, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
775 (*offset) += 4;
776 len -= 4;
777 break;
778 case X25_FAC_CLASS_D:
779 proto_item_append_text(ti, ": %s",
780 val_to_str(fac, x25_facilities_classD_vals, "Unknown (0x%02X)"));
781 facility_tree = proto_item_add_subtree(ti, ett_x25_facility);
782 proto_tree_add_item(facility_tree, hf_x25_facility_class, tvb, *offset, 1, ENC_BIG_ENDIAN);
783 byte1 = tvb_get_uint8(tvb, *offset+1);
784 proto_item_set_len(ti, byte1+2);
785 proto_tree_add_item(facility_tree, hf_x25_facility_classD, tvb, *offset, 1, ENC_BIG_ENDIAN);
786 proto_tree_add_item(facility_tree, hf_x25_facility_length, tvb, *offset+1, 1, ENC_BIG_ENDIAN);
787 if (facility_tree) {
788 switch (fac) {
789 case X25_FAC_CALL_DURATION:
791 int i;
793 if ((byte1 < 4) || (byte1 % 4)) {
794 expert_add_info(pinfo, ti, &ei_x25_facility_length);
795 return;
797 for (i = 0; (i<byte1); i+=4) {
798 proto_tree_add_bytes_format_value(facility_tree, hf_x25_call_duration, tvb, *offset+2+i, 4,
799 NULL, "%u Day(s) %02X:%02X:%02X Hour(s)",
800 tvb_get_uint8(tvb, *offset+2+i),
801 tvb_get_uint8(tvb, *offset+3+i),
802 tvb_get_uint8(tvb, *offset+4+i),
803 tvb_get_uint8(tvb, *offset+5+i));
806 break;
807 case X25_FAC_SEGMENT_COUNT:
809 int i;
811 if ((byte1 < 8) || (byte1 % 8)) {
812 expert_add_info(pinfo, ti, &ei_x25_facility_length);
813 return;
815 for (i = 0; (i<byte1); i+=8) {
816 proto_tree_add_item(facility_tree, hf_x25_segments_to_dte, tvb, *offset+2+i, 4, ENC_NA);
817 proto_tree_add_item(facility_tree, hf_x25_segments_from_dte, tvb, *offset+6+i, 4, ENC_NA);
820 break;
821 case X25_FAC_CALL_TRANSFER:
823 char *tmpbuf;
825 if (byte1 < 2) {
826 expert_add_info(pinfo, ti, &ei_x25_facility_length);
827 return;
829 byte2 = tvb_get_uint8(tvb, *offset+2);
830 if ((byte2 & 0xC0) == 0xC0) {
831 proto_tree_add_uint_format_value(facility_tree, hf_x25_facility_call_transfer_reason, tvb,
832 *offset+2, 1, byte2, "call deflection by the originally called DTE address");
834 else {
835 proto_tree_add_uint(facility_tree, hf_x25_facility_call_transfer_reason, tvb, *offset+2, 1, byte2);
837 byte3 = tvb_get_uint8(tvb, *offset+3);
838 proto_tree_add_uint(facility_tree, hf_x25_facility_call_transfer_num_semi_octets, tvb, *offset+4, 1, byte3);
839 tmpbuf = dte_address_util(pinfo->pool, tvb, *offset + 4, byte3);
841 proto_tree_add_string(facility_tree, hf_x25_dte_address, tvb, *offset+4, byte1 - 2, tmpbuf);
843 break;
844 case X25_FAC_RPOA_SELECTION_EXT:
846 int i;
848 if ((byte1 < 2) || (byte1 % 2)) {
849 expert_add_info(pinfo, ti, &ei_x25_facility_length);
850 return;
852 for (i = 0; (i<byte1); i+=2) {
853 proto_tree_add_item(facility_tree, hf_x25_data_network_identification_code, tvb, *offset+2+i, 2, ENC_BIG_ENDIAN);
856 break;
857 case X25_FAC_CALLING_ADDR_EXT:
859 char *tmpbuf;
861 if (byte1 < 1) {
862 expert_add_info(pinfo, ti, &ei_x25_facility_length);
863 return;
865 byte2 = tvb_get_uint8(tvb, *offset+2) & 0x3F;
866 proto_tree_add_uint(facility_tree, hf_x25_facility_calling_addr_ext_num_semi_octets, tvb, *offset+2, 1, byte2);
867 tmpbuf = dte_address_util(pinfo->pool, tvb, *offset + 3, byte2);
868 proto_tree_add_string(facility_tree, hf_x25_dte_address, tvb, *offset+3, byte1 - 1, tmpbuf);
870 break;
871 case X25_FAC_MONETARY_UNIT:
872 proto_tree_add_item(facility_tree, hf_x25_facility_monetary_unit, tvb, *offset+2, byte1, ENC_NA);
873 break;
874 case X25_FAC_NUI:
875 proto_tree_add_item(facility_tree, hf_x25_facility_nui, tvb, *offset+2, byte1, ENC_NA);
876 break;
877 case X25_FAC_CALLED_ADDR_EXT:
879 char *tmpbuf;
881 if (byte1 < 1) {
882 expert_add_info(pinfo, ti, &ei_x25_facility_length);
883 return;
885 byte2 = tvb_get_uint8(tvb, *offset+2) & 0x3F;
886 proto_tree_add_uint(facility_tree, hf_x25_facility_called_addr_ext_num_semi_octets, tvb, *offset+2, 1, byte2);
887 tmpbuf = dte_address_util(pinfo->pool, tvb, *offset+3, byte2);
889 proto_tree_add_string(facility_tree, hf_x25_dte_address, tvb, *offset+3, byte1 - 1, tmpbuf);
891 break;
892 case X25_FAC_ETE_TRANSIT_DELAY:
893 if (byte1 < 2)
894 break;
895 proto_tree_add_item(facility_tree, hf_x25_facility_cumulative_ete_transit_delay, tvb, *offset+2, 2, ENC_BIG_ENDIAN);
896 if (byte1 < 4)
897 break;
898 proto_tree_add_item(facility_tree, hf_x25_facility_requested_ete_transit_delay, tvb, *offset+4, 2, ENC_BIG_ENDIAN);
899 if (byte1 < 6)
900 break;
901 proto_tree_add_item(facility_tree, hf_x25_facility_max_acceptable_ete_transit_delay, tvb, *offset+6, 2, ENC_BIG_ENDIAN);
902 break;
903 case X25_FAC_CALL_DEFLECT:
905 char *tmpbuf;
907 if (byte1 < 2) {
908 expert_add_info(pinfo, ti, &ei_x25_facility_length);
909 return;
911 byte2 = tvb_get_uint8(tvb, *offset+2);
912 if ((byte2 & 0xC0) == 0xC0)
913 proto_tree_add_uint_format_value(facility_tree, hf_x25_facility_call_deflect_reason, tvb, *offset+2, 1,
914 byte2, "call DTE originated");
915 else
916 proto_tree_add_uint_format_value(facility_tree, hf_x25_facility_call_deflect_reason, tvb, *offset+2, 1,
917 byte2, "unknown");
918 byte3 = tvb_get_uint8(tvb, *offset+3);
919 proto_tree_add_uint(facility_tree, hf_x25_facility_call_deflect_num_semi_octets, tvb, *offset+3, 1, byte3);
920 tmpbuf = dte_address_util(pinfo->pool, tvb, *offset+4, byte3);
922 proto_tree_add_string(facility_tree, hf_x25_alternative_dte_address, tvb, *offset+4, byte1 - 2, tmpbuf);
924 break;
925 case X25_FAC_PRIORITY:
926 if (byte1 < 1)
927 break;
928 add_priority(facility_tree, hf_x25_facility_priority_data, tvb, *offset+2);
929 if (byte1 < 2)
930 break;
931 add_priority(facility_tree, hf_x25_facility_priority_estab_conn, tvb, *offset+3);
932 if (byte1 < 3)
933 break;
934 add_priority(facility_tree, hf_x25_facility_priority_keep_conn, tvb, *offset+4);
935 if (byte1 < 4)
936 break;
937 add_priority(facility_tree, hf_x25_facility_min_acceptable_priority_data, tvb, *offset+5);
938 if (byte1 < 5)
939 break;
940 add_priority(facility_tree, hf_x25_facility_min_acceptable_priority_estab_conn, tvb, *offset+6);
941 if (byte1 < 6)
942 break;
943 add_priority(facility_tree, hf_x25_facility_min_acceptable_priority_keep_conn, tvb, *offset+7);
944 break;
945 default:
946 proto_tree_add_item(facility_tree, hf_x25_facility_classD_unknown, tvb, *offset+2, byte1, ENC_NA);
949 byte1 = tvb_get_uint8(tvb, *offset+1);
950 (*offset) += byte1+2;
951 len -= byte1+2;
952 break;
957 static void
958 x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
959 packet_info *pinfo, bool is_registration)
961 int len1, len2;
962 int i;
963 char *addr1, *addr2;
964 char *first, *second;
965 uint8_t byte;
966 int localoffset;
968 addr1=(char *)wmem_alloc(pinfo->pool, 16);
969 addr2=(char *)wmem_alloc(pinfo->pool, 16);
971 byte = tvb_get_uint8(tvb, *offset);
972 len1 = (byte >> 0) & 0x0F;
973 len2 = (byte >> 4) & 0x0F;
975 if (tree) {
976 if (is_registration) {
977 proto_tree_add_item(tree, hf_x25_dte_address_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
978 proto_tree_add_item(tree, hf_x25_dce_address_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
980 else {
981 proto_tree_add_item(tree, hf_x25_calling_address_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
982 proto_tree_add_item(tree, hf_x25_called_address_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
985 (*offset)++;
987 localoffset = *offset;
988 byte = tvb_get_uint8(tvb, localoffset);
990 first=addr1;
991 second=addr2;
992 for (i = 0; i < (len1 + len2); i++) {
993 if (i < len1) {
994 if (i % 2 != 0) {
995 *first++ = ((byte >> 0) & 0x0F) + '0';
996 localoffset++;
997 byte = tvb_get_uint8(tvb, localoffset);
998 } else {
999 *first++ = ((byte >> 4) & 0x0F) + '0';
1001 } else {
1002 if (i % 2 != 0) {
1003 *second++ = ((byte >> 0) & 0x0F) + '0';
1004 localoffset++;
1005 byte = tvb_get_uint8(tvb, localoffset);
1006 } else {
1007 *second++ = ((byte >> 4) & 0x0F) + '0';
1012 *first = '\0';
1013 *second = '\0';
1015 if (len1) {
1016 col_add_str(pinfo->cinfo, COL_RES_DL_DST, addr1);
1017 proto_tree_add_string(tree, is_registration ? hf_x25_dce_address : hf_x25_called_address, tvb, *offset,
1018 (len1 + 1) / 2, addr1);
1020 if (len2) {
1021 col_add_str(pinfo->cinfo, COL_RES_DL_SRC, addr2);
1022 proto_tree_add_string(tree, is_registration ? hf_x25_dte_address : hf_x25_calling_address, tvb, *offset + len1/2,
1023 (len2+1)/2+(len1%2+(len2+1)%2)/2, addr2);
1025 (*offset) += ((len1 + len2 + 1) / 2);
1028 static void
1029 x25_toa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1030 packet_info *pinfo)
1032 int len1, len2;
1033 int i;
1034 char *addr1, *addr2;
1035 char *first, *second;
1036 uint8_t byte;
1037 int localoffset;
1039 addr1=(char *)wmem_alloc(pinfo->pool, 256);
1040 addr2=(char *)wmem_alloc(pinfo->pool, 256);
1042 len1 = tvb_get_uint8(tvb, *offset);
1043 proto_tree_add_item(tree, hf_x25_called_address_length, tvb, *offset, 1, ENC_NA);
1044 (*offset)++;
1046 len2 = tvb_get_uint8(tvb, *offset);
1047 proto_tree_add_item(tree, hf_x25_calling_address_length, tvb, *offset, 1, ENC_NA);
1048 (*offset)++;
1050 localoffset = *offset;
1051 byte = tvb_get_uint8(tvb, localoffset);
1054 * XXX - the first two half-octets of the address are the TOA and
1055 * NPI; process them as such and, if the TOA says an address is
1056 * an alternative address, process it correctly (i.e., not as a
1057 * sequence of half-octets containing digit values).
1059 first=addr1;
1060 second=addr2;
1061 for (i = 0; i < (len1 + len2); i++) {
1062 if (i < len1) {
1063 if (i % 2 != 0) {
1064 *first++ = ((byte >> 0) & 0x0F) + '0';
1065 localoffset++;
1066 byte = tvb_get_uint8(tvb, localoffset);
1067 } else {
1068 *first++ = ((byte >> 4) & 0x0F) + '0';
1070 } else {
1071 if (i % 2 != 0) {
1072 *second++ = ((byte >> 0) & 0x0F) + '0';
1073 localoffset++;
1074 byte = tvb_get_uint8(tvb, localoffset);
1075 } else {
1076 *second++ = ((byte >> 4) & 0x0F) + '0';
1081 *first = '\0';
1082 *second = '\0';
1084 if (len1) {
1085 col_add_str(pinfo->cinfo, COL_RES_DL_DST, addr1);
1086 proto_tree_add_string(tree, hf_x25_called_address, tvb, *offset,
1087 (len1 + 1) / 2, addr1);
1089 if (len2) {
1090 col_add_str(pinfo->cinfo, COL_RES_DL_SRC, addr2);
1091 proto_tree_add_string(tree, hf_x25_calling_address, tvb, *offset + len1/2,
1092 (len2+1)/2+(len1%2+(len2+1)%2)/2, addr2);
1094 (*offset) += ((len1 + len2 + 1) / 2);
1097 static int
1098 get_x25_pkt_len(tvbuff_t *tvb)
1100 unsigned length, called_len, calling_len, dte_len, dce_len;
1101 uint8_t byte2, bytex;
1103 byte2 = tvb_get_uint8(tvb, 2);
1104 switch (byte2)
1106 case X25_CALL_REQUEST:
1107 bytex = tvb_get_uint8(tvb, 3);
1108 called_len = (bytex >> 0) & 0x0F;
1109 calling_len = (bytex >> 4) & 0x0F;
1110 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1111 if (length < tvb_reported_length(tvb))
1112 length += (1 + tvb_get_uint8(tvb, length)); /* facilities */
1114 return MIN(tvb_reported_length(tvb),length);
1116 case X25_CALL_ACCEPTED:
1117 /* The calling/called address length byte (following the packet type)
1118 * is not mandatory, so we must check the packet length before trying
1119 * to read it */
1120 if (tvb_reported_length(tvb) == 3)
1121 return 3;
1122 bytex = tvb_get_uint8(tvb, 3);
1123 called_len = (bytex >> 0) & 0x0F;
1124 calling_len = (bytex >> 4) & 0x0F;
1125 length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1126 if (length < tvb_reported_length(tvb))
1127 length += (1 + tvb_get_uint8(tvb, length)); /* facilities */
1129 return MIN(tvb_reported_length(tvb),length);
1131 case X25_CLEAR_REQUEST:
1132 case X25_RESET_REQUEST:
1133 case X25_RESTART_REQUEST:
1134 return MIN(tvb_reported_length(tvb),5);
1136 case X25_DIAGNOSTIC:
1137 return MIN(tvb_reported_length(tvb),4);
1139 case X25_CLEAR_CONFIRMATION:
1140 case X25_INTERRUPT:
1141 case X25_INTERRUPT_CONFIRMATION:
1142 case X25_RESET_CONFIRMATION:
1143 case X25_RESTART_CONFIRMATION:
1144 return MIN(tvb_reported_length(tvb),3);
1146 case X25_REGISTRATION_REQUEST:
1147 bytex = tvb_get_uint8(tvb, 3);
1148 dce_len = (bytex >> 0) & 0x0F;
1149 dte_len = (bytex >> 4) & 0x0F;
1150 length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1151 if (length < tvb_reported_length(tvb))
1152 length += (1 + tvb_get_uint8(tvb, length)); /* registration */
1154 return MIN(tvb_reported_length(tvb),length);
1156 case X25_REGISTRATION_CONFIRMATION:
1157 bytex = tvb_get_uint8(tvb, 5);
1158 dce_len = (bytex >> 0) & 0x0F;
1159 dte_len = (bytex >> 4) & 0x0F;
1160 length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1161 if (length < tvb_reported_length(tvb))
1162 length += (1 + tvb_get_uint8(tvb, length)); /* registration */
1164 return MIN(tvb_reported_length(tvb),length);
1167 if (PACKET_IS_DATA(byte2))
1168 return MIN(tvb_reported_length(tvb),3);
1170 switch (PACKET_TYPE_FC(byte2))
1172 case X25_RR:
1173 return MIN(tvb_reported_length(tvb),3);
1175 case X25_RNR:
1176 return MIN(tvb_reported_length(tvb),3);
1178 case X25_REJ:
1179 return MIN(tvb_reported_length(tvb),3);
1182 return 0;
1185 static const value_string prt_id_vals[] = {
1186 {PRT_ID_ISO_8073, "ISO 8073 COTP"},
1187 {PRT_ID_ISO_8602, "ISO 8602 CLTP"},
1188 {PRT_ID_ISO_10736_ISO_8073, "ISO 10736 in conjunction with ISO 8073 COTP"},
1189 {PRT_ID_ISO_10736_ISO_8602, "ISO 10736 in conjunction with ISO 8602 CLTP"},
1190 {0x00, NULL}
1193 static const value_string sharing_strategy_vals[] = {
1194 {0x00, "No sharing"},
1195 {0x00, NULL}
1198 static void
1199 dissect_x25_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1200 x25_dir_t dir, bool side)
1202 proto_tree *x25_tree=0, *gfi_tree=0, *userdata_tree=0;
1203 proto_item *ti;
1204 unsigned localoffset=0;
1205 unsigned x25_pkt_len;
1206 int modulo;
1207 uint16_t vc;
1208 dissector_handle_t dissect;
1209 bool toa; /* TOA/NPI address format */
1210 uint16_t bytes0_1;
1211 uint8_t pkt_type;
1212 const char *short_name = NULL, *long_name = NULL;
1213 tvbuff_t *next_tvb = NULL;
1214 bool q_bit_set = false;
1215 bool m_bit_set;
1216 int payload_len;
1217 uint32_t frag_key;
1218 fragment_head *fd_head;
1219 heur_dtbl_entry_t *hdtbl_entry;
1222 uint8_t spi;
1223 int is_x_264;
1224 uint8_t prt_id;
1225 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X.25");
1226 col_clear(pinfo->cinfo, COL_INFO);
1228 bytes0_1 = tvb_get_ntohs(tvb, 0);
1230 modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
1231 vc = (int)(bytes0_1 & 0x0FFF);
1233 conversation_set_elements_by_id(pinfo, CONVERSATION_X25, vc);
1235 if (bytes0_1 & X25_ABIT) toa = true;
1236 else toa = false;
1238 x25_pkt_len = get_x25_pkt_len(tvb);
1239 if (x25_pkt_len < 3) /* packet too short */
1241 col_set_str(pinfo->cinfo, COL_INFO, "Invalid/short X.25 packet");
1242 if (tree)
1243 proto_tree_add_protocol_format(tree, proto_x25, tvb, 0, -1,
1244 "Invalid/short X.25 packet");
1245 return;
1248 pkt_type = tvb_get_uint8(tvb, 2);
1249 if (PACKET_IS_DATA(pkt_type)) {
1250 if (bytes0_1 & X25_QBIT)
1251 q_bit_set = true;
1254 if (tree) {
1255 ti = proto_tree_add_item(tree, proto_x25, tvb, 0, x25_pkt_len, ENC_NA);
1256 x25_tree = proto_item_add_subtree(ti, ett_x25);
1257 ti = proto_tree_add_item(x25_tree, hf_x25_gfi, tvb, 0, 2, ENC_BIG_ENDIAN);
1258 gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
1260 if (PACKET_IS_DATA(pkt_type)) {
1261 proto_tree_add_boolean(gfi_tree, hf_x25_qbit, tvb, 0, 2,
1262 bytes0_1);
1264 else if (pkt_type == X25_CALL_REQUEST ||
1265 pkt_type == X25_CALL_ACCEPTED ||
1266 pkt_type == X25_CLEAR_REQUEST ||
1267 pkt_type == X25_CLEAR_CONFIRMATION) {
1268 proto_tree_add_boolean(gfi_tree, hf_x25_abit, tvb, 0, 2,
1269 bytes0_1);
1272 if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
1273 PACKET_IS_DATA(pkt_type)) {
1274 proto_tree_add_boolean(gfi_tree, hf_x25_dbit, tvb, 0, 2,
1275 bytes0_1);
1277 proto_tree_add_uint(gfi_tree, hf_x25_mod, tvb, 0, 2, bytes0_1);
1280 switch (pkt_type) {
1281 case X25_CALL_REQUEST:
1282 switch (dir) {
1284 case X25_FROM_DCE:
1285 short_name = "Inc. call";
1286 long_name = "Incoming call";
1287 break;
1289 case X25_FROM_DTE:
1290 short_name = "Call req.";
1291 long_name = "Call request";
1292 break;
1294 case X25_UNKNOWN:
1295 short_name = "Inc. call/Call req.";
1296 long_name = "Incoming call/Call request";
1297 break;
1299 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d", short_name, vc);
1300 if (x25_tree) {
1301 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb,
1302 0, 2, bytes0_1);
1303 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1304 X25_CALL_REQUEST, "%s", long_name);
1306 localoffset = 3;
1307 if (localoffset < x25_pkt_len) { /* calling/called addresses */
1308 if (toa)
1309 x25_toa(x25_tree, (int*)&localoffset, tvb, pinfo);
1310 else
1311 x25_ntoa(x25_tree, (int*)&localoffset, tvb, pinfo, false);
1314 if (localoffset < x25_pkt_len) /* facilities */
1315 dump_facilities(x25_tree, (int*)&localoffset, tvb, pinfo);
1317 if (localoffset < tvb_reported_length(tvb)) /* user data */
1320 userdata_tree = proto_tree_add_subtree(x25_tree, tvb, localoffset, -1,
1321 ett_x25_user_data, &ti, "User data");
1323 /* X.263/ISO 9577 says that:
1325 When CLNP or ESIS are run over X.25, the SPI
1326 is 0x81 or 0x82, respectively; those are the
1327 NLPIDs for those protocol.
1329 When X.224/ISO 8073 COTP is run over X.25, and
1330 when ISO 11570 explicit identification is being
1331 used, the first octet of the user data field is
1332 a TPDU length field, and the rest is "as defined
1333 in ITU-T Rec. X.225 | ISO/IEC 8073, Annex B,
1334 or ITU-T Rec. X.264 and ISO/IEC 11570".
1336 When X.264/ISO 11570 default identification is
1337 being used, there is no user data field in the
1338 CALL REQUEST packet. This is for X.225/ISO 8073
1339 COTP.
1341 It also says that SPI values from 0x03 through 0x3f are
1342 reserved and are in use by X.224/ISO 8073 Annex B and
1343 X.264/ISO 11570. The note says that those values are
1344 not NLPIDs, they're "used by the respective higher layer
1345 protocol" and "not used for higher layer protocol
1346 identification". I infer from this and from what
1347 X.264/ISO 11570 says that this means that values in those
1348 range are valid values for the first octet of an
1349 X.224/ISO 8073 packet or for X.264/ISO 11570.
1351 Annex B of X.225/ISO 8073 mentions some additional TPDU
1352 types that can be put in what I presume is the user
1353 data of connect requests. It says that:
1355 The sending transport entity shall:
1357 a) either not transmit any TPDU in the NS-user data
1358 parameter of the N-CONNECT request primitive; or
1360 b) transmit the UN-TPDU (see ITU-T Rec. X.264 and
1361 ISO/IEC 11570) followed by the NCM-TPDU in the
1362 NS-user data parameter of the N-CONNECT request
1363 primitive.
1365 I don't know if this means that the user data field
1366 will contain a UN TPDU followed by an NCM TPDU or not.
1368 X.264/ISO 11570 says that:
1370 When default identification is being used,
1371 X.225/ISO 8073 COTP is identified. No user data
1372 is sent in the network-layer connection request.
1374 When explicit identification is being used,
1375 the user data is a UN TPDU ("Use of network
1376 connection TPDU"), which specifies the transport
1377 protocol to use over this network connection.
1378 It also says that the length of a UN TPDU shall
1379 not exceed 32 octets, i.e. shall not exceed 0x20;
1380 it says this is "due to the desire not to conflict
1381 with the protocol identifier field carried by X.25
1382 CALL REQUEST/INCOMING CALL packets", and says that
1383 field has values specified in X.244. X.244 has been
1384 superseded by X.263/ISO 9577, so that presumably
1385 means the goal is to allow a UN TPDU's length
1386 field to be distinguished from an NLPID, allowing
1387 you to tell whether X.264/ISO 11570 explicit
1388 identification is being used or an NLPID is
1389 being used as the SPI.
1391 I read this as meaning that, if the ISO mechanisms are
1392 used to identify the protocol being carried over X.25:
1394 if there's no user data in the CALL REQUEST/
1395 INCOMING CALL packet, it's COTP;
1397 if there is user data, then:
1399 if the first octet is less than or equal to
1400 32, it might be a UN TPDU, and that identifies
1401 the transport protocol being used, and
1402 it may be followed by more data, such
1403 as a COTP NCM TPDU if it's COTP;
1405 if the first octet is greater than 32, it's
1406 an NLPID, *not* a TPDU length, and the
1407 stuff following it is *not* a TPDU.
1409 Figure A.2 of X.263/ISO 9577 seems to say that the
1410 first octet of the user data is a TPDU length field,
1411 in the range 0x03 through 0x82, and says they are
1412 for X.225/ISO 8073 Annex B or X.264/ISO 11570.
1414 However, X.264/ISO 11570 seems to imply that the length
1415 field would be that of a UN TPDU, which must be less
1416 than or equal to 0x20, and X.225/ISO 8073 Annex B seems
1417 to indicate that the user data must begin with
1418 an X.264/ISO 11570 UN TPDU, so I'd say that A.2 should
1419 have said "in the range 0x03 through 0x20", instead
1420 (the length value doesn't include the length field,
1421 and the minimum UN TPDU has length, type, PRT-ID,
1422 and SHARE, so that's 3 bytes without the length). */
1423 spi = tvb_get_uint8(tvb, localoffset);
1424 if (spi > 32 || spi < 3) {
1425 /* First octet is > 32, or < 3, so the user data isn't an
1426 X.264/ISO 11570 UN TPDU */
1427 is_x_264 = false;
1428 } else {
1429 /* First octet is >= 3 and <= 32, so the user data *might*
1430 be an X.264/ISO 11570 UN TPDU. Check whether we have
1431 enough data to see if it is. */
1432 if (tvb_bytes_exist(tvb, localoffset+1, 1)) {
1433 /* We do; check whether the second octet is 1. */
1434 if (tvb_get_uint8(tvb, localoffset+1) == 0x01) {
1435 /* Yes, the second byte is 1, so it looks like
1436 a UN TPDU. */
1437 is_x_264 = true;
1438 } else {
1439 /* No, the second byte is not 1, so it's not a
1440 UN TPDU. */
1441 is_x_264 = false;
1443 } else {
1444 /* We can't see the second byte of the putative UN
1445 TPDU, so we don't know if that's what it is. */
1446 is_x_264 = -1;
1449 if (is_x_264 == -1) {
1451 * We don't know what it is; just skip it.
1453 localoffset = tvb_reported_length(tvb);
1454 } else if (is_x_264) {
1455 /* It looks like an X.264 UN TPDU, so show it as such. */
1456 if (userdata_tree) {
1457 proto_tree_add_item( userdata_tree, hf_x264_length_indicator, tvb, localoffset, 1, ENC_BIG_ENDIAN);
1458 proto_tree_add_item( userdata_tree, hf_x264_un_tpdu_id, tvb, localoffset+1, 1, ENC_BIG_ENDIAN);
1460 prt_id = tvb_get_uint8(tvb, localoffset+2);
1461 if (userdata_tree) {
1462 proto_tree_add_item( userdata_tree, hf_x264_protocol_id, tvb, localoffset+2, 1, ENC_BIG_ENDIAN);
1463 proto_tree_add_item( userdata_tree, hf_x264_sharing_strategy, tvb, localoffset+3, 1, ENC_BIG_ENDIAN);
1466 /* XXX - dissect the variable part? */
1468 /* The length doesn't include the length octet itself. */
1469 localoffset += spi + 1;
1471 switch (prt_id) {
1473 case PRT_ID_ISO_8073:
1474 /* ISO 8073 COTP */
1475 if (!pinfo->fd->visited)
1476 x25_hash_add_proto_start(vc, pinfo->num, ositp_handle);
1477 /* XXX - dissect the rest of the user data as COTP?
1478 That needs support for NCM TPDUs, etc. */
1479 break;
1481 case PRT_ID_ISO_8602:
1482 /* ISO 8602 CLTP */
1483 if (!pinfo->fd->visited)
1484 x25_hash_add_proto_start(vc, pinfo->num, ositp_handle);
1485 break;
1487 } else if (is_x_264 == 0) {
1488 /* It doesn't look like a UN TPDU, so compare the first
1489 octet of the CALL REQUEST packet with various X.263/
1490 ISO 9577 NLPIDs, as per Annex A of X.263/ISO 9577. */
1492 if (userdata_tree) {
1493 proto_tree_add_item( userdata_tree, hf_x263_sec_protocol_id, tvb, localoffset, 1, ENC_BIG_ENDIAN);
1496 if (!pinfo->fd->visited) {
1498 * Is there a dissector handle for this SPI?
1499 * If so, assign it to this virtual circuit.
1501 dissect = dissector_get_uint_handle(x25_subdissector_table, spi);
1502 if (dissect != NULL)
1503 x25_hash_add_proto_start(vc, pinfo->num, dissect);
1507 * If there's only one octet of user data, it's just
1508 * an NLPID; don't try to dissect it.
1510 if (localoffset + 1 == tvb_reported_length(tvb))
1511 return;
1514 * There's more than one octet of user data, so we'll
1515 * dissect it; for some protocols, the NLPID is considered
1516 * to be part of the PDU, so, for those cases, we don't
1517 * skip past it. For other protocols, we skip the NLPID.
1519 switch (spi) {
1521 case NLPID_ISO8473_CLNP:
1522 case NLPID_ISO9542_ESIS:
1523 case NLPID_ISO10589_ISIS:
1524 case NLPID_ISO10747_IDRP:
1525 case NLPID_SNDCF:
1527 * The NLPID is part of the PDU. Don't skip it.
1528 * But if it's all there is to the PDU, don't
1529 * bother dissecting it.
1531 break;
1533 case NLPID_SPI_X_29:
1535 * The first 4 bytes of the call user data are
1536 * the SPI plus 3 reserved bytes; they are not
1537 * part of the data to be dissected as X.29 data.
1539 localoffset += 4;
1540 break;
1542 default:
1544 * The NLPID isn't part of the PDU - skip it.
1545 * If that means there's nothing to dissect
1547 localoffset++;
1550 } else {
1551 /* if there's no user data in the CALL REQUEST/
1552 INCOMING CALL packet, it's COTP; */
1554 if (call_request_nodata_is_cotp){
1555 x25_hash_add_proto_start(vc, pinfo->num, ositp_handle);
1558 break;
1559 case X25_CALL_ACCEPTED:
1560 switch (dir) {
1562 case X25_FROM_DCE:
1563 short_name = "Call conn.";
1564 long_name = "Call connected";
1565 break;
1567 case X25_FROM_DTE:
1568 short_name = "Call acc.";
1569 long_name = "Call accepted";
1570 break;
1572 case X25_UNKNOWN:
1573 short_name = "Call conn./Call acc.";
1574 long_name = "Call connected/Call accepted";
1575 break;
1577 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d", short_name, vc);
1578 if (x25_tree) {
1579 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1580 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1581 X25_CALL_ACCEPTED, "%s", long_name);
1583 localoffset = 3;
1584 if (localoffset < x25_pkt_len) { /* calling/called addresses */
1585 if (toa)
1586 x25_toa(x25_tree, (int*)&localoffset, tvb, pinfo);
1587 else
1588 x25_ntoa(x25_tree, (int*)&localoffset, tvb, pinfo, false);
1591 if (localoffset < x25_pkt_len) /* facilities */
1592 dump_facilities(x25_tree, (int*)&localoffset, tvb, pinfo);
1593 break;
1594 case X25_CLEAR_REQUEST:
1595 switch (dir) {
1597 case X25_FROM_DCE:
1598 short_name = "Clear ind.";
1599 long_name = "Clear indication";
1600 break;
1602 case X25_FROM_DTE:
1603 short_name = "Clear req.";
1604 long_name = "Clear request";
1605 break;
1607 case X25_UNKNOWN:
1608 short_name = "Clear ind./Clear req.";
1609 long_name = "Clear indication/Clear request";
1610 break;
1612 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d %s - %s", short_name,
1613 vc, rval_to_str(tvb_get_uint8(tvb, 3), clear_code_rvals, "Unknown (0x%02x)"),
1614 val_to_str_ext(tvb_get_uint8(tvb, 4), &x25_clear_diag_vals_ext, "Unknown (0x%02x)"));
1615 x25_hash_add_proto_end(vc, pinfo->num);
1616 if (x25_tree) {
1617 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1618 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb,
1619 localoffset+2, 1, X25_CLEAR_REQUEST, "%s",
1620 long_name);
1621 proto_tree_add_item(x25_tree, hf_x25_clear_cause, tvb, 3, 1, ENC_NA);
1622 proto_tree_add_item(x25_tree, hf_x25_diagnostic, tvb, 4, 1, ENC_BIG_ENDIAN);
1624 localoffset = x25_pkt_len;
1625 break;
1626 case X25_CLEAR_CONFIRMATION:
1627 col_add_fstr(pinfo->cinfo, COL_INFO, "Clear Conf. VC:%d", vc);
1628 if (x25_tree) {
1629 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1630 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1631 X25_CLEAR_CONFIRMATION);
1633 localoffset = x25_pkt_len;
1635 if (localoffset < tvb_reported_length(tvb)) { /* extended clear conf format */
1636 if (toa)
1637 x25_toa(x25_tree, (int*)&localoffset, tvb, pinfo);
1638 else
1639 x25_ntoa(x25_tree,(int*)&localoffset, tvb, pinfo, false);
1642 if (localoffset < tvb_reported_length(tvb)) /* facilities */
1643 dump_facilities(x25_tree, (int*)&localoffset, tvb, pinfo);
1644 break;
1645 case X25_DIAGNOSTIC:
1646 col_add_fstr(pinfo->cinfo, COL_INFO, "Diag. %d",
1647 (int)tvb_get_uint8(tvb, 3));
1648 if (x25_tree) {
1649 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1650 X25_DIAGNOSTIC);
1651 proto_tree_add_item(x25_tree, hf_x25_diagnostic, tvb, 3, 1, ENC_NA);
1653 localoffset = x25_pkt_len;
1654 break;
1655 case X25_INTERRUPT:
1656 col_add_fstr(pinfo->cinfo, COL_INFO, "Interrupt VC:%d", vc);
1657 if (x25_tree) {
1658 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1659 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1660 X25_INTERRUPT);
1662 localoffset = x25_pkt_len;
1663 break;
1664 case X25_INTERRUPT_CONFIRMATION:
1665 col_add_fstr(pinfo->cinfo, COL_INFO, "Interrupt Conf. VC:%d", vc);
1666 if (x25_tree) {
1667 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1668 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1669 X25_INTERRUPT_CONFIRMATION);
1671 localoffset = x25_pkt_len;
1672 break;
1673 case X25_RESET_REQUEST:
1674 switch (dir) {
1676 case X25_FROM_DCE:
1677 short_name = "Reset ind.";
1678 long_name = "Reset indication";
1679 break;
1681 case X25_FROM_DTE:
1682 short_name = "Reset req.";
1683 long_name = "Reset request";
1684 break;
1686 case X25_UNKNOWN:
1687 short_name = "Reset ind./Reset req.";
1688 long_name = "Reset indication/Reset request";
1689 break;
1691 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d %s - Diag.:%d",
1692 short_name, vc, rval_to_str(tvb_get_uint8(tvb, 3), reset_code_rvals, "Unknown (0x%02x)"),
1693 (int)tvb_get_uint8(tvb, 4));
1694 x25_hash_add_proto_end(vc, pinfo->num);
1695 if (x25_tree) {
1696 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1697 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1698 X25_RESET_REQUEST, "%s", long_name);
1699 proto_tree_add_item(x25_tree, hf_x25_reset_cause, tvb, 3, 1, ENC_NA);
1700 proto_tree_add_item(x25_tree, hf_x25_diagnostic, tvb, 4, 1, ENC_NA);
1702 localoffset = x25_pkt_len;
1703 break;
1704 case X25_RESET_CONFIRMATION:
1705 col_add_fstr(pinfo->cinfo, COL_INFO, "Reset conf. VC:%d", vc);
1706 if (x25_tree) {
1707 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1708 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1709 X25_RESET_CONFIRMATION);
1711 localoffset = x25_pkt_len;
1712 break;
1713 case X25_RESTART_REQUEST:
1714 switch (dir) {
1716 case X25_FROM_DCE:
1717 short_name = "Restart ind.";
1718 long_name = "Restart indication";
1719 break;
1721 case X25_FROM_DTE:
1722 short_name = "Restart req.";
1723 long_name = "Restart request";
1724 break;
1726 case X25_UNKNOWN:
1727 short_name = "Restart ind./Restart req.";
1728 long_name = "Restart indication/Restart request";
1729 break;
1731 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s - Diag.:%d",
1732 short_name,
1733 rval_to_str(tvb_get_uint8(tvb, 3), restart_code_rvals, "Unknown (0x%02x)"),
1734 (int)tvb_get_uint8(tvb, 4));
1735 if (x25_tree) {
1736 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1737 X25_RESTART_REQUEST, "%s", long_name);
1738 proto_tree_add_item(x25_tree, hf_x25_restart_cause, tvb, 3, 1, ENC_NA);
1739 proto_tree_add_item(x25_tree, hf_x25_diagnostic, tvb, 4, 1, ENC_NA);
1741 localoffset = x25_pkt_len;
1742 break;
1743 case X25_RESTART_CONFIRMATION:
1744 col_set_str(pinfo->cinfo, COL_INFO, "Restart conf.");
1745 if (x25_tree)
1746 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1747 X25_RESTART_CONFIRMATION);
1748 localoffset = x25_pkt_len;
1749 break;
1750 case X25_REGISTRATION_REQUEST:
1751 col_set_str(pinfo->cinfo, COL_INFO, "Registration req.");
1752 if (x25_tree)
1753 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1754 X25_REGISTRATION_REQUEST);
1755 localoffset = 3;
1756 if (localoffset < x25_pkt_len)
1757 x25_ntoa(x25_tree, (int*)&localoffset, tvb, pinfo, true);
1759 if (x25_tree) {
1760 if (localoffset < x25_pkt_len)
1761 proto_tree_add_item( x25_tree, hf_x25_reg_request_length, tvb, localoffset, 1, ENC_BIG_ENDIAN);
1762 if (localoffset+1 < x25_pkt_len)
1763 proto_tree_add_item(x25_tree, hf_x25_registration, tvb, localoffset+1, tvb_get_uint8(tvb, localoffset) & 0x7F, ENC_NA);
1765 localoffset = tvb_reported_length(tvb);
1766 break;
1767 case X25_REGISTRATION_CONFIRMATION:
1768 col_set_str(pinfo->cinfo, COL_INFO, "Registration conf.");
1769 if (x25_tree) {
1770 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1771 X25_REGISTRATION_CONFIRMATION);
1772 proto_tree_add_item(x25_tree, hf_x25_reg_confirm_cause, tvb, 3, 1, ENC_BIG_ENDIAN);
1773 proto_tree_add_item(x25_tree, hf_x25_reg_confirm_diagnostic, tvb, 4, 1, ENC_BIG_ENDIAN);
1775 localoffset = 5;
1776 if (localoffset < x25_pkt_len)
1777 x25_ntoa(x25_tree, (int*)&localoffset, tvb, pinfo, true);
1779 if (x25_tree) {
1780 if (localoffset < x25_pkt_len)
1781 proto_tree_add_item( x25_tree, hf_x25_reg_confirm_length, tvb, localoffset, 1, ENC_BIG_ENDIAN);
1782 if (localoffset+1 < x25_pkt_len)
1783 proto_tree_add_item(x25_tree, hf_x25_registration, tvb, localoffset+1, tvb_get_uint8(tvb, localoffset) & 0x7F, ENC_NA);
1785 localoffset = tvb_reported_length(tvb);
1786 break;
1787 default:
1788 localoffset = 2;
1789 if (x25_tree) {
1790 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1791 2, bytes0_1);
1793 if (PACKET_IS_DATA(pkt_type)) {
1794 if (modulo == 8)
1795 col_add_fstr(pinfo->cinfo, COL_INFO,
1796 "Data VC:%d P(S):%d P(R):%d %s", vc,
1797 (pkt_type >> 1) & 0x07,
1798 (pkt_type >> 5) & 0x07,
1799 (pkt_type & X25_MBIT_MOD8) ? " M" : "");
1800 else
1801 col_add_fstr(pinfo->cinfo, COL_INFO,
1802 "Data VC:%d P(R):%d P(S):%d %s", vc,
1803 tvb_get_uint8(tvb, localoffset+1) >> 1,
1804 pkt_type >> 1,
1805 (tvb_get_uint8(tvb, localoffset+1) & X25_MBIT_MOD128) ? " M" : "");
1806 if (x25_tree) {
1807 if (modulo == 8) {
1808 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1809 localoffset, 1, pkt_type);
1810 proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod8, tvb,
1811 localoffset, 1, pkt_type);
1812 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod8, tvb,
1813 localoffset, 1, pkt_type);
1814 proto_tree_add_uint(x25_tree, hf_x25_type_data, tvb,
1815 localoffset, 1, pkt_type);
1817 else {
1818 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod128, tvb,
1819 localoffset, 1, pkt_type);
1820 proto_tree_add_uint(x25_tree, hf_x25_type_data, tvb,
1821 localoffset, 1, pkt_type);
1822 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
1823 localoffset+1, 1, ENC_NA);
1824 proto_tree_add_item(x25_tree, hf_x25_mbit_mod128, tvb,
1825 localoffset+1, 1, ENC_NA);
1828 if (modulo == 8) {
1829 m_bit_set = pkt_type & X25_MBIT_MOD8;
1830 localoffset += 1;
1831 } else {
1832 m_bit_set = tvb_get_uint8(tvb, localoffset+1) & X25_MBIT_MOD128;
1833 localoffset += 2;
1835 payload_len = tvb_reported_length_remaining(tvb, localoffset);
1836 if (reassemble_x25) {
1838 * Reassemble received and sent traffic separately.
1839 * We don't reassemble traffic with an unknown direction
1840 * at all.
1842 frag_key = vc;
1843 if (side) {
1845 * OR in an extra bit to distinguish from traffic
1846 * in the other direction.
1848 frag_key |= 0x10000;
1850 fd_head = fragment_add_seq_next(&x25_reassembly_table,
1851 tvb, localoffset,
1852 pinfo, frag_key, NULL,
1853 payload_len, m_bit_set);
1854 pinfo->fragmented = m_bit_set;
1856 /* Fragment handling is not adapted to handle several x25
1857 * packets in the same frame. This is common with XOT and
1858 * shorter packet sizes.
1859 * Therefore, fragment_add_seq_next seem to always return fd_head
1860 * A fix to use m_bit_set to only show fragments for last pkt
1862 if (!m_bit_set && fd_head) {
1863 if (fd_head->next) {
1864 proto_item *frag_tree_item;
1866 /* This is the last packet */
1867 next_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
1868 add_new_data_source(pinfo, next_tvb, "Reassembled X.25");
1869 if (x25_tree) {
1870 show_fragment_seq_tree(fd_head,
1871 &x25_frag_items,
1872 x25_tree,
1873 pinfo, next_tvb, &frag_tree_item);
1878 if (m_bit_set && next_tvb == NULL) {
1880 * This isn't the last packet, so just
1881 * show it as X.25 user data.
1883 proto_tree_add_item(x25_tree, hf_x25_user_data, tvb, localoffset, -1, ENC_NA);
1884 return;
1887 } else {
1889 * Non-data packets (RR, RNR, REJ).
1891 if (modulo == 8) {
1892 if (x25_tree) {
1893 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1894 localoffset, 1, pkt_type);
1895 proto_tree_add_item(x25_tree, hf_x25_type_fc_mod8, tvb,
1896 localoffset, 1, ENC_BIG_ENDIAN);
1898 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d P(R):%d",
1899 val_to_str(PACKET_TYPE_FC(pkt_type), vals_x25_type, "Unknown (0x%02X)"),
1900 vc, (pkt_type >> 5) & 0x07);
1901 localoffset += 1;
1902 } else {
1903 if (x25_tree) {
1904 proto_tree_add_item(x25_tree, hf_x25_type, tvb,
1905 localoffset, 1, ENC_BIG_ENDIAN);
1906 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
1907 localoffset+1, 1, ENC_BIG_ENDIAN);
1909 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d P(R):%d",
1910 val_to_str(PACKET_TYPE_FC(pkt_type), vals_x25_type, "Unknown (0x%02X)"),
1911 vc, tvb_get_uint8(tvb, localoffset+1) >> 1);
1912 localoffset += 2;
1915 break;
1918 if (localoffset >= tvb_reported_length(tvb))
1919 return;
1920 if (pinfo->fragmented)
1921 return;
1923 if (!next_tvb)
1924 next_tvb = tvb_new_subset_remaining(tvb, localoffset);
1926 /* See if there's already a dissector for this circuit. */
1927 if (try_conversation_dissector_by_id(CONVERSATION_X25, vc, next_tvb, pinfo,
1928 tree, &q_bit_set)) {
1929 return; /* found it and dissected it */
1932 /* Did the user suggest QLLC/SNA? */
1933 if (payload_is_qllc_sna) {
1934 /* Yes - dissect it as QLLC/SNA. */
1935 if (!pinfo->fd->visited)
1936 x25_hash_add_proto_start(vc, pinfo->num, qllc_handle);
1937 call_dissector_with_data(qllc_handle, next_tvb, pinfo, tree, &q_bit_set);
1938 return;
1941 if (payload_check_data){
1942 /* If the Call Req. has not been captured, let's look at the first
1943 two bytes of the payload to see if this looks like COTP. */
1944 if (tvb_get_uint8(next_tvb, 0) == tvb_reported_length(next_tvb)-1) {
1945 /* First byte contains the length of the remaining buffer */
1946 if ((tvb_get_uint8(next_tvb, 1) & 0x0F) == 0) {
1947 /* Second byte contains a valid COTP TPDU */
1948 if (!pinfo->fd->visited)
1949 x25_hash_add_proto_start(vc, pinfo->num, ositp_handle);
1950 call_dissector(ositp_handle, next_tvb, pinfo, tree);
1951 return;
1955 /* Then let's look at the first byte of the payload to see if this
1956 looks like IP or CLNP. */
1957 switch (tvb_get_uint8(next_tvb, 0)) {
1959 case 0x45:
1960 /* Looks like an IP header */
1961 if (!pinfo->fd->visited)
1962 x25_hash_add_proto_start(vc, pinfo->num, ip_handle);
1963 call_dissector(ip_handle, next_tvb, pinfo, tree);
1964 return;
1966 case NLPID_ISO8473_CLNP:
1967 if (!pinfo->fd->visited)
1968 x25_hash_add_proto_start(vc, pinfo->num, clnp_handle);
1969 call_dissector(clnp_handle, next_tvb, pinfo, tree);
1970 return;
1974 /* Try the heuristic dissectors. */
1975 if (dissector_try_heuristic(x25_heur_subdissector_list, next_tvb, pinfo,
1976 tree, &hdtbl_entry, NULL)) {
1977 return;
1980 /* All else failed; dissect it as raw data */
1981 call_data_dissector(next_tvb, pinfo, tree);
1985 * X.25 dissector for use when "pinfo->pseudo_header" points to a
1986 * "struct x25_phdr".
1988 static int
1989 dissect_x25_dir(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1991 dissect_x25_common(tvb, pinfo, tree,
1992 (pinfo->pseudo_header->dte_dce.flags & FROM_DCE) ? X25_FROM_DCE :
1993 X25_FROM_DTE,
1994 pinfo->pseudo_header->dte_dce.flags & FROM_DCE);
1995 return tvb_captured_length(tvb);
1999 * X.25 dissector for use when "pinfo->pseudo_header" doesn't point to a
2000 * "struct x25_phdr".
2002 static int
2003 dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2005 int direction;
2008 * We don't know if this packet is DTE->DCE or DCE->DCE.
2009 * However, we can, at least, distinguish between the two
2010 * sides of the conversation, based on the addresses and
2011 * ports.
2013 direction = cmp_address(&pinfo->src, &pinfo->dst);
2014 if (direction == 0)
2015 direction = (pinfo->srcport > pinfo->destport)*2 - 1;
2016 dissect_x25_common(tvb, pinfo, tree, X25_UNKNOWN, direction > 0);
2017 return tvb_captured_length(tvb);
2020 void
2021 proto_register_x25(void)
2023 static hf_register_info hf[] = {
2024 { &hf_x25_facility,
2025 { "Facility", "x25.facility", FT_NONE, BASE_NONE, NULL, 0,
2026 NULL, HFILL }},
2027 { &hf_x25_facilities_length,
2028 { "Facilities Length", "x25.facilities_length", FT_UINT8, BASE_DEC, NULL, 0,
2029 NULL, HFILL }},
2030 { &hf_x25_facility_length,
2031 { "Length", "x25.facility_length", FT_UINT8, BASE_DEC, NULL, 0,
2032 NULL, HFILL }},
2033 { &hf_x25_facility_class,
2034 { "Facility Class", "x25.facility.class", FT_UINT8, BASE_HEX, VALS(x25_facilities_class_vals), X25_FAC_CLASS_MASK,
2035 NULL, HFILL }},
2036 { &hf_x25_facility_classA,
2037 { "Code", "x25.facility.classA", FT_UINT8, BASE_HEX, VALS(x25_facilities_classA_vals), 0,
2038 "Facility ClassA Code", HFILL }},
2039 { &hf_x25_facility_classA_comp_mark,
2040 { "Parameter", "x25.facility.comp_mark", FT_UINT8, BASE_DEC, VALS(x25_facilities_classA_comp_mark_vals), 0,
2041 "Facility Marker Parameter", HFILL }},
2042 { &hf_x25_facility_classA_reverse,
2043 { "Parameter", "x25.facility.reverse", FT_UINT8, BASE_HEX, NULL, 0,
2044 "Facility Reverse Charging Parameter", HFILL }},
2045 { &hf_x25_facility_classA_charging_info,
2046 { "Parameter", "x25.facility.charging_info", FT_UINT8, BASE_HEX, NULL, 0,
2047 "Facility Charging Information Parameter", HFILL }},
2048 { &hf_x25_facility_reverse_charging,
2049 { "Reverse charging", "x25.reverse_charging", FT_BOOLEAN, 8, TFS(&x25_reverse_charging_val), 0x01,
2050 NULL, HFILL }},
2051 { &hf_x25_facility_charging_info,
2052 { "Charging information", "x25.charging_info", FT_BOOLEAN, 8, TFS(&tfs_requested_not_requested), 0x01,
2053 NULL, HFILL }},
2054 { &hf_x25_facility_throughput_called_dte,
2055 { "From the called DTE", "x25.facility.throughput.called_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classA_throughput_vals), 0xF0,
2056 "Facility Throughput called DTE", HFILL }},
2057 { &hf_x25_throughput_called_dte,
2058 { "From the calling DTE", "x25.facility.throughput.calling_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classA_throughput_vals), 0x0F,
2059 "Facility Throughput calling DTE", HFILL }},
2060 { &hf_x25_facility_classA_cug,
2061 { "Closed user group", "x25.facility.cug", FT_UINT8, BASE_HEX, NULL, 0,
2062 "Facility Closed user group", HFILL }},
2063 { &hf_x25_facility_classA_called_motif,
2064 { "Parameter", "x25.facility.called_motif", FT_UINT8, BASE_HEX, NULL, 0,
2065 "Facility Called address modified parameter", HFILL }},
2066 { &hf_x25_facility_classA_cug_outgoing_acc,
2067 { "Closed user group", "x25.facility.cug_outgoing_acc", FT_UINT8, BASE_HEX, NULL, 0,
2068 "Facility Closed user group with outgoing access selection", HFILL }},
2069 { &hf_x25_facility_classA_throughput_min,
2070 { "Parameter", "x25.facility.throughput_min", FT_UINT8, BASE_HEX, NULL, 0,
2071 "Facility Minimum throughput class parameter", HFILL }},
2072 { &hf_x25_facility_classA_express_data,
2073 { "Parameter", "x25.facility.express_data", FT_UINT8, BASE_HEX, NULL, 0,
2074 "Facility Negotiation of express data parameter", HFILL }},
2075 { &hf_x25_facility_classA_unknown,
2076 { "Parameter", "x25.facility.classA_unknown", FT_UINT8, BASE_HEX, NULL, 0,
2077 "Facility Class A unknown parameter", HFILL }},
2078 { &hf_x25_facility_classB,
2079 { "Code", "x25.facility.classB", FT_UINT8, BASE_HEX, VALS(x25_facilities_classB_vals), 0,
2080 "Facility ClassB Code", HFILL }},
2081 { &hf_x25_facility_classB_bilateral_cug,
2082 { "Bilateral CUG", "x25.facility.bilateral_cug", FT_UINT16, BASE_HEX, NULL, 0,
2083 "Facility Bilateral CUG", HFILL }},
2084 { &hf_x25_facility_packet_size_called_dte,
2085 { "From the called DTE", "x25.facility.packet_size.called_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classB_packet_size_vals), 0,
2086 "Facility Packet size from the called DTE", HFILL }},
2087 { &hf_x25_facility_packet_size_calling_dte,
2088 { "From the calling DTE", "x25.facility.packet_size.calling_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classB_packet_size_vals), 0,
2089 "Facility Packet size from the calling DTE", HFILL }},
2090 { &hf_x25_facility_data_network_id_code,
2091 { "Data network identification code", "x25.facility.data_network_id_code", FT_UINT16, BASE_HEX, NULL, 0,
2092 "Facility RPOA selection data network identification code", HFILL }},
2093 { &hf_x25_facility_cug_ext,
2094 { "Closed user group", "x25.facility.cug_ext", FT_UINT16, BASE_HEX, NULL, 0,
2095 "Facility Extended closed user group selection", HFILL }},
2096 { &hf_x25_facility_cug_outgoing_acc_ext,
2097 { "Closed user group", "x25.facility.cug_outgoing_acc_ext", FT_UINT16, BASE_HEX, NULL, 0,
2098 "Facility Extended closed user group with outgoing access selection", HFILL }},
2099 { &hf_x25_facility_transit_delay,
2100 { "Transit delay (ms)", "x25.facility.transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2101 "Facility Transit delay selection and indication", HFILL }},
2102 { &hf_x25_facility_classB_unknown,
2103 { "Parameter", "x25.facility.classB_unknown", FT_UINT16, BASE_HEX, NULL, 0,
2104 "Facility Class B unknown parameter", HFILL }},
2105 { &hf_x25_facility_classC_unknown,
2106 { "Parameter", "x25.facility.classC_unknown", FT_UINT24, BASE_HEX, NULL, 0,
2107 "Facility Class C unknown parameter", HFILL }},
2108 { &hf_x25_facility_classC,
2109 { "Code", "x25.facility.classC", FT_UINT8, BASE_HEX, VALS(x25_facilities_classC_vals), 0,
2110 "Facility ClassC Code", HFILL }},
2111 { &hf_x25_facility_classD,
2112 { "Code", "x25.facility.classD", FT_UINT8, BASE_HEX, VALS(x25_facilities_classD_vals), 0,
2113 "Facility ClassD Code", HFILL }},
2114 { &hf_x25_gfi,
2115 { "GFI", "x25.gfi", FT_UINT16, BASE_DEC, NULL, 0xF000,
2116 "General format identifier", HFILL }},
2117 { &hf_x25_abit,
2118 { "A Bit", "x25.a", FT_BOOLEAN, 16, NULL, X25_ABIT,
2119 "Address Bit", HFILL }},
2120 { &hf_x25_qbit,
2121 { "Q Bit", "x25.q", FT_BOOLEAN, 16, NULL, X25_QBIT,
2122 "Qualifier Bit", HFILL }},
2123 { &hf_x25_dbit,
2124 { "D Bit", "x25.d", FT_BOOLEAN, 16, NULL, X25_DBIT,
2125 "Delivery Confirmation Bit", HFILL }},
2126 { &hf_x25_mod,
2127 { "Modulo", "x25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
2128 "Specifies whether the frame is modulo 8 or 128", HFILL }},
2129 { &hf_x25_lcn,
2130 { "Logical Channel", "x25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
2131 "Logical Channel Number", HFILL }},
2132 { &hf_x25_type,
2133 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
2134 NULL, HFILL }},
2135 { &hf_x25_type_fc_mod8,
2136 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x1F,
2137 NULL, HFILL }},
2138 { &hf_x25_type_data,
2139 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x01,
2140 NULL, HFILL }},
2141 { &hf_x25_diagnostic,
2142 { "Diagnostic", "x25.diagnostic", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &x25_clear_diag_vals_ext, 0,
2143 NULL, HFILL }},
2144 { &hf_x25_p_r_mod8,
2145 { "P(R)", "x25.p_r", FT_UINT8, BASE_DEC, NULL, 0xE0,
2146 "Packet Receive Sequence Number", HFILL }},
2147 { &hf_x25_p_r_mod128,
2148 { "P(R)", "x25.p_r", FT_UINT8, BASE_DEC, NULL, 0xFE,
2149 "Packet Receive Sequence Number", HFILL }},
2150 { &hf_x25_mbit_mod8,
2151 { "M Bit", "x25.m", FT_BOOLEAN, 8, TFS(&m_bit_tfs), X25_MBIT_MOD8,
2152 "More Bit", HFILL }},
2153 { &hf_x25_mbit_mod128,
2154 { "M Bit", "x25.m", FT_BOOLEAN, 8, TFS(&m_bit_tfs), X25_MBIT_MOD128,
2155 "More Bit", HFILL }},
2156 { &hf_x25_p_s_mod8,
2157 { "P(S)", "x25.p_s", FT_UINT8, BASE_DEC, NULL, 0x0E,
2158 "Packet Send Sequence Number", HFILL }},
2159 { &hf_x25_p_s_mod128,
2160 { "P(S)", "x25.p_s", FT_UINT8, BASE_DEC, NULL, 0xFE,
2161 "Packet Send Sequence Number", HFILL }},
2162 { &hf_x25_window_size_called_dte,
2163 { "From the called DTE", "x25.window_size.called_dte", FT_UINT8, BASE_DEC, NULL, 0x7F,
2164 NULL, HFILL }},
2165 { &hf_x25_window_size_calling_dte,
2166 { "From the calling DTE", "x25.window_size.calling_dte", FT_UINT8, BASE_DEC, NULL, 0x7F,
2167 NULL, HFILL }},
2168 { &hf_x25_dte_address_length,
2169 { "DTE address length", "x25.dte_address_length", FT_UINT8, BASE_DEC, NULL, 0xF0,
2170 NULL, HFILL }},
2171 { &hf_x25_dce_address_length,
2172 { "DCE address length", "x25.dce_address_length", FT_UINT8, BASE_DEC, NULL, 0x0F,
2173 NULL, HFILL }},
2174 { &hf_x25_calling_address_length,
2175 { "Calling address length", "x25.calling_address_length", FT_UINT8, BASE_DEC, NULL, 0xF0,
2176 NULL, HFILL }},
2177 { &hf_x25_called_address_length,
2178 { "Called address length", "x25.called_address_length", FT_UINT8, BASE_DEC, NULL, 0x0F,
2179 NULL, HFILL }},
2180 { &hf_x25_facility_call_transfer_reason,
2181 { "Reason", "x25.facility.call_transfer_reason", FT_UINT8, BASE_DEC, VALS(x25_facilities_call_transfer_reason_vals), 0,
2182 NULL, HFILL }},
2183 { &hf_x25_facility_monetary_unit,
2184 { "Monetary unit", "x25.facility.monetary_unit", FT_BYTES, BASE_NONE, NULL, 0,
2185 NULL, HFILL }},
2186 { &hf_x25_facility_nui,
2187 { "NUI", "x25.facility.nui", FT_BYTES, BASE_NONE, NULL, 0,
2188 NULL, HFILL }},
2189 { &hf_x25_facility_cumulative_ete_transit_delay,
2190 { "Cumulative end-to-end transit delay (ms)", "x25.facility.cumulative_ete_transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2191 NULL, HFILL }},
2192 { &hf_x25_facility_requested_ete_transit_delay,
2193 { "Requested end-to-end transit delay (ms)", "x25.facility.requested_ete_transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2194 NULL, HFILL }},
2195 { &hf_x25_facility_max_acceptable_ete_transit_delay,
2196 { "Maximum acceptable end-to-end transit delay (ms)", "x25.facility.mac_acceptable_ete_transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2197 NULL, HFILL }},
2198 { &hf_x25_facility_priority_data,
2199 { "Priority for data", "x25.facility.priority_data", FT_UINT8, BASE_DEC, NULL, 0,
2200 NULL, HFILL }},
2201 { &hf_x25_facility_priority_estab_conn,
2202 { "Priority for establishing connection", "x25.facility.priority_estab_conn", FT_UINT8, BASE_DEC, NULL, 0,
2203 NULL, HFILL }},
2204 { &hf_x25_facility_priority_keep_conn,
2205 { "Priority for keeping connection", "x25.facility.priority_keep_conn", FT_UINT8, BASE_DEC, NULL, 0,
2206 NULL, HFILL }},
2207 { &hf_x25_facility_min_acceptable_priority_data,
2208 { "Minimum acceptable priority for data", "x25.facility.min_acceptable_priority_data", FT_UINT8, BASE_DEC, NULL, 0,
2209 NULL, HFILL }},
2210 { &hf_x25_facility_min_acceptable_priority_estab_conn,
2211 { "Minimum acceptable priority for establishing connection", "x25.facility.min_acceptable_priority_estab_conn", FT_UINT8, BASE_DEC, NULL, 0,
2212 NULL, HFILL }},
2213 { &hf_x25_facility_min_acceptable_priority_keep_conn,
2214 { "Minimum acceptable priority for keeping connection", "x25.facility.min_acceptable_priority_keep_conn", FT_UINT8, BASE_DEC, NULL, 0,
2215 NULL, HFILL }},
2216 { &hf_x25_facility_classD_unknown,
2217 { "Parameter", "x25.facility.classD_unknown", FT_BYTES, BASE_NONE, NULL, 0,
2218 "Facility Class D unknown parameter", HFILL }},
2219 { &hf_x25_facility_call_transfer_num_semi_octets,
2220 { "Number of semi-octets in DTE address", "x25.facility.call_transfer_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2221 NULL, HFILL }},
2222 { &hf_x25_facility_calling_addr_ext_num_semi_octets,
2223 { "Number of semi-octets in DTE address", "x25.facility.calling_addr_ext_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2224 NULL, HFILL }},
2225 { &hf_x25_facility_called_addr_ext_num_semi_octets,
2226 { "Number of semi-octets in DTE address", "x25.facility.called_addr_ext_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2227 NULL, HFILL }},
2228 { &hf_x25_facility_call_deflect_num_semi_octets,
2229 { "Number of semi-octets in the alternative DTE address", "x25.facility.call_deflect_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2230 NULL, HFILL }},
2231 { &hf_x264_length_indicator,
2232 { "X.264 length indicator", "x25.x264_length_indicator", FT_UINT8, BASE_DEC, NULL, 0,
2233 NULL, HFILL }},
2234 { &hf_x264_un_tpdu_id,
2235 { "X.264 UN TPDU identifier", "x25.x264_un_tpdu_id", FT_UINT8, BASE_HEX, NULL, 0,
2236 NULL, HFILL }},
2237 { &hf_x264_protocol_id,
2238 { "X.264 protocol identifier", "x25.x264_protocol_id", FT_UINT8, BASE_HEX, VALS(prt_id_vals), 0,
2239 NULL, HFILL }},
2240 { &hf_x264_sharing_strategy,
2241 { "X.264 sharing strategy", "x25.x264_sharing_strategy", FT_UINT8, BASE_HEX, VALS(sharing_strategy_vals), 0,
2242 NULL, HFILL }},
2243 { &hf_x263_sec_protocol_id,
2244 { "X.263 secondary protocol ID", "x25.x263_sec_protocol_id", FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0,
2245 NULL, HFILL }},
2246 { &hf_x25_reg_request_length,
2247 { "Registration length", "x25.reg_request_length", FT_UINT8, BASE_DEC, NULL, 0x7F,
2248 NULL, HFILL }},
2249 { &hf_x25_reg_confirm_length,
2250 { "Registration length", "x25.reg_confirm_length", FT_UINT8, BASE_DEC, NULL, 0x7F,
2251 NULL, HFILL }},
2253 { &hf_x25_segment_overlap,
2254 { "Fragment overlap", "x25.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2255 "Fragment overlaps with other fragments", HFILL }},
2257 { &hf_x25_segment_overlap_conflict,
2258 { "Conflicting data in fragment overlap", "x25.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2259 "Overlapping fragments contained conflicting data", HFILL }},
2261 { &hf_x25_segment_multiple_tails,
2262 { "Multiple tail fragments found", "x25.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2263 "Several tails were found when defragmenting the packet", HFILL }},
2265 { &hf_x25_segment_too_long_segment,
2266 { "Fragment too long", "x25.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2267 "Fragment contained data past end of packet", HFILL }},
2269 { &hf_x25_segment_error,
2270 { "Defragmentation error", "x25.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2271 "Defragmentation error due to illegal fragments", HFILL }},
2273 { &hf_x25_segment_count,
2274 { "Fragment count", "x25.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2275 NULL, HFILL }},
2277 { &hf_x25_reassembled_length,
2278 { "Reassembled X.25 length", "x25.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
2279 "The total length of the reassembled payload", HFILL }},
2281 { &hf_x25_segment,
2282 { "X.25 Fragment", "x25.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2283 NULL, HFILL }},
2285 { &hf_x25_segments,
2286 { "X.25 Fragments", "x25.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2287 NULL, HFILL }},
2289 { &hf_x25_fast_select,
2290 { "Fast select", "x25.fast_select", FT_UINT8, BASE_DEC, VALS(x25_fast_select_vals), 0xC0,
2291 NULL, HFILL }},
2293 { &hf_x25_icrd,
2294 { "ICRD", "x25.icrd", FT_UINT8, BASE_DEC, VALS(x25_icrd_vals), 0x30,
2295 NULL, HFILL }},
2297 { &hf_x25_reg_confirm_cause,
2298 { "Cause", "x25.reg_confirm.cause", FT_UINT8, BASE_DEC, VALS(x25_registration_code_vals), 0,
2299 NULL, HFILL }},
2301 { &hf_x25_reg_confirm_diagnostic,
2302 { "Diagnostic", "x25.reg_confirm.diagnostic", FT_UINT8, BASE_DEC, VALS(x25_registration_code_vals), 0,
2303 NULL, HFILL }},
2305 /* Generated from convert_proto_tree_add_text.pl */
2306 { &hf_x25_call_duration, { "Call duration", "x25.call_duration", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2307 { &hf_x25_segments_to_dte, { "Segments sent to DTE", "x25.segments_to_dte", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2308 { &hf_x25_segments_from_dte, { "Segments received from DTE", "x25.segments_from_dte", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2309 { &hf_x25_dte_address, { "DTE address", "x25.dte_address", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2310 { &hf_x25_data_network_identification_code, { "Data network identification code", "x25.data_network_identification_code", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2311 { &hf_x25_facility_call_deflect_reason, { "Reason", "x25.facility.call_deflect_reason", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2312 { &hf_x25_alternative_dte_address, { "Alternative DTE address", "x25.alternative_dte_address", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2313 { &hf_x25_dce_address, { "DCE address", "x25.dce_address", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2314 { &hf_x25_called_address, { "Called address", "x25.called_address", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2315 { &hf_x25_calling_address, { "Calling address", "x25.calling_address", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2316 { &hf_x25_clear_cause, { "Cause", "x25.clear_cause", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(clear_code_rvals), 0x0, NULL, HFILL }},
2317 { &hf_x25_reset_cause, { "Cause", "x25.reset_cause", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(reset_code_rvals), 0x0, NULL, HFILL }},
2318 { &hf_x25_restart_cause, { "Cause", "x25.restart_cause", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(restart_code_rvals), 0x0, NULL, HFILL }},
2319 { &hf_x25_registration, { "Registration", "x25.registration", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2320 { &hf_x25_user_data, { "User data", "x25.user_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2323 static int *ett[] = {
2324 &ett_x25,
2325 &ett_x25_gfi,
2326 &ett_x25_facilities,
2327 &ett_x25_facility,
2328 &ett_x25_user_data,
2329 &ett_x25_segment,
2330 &ett_x25_segments
2333 static ei_register_info ei[] = {
2334 { &ei_x25_facility_length, { "x25.facility_length.bogus", PI_PROTOCOL, PI_WARN, "Bogus length", EXPFILL }},
2337 module_t *x25_module;
2338 expert_module_t* expert_x25;
2340 proto_x25 = proto_register_protocol ("X.25", "X.25", "x25");
2341 proto_register_field_array (proto_x25, hf, array_length(hf));
2342 proto_register_subtree_array(ett, array_length(ett));
2343 expert_x25 = expert_register_protocol(proto_x25);
2344 expert_register_field_array(expert_x25, ei, array_length(ei));
2346 x25_subdissector_table = register_dissector_table("x.25.spi",
2347 "X.25 secondary protocol identifier", proto_x25, FT_UINT8, BASE_HEX);
2348 x25_heur_subdissector_list = register_heur_dissector_list_with_description("x.25", "X.25 payload", proto_x25);
2350 register_dissector("x.25_dir", dissect_x25_dir, proto_x25);
2351 x25_handle = register_dissector("x.25", dissect_x25, proto_x25);
2353 /* Preferences */
2354 x25_module = prefs_register_protocol(proto_x25, NULL);
2355 /* For reading older preference files with "x.25." preferences */
2356 prefs_register_module_alias("x.25", x25_module);
2357 prefs_register_obsolete_preference(x25_module, "non_q_bit_is_sna");
2358 prefs_register_bool_preference(x25_module, "payload_is_qllc_sna",
2359 "Default to QLLC/SNA",
2360 "If CALL REQUEST not seen or didn't specify protocol, dissect as QLLC/SNA",
2361 &payload_is_qllc_sna);
2362 prefs_register_bool_preference(x25_module, "call_request_nodata_is_cotp",
2363 "Assume COTP for Call Request without data",
2364 "If CALL REQUEST has no data, assume the protocol handled is COTP",
2365 &call_request_nodata_is_cotp);
2366 prefs_register_bool_preference(x25_module, "payload_check_data",
2367 "Check data for COTP/IP/CLNP",
2368 "If CALL REQUEST not seen or didn't specify protocol, check user data before checking heuristic dissectors",
2369 &payload_check_data);
2370 prefs_register_bool_preference(x25_module, "reassemble",
2371 "Reassemble fragmented X.25 packets",
2372 "Reassemble fragmented X.25 packets",
2373 &reassemble_x25);
2374 reassembly_table_register(&x25_reassembly_table,
2375 &addresses_reassembly_table_functions);
2378 void
2379 proto_reg_handoff_x25(void)
2382 * Get handles for various dissectors.
2384 ip_handle = find_dissector_add_dependency("ip", proto_x25);
2385 clnp_handle = find_dissector_add_dependency("clnp", proto_x25);
2386 ositp_handle = find_dissector_add_dependency("ositp", proto_x25);
2387 qllc_handle = find_dissector_add_dependency("qllc", proto_x25);
2389 dissector_add_uint("llc.dsap", SAP_X25, x25_handle);
2390 dissector_add_uint("lapd.sapi", LAPD_SAPI_X25, x25_handle);
2391 dissector_add_uint("ax25.pid", AX25_P_ROSE, x25_handle);
2392 dissector_add_uint("sflow_245.header_protocol", SFLOW_245_HEADER_X25, x25_handle);
2396 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2398 * Local variables:
2399 * c-basic-offset: 4
2400 * tab-width: 8
2401 * indent-tabs-mode: nil
2402 * End:
2404 * vi: set shiftwidth=4 tabstop=8 expandtab:
2405 * :indentSize=4:tabSize=8:noTabs=true: