MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-x25.c
blob3ce0232856996e30478a2e5037bae6368b098d83
1 /* packet-x25.c
2 * Routines for X.25 packet disassembly
3 * Olivier Abad <oabad@noos.fr>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998
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.
26 #include "config.h"
28 #include <string.h>
30 #include <glib.h>
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.
47 typedef enum {
48 X25_FROM_DCE, /* DCE->DTE */
49 X25_FROM_DTE, /* DTE->DCE */
50 X25_UNKNOWN /* direction unknown */
51 } x25_dir_t;
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
71 #define X25_RR 0x01
72 #define X25_RNR 0x05
73 #define X25_REJ 0x09
74 #define X25_DATA 0x00
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[] = {
226 { 1, "8" },
227 { 2, "128" },
228 { 0, NULL}
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" },
245 { X25_RR, "RR" },
246 { X25_RNR, "RNR" },
247 { X25_REJ, "REJ" },
248 { X25_DATA, "Data" },
249 { 0, NULL}
252 static struct true_false_string m_bit_tfs = {
253 "More data follows",
254 "End of data"
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" },
262 { 0, NULL}
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" },
270 { 0, NULL}
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" },
377 { 0, NULL}
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" },
387 { 0, NULL}
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" },
395 { 0, NULL}
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" },
408 { 0, NULL}
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" },
415 { 0, NULL}
418 static const value_string x25_facilities_classA_throughput_vals[] = {
419 { 3, "75 bps" },
420 { 4, "150 bps" },
421 { 5, "300 bps" },
422 { 6, "600 bps" },
423 { 7, "1200 bps" },
424 { 8, "2400 bps" },
425 { 9, "4800 bps" },
426 { 10, "9600 bps" },
427 { 11, "19200 bps" },
428 { 12, "48000 bps" },
429 { 13, "64000 bps" },
430 { 0, NULL}
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" },
441 { 0, NULL}
444 static const value_string x25_facilities_classB_packet_size_vals[] = {
445 { 0x04, "16" },
446 { 0x05, "32" },
447 { 0x06, "64" },
448 { 0x07, "128" },
449 { 0x08, "256" },
450 { 0x09, "512" },
451 { 0x0A, "1024" },
452 { 0x0B, "2048" },
453 { 0x0C, "4096" },
454 { 0, NULL}
457 static const value_string x25_facilities_classC_vals[] = {
458 { 0, NULL}
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" },
473 { 0, NULL}
476 static struct true_false_string x25_reverse_charging_val = {
477 "Requested",
478 "Not requested"
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" },
486 { 0, NULL}
489 static const fragment_items x25_frag_items = {
490 &ett_x25_segment,
491 &ett_x25_segments,
492 &hf_x25_segments,
493 &hf_x25_segment,
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,
500 NULL,
501 &hf_x25_reassembled_length,
502 /* Reassembled data field */
503 NULL,
504 "segments"
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;
513 /* Preferences */
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;
526 static void
527 x25_hash_add_proto_start(guint16 vc, guint32 frame, dissector_handle_t dissect)
529 circuit_t *circuit;
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);
548 * Set its dissector.
550 circuit_set_dissector(circuit, dissect);
553 static void
554 x25_hash_add_proto_end(guint16 vc, guint32 frame)
556 circuit_t *circuit;
559 * Try to find the circuit.
561 circuit = find_circuit(CT_X25, vc, frame);
564 * If we succeeded, close it.
566 if (circuit != NULL)
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";
575 switch(code)
577 case 0x01:
578 return "Number Busy";
579 case 0x03:
580 return "Invalid Facility Requested";
581 case 0x05:
582 return "Network Congestion";
583 case 0x09:
584 return "Out Of Order";
585 case 0x0B:
586 return "Access Barred";
587 case 0x0D:
588 return "Not Obtainable";
589 case 0x11:
590 return "Remote Procedure Error";
591 case 0x13:
592 return "Local Procedure Error";
593 case 0x15:
594 return "RPOA Out Of Order";
595 case 0x19:
596 return "Reverse Charging Acceptance Not Subscribed";
597 case 0x21:
598 return "Incompatible Destination";
599 case 0x29:
600 return "Fast Select Acceptance Not Subscribed";
601 case 0x39:
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";
613 switch(code)
615 case 0x01:
616 return "Out of order";
617 case 0x03:
618 return "Remote Procedure Error";
619 case 0x05:
620 return "Local Procedure Error";
621 case 0x07:
622 return "Network Congestion";
623 case 0x09:
624 return "Remote DTE operational";
625 case 0x0F:
626 return "Network operational";
627 case 0x11:
628 return "Incompatible Destination";
629 case 0x1D:
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";
641 switch(code)
643 case 0x01:
644 return "Local Procedure Error";
645 case 0x03:
646 return "Network Congestion";
647 case 0x07:
648 return "Network Operational";
649 case 0x7F:
650 return "Registration/cancellation confirmed";
653 return wmem_strdup_printf(wmem_packet_scope(),"Unknown %02X", code);
656 static char *
657 dte_address_util(tvbuff_t *tvb, int offset, guint8 len)
659 int i;
660 char *tmpbuf = (char *)wmem_alloc(wmem_packet_scope(), 258);
662 for (i = 0; (i<len)&&(i<256); i++) {
663 if (i % 2 == 0) {
664 tmpbuf[i] = ((tvb_get_guint8(tvb, offset+i/2) >> 4) & 0x0F) + '0';
665 /* if > 9, convert to the right hexadecimal letter */
666 if (tmpbuf[i] > '9')
667 tmpbuf[i] += ('A' - '0' - 10);
668 } else {
669 tmpbuf[i] = (tvb_get_guint8(tvb, offset+i/2) & 0x0F) + '0';
670 /* if > 9, convert to the right hexadecimal letter */
671 if (tmpbuf[i] > '9')
672 tmpbuf[i] += ('A' - '0' - 10);
676 tmpbuf[i] = '\0';
678 return tmpbuf;
681 static void
682 add_priority(proto_tree *tree, int hf, tvbuff_t *tvb, int offset)
684 guint8 priority;
686 priority = tvb_get_guint8(tvb, offset);
687 if (priority == 255)
688 proto_tree_add_uint_format_value(tree, hf, tvb, offset, 1, priority,
689 "Unspecified (255)");
690 else
691 proto_tree_add_uint(tree, hf, tvb, offset, 1, priority);
694 static void
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);
703 if (len && tree) {
704 ti = proto_tree_add_text(tree, tvb, *offset, len + 1,
705 "Facilities");
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);
709 (*offset)++;
711 while (len > 0) {
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);
722 if (facility_tree) {
723 switch (fac) {
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);
726 break;
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);
732 break;
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);
736 break;
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);
740 break;
741 case X25_FAC_CUG:
742 proto_tree_add_item(facility_tree, hf_x25_facility_classA_cug, tvb, *offset+1, 1, ENC_NA);
743 break;
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);
746 break;
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);
749 break;
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);
752 break;
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);
755 break;
756 default:
757 proto_tree_add_item(facility_tree, hf_x25_facility_classA_unknown, tvb, *offset+1, 1, ENC_NA);
758 break;
761 (*offset) += 2;
762 len -= 2;
763 break;
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);
771 if (facility_tree) {
772 switch (fac) {
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);
775 break;
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);
779 break;
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);
783 break;
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);
786 break;
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);
789 break;
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);
792 break;
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);
795 break;
796 default:
797 proto_tree_add_item(facility_tree, hf_x25_facility_classB_unknown, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
798 break;
801 (*offset) += 3;
802 len -= 3;
803 break;
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);
811 if (facility_tree) {
812 proto_tree_add_item(facility_tree, hf_x25_facility_classC_unknown, tvb, *offset+1, 2, ENC_BIG_ENDIAN);
814 (*offset) += 4;
815 len -= 4;
816 break;
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);
826 if (facility_tree) {
827 switch (fac) {
828 case X25_FAC_CALL_DURATION:
830 int i;
832 if ((byte1 < 4) || (byte1 % 4)) {
833 expert_add_info(pinfo, ti, &ei_x25_facility_length);
834 return;
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));
845 break;
846 case X25_FAC_SEGMENT_COUNT:
848 int i;
850 if ((byte1 < 8) || (byte1 % 8)) {
851 expert_add_info(pinfo, ti, &ei_x25_facility_length);
852 return;
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));
869 break;
870 case X25_FAC_CALL_TRANSFER:
872 char *tmpbuf;
874 if (byte1 < 2) {
875 expert_add_info(pinfo, ti, &ei_x25_facility_length);
876 return;
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");
883 else {
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);
893 break;
894 case X25_FAC_RPOA_SELECTION_EXT:
896 int i;
898 if ((byte1 < 2) || (byte1 % 2)) {
899 expert_add_info(pinfo, ti, &ei_x25_facility_length);
900 return;
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));
908 break;
909 case X25_FAC_CALLING_ADDR_EXT:
911 char *tmpbuf;
913 if (byte1 < 1) {
914 expert_add_info(pinfo, ti, &ei_x25_facility_length);
915 return;
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);
923 break;
924 case X25_FAC_MONETARY_UNIT:
925 proto_tree_add_item(facility_tree, hf_x25_facility_monetary_unit, tvb, *offset+2, byte1, ENC_NA);
926 break;
927 case X25_FAC_NUI:
928 proto_tree_add_item(facility_tree, hf_x25_facility_nui, tvb, *offset+2, byte1, ENC_NA);
929 break;
930 case X25_FAC_CALLED_ADDR_EXT:
932 char *tmpbuf;
934 if (byte1 < 1) {
935 expert_add_info(pinfo, ti, &ei_x25_facility_length);
936 return;
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);
945 break;
946 case X25_FAC_ETE_TRANSIT_DELAY:
947 if (byte1 < 2)
948 break;
949 proto_tree_add_item(facility_tree, hf_x25_facility_cumulative_ete_transit_delay, tvb, *offset+2, 2, ENC_BIG_ENDIAN);
950 if (byte1 < 4)
951 break;
952 proto_tree_add_item(facility_tree, hf_x25_facility_requested_ete_transit_delay, tvb, *offset+4, 2, ENC_BIG_ENDIAN);
953 if (byte1 < 6)
954 break;
955 proto_tree_add_item(facility_tree, hf_x25_facility_max_acceptable_ete_transit_delay, tvb, *offset+6, 2, ENC_BIG_ENDIAN);
956 break;
957 case X25_FAC_CALL_DEFLECT:
959 char *tmpbuf;
961 if (byte1 < 2) {
962 expert_add_info(pinfo, ti, &ei_x25_facility_length);
963 return;
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");
969 else
970 proto_tree_add_text(facility_tree, tvb, *offset+2, 1,
971 "Reason: unknown");
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);
979 break;
980 case X25_FAC_PRIORITY:
981 if (byte1 < 1)
982 break;
983 add_priority(facility_tree, hf_x25_facility_priority_data, tvb, *offset+2);
984 if (byte1 < 2)
985 break;
986 add_priority(facility_tree, hf_x25_facility_priority_estab_conn, tvb, *offset+3);
987 if (byte1 < 3)
988 break;
989 add_priority(facility_tree, hf_x25_facility_priority_keep_conn, tvb, *offset+4);
990 if (byte1 < 4)
991 break;
992 add_priority(facility_tree, hf_x25_facility_min_acceptable_priority_data, tvb, *offset+5);
993 if (byte1 < 5)
994 break;
995 add_priority(facility_tree, hf_x25_facility_min_acceptable_priority_estab_conn, tvb, *offset+6);
996 if (byte1 < 6)
997 break;
998 add_priority(facility_tree, hf_x25_facility_min_acceptable_priority_keep_conn, tvb, *offset+7);
999 break;
1000 default:
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;
1006 len -= byte1+2;
1007 break;
1012 static void
1013 x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1014 packet_info *pinfo, gboolean is_registration)
1016 int len1, len2;
1017 int i;
1018 char *addr1, *addr2;
1019 char *first, *second;
1020 guint8 byte;
1021 int localoffset;
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;
1030 if (tree) {
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);
1035 else {
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);
1040 (*offset)++;
1042 localoffset = *offset;
1043 byte = tvb_get_guint8(tvb, localoffset);
1045 first=addr1;
1046 second=addr2;
1047 for (i = 0; i < (len1 + len2); i++) {
1048 if (i < len1) {
1049 if (i % 2 != 0) {
1050 *first++ = ((byte >> 0) & 0x0F) + '0';
1051 localoffset++;
1052 byte = tvb_get_guint8(tvb, localoffset);
1053 } else {
1054 *first++ = ((byte >> 4) & 0x0F) + '0';
1056 } else {
1057 if (i % 2 != 0) {
1058 *second++ = ((byte >> 0) & 0x0F) + '0';
1059 localoffset++;
1060 byte = tvb_get_guint8(tvb, localoffset);
1061 } else {
1062 *second++ = ((byte >> 4) & 0x0F) + '0';
1067 *first = '\0';
1068 *second = '\0';
1070 if (len1) {
1071 col_add_str(pinfo->cinfo, COL_RES_DL_DST, addr1);
1072 if (tree)
1073 proto_tree_add_text(tree, tvb, *offset,
1074 (len1 + 1) / 2,
1075 is_registration ?
1076 "DCE address: %s" :
1077 "Called address: %s",
1078 addr1);
1080 if (len2) {
1081 col_add_str(pinfo->cinfo, COL_RES_DL_SRC, addr2);
1082 if (tree)
1083 proto_tree_add_text(tree, tvb, *offset + len1/2,
1084 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1085 is_registration ?
1086 "DTE address: %s" :
1087 "Calling address: %s",
1088 addr2);
1090 (*offset) += ((len1 + len2 + 1) / 2);
1093 static void
1094 x25_toa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1095 packet_info *pinfo)
1097 int len1, len2;
1098 int i;
1099 char *addr1, *addr2;
1100 char *first, *second;
1101 guint8 byte;
1102 int localoffset;
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);
1108 if (tree) {
1109 proto_tree_add_text(tree, tvb, *offset, 1,
1110 "Called address length: %u",
1111 len1);
1113 (*offset)++;
1115 len2 = tvb_get_guint8(tvb, *offset);
1116 if (tree) {
1117 proto_tree_add_text(tree, tvb, *offset, 1,
1118 "Calling address length: %u",
1119 len2);
1121 (*offset)++;
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).
1132 first=addr1;
1133 second=addr2;
1134 for (i = 0; i < (len1 + len2); i++) {
1135 if (i < len1) {
1136 if (i % 2 != 0) {
1137 *first++ = ((byte >> 0) & 0x0F) + '0';
1138 localoffset++;
1139 byte = tvb_get_guint8(tvb, localoffset);
1140 } else {
1141 *first++ = ((byte >> 4) & 0x0F) + '0';
1143 } else {
1144 if (i % 2 != 0) {
1145 *second++ = ((byte >> 0) & 0x0F) + '0';
1146 localoffset++;
1147 byte = tvb_get_guint8(tvb, localoffset);
1148 } else {
1149 *second++ = ((byte >> 4) & 0x0F) + '0';
1154 *first = '\0';
1155 *second = '\0';
1157 if (len1) {
1158 col_add_str(pinfo->cinfo, COL_RES_DL_DST, addr1);
1159 if (tree)
1160 proto_tree_add_text(tree, tvb, *offset,
1161 (len1 + 1) / 2,
1162 "Called address: %s",
1163 addr1);
1165 if (len2) {
1166 col_add_str(pinfo->cinfo, COL_RES_DL_SRC, addr2);
1167 if (tree)
1168 proto_tree_add_text(tree, tvb, *offset + len1/2,
1169 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1170 "Calling address: %s",
1171 addr2);
1173 (*offset) += ((len1 + len2 + 1) / 2);
1176 static int
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);
1183 switch (byte2)
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
1198 * to read it */
1199 if (tvb_reported_length(tvb) == 3)
1200 return(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:
1219 case X25_INTERRUPT:
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))
1251 case X25_RR:
1252 return MIN(tvb_reported_length(tvb),3);
1254 case X25_RNR:
1255 return MIN(tvb_reported_length(tvb),3);
1257 case X25_REJ:
1258 return MIN(tvb_reported_length(tvb),3);
1261 return 0;
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"},
1269 {0x00, NULL}
1272 static const value_string sharing_strategy_vals[] = {
1273 {0x00, "No sharing"},
1274 {0x00, NULL}
1277 static void
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;
1282 proto_item *ti;
1283 guint localoffset=0;
1284 guint x25_pkt_len;
1285 int modulo;
1286 guint16 vc;
1287 dissector_handle_t dissect;
1288 gboolean toa; /* TOA/NPI address format */
1289 guint16 bytes0_1;
1290 guint8 pkt_type;
1291 const char *short_name = NULL, *long_name = NULL;
1292 tvbuff_t *next_tvb = NULL;
1293 gboolean q_bit_set = FALSE;
1294 gboolean m_bit_set;
1295 gint payload_len;
1296 guint32 frag_key;
1297 fragment_head *fd_head;
1300 guint8 spi;
1301 int is_x_264;
1302 guint8 prt_id;
1303 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X.25");
1304 col_clear(pinfo->cinfo, COL_INFO);
1306 bytes0_1 = tvb_get_ntohs(tvb, 0);
1308 modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
1309 vc = (int)(bytes0_1 & 0x0FFF);
1311 pinfo->ctype = CT_X25;
1312 pinfo->circuit_id = vc;
1314 if (bytes0_1 & X25_ABIT) toa = TRUE;
1315 else toa = FALSE;
1317 x25_pkt_len = get_x25_pkt_len(tvb);
1318 if (x25_pkt_len < 3) /* packet too short */
1320 col_set_str(pinfo->cinfo, COL_INFO, "Invalid/short X.25 packet");
1321 if (tree)
1322 proto_tree_add_protocol_format(tree, proto_x25, tvb, 0, -1,
1323 "Invalid/short X.25 packet");
1324 return;
1327 pkt_type = tvb_get_guint8(tvb, 2);
1328 if (PACKET_IS_DATA(pkt_type)) {
1329 if (bytes0_1 & X25_QBIT)
1330 q_bit_set = TRUE;
1333 if (tree) {
1334 ti = proto_tree_add_item(tree, proto_x25, tvb, 0, x25_pkt_len, ENC_NA);
1335 x25_tree = proto_item_add_subtree(ti, ett_x25);
1336 ti = proto_tree_add_item(x25_tree, hf_x25_gfi, tvb, 0, 2, ENC_BIG_ENDIAN);
1337 gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
1339 if (PACKET_IS_DATA(pkt_type)) {
1340 proto_tree_add_boolean(gfi_tree, hf_x25_qbit, tvb, 0, 2,
1341 bytes0_1);
1343 else if (pkt_type == X25_CALL_REQUEST ||
1344 pkt_type == X25_CALL_ACCEPTED ||
1345 pkt_type == X25_CLEAR_REQUEST ||
1346 pkt_type == X25_CLEAR_CONFIRMATION) {
1347 proto_tree_add_boolean(gfi_tree, hf_x25_abit, tvb, 0, 2,
1348 bytes0_1);
1351 if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
1352 PACKET_IS_DATA(pkt_type)) {
1353 proto_tree_add_boolean(gfi_tree, hf_x25_dbit, tvb, 0, 2,
1354 bytes0_1);
1356 proto_tree_add_uint(gfi_tree, hf_x25_mod, tvb, 0, 2, bytes0_1);
1359 switch (pkt_type) {
1360 case X25_CALL_REQUEST:
1361 switch (dir) {
1363 case X25_FROM_DCE:
1364 short_name = "Inc. call";
1365 long_name = "Incoming call";
1366 break;
1368 case X25_FROM_DTE:
1369 short_name = "Call req.";
1370 long_name = "Call request";
1371 break;
1373 case X25_UNKNOWN:
1374 short_name = "Inc. call/Call req.";
1375 long_name = "Incoming call/Call request";
1376 break;
1378 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d", short_name, vc);
1379 if (x25_tree) {
1380 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb,
1381 0, 2, bytes0_1);
1382 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1383 X25_CALL_REQUEST, "%s", long_name);
1385 localoffset = 3;
1386 if (localoffset < x25_pkt_len) { /* calling/called addresses */
1387 if (toa)
1388 x25_toa(x25_tree, (gint*)&localoffset, tvb, pinfo);
1389 else
1390 x25_ntoa(x25_tree, (gint*)&localoffset, tvb, pinfo, FALSE);
1393 if (localoffset < x25_pkt_len) /* facilities */
1394 dump_facilities(x25_tree, (gint*)&localoffset, tvb, pinfo);
1396 if (localoffset < tvb_reported_length(tvb)) /* user data */
1399 if (x25_tree) {
1400 ti = proto_tree_add_text(x25_tree, tvb, localoffset, -1,
1401 "User data");
1402 userdata_tree = proto_item_add_subtree(ti, ett_x25_user_data);
1405 /* X.263/ISO 9577 says that:
1407 When CLNP or ESIS are run over X.25, the SPI
1408 is 0x81 or 0x82, respectively; those are the
1409 NLPIDs for those protocol.
1411 When X.224/ISO 8073 COTP is run over X.25, and
1412 when ISO 11570 explicit identification is being
1413 used, the first octet of the user data field is
1414 a TPDU length field, and the rest is "as defined
1415 in ITU-T Rec. X.225 | ISO/IEC 8073, Annex B,
1416 or ITU-T Rec. X.264 and ISO/IEC 11570".
1418 When X.264/ISO 11570 default identification is
1419 being used, there is no user data field in the
1420 CALL REQUEST packet. This is for X.225/ISO 8073
1421 COTP.
1423 It also says that SPI values from 0x03 through 0x3f are
1424 reserved and are in use by X.224/ISO 8073 Annex B and
1425 X.264/ISO 11570. The note says that those values are
1426 not NLPIDs, they're "used by the respective higher layer
1427 protocol" and "not used for higher layer protocol
1428 identification". I infer from this and from what
1429 X.264/ISO 11570 says that this means that values in those
1430 range are valid values for the first octet of an
1431 X.224/ISO 8073 packet or for X.264/ISO 11570.
1433 Annex B of X.225/ISO 8073 mentions some additional TPDU
1434 types that can be put in what I presume is the user
1435 data of connect requests. It says that:
1437 The sending transport entity shall:
1439 a) either not transmit any TPDU in the NS-user data
1440 parameter of the N-CONNECT request primitive; or
1442 b) transmit the UN-TPDU (see ITU-T Rec. X.264 and
1443 ISO/IEC 11570) followed by the NCM-TPDU in the
1444 NS-user data parameter of the N-CONNECT request
1445 primitive.
1447 I don't know if this means that the user data field
1448 will contain a UN TPDU followed by an NCM TPDU or not.
1450 X.264/ISO 11570 says that:
1452 When default identification is being used,
1453 X.225/ISO 8073 COTP is identified. No user data
1454 is sent in the network-layer connection request.
1456 When explicit identification is being used,
1457 the user data is a UN TPDU ("Use of network
1458 connection TPDU"), which specifies the transport
1459 protocol to use over this network connection.
1460 It also says that the length of a UN TPDU shall
1461 not exceed 32 octets, i.e. shall not exceed 0x20;
1462 it says this is "due to the desire not to conflict
1463 with the protocol identifier field carried by X.25
1464 CALL REQUEST/INCOMING CALL packets", and says that
1465 field has values specified in X.244. X.244 has been
1466 superseded by X.263/ISO 9577, so that presumably
1467 means the goal is to allow a UN TPDU's length
1468 field to be distinguished from an NLPID, allowing
1469 you to tell whether X.264/ISO 11570 explicit
1470 identification is being used or an NLPID is
1471 being used as the SPI.
1473 I read this as meaning that, if the ISO mechanisms are
1474 used to identify the protocol being carried over X.25:
1476 if there's no user data in the CALL REQUEST/
1477 INCOMING CALL packet, it's COTP;
1479 if there is user data, then:
1481 if the first octet is less than or equal to
1482 32, it might be a UN TPDU, and that identifies
1483 the transport protocol being used, and
1484 it may be followed by more data, such
1485 as a COTP NCM TPDU if it's COTP;
1487 if the first octet is greater than 32, it's
1488 an NLPID, *not* a TPDU length, and the
1489 stuff following it is *not* a TPDU.
1491 Figure A.2 of X.263/ISO 9577 seems to say that the
1492 first octet of the user data is a TPDU length field,
1493 in the range 0x03 through 0x82, and says they are
1494 for X.225/ISO 8073 Annex B or X.264/ISO 11570.
1496 However, X.264/ISO 11570 seems to imply that the length
1497 field would be that of a UN TPDU, which must be less
1498 than or equal to 0x20, and X.225/ISO 8073 Annex B seems
1499 to indicate that the user data must begin with
1500 an X.264/ISO 11570 UN TPDU, so I'd say that A.2 should
1501 have said "in the range 0x03 through 0x20", instead
1502 (the length value doesn't include the length field,
1503 and the minimum UN TPDU has length, type, PRT-ID,
1504 and SHARE, so that's 3 bytes without the length). */
1505 spi = tvb_get_guint8(tvb, localoffset);
1506 if (spi > 32 || spi < 3) {
1507 /* First octet is > 32, or < 3, so the user data isn't an
1508 X.264/ISO 11570 UN TPDU */
1509 is_x_264 = FALSE;
1510 } else {
1511 /* First octet is >= 3 and <= 32, so the user data *might*
1512 be an X.264/ISO 11570 UN TPDU. Check whether we have
1513 enough data to see if it is. */
1514 if (tvb_bytes_exist(tvb, localoffset+1, 1)) {
1515 /* We do; check whether the second octet is 1. */
1516 if (tvb_get_guint8(tvb, localoffset+1) == 0x01) {
1517 /* Yes, the second byte is 1, so it looks like
1518 a UN TPDU. */
1519 is_x_264 = TRUE;
1520 } else {
1521 /* No, the second byte is not 1, so it's not a
1522 UN TPDU. */
1523 is_x_264 = FALSE;
1525 } else {
1526 /* We can't see the second byte of the putative UN
1527 TPDU, so we don't know if that's what it is. */
1528 is_x_264 = -1;
1531 if (is_x_264 == -1) {
1533 * We don't know what it is; just skip it.
1535 localoffset = tvb_length(tvb);
1536 } else if (is_x_264) {
1537 /* It looks like an X.264 UN TPDU, so show it as such. */
1538 if (userdata_tree) {
1539 proto_tree_add_item( userdata_tree, hf_x264_length_indicator, tvb, localoffset, 1, ENC_NA);
1540 proto_tree_add_item( userdata_tree, hf_x264_un_tpdu_id, tvb, localoffset+1, 1, ENC_NA);
1542 prt_id = tvb_get_guint8(tvb, localoffset+2);
1543 if (userdata_tree) {
1544 proto_tree_add_item( userdata_tree, hf_x264_protocol_id, tvb, localoffset+2, 1, ENC_NA);
1545 proto_tree_add_item( userdata_tree, hf_x264_sharing_strategy, tvb, localoffset+3, 1, ENC_NA);
1548 /* XXX - dissect the variable part? */
1550 /* The length doesn't include the length octet itself. */
1551 localoffset += spi + 1;
1553 switch (prt_id) {
1555 case PRT_ID_ISO_8073:
1556 /* ISO 8073 COTP */
1557 if (!pinfo->fd->flags.visited)
1558 x25_hash_add_proto_start(vc, pinfo->fd->num, ositp_handle);
1559 /* XXX - dissect the rest of the user data as COTP?
1560 That needs support for NCM TPDUs, etc. */
1561 break;
1563 case PRT_ID_ISO_8602:
1564 /* ISO 8602 CLTP */
1565 if (!pinfo->fd->flags.visited)
1566 x25_hash_add_proto_start(vc, pinfo->fd->num, ositp_handle);
1567 break;
1569 } else if (is_x_264 == 0) {
1570 /* It doesn't look like a UN TPDU, so compare the first
1571 octet of the CALL REQUEST packet with various X.263/
1572 ISO 9577 NLPIDs, as per Annex A of X.263/ISO 9577. */
1574 if (userdata_tree) {
1575 proto_tree_add_item( userdata_tree, hf_x263_sec_protocol_id, tvb, localoffset, 1, ENC_NA);
1578 if (!pinfo->fd->flags.visited) {
1580 * Is there a dissector handle for this SPI?
1581 * If so, assign it to this virtual circuit.
1583 dissect = dissector_get_uint_handle(x25_subdissector_table, spi);
1584 if (dissect != NULL)
1585 x25_hash_add_proto_start(vc, pinfo->fd->num, dissect);
1589 * If there's only one octet of user data, it's just
1590 * an NLPID; don't try to dissect it.
1592 if (localoffset + 1 == tvb_reported_length(tvb))
1593 return;
1596 * There's more than one octet of user data, so we'll
1597 * dissect it; for some protocols, the NLPID is considered
1598 * to be part of the PDU, so, for those cases, we don't
1599 * skip past it. For other protocols, we skip the NLPID.
1601 switch (spi) {
1603 case NLPID_ISO8473_CLNP:
1604 case NLPID_ISO9542_ESIS:
1605 case NLPID_ISO10589_ISIS:
1606 case NLPID_ISO10747_IDRP:
1607 case NLPID_SNDCF:
1609 * The NLPID is part of the PDU. Don't skip it.
1610 * But if it's all there is to the PDU, don't
1611 * bother dissecting it.
1613 break;
1615 case NLPID_SPI_X_29:
1617 * The first 4 bytes of the call user data are
1618 * the SPI plus 3 reserved bytes; they are not
1619 * part of the data to be dissected as X.29 data.
1621 localoffset += 4;
1622 break;
1624 default:
1626 * The NLPID isn't part of the PDU - skip it.
1627 * If that means there's nothing to dissect
1629 localoffset++;
1632 } else {
1633 /* if there's no user data in the CALL REQUEST/
1634 INCOMING CALL packet, it's COTP; */
1636 if (call_request_nodata_is_cotp){
1637 x25_hash_add_proto_start(vc, pinfo->fd->num, ositp_handle);
1640 break;
1641 case X25_CALL_ACCEPTED:
1642 switch (dir) {
1644 case X25_FROM_DCE:
1645 short_name = "Call conn.";
1646 long_name = "Call connected";
1647 break;
1649 case X25_FROM_DTE:
1650 short_name = "Call acc.";
1651 long_name = "Call accepted";
1652 break;
1654 case X25_UNKNOWN:
1655 short_name = "Call conn./Call acc.";
1656 long_name = "Call connected/Call accepted";
1657 break;
1659 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d", short_name, vc);
1660 if (x25_tree) {
1661 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1662 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1663 X25_CALL_ACCEPTED, "%s", long_name);
1665 localoffset = 3;
1666 if (localoffset < x25_pkt_len) { /* calling/called addresses */
1667 if (toa)
1668 x25_toa(x25_tree, (gint*)&localoffset, tvb, pinfo);
1669 else
1670 x25_ntoa(x25_tree, (gint*)&localoffset, tvb, pinfo, FALSE);
1673 if (localoffset < x25_pkt_len) /* facilities */
1674 dump_facilities(x25_tree, (gint*)&localoffset, tvb, pinfo);
1675 break;
1676 case X25_CLEAR_REQUEST:
1677 switch (dir) {
1679 case X25_FROM_DCE:
1680 short_name = "Clear ind.";
1681 long_name = "Clear indication";
1682 break;
1684 case X25_FROM_DTE:
1685 short_name = "Clear req.";
1686 long_name = "Clear request";
1687 break;
1689 case X25_UNKNOWN:
1690 short_name = "Clear ind./Clear req.";
1691 long_name = "Clear indication/Clear request";
1692 break;
1694 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d %s - %s", short_name,
1695 vc, clear_code(tvb_get_guint8(tvb, 3)),
1696 val_to_str_ext(tvb_get_guint8(tvb, 4), &x25_clear_diag_vals_ext, "Unknown (0x%02x)"));
1697 x25_hash_add_proto_end(vc, pinfo->fd->num);
1698 if (x25_tree) {
1699 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1700 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb,
1701 localoffset+2, 1, X25_CLEAR_REQUEST, "%s",
1702 long_name);
1703 proto_tree_add_text(x25_tree, tvb, 3, 1,
1704 "Cause: %s", clear_code(tvb_get_guint8(tvb, 3)));
1705 proto_tree_add_item(x25_tree, hf_x25_diagnostic, tvb, 4, 1, ENC_NA);
1707 localoffset = x25_pkt_len;
1708 break;
1709 case X25_CLEAR_CONFIRMATION:
1710 col_add_fstr(pinfo->cinfo, COL_INFO, "Clear Conf. VC:%d", vc);
1711 if (x25_tree) {
1712 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1713 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1714 X25_CLEAR_CONFIRMATION);
1716 localoffset = x25_pkt_len;
1718 if (localoffset < tvb_reported_length(tvb)) { /* extended clear conf format */
1719 if (toa)
1720 x25_toa(x25_tree, (gint*)&localoffset, tvb, pinfo);
1721 else
1722 x25_ntoa(x25_tree,(gint*)&localoffset, tvb, pinfo, FALSE);
1725 if (localoffset < tvb_reported_length(tvb)) /* facilities */
1726 dump_facilities(x25_tree, (gint*)&localoffset, tvb, pinfo);
1727 break;
1728 case X25_DIAGNOSTIC:
1729 col_add_fstr(pinfo->cinfo, COL_INFO, "Diag. %d",
1730 (int)tvb_get_guint8(tvb, 3));
1731 if (x25_tree) {
1732 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1733 X25_DIAGNOSTIC);
1734 proto_tree_add_text(x25_tree, tvb, 3, 1,
1735 "Diagnostic: %d", (int)tvb_get_guint8(tvb, 3));
1737 localoffset = x25_pkt_len;
1738 break;
1739 case X25_INTERRUPT:
1740 col_add_fstr(pinfo->cinfo, COL_INFO, "Interrupt VC:%d", vc);
1741 if (x25_tree) {
1742 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1743 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1744 X25_INTERRUPT);
1746 localoffset = x25_pkt_len;
1747 break;
1748 case X25_INTERRUPT_CONFIRMATION:
1749 col_add_fstr(pinfo->cinfo, COL_INFO, "Interrupt Conf. VC:%d", vc);
1750 if (x25_tree) {
1751 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1752 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1753 X25_INTERRUPT_CONFIRMATION);
1755 localoffset = x25_pkt_len;
1756 break;
1757 case X25_RESET_REQUEST:
1758 switch (dir) {
1760 case X25_FROM_DCE:
1761 short_name = "Reset ind.";
1762 long_name = "Reset indication";
1763 break;
1765 case X25_FROM_DTE:
1766 short_name = "Reset req.";
1767 long_name = "Reset request";
1768 break;
1770 case X25_UNKNOWN:
1771 short_name = "Reset ind./Reset req.";
1772 long_name = "Reset indication/Reset request";
1773 break;
1775 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d %s - Diag.:%d",
1776 short_name, vc, reset_code(tvb_get_guint8(tvb, 3)),
1777 (int)tvb_get_guint8(tvb, 4));
1778 x25_hash_add_proto_end(vc, pinfo->fd->num);
1779 if (x25_tree) {
1780 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1781 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1782 X25_RESET_REQUEST, "%s", long_name);
1783 proto_tree_add_text(x25_tree, tvb, 3, 1,
1784 "Cause: %s", reset_code(tvb_get_guint8(tvb, 3)));
1785 proto_tree_add_text(x25_tree, tvb, 4, 1,
1786 "Diagnostic: %d", (int)tvb_get_guint8(tvb, 4));
1788 localoffset = x25_pkt_len;
1789 break;
1790 case X25_RESET_CONFIRMATION:
1791 col_add_fstr(pinfo->cinfo, COL_INFO, "Reset conf. VC:%d", vc);
1792 if (x25_tree) {
1793 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1794 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1795 X25_RESET_CONFIRMATION);
1797 localoffset = x25_pkt_len;
1798 break;
1799 case X25_RESTART_REQUEST:
1800 switch (dir) {
1802 case X25_FROM_DCE:
1803 short_name = "Restart ind.";
1804 long_name = "Restart indication";
1805 break;
1807 case X25_FROM_DTE:
1808 short_name = "Restart req.";
1809 long_name = "Restart request";
1810 break;
1812 case X25_UNKNOWN:
1813 short_name = "Restart ind./Restart req.";
1814 long_name = "Restart indication/Restart request";
1815 break;
1817 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s - Diag.:%d",
1818 short_name,
1819 restart_code(tvb_get_guint8(tvb, 3)),
1820 (int)tvb_get_guint8(tvb, 4));
1821 if (x25_tree) {
1822 proto_tree_add_uint_format_value(x25_tree, hf_x25_type, tvb, 2, 1,
1823 X25_RESTART_REQUEST, "%s", long_name);
1824 proto_tree_add_text(x25_tree, tvb, 3, 1,
1825 "Cause: %s", restart_code(tvb_get_guint8(tvb, 3)));
1826 proto_tree_add_text(x25_tree, tvb, 4, 1,
1827 "Diagnostic: %d", (int)tvb_get_guint8(tvb, 4));
1829 localoffset = x25_pkt_len;
1830 break;
1831 case X25_RESTART_CONFIRMATION:
1832 col_set_str(pinfo->cinfo, COL_INFO, "Restart conf.");
1833 if (x25_tree)
1834 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1835 X25_RESTART_CONFIRMATION);
1836 localoffset = x25_pkt_len;
1837 break;
1838 case X25_REGISTRATION_REQUEST:
1839 col_set_str(pinfo->cinfo, COL_INFO, "Registration req.");
1840 if (x25_tree)
1841 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1842 X25_REGISTRATION_REQUEST);
1843 localoffset = 3;
1844 if (localoffset < x25_pkt_len)
1845 x25_ntoa(x25_tree, (gint*)&localoffset, tvb, pinfo, TRUE);
1847 if (x25_tree) {
1848 if (localoffset < x25_pkt_len)
1849 proto_tree_add_item( x25_tree, hf_x25_reg_request_length, tvb, localoffset, 1, ENC_NA);
1850 if (localoffset+1 < x25_pkt_len)
1851 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1852 tvb_get_guint8(tvb, localoffset) & 0x7F,
1853 "Registration");
1855 localoffset = tvb_reported_length(tvb);
1856 break;
1857 case X25_REGISTRATION_CONFIRMATION:
1858 col_set_str(pinfo->cinfo, COL_INFO, "Registration conf.");
1859 if (x25_tree) {
1860 proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1861 X25_REGISTRATION_CONFIRMATION);
1862 proto_tree_add_item(x25_tree, hf_x25_reg_confirm_cause, tvb, 3, 1, ENC_NA);
1863 proto_tree_add_item(x25_tree, hf_x25_reg_confirm_diagnostic, tvb, 4, 1, ENC_NA);
1865 localoffset = 5;
1866 if (localoffset < x25_pkt_len)
1867 x25_ntoa(x25_tree, (gint*)&localoffset, tvb, pinfo, TRUE);
1869 if (x25_tree) {
1870 if (localoffset < x25_pkt_len)
1871 proto_tree_add_item( x25_tree, hf_x25_reg_confirm_length, tvb, localoffset, 1, ENC_NA);
1872 if (localoffset+1 < x25_pkt_len)
1873 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1874 tvb_get_guint8(tvb, localoffset) & 0x7F,
1875 "Registration");
1877 localoffset = tvb_reported_length(tvb);
1878 break;
1879 default:
1880 localoffset = 2;
1881 if (x25_tree) {
1882 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1883 2, bytes0_1);
1885 if (PACKET_IS_DATA(pkt_type)) {
1886 if (modulo == 8)
1887 col_add_fstr(pinfo->cinfo, COL_INFO,
1888 "Data VC:%d P(S):%d P(R):%d %s", vc,
1889 (pkt_type >> 1) & 0x07,
1890 (pkt_type >> 5) & 0x07,
1891 (pkt_type & X25_MBIT_MOD8) ? " M" : "");
1892 else
1893 col_add_fstr(pinfo->cinfo, COL_INFO,
1894 "Data VC:%d P(S):%d P(R):%d %s", vc,
1895 tvb_get_guint8(tvb, localoffset+1) >> 1,
1896 pkt_type >> 1,
1897 (tvb_get_guint8(tvb, localoffset+1) & X25_MBIT_MOD128) ? " M" : "");
1898 if (x25_tree) {
1899 if (modulo == 8) {
1900 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1901 localoffset, 1, pkt_type);
1902 proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod8, tvb,
1903 localoffset, 1, pkt_type);
1904 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod8, tvb,
1905 localoffset, 1, pkt_type);
1906 proto_tree_add_uint(x25_tree, hf_x25_type_data, tvb,
1907 localoffset, 1, pkt_type);
1909 else {
1910 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod128, tvb,
1911 localoffset, 1, pkt_type);
1912 proto_tree_add_uint(x25_tree, hf_x25_type_data, tvb,
1913 localoffset, 1, pkt_type);
1914 proto_tree_add_uint(x25_tree, hf_x25_p_s_mod128, tvb,
1915 localoffset+1, 1,
1916 tvb_get_guint8(tvb, localoffset+1));
1917 proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod128, tvb,
1918 localoffset+1, 1,
1919 tvb_get_guint8(tvb, localoffset+1));
1922 if (modulo == 8) {
1923 m_bit_set = pkt_type & X25_MBIT_MOD8;
1924 localoffset += 1;
1925 } else {
1926 m_bit_set = tvb_get_guint8(tvb, localoffset+1) & X25_MBIT_MOD128;
1927 localoffset += 2;
1929 payload_len = tvb_reported_length_remaining(tvb, localoffset);
1930 if (reassemble_x25) {
1932 * Reassemble received and sent traffic separately.
1933 * We don't reassemble traffic with an unknown direction
1934 * at all.
1936 frag_key = vc;
1937 if (side) {
1939 * OR in an extra bit to distinguish from traffic
1940 * in the other direction.
1942 frag_key |= 0x10000;
1944 fd_head = fragment_add_seq_next(&x25_reassembly_table,
1945 tvb, localoffset,
1946 pinfo, frag_key, NULL,
1947 payload_len, m_bit_set);
1948 pinfo->fragmented = m_bit_set;
1950 /* Fragment handling is not adapted to handle several x25
1951 * packets in the same frame. This is common with XOT and
1952 * shorter packet sizes.
1953 * Therefore, fragment_add_seq_next seem to always return fd_head
1954 * A fix to use m_bit_set to only show fragments for last pkt
1956 if (!m_bit_set && fd_head) {
1957 if (fd_head->next) {
1958 proto_item *frag_tree_item;
1960 /* This is the last packet */
1961 next_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
1962 add_new_data_source(pinfo, next_tvb, "Reassembled X.25");
1963 if (x25_tree) {
1964 show_fragment_seq_tree(fd_head,
1965 &x25_frag_items,
1966 x25_tree,
1967 pinfo, next_tvb, &frag_tree_item);
1972 if (m_bit_set && next_tvb == NULL) {
1974 * This isn't the last packet, so just
1975 * show it as X.25 user data.
1977 proto_tree_add_text(x25_tree, tvb, localoffset, -1,
1978 "User data (%u byte%s)", payload_len,
1979 plurality(payload_len, "", "s"));
1980 return;
1983 } else {
1985 * Non-data packets (RR, RNR, REJ).
1987 if (modulo == 8) {
1988 if (x25_tree) {
1989 proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1990 localoffset, 1, pkt_type);
1991 proto_tree_add_item(x25_tree, hf_x25_type_fc_mod8, tvb,
1992 localoffset, 1, ENC_NA);
1994 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d P(R):%d",
1995 val_to_str(PACKET_TYPE_FC(pkt_type), vals_x25_type, "Unknown (0x%02X)"),
1996 vc, (pkt_type >> 5) & 0x07);
1997 localoffset += 1;
1998 } else {
1999 if (x25_tree) {
2000 proto_tree_add_item(x25_tree, hf_x25_type, tvb,
2001 localoffset, 1, ENC_NA);
2002 proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
2003 localoffset+1, 1, ENC_NA);
2005 col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d P(R):%d",
2006 val_to_str(PACKET_TYPE_FC(pkt_type), vals_x25_type, "Unknown (0x%02X)"),
2007 vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
2008 localoffset += 2;
2011 break;
2014 if (localoffset >= tvb_reported_length(tvb))
2015 return;
2016 if (pinfo->fragmented)
2017 return;
2019 if (!next_tvb)
2020 next_tvb = tvb_new_subset_remaining(tvb, localoffset);
2022 /* See if there's already a dissector for this circuit. */
2023 if (try_circuit_dissector(CT_X25, vc, pinfo->fd->num, next_tvb, pinfo,
2024 tree, &q_bit_set)) {
2025 return; /* found it and dissected it */
2028 /* Did the user suggest QLLC/SNA? */
2029 if (payload_is_qllc_sna) {
2030 /* Yes - dissect it as QLLC/SNA. */
2031 if (!pinfo->fd->flags.visited)
2032 x25_hash_add_proto_start(vc, pinfo->fd->num, qllc_handle);
2033 call_dissector_with_data(qllc_handle, next_tvb, pinfo, tree, &q_bit_set);
2034 return;
2037 if (payload_check_data){
2038 /* If the Call Req. has not been captured, let's look at the first
2039 two bytes of the payload to see if this looks like COTP. */
2040 if (tvb_get_guint8(tvb, localoffset) == tvb_length(next_tvb)-1) {
2041 /* First byte contains the length of the remaining buffer */
2042 if ((tvb_get_guint8(tvb, localoffset+1) & 0x0F) == 0) {
2043 /* Second byte contains a valid COTP TPDU */
2044 if (!pinfo->fd->flags.visited)
2045 x25_hash_add_proto_start(vc, pinfo->fd->num, ositp_handle);
2046 call_dissector(ositp_handle, next_tvb, pinfo, tree);
2047 return;
2051 /* Then let's look at the first byte of the payload to see if this
2052 looks like IP or CLNP. */
2053 switch (tvb_get_guint8(tvb, localoffset)) {
2055 case 0x45:
2056 /* Looks like an IP header */
2057 if (!pinfo->fd->flags.visited)
2058 x25_hash_add_proto_start(vc, pinfo->fd->num, ip_handle);
2059 call_dissector(ip_handle, next_tvb, pinfo, tree);
2060 return;
2062 case NLPID_ISO8473_CLNP:
2063 if (!pinfo->fd->flags.visited)
2064 x25_hash_add_proto_start(vc, pinfo->fd->num, clnp_handle);
2065 call_dissector(clnp_handle, next_tvb, pinfo, tree);
2066 return;
2070 /* Try the heuristic dissectors. */
2071 if (dissector_try_heuristic(x25_heur_subdissector_list, next_tvb, pinfo,
2072 tree, NULL)) {
2073 return;
2076 /* All else failed; dissect it as raw data */
2077 call_dissector(data_handle, next_tvb, pinfo, tree);
2081 * X.25 dissector for use when "pinfo->pseudo_header" points to a
2082 * "struct x25_phdr".
2084 static void
2085 dissect_x25_dir(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2087 dissect_x25_common(tvb, pinfo, tree,
2088 (pinfo->pseudo_header->x25.flags & FROM_DCE) ? X25_FROM_DCE :
2089 X25_FROM_DTE,
2090 pinfo->pseudo_header->x25.flags & FROM_DCE);
2094 * X.25 dissector for use when "pinfo->pseudo_header" doesn't point to a
2095 * "struct x25_phdr".
2097 static void
2098 dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2100 int direction;
2103 * We don't know if this packet is DTE->DCE or DCE->DCE.
2104 * However, we can, at least, distinguish between the two
2105 * sides of the conversation, based on the addresses and
2106 * ports.
2108 direction = CMP_ADDRESS(&pinfo->src, &pinfo->dst);
2109 if (direction == 0)
2110 direction = (pinfo->srcport > pinfo->destport)*2 - 1;
2111 dissect_x25_common(tvb, pinfo, tree, X25_UNKNOWN, direction > 0);
2114 static void
2115 x25_reassemble_init(void)
2117 reassembly_table_init(&x25_reassembly_table,
2118 &addresses_reassembly_table_functions);
2121 void
2122 proto_register_x25(void)
2124 static hf_register_info hf[] = {
2125 { &hf_x25_facility,
2126 { "Facility", "x25.facility", FT_NONE, BASE_NONE, NULL, 0,
2127 NULL, HFILL }},
2128 { &hf_x25_facilities_length,
2129 { "Facilities Length", "x25.facilities_length", FT_UINT8, BASE_DEC, NULL, 0,
2130 NULL, HFILL }},
2131 { &hf_x25_facility_length,
2132 { "Length", "x25.facility_length", FT_UINT8, BASE_DEC, NULL, 0,
2133 NULL, HFILL }},
2134 { &hf_x25_facility_class,
2135 { "Facility Class", "x25.facility.class", FT_UINT8, BASE_HEX, VALS(x25_facilities_class_vals), X25_FAC_CLASS_MASK,
2136 NULL, HFILL }},
2137 { &hf_x25_facility_classA,
2138 { "Code", "x25.facility.classA", FT_UINT8, BASE_HEX, VALS(x25_facilities_classA_vals), 0,
2139 "Facility ClassA Code", HFILL }},
2140 { &hf_x25_facility_classA_comp_mark,
2141 { "Parameter", "x25.facility.comp_mark", FT_UINT8, BASE_DEC, VALS(x25_facilities_classA_comp_mark_vals), 0,
2142 "Facility Marker Parameter", HFILL }},
2143 { &hf_x25_facility_classA_reverse,
2144 { "Parameter", "x25.facility.reverse", FT_UINT8, BASE_HEX, NULL, 0,
2145 "Facility Reverse Charging Parameter", HFILL }},
2146 { &hf_x25_facility_classA_charging_info,
2147 { "Parameter", "x25.facility.charging_info", FT_UINT8, BASE_HEX, NULL, 0,
2148 "Facility Charging Information Parameter", HFILL }},
2149 { &hf_x25_facility_reverse_charging,
2150 { "Reverse charging", "x25.reverse_charging", FT_BOOLEAN, 8, TFS(&x25_reverse_charging_val), 0x01,
2151 NULL, HFILL }},
2152 { &hf_x25_facility_charging_info,
2153 { "Charging information", "x25.charging_info", FT_BOOLEAN, 8, TFS(&tfs_requested_not_requested), 0x01,
2154 NULL, HFILL }},
2155 { &hf_x25_facility_throughput_called_dte,
2156 { "From the called DTE", "x25.facility.throughput.called_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classA_throughput_vals), 0xF0,
2157 "Facility Throughput called DTE", HFILL }},
2158 { &hf_x25_throughput_called_dte,
2159 { "From the calling DTE", "x25.facility.throughput.called_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classA_throughput_vals), 0x0F,
2160 "Facility Throughput called DTE", HFILL }},
2161 { &hf_x25_facility_classA_cug,
2162 { "Closed user group", "x25.facility.cug", FT_UINT8, BASE_HEX, NULL, 0,
2163 "Facility Closed user group", HFILL }},
2164 { &hf_x25_facility_classA_called_motif,
2165 { "Parameter", "x25.facility.called_motif", FT_UINT8, BASE_HEX, NULL, 0,
2166 "Facility Called address modified parameter", HFILL }},
2167 { &hf_x25_facility_classA_cug_outgoing_acc,
2168 { "Closed user group", "x25.facility.cug_outgoing_acc", FT_UINT8, BASE_HEX, NULL, 0,
2169 "Facility Closed user group with outgoing access selection", HFILL }},
2170 { &hf_x25_facility_classA_throughput_min,
2171 { "Parameter", "x25.facility.throughput_min", FT_UINT8, BASE_HEX, NULL, 0,
2172 "Facility Minimum throughput class parameter", HFILL }},
2173 { &hf_x25_facility_classA_express_data,
2174 { "Parameter", "x25.facility.express_data", FT_UINT8, BASE_HEX, NULL, 0,
2175 "Facility Negotiation of express data parameter", HFILL }},
2176 { &hf_x25_facility_classA_unknown,
2177 { "Parameter", "x25.facility.classA_unknown", FT_UINT8, BASE_HEX, NULL, 0,
2178 "Facility Class A unknown parameter", HFILL }},
2179 { &hf_x25_facility_classB,
2180 { "Code", "x25.facility.classB", FT_UINT8, BASE_HEX, VALS(x25_facilities_classB_vals), 0,
2181 "Facility ClassB Code", HFILL }},
2182 { &hf_x25_facility_classB_bilateral_cug,
2183 { "Bilateral CUG", "x25.facility.bilateral_cug", FT_UINT16, BASE_HEX, NULL, 0,
2184 "Facility Bilateral CUG", HFILL }},
2185 { &hf_x25_facility_packet_size_called_dte,
2186 { "From the called DTE", "x25.facility.packet_size.called_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classB_packet_size_vals), 0,
2187 "Facility Packet size from the called DTE", HFILL }},
2188 { &hf_x25_facility_packet_size_calling_dte,
2189 { "From the calling DTE", "x25.facility.packet_size.calling_dte", FT_UINT8, BASE_DEC, VALS(x25_facilities_classB_packet_size_vals), 0,
2190 "Facility Packet size from the calling DTE", HFILL }},
2191 { &hf_x25_facility_data_network_id_code,
2192 { "Data network identification code", "x25.facility.data_network_id_code", FT_UINT16, BASE_HEX, NULL, 0,
2193 "Facility RPOA selection data network identification code", HFILL }},
2194 { &hf_x25_facility_cug_ext,
2195 { "Closed user group", "x25.facility.cug_ext", FT_UINT16, BASE_HEX, NULL, 0,
2196 "Facility Extended closed user group selection", HFILL }},
2197 { &hf_x25_facility_cug_outgoing_acc_ext,
2198 { "Closed user group", "x25.facility.cug_outgoing_acc_ext", FT_UINT16, BASE_HEX, NULL, 0,
2199 "Facility Extended closed user group with outgoing access selection", HFILL }},
2200 { &hf_x25_facility_transit_delay,
2201 { "Transit delay (ms)", "x25.facility.transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2202 "Facility Transit delay selection and indication", HFILL }},
2203 { &hf_x25_facility_classB_unknown,
2204 { "Parameter", "x25.facility.classB_unknown", FT_UINT16, BASE_HEX, NULL, 0,
2205 "Facility Class B unknown parameter", HFILL }},
2206 { &hf_x25_facility_classC_unknown,
2207 { "Parameter", "x25.facility.classC_unknown", FT_UINT24, BASE_HEX, NULL, 0,
2208 "Facility Class C unknown parameter", HFILL }},
2209 { &hf_x25_facility_classC,
2210 { "Code", "x25.facility.classC", FT_UINT8, BASE_HEX, VALS(x25_facilities_classC_vals), 0,
2211 "Facility ClassC Code", HFILL }},
2212 { &hf_x25_facility_classD,
2213 { "Code", "x25.facility.classD", FT_UINT8, BASE_HEX, VALS(x25_facilities_classD_vals), 0,
2214 "Facility ClassD Code", HFILL }},
2215 { &hf_x25_gfi,
2216 { "GFI", "x25.gfi", FT_UINT16, BASE_DEC, NULL, 0xF000,
2217 "General format identifier", HFILL }},
2218 { &hf_x25_abit,
2219 { "A Bit", "x25.a", FT_BOOLEAN, 16, NULL, X25_ABIT,
2220 "Address Bit", HFILL }},
2221 { &hf_x25_qbit,
2222 { "Q Bit", "x25.q", FT_BOOLEAN, 16, NULL, X25_QBIT,
2223 "Qualifier Bit", HFILL }},
2224 { &hf_x25_dbit,
2225 { "D Bit", "x25.d", FT_BOOLEAN, 16, NULL, X25_DBIT,
2226 "Delivery Confirmation Bit", HFILL }},
2227 { &hf_x25_mod,
2228 { "Modulo", "x25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
2229 "Specifies whether the frame is modulo 8 or 128", HFILL }},
2230 { &hf_x25_lcn,
2231 { "Logical Channel", "x25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
2232 "Logical Channel Number", HFILL }},
2233 { &hf_x25_type,
2234 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
2235 NULL, HFILL }},
2236 { &hf_x25_type_fc_mod8,
2237 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x1F,
2238 NULL, HFILL }},
2239 { &hf_x25_type_data,
2240 { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x01,
2241 NULL, HFILL }},
2242 { &hf_x25_diagnostic,
2243 { "Diagnostic", "x25.diagnostic", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &x25_clear_diag_vals_ext, 0,
2244 NULL, HFILL }},
2245 { &hf_x25_p_r_mod8,
2246 { "P(R)", "x25.p_r", FT_UINT8, BASE_DEC, NULL, 0xE0,
2247 "Packet Receive Sequence Number", HFILL }},
2248 { &hf_x25_p_r_mod128,
2249 { "P(R)", "x25.p_r", FT_UINT8, BASE_DEC, NULL, 0xFE,
2250 "Packet Receive Sequence Number", HFILL }},
2251 { &hf_x25_mbit_mod8,
2252 { "M Bit", "x25.m", FT_BOOLEAN, 8, TFS(&m_bit_tfs), X25_MBIT_MOD8,
2253 "More Bit", HFILL }},
2254 { &hf_x25_mbit_mod128,
2255 { "M Bit", "x25.m", FT_BOOLEAN, 8, TFS(&m_bit_tfs), X25_MBIT_MOD128,
2256 "More Bit", HFILL }},
2257 { &hf_x25_p_s_mod8,
2258 { "P(S)", "x25.p_s", FT_UINT8, BASE_DEC, NULL, 0x0E,
2259 "Packet Send Sequence Number", HFILL }},
2260 { &hf_x25_p_s_mod128,
2261 { "P(S)", "x25.p_s", FT_UINT8, BASE_DEC, NULL, 0xFE,
2262 "Packet Send Sequence Number", HFILL }},
2263 { &hf_x25_window_size_called_dte,
2264 { "From the called DTE", "x25.window_size.called_dte", FT_UINT8, BASE_DEC, NULL, 0x7F,
2265 NULL, HFILL }},
2266 { &hf_x25_window_size_calling_dte,
2267 { "From the calling DTE", "x25.window_size.calling_dte", FT_UINT8, BASE_DEC, NULL, 0x7F,
2268 NULL, HFILL }},
2269 { &hf_x25_dte_address_length,
2270 { "DTE address length", "x25.dte_address_length", FT_UINT8, BASE_DEC, NULL, 0xF0,
2271 NULL, HFILL }},
2272 { &hf_x25_dce_address_length,
2273 { "DCE address length", "x25.dce_address_length", FT_UINT8, BASE_DEC, NULL, 0x0F,
2274 NULL, HFILL }},
2275 { &hf_x25_calling_address_length,
2276 { "Calling address length", "x25.calling_address_length", FT_UINT8, BASE_DEC, NULL, 0xF0,
2277 NULL, HFILL }},
2278 { &hf_x25_called_address_length,
2279 { "Called address length", "x25.called_address_length", FT_UINT8, BASE_DEC, NULL, 0x0F,
2280 NULL, HFILL }},
2281 { &hf_x25_facility_call_transfer_reason,
2282 { "Reason", "x25.facility.call_transfer_reason", FT_UINT8, BASE_DEC, VALS(x25_facilities_call_transfer_reason_vals), 0,
2283 NULL, HFILL }},
2284 { &hf_x25_facility_monetary_unit,
2285 { "Monetary unit", "x25.facility.monetary_unit", FT_BYTES, BASE_NONE, NULL, 0,
2286 NULL, HFILL }},
2287 { &hf_x25_facility_nui,
2288 { "NUI", "x25.facility.nui", FT_BYTES, BASE_NONE, NULL, 0,
2289 NULL, HFILL }},
2290 { &hf_x25_facility_cumulative_ete_transit_delay,
2291 { "Cumulative end-to-end transit delay (ms)", "x25.facility.cumulative_ete_transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2292 NULL, HFILL }},
2293 { &hf_x25_facility_requested_ete_transit_delay,
2294 { "Requested end-to-end transit delay (ms)", "x25.facility.requested_ete_transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2295 NULL, HFILL }},
2296 { &hf_x25_facility_max_acceptable_ete_transit_delay,
2297 { "Maximum acceptable end-to-end transit delay (ms)", "x25.facility.mac_acceptable_ete_transit_delay", FT_UINT16, BASE_DEC, NULL, 0,
2298 NULL, HFILL }},
2299 { &hf_x25_facility_priority_data,
2300 { "Priority for data", "x25.facility.priority_data", FT_UINT8, BASE_DEC, NULL, 0,
2301 NULL, HFILL }},
2302 { &hf_x25_facility_priority_estab_conn,
2303 { "Priority for establishing connection", "x25.facility.priority_estab_conn", FT_UINT8, BASE_DEC, NULL, 0,
2304 NULL, HFILL }},
2305 { &hf_x25_facility_priority_keep_conn,
2306 { "Priority for keeping connection", "x25.facility.priority_keep_conn", FT_UINT8, BASE_DEC, NULL, 0,
2307 NULL, HFILL }},
2308 { &hf_x25_facility_min_acceptable_priority_data,
2309 { "Minimum acceptable priority for data", "x25.facility.min_acceptable_priority_data", FT_UINT8, BASE_DEC, NULL, 0,
2310 NULL, HFILL }},
2311 { &hf_x25_facility_min_acceptable_priority_estab_conn,
2312 { "Minimum acceptable priority for establishing connection", "x25.facility.min_acceptable_priority_estab_conn", FT_UINT8, BASE_DEC, NULL, 0,
2313 NULL, HFILL }},
2314 { &hf_x25_facility_min_acceptable_priority_keep_conn,
2315 { "Minimum acceptable priority for keeping connection", "x25.facility.min_acceptable_priority_keep_conn", FT_UINT8, BASE_DEC, NULL, 0,
2316 NULL, HFILL }},
2317 { &hf_x25_facility_classD_unknown,
2318 { "Parameter", "x25.facility.classD_unknown", FT_BYTES, BASE_NONE, NULL, 0,
2319 "Facility Class D unknown parameter", HFILL }},
2320 { &hf_x25_facility_call_transfer_num_semi_octets,
2321 { "Number of semi-octets in DTE address", "x25.facility.call_transfer_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2322 NULL, HFILL }},
2323 { &hf_x25_facility_calling_addr_ext_num_semi_octets,
2324 { "Number of semi-octets in DTE address", "x25.facility.calling_addr_ext_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2325 NULL, HFILL }},
2326 { &hf_x25_facility_called_addr_ext_num_semi_octets,
2327 { "Number of semi-octets in DTE address", "x25.facility.called_addr_ext_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2328 NULL, HFILL }},
2329 { &hf_x25_facility_call_deflect_num_semi_octets,
2330 { "Number of semi-octets in the alternative DTE address", "x25.facility.call_deflect_num_semi_octets", FT_UINT8, BASE_DEC, NULL, 0,
2331 NULL, HFILL }},
2332 { &hf_x264_length_indicator,
2333 { "X.264 length indicator", "x25.x264_length_indicator", FT_UINT8, BASE_DEC, NULL, 0,
2334 NULL, HFILL }},
2335 { &hf_x264_un_tpdu_id,
2336 { "X.264 UN TPDU identifier", "x25.x264_un_tpdu_id", FT_UINT8, BASE_HEX, NULL, 0,
2337 NULL, HFILL }},
2338 { &hf_x264_protocol_id,
2339 { "X.264 protocol identifier", "x25.x264_protocol_id", FT_UINT8, BASE_HEX, VALS(prt_id_vals), 0,
2340 NULL, HFILL }},
2341 { &hf_x264_sharing_strategy,
2342 { "X.264 sharing strategy", "x25.x264_sharing_strategy", FT_UINT8, BASE_HEX, VALS(sharing_strategy_vals), 0,
2343 NULL, HFILL }},
2344 { &hf_x263_sec_protocol_id,
2345 { "X.263 secondary protocol ID", "x25.x263_sec_protocol_id", FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0,
2346 NULL, HFILL }},
2347 { &hf_x25_reg_request_length,
2348 { "Registration length", "x25.reg_request_length", FT_UINT8, BASE_DEC, NULL, 0x7F,
2349 NULL, HFILL }},
2350 { &hf_x25_reg_confirm_length,
2351 { "Registration length", "x25.reg_confirm_length", FT_UINT8, BASE_DEC, NULL, 0x7F,
2352 NULL, HFILL }},
2354 { &hf_x25_segment_overlap,
2355 { "Fragment overlap", "x25.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2356 "Fragment overlaps with other fragments", HFILL }},
2358 { &hf_x25_segment_overlap_conflict,
2359 { "Conflicting data in fragment overlap", "x25.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2360 "Overlapping fragments contained conflicting data", HFILL }},
2362 { &hf_x25_segment_multiple_tails,
2363 { "Multiple tail fragments found", "x25.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2364 "Several tails were found when defragmenting the packet", HFILL }},
2366 { &hf_x25_segment_too_long_segment,
2367 { "Fragment too long", "x25.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2368 "Fragment contained data past end of packet", HFILL }},
2370 { &hf_x25_segment_error,
2371 { "Defragmentation error", "x25.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2372 "Defragmentation error due to illegal fragments", HFILL }},
2374 { &hf_x25_segment_count,
2375 { "Fragment count", "x25.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2376 NULL, HFILL }},
2378 { &hf_x25_reassembled_length,
2379 { "Reassembled X.25 length", "x25.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
2380 "The total length of the reassembled payload", HFILL }},
2382 { &hf_x25_segment,
2383 { "X.25 Fragment", "x25.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2384 "X25 Fragment", HFILL }},
2386 { &hf_x25_segments,
2387 { "X.25 Fragments", "x25.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
2388 NULL, HFILL }},
2390 { &hf_x25_fast_select,
2391 { "Fast select", "x25.fast_select", FT_UINT8, BASE_DEC, VALS(x25_fast_select_vals), 0xC0,
2392 NULL, HFILL }},
2394 { &hf_x25_icrd,
2395 { "ICRD", "x25.icrd", FT_UINT8, BASE_DEC, VALS(x25_icrd_vals), 0x30,
2396 NULL, HFILL }},
2398 { &hf_x25_reg_confirm_cause,
2399 { "Cause", "x25.reg_confirm.cause", FT_UINT8, BASE_DEC, VALS(x25_registration_code_vals), 0,
2400 NULL, HFILL }},
2402 { &hf_x25_reg_confirm_diagnostic,
2403 { "Diagnostic", "x25.reg_confirm.diagnostic", FT_UINT8, BASE_DEC, VALS(x25_registration_code_vals), 0,
2404 NULL, HFILL }},
2407 static gint *ett[] = {
2408 &ett_x25,
2409 &ett_x25_gfi,
2410 &ett_x25_facilities,
2411 &ett_x25_facility,
2412 &ett_x25_user_data,
2413 &ett_x25_segment,
2414 &ett_x25_segments
2417 static ei_register_info ei[] = {
2418 { &ei_x25_facility_length, { "x25.facility_length.bogus", PI_PROTOCOL, PI_WARN, "Bogus length", EXPFILL }},
2421 module_t *x25_module;
2422 expert_module_t* expert_x25;
2424 proto_x25 = proto_register_protocol ("X.25", "X.25", "x25");
2425 proto_register_field_array (proto_x25, hf, array_length(hf));
2426 proto_register_subtree_array(ett, array_length(ett));
2427 expert_x25 = expert_register_protocol(proto_x25);
2428 expert_register_field_array(expert_x25, ei, array_length(ei));
2430 x25_subdissector_table = register_dissector_table("x.25.spi",
2431 "X.25 secondary protocol identifier", FT_UINT8, BASE_HEX);
2432 register_heur_dissector_list("x.25", &x25_heur_subdissector_list);
2434 register_dissector("x.25_dir", dissect_x25_dir, proto_x25);
2435 register_dissector("x.25", dissect_x25, proto_x25);
2437 /* Preferences */
2438 x25_module = prefs_register_protocol(proto_x25, NULL);
2439 prefs_register_obsolete_preference(x25_module, "non_q_bit_is_sna");
2440 prefs_register_bool_preference(x25_module, "payload_is_qllc_sna",
2441 "Default to QLLC/SNA",
2442 "If CALL REQUEST not seen or didn't specify protocol, dissect as QLLC/SNA",
2443 &payload_is_qllc_sna);
2444 prefs_register_bool_preference(x25_module, "call_request_nodata_is_cotp",
2445 "Assume COTP for Call Request without data",
2446 "If CALL REQUEST has no data, assume the protocol handled is COTP",
2447 &call_request_nodata_is_cotp);
2448 prefs_register_bool_preference(x25_module, "payload_check_data",
2449 "Check data for COTP/IP/CLNP",
2450 "If CALL REQUEST not seen or didn't specify protocol, check user data before checking heuristic dissectors",
2451 &payload_check_data);
2452 prefs_register_bool_preference(x25_module, "reassemble",
2453 "Reassemble fragmented X.25 packets",
2454 "Reassemble fragmented X.25 packets",
2455 &reassemble_x25);
2456 register_init_routine(&x25_reassemble_init);
2459 void
2460 proto_reg_handoff_x25(void)
2462 dissector_handle_t x25_handle;
2465 * Get handles for various dissectors.
2467 ip_handle = find_dissector("ip");
2468 clnp_handle = find_dissector("clnp");
2469 ositp_handle = find_dissector("ositp");
2470 qllc_handle = find_dissector("qllc");
2471 data_handle = find_dissector("data");
2473 x25_handle = find_dissector("x.25");
2474 dissector_add_uint("llc.dsap", SAP_X25, x25_handle);
2475 dissector_add_uint("lapd.sapi", LAPD_SAPI_X25, x25_handle);
2476 dissector_add_uint("ax25.pid", AX25_P_ROSE, x25_handle);