Add a routine tro look for a given port in a given dissector table and,
[obnox/wireshark/wip.git] / packet-x25.c
1 /* packet-x25.c
2  * Routines for x25 packet disassembly
3  * Olivier Abad <oabad@cybercable.fr>
4  *
5  * $Id: packet-x25.c,v 1.59 2001/12/03 05:07:16 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998
10  * 
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.
15  * 
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.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #include <stdio.h>
35 #include <glib.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include "llcsaps.h"
39 #include "packet.h"
40 #include "prefs.h"
41 #include "nlpid.h"
42 #include "x264_prt_id.h"
43
44 #define FROM_DCE                        0x80
45
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
63
64 #define X25_FAC_CLASS_MASK              0xC0
65
66 #define X25_FAC_CLASS_A                 0x00
67 #define X25_FAC_CLASS_B                 0x40
68 #define X25_FAC_CLASS_C                 0x80
69 #define X25_FAC_CLASS_D                 0xC0
70
71 #define X25_FAC_COMP_MARK               0x00
72 #define X25_FAC_REVERSE                 0x01
73 #define X25_FAC_THROUGHPUT              0x02
74 #define X25_FAC_CUG                     0x03
75 #define X25_FAC_CALLED_MODIF            0x08
76 #define X25_FAC_CUG_OUTGOING_ACC        0x09
77 #define X25_FAC_THROUGHPUT_MIN          0x0A
78 #define X25_FAC_EXPRESS_DATA            0x0B
79 #define X25_FAC_BILATERAL_CUG           0x41
80 #define X25_FAC_PACKET_SIZE             0x42
81 #define X25_FAC_WINDOW_SIZE             0x43
82 #define X25_FAC_RPOA_SELECTION          0x44
83 #define X25_FAC_TRANSIT_DELAY           0x49
84 #define X25_FAC_CALL_TRANSFER           0xC3
85 #define X25_FAC_CALLED_ADDR_EXT         0xC9
86 #define X25_FAC_ETE_TRANSIT_DELAY       0xCA
87 #define X25_FAC_CALLING_ADDR_EXT        0xCB
88 #define X25_FAC_CALL_DEFLECT            0xD1
89 #define X25_FAC_PRIORITY                0xD2
90
91 static int proto_x25 = -1;
92 static int hf_x25_gfi = -1;
93 static int hf_x25_abit = -1;
94 static int hf_x25_qbit = -1;
95 static int hf_x25_dbit = -1;
96 static int hf_x25_mod = -1;
97 static int hf_x25_lcn = -1;
98 static int hf_x25_type = -1;
99 static int hf_x25_p_r_mod8 = -1;
100 static int hf_x25_p_r_mod128 = -1;
101 static int hf_x25_mbit_mod8 = -1;
102 static int hf_x25_mbit_mod128 = -1;
103 static int hf_x25_p_s_mod8 = -1;
104 static int hf_x25_p_s_mod128 = -1;
105
106 static gint ett_x25 = -1;
107 static gint ett_x25_gfi = -1;
108 static gint ett_x25_fac = -1;
109 static gint ett_x25_fac_unknown = -1;
110 static gint ett_x25_fac_mark = -1;
111 static gint ett_x25_fac_reverse = -1;
112 static gint ett_x25_fac_throughput = -1;
113 static gint ett_x25_fac_cug = -1;
114 static gint ett_x25_fac_called_modif = -1;
115 static gint ett_x25_fac_cug_outgoing_acc = -1;
116 static gint ett_x25_fac_throughput_min = -1;
117 static gint ett_x25_fac_express_data = -1;
118 static gint ett_x25_fac_bilateral_cug = -1;
119 static gint ett_x25_fac_packet_size = -1;
120 static gint ett_x25_fac_window_size = -1;
121 static gint ett_x25_fac_rpoa_selection = -1;
122 static gint ett_x25_fac_transit_delay = -1;
123 static gint ett_x25_fac_call_transfer = -1;
124 static gint ett_x25_fac_called_addr_ext = -1;
125 static gint ett_x25_fac_ete_transit_delay = -1;
126 static gint ett_x25_fac_calling_addr_ext = -1;
127 static gint ett_x25_fac_call_deflect = -1;
128 static gint ett_x25_fac_priority = -1;
129 static gint ett_x25_user_data = -1;
130
131 static const value_string vals_modulo[] = {
132         { 1, "8" },
133         { 2, "128" },
134         { 0, NULL}
135 };
136
137 static const value_string vals_x25_type[] = {
138         { X25_CALL_REQUEST, "Call" },
139         { X25_CALL_ACCEPTED, "Call Accepted" },
140         { X25_CLEAR_REQUEST, "Clear" },
141         { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
142         { X25_INTERRUPT, "Interrupt" },
143         { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
144         { X25_RESET_REQUEST, "Reset" },
145         { X25_RESET_CONFIRMATION, "Reset Confirmation" },
146         { X25_RESTART_REQUEST, "Restart" },
147         { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
148         { X25_REGISTRATION_REQUEST, "Registration" },
149         { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
150         { X25_DIAGNOSTIC, "Diagnostic" },
151         { X25_RR, "RR" },
152         { X25_RNR, "RNR" },
153         { X25_REJ, "REJ" },
154         { X25_DATA, "DATA" },
155         { 0,   NULL}
156 };
157
158 static dissector_handle_t ip_handle;
159 static dissector_handle_t ositp_handle;
160 static dissector_handle_t sna_handle;
161 static dissector_handle_t qllc_handle;
162 static dissector_handle_t data_handle;
163
164 /* Preferences */
165 static gboolean non_q_bit_is_sna = FALSE;
166
167 static dissector_table_t x25_subdissector_table;
168
169 /*
170  * each vc_info node contains :
171  *   the time of the first frame using this dissector (secs and usecs)
172  *   the time of the last frame using this dissector (0 if it is unknown)
173  *   a handle for the dissector
174  *
175  * the "time of first frame" is initialized when a Call Req. is received
176  * the "time of last frame" is initialized when a Clear, Reset, or Restart
177  * is received
178  */
179 typedef struct _vc_info {
180         guint32 first_frame_secs, first_frame_usecs;
181         guint32 last_frame_secs, last_frame_usecs;
182         dissector_handle_t dissect;
183         struct _vc_info *next;
184 } vc_info;
185
186 /*
187  * the hash table will contain linked lists of global_vc_info
188  * each global_vc_info struct contains :
189  *   the VC number (the hash table is indexed with VC % 64)
190  *   a linked list of vc_info
191  */
192 typedef struct _global_vc_info {
193         int vc_num;
194         vc_info *info;
195         struct _global_vc_info *next;
196 } global_vc_info;
197
198 static global_vc_info *hash_table[64];
199
200 static void
201 free_vc_info(vc_info *pt)
202 {
203   vc_info *vci = pt;
204
205   while (pt) {
206     vci = pt;
207     pt = pt->next;
208     g_free(vci);
209   }
210 }
211
212 static void
213 reinit_x25_hashtable(void)
214 {
215   int i;
216
217   for (i=0; i<64; i++) {
218     if (hash_table[i]) /* not NULL ==> free */
219     {
220       global_vc_info *hash_ent, *hash_ent2;
221       hash_ent2 = hash_ent = hash_table[i];
222       while (hash_ent)
223       {
224         hash_ent2 = hash_ent;
225         hash_ent = hash_ent->next;
226         free_vc_info(hash_ent2->info);
227         g_free(hash_ent2);
228       }
229       hash_table[i]=0;
230     }
231   }
232 }
233
234 static void
235 x25_hash_add_proto_start(guint16 vc, guint32 frame_secs, guint32 frame_usecs,
236                          dissector_handle_t dissect)
237 {
238   int idx = vc % 64;
239   global_vc_info *hash_ent;
240   global_vc_info *hash_ent2;
241
242   if (hash_table[idx] == 0)
243   {
244     hash_ent = (global_vc_info *)g_malloc(sizeof(global_vc_info));
245     if (!hash_ent) {
246       fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
247       exit(1);
248     }
249     hash_ent->vc_num = vc;
250     hash_ent->next=0;
251     hash_ent->info = (vc_info *)g_malloc(sizeof(vc_info));
252     if (!hash_ent->info) {
253       fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
254       exit(1);
255     }
256     hash_ent->info->first_frame_secs = frame_secs;
257     hash_ent->info->first_frame_usecs = frame_usecs;
258     hash_ent->info->last_frame_secs = 0;
259     hash_ent->info->last_frame_usecs = 0;
260     hash_ent->info->dissect = dissect;
261     hash_ent->info->next = 0;
262     hash_table[idx] = hash_ent;
263   }
264   else
265   {
266     hash_ent2 = hash_ent = hash_table[idx];
267     /* search an entry with the same VC number */
268     while (hash_ent != NULL && hash_ent->vc_num != vc) {
269       hash_ent2 = hash_ent;
270       hash_ent = hash_ent->next;
271     }
272     if (hash_ent != NULL) /* hash_ent->vc_num == vc */
273     {
274       vc_info *vci = hash_ent->info;
275       while (vci->next) vci = vci->next; /* last element */
276       if (vci->dissect == dissect) {
277         vci->last_frame_secs = 0;
278         vci->last_frame_usecs = 0;
279       }
280       else {
281         vci->next = (vc_info *)g_malloc(sizeof(vc_info));
282         if (vci->next == 0) {
283           fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
284           exit(1);
285         }
286         vci->next->first_frame_secs = frame_secs;
287         vci->next->first_frame_usecs = frame_usecs;
288         vci->next->last_frame_secs = 0;
289         vci->next->last_frame_usecs = 0;
290         vci->next->dissect = dissect;
291         vci->next->next = 0;
292       }
293     }
294     else /* new vc number */
295     {
296       hash_ent2->next = (global_vc_info *)g_malloc(sizeof(global_vc_info));
297       if (!hash_ent2->next) {
298         fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
299         exit(1);
300       }
301       hash_ent2->next->info = (vc_info *)g_malloc(sizeof(vc_info));
302       if (!hash_ent2->next->info) {
303         fprintf(stderr, "Could not allocate space for hash structure in dissect_x25\n");
304         exit(1);
305       }
306       hash_ent2->next->info->first_frame_secs = frame_secs;
307       hash_ent2->next->info->first_frame_usecs = frame_usecs;
308       hash_ent2->next->info->last_frame_secs = 0;
309       hash_ent2->next->info->last_frame_usecs = 0;
310       hash_ent2->next->info->dissect = dissect;
311       hash_ent2->next->info->next = 0;
312     }
313   }
314 }
315
316 static void
317 x25_hash_add_proto_end(guint16 vc, guint32 frame_secs, guint32 frame_usecs)
318 {
319   global_vc_info *hash_ent = hash_table[vc%64];
320   vc_info *vci;
321
322   if (!hash_ent) return;
323   while(hash_ent->vc_num != vc) hash_ent = hash_ent->next;
324   if (!hash_ent) return;
325
326   vci = hash_ent->info;
327   while (vci->next) vci = vci->next;
328   vci->last_frame_secs = frame_secs;
329   vci->last_frame_usecs = frame_usecs;
330 }
331
332 static dissector_handle_t
333 x25_hash_get_dissect(guint32 frame_secs, guint32 frame_usecs, guint16 vc)
334 {
335   global_vc_info *hash_ent = hash_table[vc%64];
336   vc_info *vci;
337   vc_info *vci2;
338
339   if (!hash_ent)
340     return NULL;
341
342   while (hash_ent && hash_ent->vc_num != vc)
343     hash_ent = hash_ent->next;
344   if (!hash_ent)
345     return NULL;
346
347   /* a hash_ent was found for this VC number */
348   vci2 = vci = hash_ent->info;
349
350   /* looking for an entry matching our frame time */
351   while (vci && (vci->last_frame_secs < frame_secs ||
352                  (vci->last_frame_secs == frame_secs &&
353                   vci->last_frame_usecs < frame_usecs))) {
354     vci2 = vci;
355     vci = vci->next;
356   }
357   /* we reached last record, and previous record has a non zero
358    * last frame time ==> no dissector */
359   if (!vci && (vci2->last_frame_secs || vci2->last_frame_usecs))
360     return NULL;
361
362   /* we reached last record, and previous record has a zero last frame time
363    * ==> dissector for previous frame has not been "stopped" by a Clear, etc */
364   if (!vci) {
365     /* if the start time for vci2 is greater than our frame time
366      * ==> no dissector */
367     if (frame_secs < vci2->first_frame_secs ||
368         (frame_secs == vci2->first_frame_secs &&
369          frame_usecs < vci2->first_frame_usecs))
370       return NULL;
371     else
372       return vci2->dissect;
373   }
374
375   /* our frame time is before vci's end. Check if it is after vci's start */
376   if (frame_secs < vci->first_frame_secs ||
377       (frame_secs == vci->first_frame_secs &&
378        frame_usecs < vci->first_frame_usecs))
379     return NULL;
380   else
381     return vci->dissect;
382 }
383
384 static char *clear_code(unsigned char code)
385 {
386     static char buffer[25];
387
388     if (code == 0x00 || (code & 0x80) == 0x80)
389         return "DTE Originated";
390     if (code == 0x01)
391         return "Number Busy";
392     if (code == 0x03)
393         return "Invalid Facility Requested";
394     if (code == 0x05)
395         return "Network Congestion";
396     if (code == 0x09)
397         return "Out Of Order";
398     if (code == 0x0B)
399         return "Access Barred";
400     if (code == 0x0D)
401         return "Not Obtainable";
402     if (code == 0x11)
403         return "Remote Procedure Error";
404     if (code == 0x13)
405         return "Local Procedure Error";
406     if (code == 0x15)
407         return "RPOA Out Of Order";
408     if (code == 0x19)
409         return "Reverse Charging Acceptance Not Subscribed";
410     if (code == 0x21)
411         return "Incompatible Destination";
412     if (code == 0x29)
413         return "Fast Select Acceptance Not Subscribed";
414     if (code == 0x39)
415         return "Destination Absent";
416
417     sprintf(buffer, "Unknown %02X", code);
418
419     return buffer;
420 }
421
422 static char *clear_diag(unsigned char code)
423 {
424     static char buffer[25];
425
426     if (code == 0)
427         return "No additional information";
428     if (code == 1)
429         return "Invalid P(S)";
430     if (code == 2)
431         return "Invalid P(R)";
432     if (code == 16)
433         return "Packet type invalid";
434     if (code == 17)
435         return "Packet type invalid for state r1";
436     if (code == 18)
437         return "Packet type invalid for state r2";
438     if (code == 19)
439         return "Packet type invalid for state r3";
440     if (code == 20)
441         return "Packet type invalid for state p1";
442     if (code == 21)
443         return "Packet type invalid for state p2";
444     if (code == 22)
445         return "Packet type invalid for state p3";
446     if (code == 23)
447         return "Packet type invalid for state p4";
448     if (code == 24)
449         return "Packet type invalid for state p5";
450     if (code == 25)
451         return "Packet type invalid for state p6";
452     if (code == 26)
453         return "Packet type invalid for state p7";
454     if (code == 27)
455         return "Packet type invalid for state d1";
456     if (code == 28)
457         return "Packet type invalid for state d2";
458     if (code == 29)
459         return "Packet type invalid for state d3";
460     if (code == 32)
461         return "Packet not allowed";
462     if (code == 33)
463         return "Unidentifiable packet";
464     if (code == 34)
465         return "Call on one-way logical channel";
466     if (code == 35)
467         return "Invalid packet type on a PVC";
468     if (code == 36)
469         return "Packet on unassigned LC";
470     if (code == 37)
471         return "Reject not subscribed to";
472     if (code == 38)
473         return "Packet too short";
474     if (code == 39)
475         return "Packet too long";
476     if (code == 40)
477         return "Invalid general format identifier";
478     if (code == 41)
479         return "Restart/registration packet with nonzero bits";
480     if (code == 42)
481         return "Packet type not compatible with facility";
482     if (code == 43)
483         return "Unauthorised interrupt confirmation";
484     if (code == 44)
485         return "Unauthorised interrupt";
486     if (code == 45)
487         return "Unauthorised reject";
488     if (code == 48)
489         return "Time expired";
490     if (code == 49)
491         return "Time expired for incoming call";
492     if (code == 50)
493         return "Time expired for clear indication";
494     if (code == 51)
495         return "Time expired for reset indication";
496     if (code == 52)
497         return "Time expired for restart indication";
498     if (code == 53)
499         return "Time expired for call deflection";
500     if (code == 64)
501         return "Call set-up/clearing or registration pb.";
502     if (code == 65)
503         return "Facility/registration code not allowed";
504     if (code == 66)
505         return "Facility parameter not allowed";
506     if (code == 67)
507         return "Invalid called DTE address";
508     if (code == 68)
509         return "Invalid calling DTE address";
510     if (code == 69)
511         return "Invalid facility/registration length";
512     if (code == 70)
513         return "Incoming call barred";
514     if (code == 71)
515         return "No logical channel available";
516     if (code == 72)
517         return "Call collision";
518     if (code == 73)
519         return "Duplicate facility requested";
520     if (code == 74)
521         return "Non zero address length";
522     if (code == 75)
523         return "Non zero facility length";
524     if (code == 76)
525         return "Facility not provided when expected";
526     if (code == 77)
527         return "Invalid CCITT-specified DTE facility";
528     if (code == 78)
529         return "Max. nb of call redir/defl. exceeded";
530     if (code == 80)
531         return "Miscellaneous";
532     if (code == 81)
533         return "Improper cause code from DTE";
534     if (code == 82)
535         return "Not aligned octet";
536     if (code == 83)
537         return "Inconsistent Q bit setting";
538     if (code == 84)
539         return "NUI problem";
540     if (code == 112)
541         return "International problem";
542     if (code == 113)
543         return "Remote network problem";
544     if (code == 114)
545         return "International protocol problem";
546     if (code == 115)
547         return "International link out of order";
548     if (code == 116)
549         return "International link busy";
550     if (code == 117)
551         return "Transit network facility problem";
552     if (code == 118)
553         return "Remote network facility problem";
554     if (code == 119)
555         return "International routing problem";
556     if (code == 120)
557         return "Temporary routing problem";
558     if (code == 121)
559         return "Unknown called DNIC";
560     if (code == 122)
561         return "Maintenance action";
562     if (code == 144)
563         return "Timer expired or retransmission count surpassed";
564     if (code == 145)
565         return "Timer expired or retransmission count surpassed for INTERRUPT";
566     if (code == 146)
567         return "Timer expired or retransmission count surpassed for DATA "
568                "packet transmission";
569     if (code == 147)
570         return "Timer expired or retransmission count surpassed for REJECT";
571     if (code == 160)
572         return "DTE-specific signals";
573     if (code == 161)
574         return "DTE operational";
575     if (code == 162)
576         return "DTE not operational";
577     if (code == 163)
578         return "DTE resource constraint";
579     if (code == 164)
580         return "Fast select not subscribed";
581     if (code == 165)
582         return "Invalid partially full DATA packet";
583     if (code == 166)
584         return "D-bit procedure not supported";
585     if (code == 167)
586         return "Registration/Cancellation confirmed";
587     if (code == 224)
588         return "OSI network service problem";
589     if (code == 225)
590         return "Disconnection (transient condition)";
591     if (code == 226)
592         return "Disconnection (permanent condition)";
593     if (code == 227)
594         return "Connection rejection - reason unspecified (transient "
595                "condition)";
596     if (code == 228)
597         return "Connection rejection - reason unspecified (permanent "
598                "condition)";
599     if (code == 229)
600         return "Connection rejection - quality of service not available "
601                "transient condition)";
602     if (code == 230)
603         return "Connection rejection - quality of service not available "
604                "permanent condition)";
605     if (code == 231)
606         return "Connection rejection - NSAP unreachable (transient condition)";
607     if (code == 232)
608         return "Connection rejection - NSAP unreachable (permanent condition)";
609     if (code == 233)
610         return "reset - reason unspecified";
611     if (code == 234)
612         return "reset - congestion";
613     if (code == 235)
614         return "Connection rejection - NSAP address unknown (permanent "
615                "condition)";
616     if (code == 240)
617         return "Higher layer initiated";
618     if (code == 241)
619         return "Disconnection - normal";
620     if (code == 242)
621         return "Disconnection - abnormal";
622     if (code == 243)
623         return "Disconnection - incompatible information in user data";
624     if (code == 244)
625         return "Connection rejection - reason unspecified (transient "
626                "condition)";
627     if (code == 245)
628         return "Connection rejection - reason unspecified (permanent "
629                "condition)";
630     if (code == 246)
631         return "Connection rejection - quality of service not available "
632                "(transient condition)";
633     if (code == 247)
634         return "Connection rejection - quality of service not available "
635                "(permanent condition)";
636     if (code == 248)
637         return "Connection rejection - incompatible information in user data";
638     if (code == 249)
639         return "Connection rejection - unrecognizable protocol indentifier "
640                "in user data";
641     if (code == 250)
642         return "Reset - user resynchronization";
643
644     sprintf(buffer, "Unknown %d", code);
645
646     return buffer;
647 }
648
649 static char *reset_code(unsigned char code)
650 {
651     static char buffer[25];
652
653     if (code == 0x00 || (code & 0x80) == 0x80)
654         return "DTE Originated";
655     if (code == 0x01)
656         return "Out of order";
657     if (code == 0x03)
658         return "Remote Procedure Error";
659     if (code == 0x05)
660         return "Local Procedure Error";
661     if (code == 0x07)
662         return "Network Congestion";
663     if (code == 0x09)
664         return "Remote DTE operational";
665     if (code == 0x0F)
666         return "Network operational";
667     if (code == 0x11)
668         return "Incompatible Destination";
669     if (code == 0x1D)
670         return "Network out of order";
671
672     sprintf(buffer, "Unknown %02X", code);
673
674     return buffer;
675 }
676
677 static char *restart_code(unsigned char code)
678 {
679     static char buffer[25];
680
681     if (code == 0x00 || (code & 0x80) == 0x80)
682         return "DTE Originated";
683     if (code == 0x01)
684         return "Local Procedure Error";
685     if (code == 0x03)
686         return "Network Congestion";
687     if (code == 0x07)
688         return "Network Operational";
689     if (code == 0x7F)
690         return "Registration/cancellation confirmed";
691
692     sprintf(buffer, "Unknown %02X", code);
693
694     return buffer;
695 }
696
697 static char *registration_code(unsigned char code)
698 {
699     static char buffer[25];
700
701     if (code == 0x03)
702         return "Invalid facility request";
703     if (code == 0x05)
704         return "Network congestion";
705     if (code == 0x13)
706         return "Local procedure error";
707     if (code == 0x7F)
708         return "Registration/cancellation confirmed";
709
710     sprintf(buffer, "Unknown %02X", code);
711
712     return buffer;
713 }
714
715 static void
716 dump_facilities(proto_tree *tree, int *offset, tvbuff_t *tvb)
717 {
718     guint8 fac, byte1, byte2, byte3;
719     guint32 len;      /* facilities length */
720     proto_item *ti=0;
721     proto_tree *fac_tree = 0;
722     proto_tree *fac_subtree;
723
724     len = tvb_get_guint8(tvb, *offset);
725     if (len && tree) {
726         ti = proto_tree_add_text(tree, tvb, *offset, len + 1,
727                                  "Facilities");
728         fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
729         proto_tree_add_text(fac_tree, tvb, *offset, 1,
730                             "Facilities length: %d", len);
731     }
732     (*offset)++;
733
734     while (len > 0) {
735         fac = tvb_get_guint8(tvb, *offset);
736         switch(fac & X25_FAC_CLASS_MASK) {
737         case X25_FAC_CLASS_A:
738             switch (fac) {
739             case X25_FAC_COMP_MARK:
740                 if (fac_tree)
741                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
742                             "Code : 00 (Marker)");
743                 switch (tvb_get_guint8(tvb, *offset + 1)) {
744                 case 0x00:
745                     if (fac_tree) {
746                         fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
747                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
748                                             "Parameter : 00 (Network complementary "
749                                             "services - calling DTE)");
750                     }
751                     break;
752                 case 0xFF:
753                     if (fac_tree) {
754                         fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
755                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
756                                             "Parameter : FF (Network complementary "
757                                             "services - called DTE)");
758                     }
759                     break;
760                 case 0x0F:
761                     if (fac_tree) {
762                         fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
763                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
764                                             "Parameter : 0F (DTE complementary "
765                                             "services)");
766                     }
767                     break;
768                 default:
769                     if (fac_tree) {
770                         fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
771                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
772                                             "Parameter : %02X (Unknown marker)",
773                                             tvb_get_guint8(tvb, *offset+1));
774                     }
775                     break;
776                 }
777                 break;
778             case X25_FAC_REVERSE:
779                 if (fac_tree) {
780                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
781                             "(Reverse charging / Fast select)", fac);
782                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
783                     byte1 = tvb_get_guint8(tvb, *offset + 1);
784                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
785                             "Parameter : %02X", byte1);
786                     if (byte1 & 0xC0)
787                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
788                                 "11.. .... = Fast select with restriction");
789                     else if (byte1 & 0x80)
790                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
791                                 "10.. .... = Fast select - no restriction");
792                     else
793                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
794                                 "00.. .... = Fast select not requested");
795                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
796                             decode_boolean_bitfield(byte1, 0x01, 1*8,
797                                 "Reverse charging requested",
798                                 "Reverse charging not requested"));
799                 }
800                 break;
801             case X25_FAC_THROUGHPUT:
802                 if (fac_tree) {
803                     char tmpbuf[80];
804
805                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
806                             "(Throughput class negociation)", fac);
807                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
808                     byte1 = tvb_get_guint8(tvb, *offset + 1);
809                     switch (byte1 >> 4)
810                     {
811                     case 3:
812                     case 4:
813                     case 5:
814                     case 6:
815                     case 7:
816                     case 8:
817                     case 9:
818                     case 10:
819                     case 11:
820                         sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
821                                 75*(1<<((byte1 >> 4)-3)));
822                         break;
823                     case 12:
824                         sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
825                         break;
826                     case 13:
827                         sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
828                         break;
829                     default:
830                         sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
831                     }
832                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
833                             decode_numeric_bitfield(byte1, 0xF0, 1*8, tmpbuf));
834                     switch (byte1 & 0x0F)
835                     {
836                     case 3:
837                     case 4:
838                     case 5:
839                     case 6:
840                     case 7:
841                     case 8:
842                     case 9:
843                     case 10:
844                     case 11:
845                         sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
846                                 75*(1<<((byte1 & 0x0F)-3)));
847                         break;
848                     case 12:
849                         sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
850                         break;
851                     case 13:
852                         sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
853                         break;
854                     default:
855                         sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
856                     }
857                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
858                             decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
859                 }
860                 break;
861             case X25_FAC_CUG:
862                 if (fac_tree) {
863                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
864                             "(Closed user group selection)", fac);
865                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
866                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
867                             "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
868                 }
869                 break;
870             case X25_FAC_CALLED_MODIF:
871                 if (fac_tree) {
872                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
873                             "(Called address modified)", fac);
874                     fac_subtree = proto_item_add_subtree(ti,
875                             ett_x25_fac_called_modif);
876                     proto_tree_add_text(fac_tree, tvb, *offset+1, 1,
877                             "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
878                 }
879                 break;
880             case X25_FAC_CUG_OUTGOING_ACC:
881                 if (fac_tree) {
882                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
883                             "(Closed user group with outgoing access selection)",
884                             fac);
885                     fac_subtree = proto_item_add_subtree(ti,
886                             ett_x25_fac_cug_outgoing_acc);
887                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
888                             "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
889                 }
890                 break;
891             case X25_FAC_THROUGHPUT_MIN:
892                 if (fac_tree) {
893                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
894                             "(Minimum throughput class)", fac);
895                     fac_subtree = proto_item_add_subtree(ti,
896                             ett_x25_fac_throughput_min);
897                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
898                             "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
899                 }
900                 break;
901             case X25_FAC_EXPRESS_DATA:
902                 if (fac_tree) {
903                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
904                             "(Negociation of express data)", fac);
905                     fac_subtree = proto_item_add_subtree(ti,
906                             ett_x25_fac_express_data);
907                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
908                             "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
909                 }
910                 break;
911             default:
912                 if (fac_tree) {
913                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
914                             "Code : %02X (Unknown class A)", fac);
915                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
916                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
917                             "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
918                 }
919                 break;
920             }
921             (*offset) += 2;
922             len -= 2;
923             break;
924         case X25_FAC_CLASS_B:
925             switch (fac) {
926             case X25_FAC_BILATERAL_CUG:
927                 if (fac_tree) {
928                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
929                             "(Bilateral closed user group selection)", fac);
930                     fac_subtree = proto_item_add_subtree(ti,
931                             ett_x25_fac_bilateral_cug);
932                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
933                                         "Bilateral CUG: %04X",
934                                         tvb_get_ntohs(tvb, *offset+1));
935                 }
936                 break;
937             case X25_FAC_PACKET_SIZE:
938                 if (fac_tree)
939                 {
940                     char tmpbuf[80];
941
942                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
943                             "(Packet size)", fac);
944                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
945                     byte1 = tvb_get_guint8(tvb, *offset + 1);
946                     switch (byte1)
947                     {
948                     case 0x04:
949                         sprintf(tmpbuf, "From the called DTE : %%u (16)");
950                         break;
951                     case 0x05:
952                         sprintf(tmpbuf, "From the called DTE : %%u (32)");
953                         break;
954                     case 0x06:
955                         sprintf(tmpbuf, "From the called DTE : %%u (64)");
956                         break;
957                     case 0x07:
958                         sprintf(tmpbuf, "From the called DTE : %%u (128)");
959                         break;
960                     case 0x08:
961                         sprintf(tmpbuf, "From the called DTE : %%u (256)");
962                         break;
963                     case 0x0D:
964                         sprintf(tmpbuf, "From the called DTE : %%u (512)");
965                         break;
966                     case 0x0C:
967                         sprintf(tmpbuf, "From the called DTE : %%u (1024)");
968                         break;
969                     case 0x0E:
970                         sprintf(tmpbuf, "From the called DTE : %%u (2048)");
971                         break;
972                     case 0x0F:
973                         sprintf(tmpbuf, "From the called DTE : %%u (4096)");
974                         break;
975                     default:
976                         sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
977                         break;
978                     }
979                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
980                             decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
981
982                     byte2 = tvb_get_guint8(tvb, *offset + 1);
983                     switch (byte2)
984                     {
985                     case 0x04:
986                         sprintf(tmpbuf, "From the calling DTE : %%u (16)");
987                         break;
988                     case 0x05:
989                         sprintf(tmpbuf, "From the calling DTE : %%u (32)");
990                         break;
991                     case 0x06:
992                         sprintf(tmpbuf, "From the calling DTE : %%u (64)");
993                         break;
994                     case 0x07:
995                         sprintf(tmpbuf, "From the calling DTE : %%u (128)");
996                         break;
997                     case 0x08:
998                         sprintf(tmpbuf, "From the calling DTE : %%u (256)");
999                         break;
1000                     case 0x0D:
1001                         sprintf(tmpbuf, "From the calling DTE : %%u (512)");
1002                         break;
1003                     case 0x0C:
1004                         sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
1005                         break;
1006                     case 0x0E:
1007                         sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
1008                         break;
1009                     case 0x0F:
1010                         sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
1011                         break;
1012                     default:
1013                         sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
1014                         break;
1015                     }
1016                     proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1017                             decode_numeric_bitfield(byte2, 0x0F, 1*8, tmpbuf));
1018                 }
1019                 break;
1020             case X25_FAC_WINDOW_SIZE:
1021                 if (fac_tree) {
1022                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1023                             "(Window size)", fac);
1024                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
1025                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1026                             decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+1),
1027                                 0x7F, 1*8, "From the called DTE: %u"));
1028                     proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1029                             decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+2),
1030                                 0x7F, 1*8, "From the calling DTE: %u"));
1031                 }
1032                 break;
1033             case X25_FAC_RPOA_SELECTION:
1034                 if (fac_tree) {
1035                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1036                             "(RPOA selection)", fac);
1037                     fac_subtree = proto_item_add_subtree(ti,
1038                             ett_x25_fac_rpoa_selection);
1039                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
1040                                         "Data network identification code : %04X",
1041                                         tvb_get_ntohs(tvb, *offset+1));
1042                 }
1043                 break;
1044             case X25_FAC_TRANSIT_DELAY:
1045                 if (fac_tree) {
1046                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1047                             "(Transit delay selection and indication)", fac);
1048                     fac_subtree = proto_item_add_subtree(ti,
1049                             ett_x25_fac_transit_delay);
1050                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
1051                                         "Transit delay: %d ms",
1052                                         tvb_get_ntohs(tvb, *offset+1));
1053                 }
1054                 break;
1055             default:
1056                 if (fac_tree) {
1057                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1058                             "Code : %02X (Unknown class B)", fac);
1059                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1060                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
1061                             "Parameter %04X", tvb_get_ntohs(tvb, *offset+1));
1062                 }
1063                 break;
1064             }
1065             (*offset) += 3;
1066             len -= 3;
1067             break;
1068         case X25_FAC_CLASS_C:
1069             if (fac_tree) {
1070                 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1071                         "Code : %02X (Unknown class C)", fac);
1072                 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1073                 proto_tree_add_text(fac_subtree, tvb, *offset+1, 3,
1074                         "Parameter %06X",
1075                         tvb_get_ntoh24(tvb, *offset+1));
1076             }
1077             (*offset) += 4;
1078             len -= 4;
1079             break;
1080         case X25_FAC_CLASS_D:
1081             switch (fac) {
1082             case X25_FAC_CALL_TRANSFER:
1083                 if (fac_tree) {
1084                     int i;
1085                     char tmpbuf[256];
1086
1087                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1088                             "(Call redirection or deflection notification)", fac);
1089                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
1090                     byte1 = tvb_get_guint8(tvb, *offset+1);
1091                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1092                             "Length : %u", byte1);
1093                     byte2 = tvb_get_guint8(tvb, *offset+2);
1094                     if ((byte2 & 0xC0) == 0xC0) {
1095                         proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1096                                 "Reason : call deflection by the originally "
1097                                 "called DTE address");
1098                     }
1099                     else {
1100                         switch (byte2) {
1101                         case 0x01:
1102                             proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1103                                     "Reason : originally called DTE busy");
1104                             break;
1105                         case 0x07:
1106                             proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1107                                     "Reason : call dist. within a hunt group");
1108                             break;
1109                         case 0x09:
1110                             proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1111                                     "Reason : originally called DTE out of order");
1112                             break;
1113                         case 0x0F:
1114                             proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1115                                     "Reason : systematic call redirection");
1116                             break;
1117                         default:
1118                             proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1119                                     "Reason : unknown");
1120                             break;
1121                         }
1122                     }
1123                     byte3 = tvb_get_guint8(tvb, *offset+3);
1124                     proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1125                             "Number of semi-octets in DTE address : %u",
1126                             byte3);
1127                     for (i = 0; i < byte3; i++) {
1128                         if (i % 2 == 0) {
1129                             tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1130                                     & 0x0F) + '0';
1131                             /* if > 9, convert to the right hexadecimal letter */
1132                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1133                         } else {
1134                             tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1135                                     & 0x0F) + '0';
1136                             /* if > 9, convert to the right hexadecimal letter */
1137                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1138                         }
1139                     }
1140                     tmpbuf[i] = 0;
1141                     proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1142                             "DTE address : %s", tmpbuf);
1143                 }
1144                 break;
1145             case X25_FAC_CALLING_ADDR_EXT:
1146                 if (fac_tree) {
1147                     int i;
1148                     char tmpbuf[256];
1149
1150                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1151                             "(Calling address extension)", fac);
1152                     fac_subtree = proto_item_add_subtree(ti,
1153                             ett_x25_fac_calling_addr_ext);
1154                     byte1 = tvb_get_guint8(tvb, *offset+1);
1155                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1156                             "Length : %u", byte1);
1157                     byte2 = tvb_get_guint8(tvb, *offset+2);
1158                     proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1159                             "Number of semi-octets in DTE address : %u", byte2);
1160                     for (i = 0; i < byte2; i++) {
1161                         if (i % 2 == 0) {
1162                             tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1163                                     & 0x0F) + '0';
1164                             /* if > 9, convert to the right hexadecimal letter */
1165                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1166                         } else {
1167                             tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1168                                     & 0x0F) + '0';
1169                             /* if > 9, convert to the right hexadecimal letter */
1170                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1171                         }
1172                     }
1173                     tmpbuf[i] = 0;
1174                     proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1175                             "DTE address : %s", tmpbuf);
1176                 }
1177                 break;
1178             case X25_FAC_CALLED_ADDR_EXT:
1179                 if (fac_tree) {
1180                     int i;
1181                     char tmpbuf[256];
1182
1183                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1184                             "(Called address extension)", fac);
1185                     fac_subtree = proto_item_add_subtree(ti,
1186                             ett_x25_fac_called_addr_ext);
1187                     byte1 = tvb_get_guint8(tvb, *offset+1);
1188                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1189                             "Length : %u", byte1);
1190                     byte2 = tvb_get_guint8(tvb, *offset+2);
1191                     proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1192                             "Number of semi-octets in DTE address : %u", byte2);
1193                     for (i = 0; i < byte2; i++) {
1194                         if (i % 2 == 0) {
1195                             tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1196                                     & 0x0F) + '0';
1197                             /* if > 9, convert to the right hexadecimal letter */
1198                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1199                         } else {
1200                             tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1201                                     & 0x0F) + '0';
1202                             /* if > 9, convert to the right hexadecimal letter */
1203                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1204                         }
1205                     }
1206                     tmpbuf[i] = 0;
1207                     proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1208                             "DTE address : %s", tmpbuf);
1209                 }
1210                 break;
1211             case X25_FAC_ETE_TRANSIT_DELAY:
1212                 if (fac_tree) {
1213                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1214                             "(End to end transit delay)", fac);
1215                     fac_subtree = proto_item_add_subtree(ti,
1216                             ett_x25_fac_ete_transit_delay);
1217                     byte1 = tvb_get_guint8(tvb, *offset+1);
1218                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1219                             "Length : %u", byte1);
1220                     proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1221                 }
1222                 break;
1223             case X25_FAC_CALL_DEFLECT:
1224                 if (fac_tree) {
1225                     int i;
1226                     char tmpbuf[256];
1227
1228                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1229                             "(Call deflection selection)", fac);
1230                     fac_subtree = proto_item_add_subtree(ti,
1231                             ett_x25_fac_call_deflect);
1232                     byte1 = tvb_get_guint8(tvb, *offset+1);
1233                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1234                             "Length : %u", byte1);
1235                     byte2 = tvb_get_guint8(tvb, *offset+2);
1236                     if ((byte2 & 0xC0) == 0xC0)
1237                         proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1238                                 "Reason : call DTE originated");
1239                     else
1240                         proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1241                                 "Reason : unknown");
1242                     byte3 = tvb_get_guint8(tvb, *offset+3);
1243                     proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1244                             "Number of semi-octets in the alternative DTE address : %u",
1245                             byte3);
1246                     for (i = 0; i < byte3; i++) {
1247                         if (i % 2 == 0) {
1248                             tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1249                                     & 0x0F) + '0';
1250                             /* if > 9, convert to the right hexadecimal letter */
1251                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1252                         } else {
1253                             tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1254                                     & 0x0F) + '0';
1255                             /* if > 9, convert to the right hexadecimal letter */
1256                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1257                         }
1258                     }
1259                     tmpbuf[i] = 0;
1260                     proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1261                             "Alternative DTE address : %s", tmpbuf);
1262                 }
1263                 break;
1264             case X25_FAC_PRIORITY:
1265                 if (fac_tree) {
1266                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1267                             "Code : %02X (Priority)", fac);
1268                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
1269                     byte1 = tvb_get_guint8(tvb, *offset+1);
1270                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1271                             "Length : %u", byte1);
1272                     proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1273                 }
1274                 break;
1275             default:
1276                 if (fac_tree) {
1277                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1278                             "Code : %02X (Unknown class D)", fac);
1279                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1280                     byte1 = tvb_get_guint8(tvb, *offset+1);
1281                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1282                             "Length : %u", byte1);
1283                     proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1284                 }
1285             }
1286             byte1 = tvb_get_guint8(tvb, *offset+1);
1287             (*offset) += byte1+2;
1288             len -= byte1+2;
1289             break;
1290         }
1291     }
1292 }
1293
1294 static void
1295 x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1296          frame_data *fd, gboolean toa)
1297 {
1298     int len1, len2;
1299     int i;
1300     char addr1[16], addr2[16];
1301     char *first, *second;
1302     guint8 byte;
1303     int localoffset;
1304
1305     byte = tvb_get_guint8(tvb, *offset);
1306     len1 = (byte >> 4) & 0x0F;
1307     len2 = (byte >> 0) & 0x0F;
1308     if (tree) {
1309         proto_tree_add_text(tree, tvb, *offset, 1,
1310                 decode_numeric_bitfield(byte, 0xF0, 1*8,
1311                     toa ? "Called address length : %u" :
1312                           "Calling address length : %u"));
1313         proto_tree_add_text(tree, tvb, *offset, 1,
1314                 decode_numeric_bitfield(byte, 0x0F, 1*8,
1315                     toa ? "Calling address length : %u" :
1316                           "Called address length : %u"));
1317     }
1318     (*offset)++;
1319
1320     localoffset = *offset;
1321     byte = tvb_get_guint8(tvb, localoffset);
1322
1323     first=addr1;
1324     second=addr2;
1325     for (i = 0; i < (len1 + len2); i++) {
1326         if (i < len1) {
1327             if (i % 2 != 0) {
1328                 *first++ = ((byte >> 0) & 0x0F) + '0';
1329                 localoffset++;
1330                 byte = tvb_get_guint8(tvb, localoffset);
1331             } else {
1332                 *first++ = ((byte >> 4) & 0x0F) + '0';
1333             }
1334         } else {
1335             if (i % 2 != 0) {
1336                 *second++ = ((byte >> 0) & 0x0F) + '0';
1337                 localoffset++;
1338                 byte = tvb_get_guint8(tvb, localoffset);
1339             } else {
1340                 *second++ = ((byte >> 4) & 0x0F) + '0';
1341             }
1342         }
1343     }
1344
1345     *first  = '\0';
1346     *second = '\0';
1347
1348     if (len1) {
1349         if (toa) {
1350             if (check_col(fd, COL_RES_DL_DST))
1351                 col_add_str(fd, COL_RES_DL_DST, addr1);
1352         }
1353         else {
1354             if(check_col(fd, COL_RES_DL_SRC))
1355                 col_add_str(fd, COL_RES_DL_SRC, addr1);
1356         }
1357         if (tree)
1358             proto_tree_add_text(tree, tvb, *offset,
1359                                 (len1 + 1) / 2,
1360                                 "%s address : %s",
1361                                 toa ? "Called" : "Calling",
1362                                 addr1);
1363     }
1364     if (len2) {
1365         if (toa) {
1366             if (check_col(fd, COL_RES_DL_SRC))
1367                 col_add_str(fd, COL_RES_DL_SRC, addr2);
1368         }
1369         else {
1370             if(check_col(fd, COL_RES_DL_DST))
1371                 col_add_str(fd, COL_RES_DL_DST, addr2);
1372         }
1373         if (tree)
1374             proto_tree_add_text(tree, tvb, *offset + len1/2,
1375                                 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1376                                 "%s address : %s",
1377                                 toa ? "Calling" : "Called",
1378                                 addr2);
1379     }
1380     (*offset) += ((len1 + len2 + 1) / 2);
1381 }
1382
1383 static int
1384 get_x25_pkt_len(tvbuff_t *tvb)
1385 {
1386     guint length, called_len, calling_len, dte_len, dce_len;
1387     guint8 byte2, bytex;
1388
1389     byte2 = tvb_get_guint8(tvb, 2);
1390     switch (byte2)
1391     {
1392     case X25_CALL_REQUEST:
1393         bytex = tvb_get_guint8(tvb, 3);
1394         called_len  = (bytex >> 0) & 0x0F;
1395         calling_len = (bytex >> 4) & 0x0F;
1396         length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1397         if (length < tvb_reported_length(tvb))
1398             length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1399
1400         return MIN(tvb_reported_length(tvb),length);
1401
1402     case X25_CALL_ACCEPTED:
1403         /* The calling/called address length byte (following the packet type)
1404          * is not mandatory, so we must check the packet length before trying
1405          * to read it */
1406         if (tvb_reported_length(tvb) == 3)
1407             return(3);
1408         bytex = tvb_get_guint8(tvb, 3);
1409         called_len  = (bytex >> 0) & 0x0F;
1410         calling_len = (bytex >> 4) & 0x0F;
1411         length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1412         if (length < tvb_reported_length(tvb))
1413             length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1414
1415         return MIN(tvb_reported_length(tvb),length);
1416
1417     case X25_CLEAR_REQUEST:
1418     case X25_RESET_REQUEST:
1419     case X25_RESTART_REQUEST:
1420         return MIN(tvb_reported_length(tvb),5);
1421
1422     case X25_DIAGNOSTIC:
1423         return MIN(tvb_reported_length(tvb),4);
1424
1425     case X25_CLEAR_CONFIRMATION:
1426     case X25_INTERRUPT:
1427     case X25_INTERRUPT_CONFIRMATION:
1428     case X25_RESET_CONFIRMATION:
1429     case X25_RESTART_CONFIRMATION:
1430         return MIN(tvb_reported_length(tvb),3);
1431
1432     case X25_REGISTRATION_REQUEST:
1433         bytex = tvb_get_guint8(tvb, 3);
1434         dce_len = (bytex >> 0) & 0x0F;
1435         dte_len = (bytex >> 4) & 0x0F;
1436         length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1437         if (length < tvb_reported_length(tvb))
1438             length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1439
1440         return MIN(tvb_reported_length(tvb),length);
1441
1442     case X25_REGISTRATION_CONFIRMATION:
1443         bytex = tvb_get_guint8(tvb, 5);
1444         dce_len = (bytex >> 0) & 0x0F;
1445         dte_len = (bytex >> 4) & 0x0F;
1446         length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1447         if (length < tvb_reported_length(tvb))
1448             length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1449
1450         return MIN(tvb_reported_length(tvb),length);
1451     }
1452
1453     if ((byte2 & 0x01) == X25_DATA) return MIN(tvb_reported_length(tvb),3);
1454
1455     switch (byte2 & 0x1F)
1456     {
1457     case X25_RR:
1458         return MIN(tvb_reported_length(tvb),3);
1459
1460     case X25_RNR:
1461         return MIN(tvb_reported_length(tvb),3);
1462
1463     case X25_REJ:
1464         return MIN(tvb_reported_length(tvb),3);
1465     }
1466
1467     return 0;
1468 }
1469
1470 static const value_string prt_id_vals[] = {
1471         {PRT_ID_ISO_8073,           "ISO 8073 COTP"},
1472         {PRT_ID_ISO_8602,           "ISO 8602 CLTP"},
1473         {PRT_ID_ISO_10736_ISO_8073, "ISO 10736 in conjunction with ISO 8073 COTP"},
1474         {PRT_ID_ISO_10736_ISO_8602, "ISO 10736 in conjunction with ISO 8602 CLTP"},
1475         {0x00,                      NULL}
1476 };
1477
1478 static const value_string sharing_strategy_vals[] = {
1479         {0x00,            "No sharing"},
1480         {0x00,            NULL}
1481 };
1482
1483 static void
1484 dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1485 {
1486     proto_tree *x25_tree=0, *gfi_tree=0, *userdata_tree=0;
1487     proto_item *ti;
1488     guint localoffset=0;
1489     guint x25_pkt_len;
1490     int modulo;
1491     guint16 vc;
1492     dissector_handle_t dissect;
1493     gboolean toa;         /* TOA/NPI address format */
1494     guint16 bytes0_1;
1495     guint8 pkt_type;
1496     tvbuff_t *next_tvb;
1497     gboolean q_bit_set = FALSE;
1498
1499     if (check_col(pinfo->fd, COL_PROTOCOL))
1500         col_set_str(pinfo->fd, COL_PROTOCOL, "X.25");
1501
1502     bytes0_1 = tvb_get_ntohs(tvb, 0);
1503
1504     modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
1505     vc     = (int)(bytes0_1 & 0x0FFF);
1506
1507     if (bytes0_1 & 0x8000) toa = TRUE;
1508     else toa = FALSE;
1509
1510     x25_pkt_len = get_x25_pkt_len(tvb);
1511     if (x25_pkt_len < 3) /* packet too short */
1512     {
1513         if (check_col(pinfo->fd, COL_INFO))
1514             col_set_str(pinfo->fd, COL_INFO, "Invalid/short X.25 packet");
1515         if (tree)
1516             proto_tree_add_protocol_format(tree, proto_x25, tvb, 0,
1517                     tvb_length(tvb), "Invalid/short X.25 packet");
1518         return;
1519     }
1520
1521     pkt_type = tvb_get_guint8(tvb, 2);
1522
1523     if (tree) {
1524         ti = proto_tree_add_item(tree, proto_x25, tvb, 0, x25_pkt_len, FALSE);
1525         x25_tree = proto_item_add_subtree(ti, ett_x25);
1526         ti = proto_tree_add_item(x25_tree, hf_x25_gfi, tvb, 0, 2, FALSE);
1527         gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
1528
1529         if ((pkt_type & 0x01) == X25_DATA) {
1530             proto_tree_add_boolean(gfi_tree, hf_x25_qbit, tvb, 0, 2,
1531                 bytes0_1);
1532             if (bytes0_1 & 0x8000) {
1533                 q_bit_set = TRUE;
1534             }
1535         }
1536         else if (pkt_type == X25_CALL_REQUEST ||
1537             pkt_type == X25_CALL_ACCEPTED ||
1538             pkt_type == X25_CLEAR_REQUEST ||
1539             pkt_type == X25_CLEAR_CONFIRMATION) {
1540             proto_tree_add_boolean(gfi_tree, hf_x25_abit, tvb, 0, 2,
1541                 bytes0_1);
1542         }
1543
1544         if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
1545             (pkt_type & 0x01) == X25_DATA) {
1546             proto_tree_add_boolean(gfi_tree, hf_x25_dbit, tvb, 0, 2,
1547                 bytes0_1);
1548         }
1549         proto_tree_add_uint(gfi_tree, hf_x25_mod, tvb, 0, 2, bytes0_1);
1550     }
1551
1552     switch (pkt_type) {
1553     case X25_CALL_REQUEST:
1554         if (check_col(pinfo->fd, COL_INFO))
1555             col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1556                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Inc. call"
1557                                                                  : "Call req." ,
1558                     vc);
1559         if (x25_tree) {
1560             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb,
1561                     0, 2, bytes0_1);
1562             proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1563                     X25_CALL_REQUEST,
1564                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Incoming call"
1565                                                                  : "Call request");
1566         }
1567         localoffset = 3;
1568         if (localoffset < x25_pkt_len) /* calling/called addresses */
1569             x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1570
1571         if (localoffset < x25_pkt_len) /* facilities */
1572             dump_facilities(x25_tree, &localoffset, tvb);
1573
1574         if (localoffset < tvb_reported_length(tvb)) /* user data */
1575         {
1576             guint8 spi;
1577             int is_x_264;
1578             guint8 prt_id;
1579
1580             if (x25_tree) {
1581                 ti = proto_tree_add_text(x25_tree, tvb, localoffset,
1582                         tvb_length_remaining(tvb, localoffset),
1583                         "User data");
1584                 userdata_tree = proto_item_add_subtree(ti, ett_x25_user_data);
1585             }
1586
1587             /* X.263/ISO 9577 says that:
1588
1589                     When CLNP or ESIS are run over X.25, the SPI
1590                     is 0x81 or 0x82, respectively; those are the
1591                     NLPIDs for those protocol.
1592
1593                     When X.224/ISO 8073 COTP is run over X.25, and
1594                     when ISO 11570 explicit identification is being
1595                     used, the first octet of the user data field is
1596                     a TPDU length field, and the rest is "as defined
1597                     in ITU-T Rec. X.225 | ISO/IEC 8073, Annex B,
1598                     or ITU-T Rec. X.264 and ISO/IEC 11570".
1599
1600                     When X.264/ISO 11570 default identification is
1601                     being used, there is no user data field in the
1602                     CALL REQUEST packet.  This is for X.225/ISO 8073
1603                     COTP.
1604
1605                It also says that SPI values from 0x03 through 0x3f are
1606                reserved and are in use by X.224/ISO 8073 Annex B and
1607                X.264/ISO 11570.  The note says that those values are
1608                not NLPIDs, they're "used by the respective higher layer
1609                protocol" and "not used for higher layer protocol
1610                identification".  I infer from this and from what
1611                X.264/ISO 11570 says that this means that values in those
1612                range are valid values for the first octet of an
1613                X.224/ISO 8073 packet or for X.264/ISO 11570.
1614
1615                Annex B of X.225/ISO 8073 mentions some additional TPDU
1616                types that can be put in what I presume is the user
1617                data of connect requests.  It says that:
1618
1619                     The sending transport entity shall:
1620
1621                         a) either not transmit any TPDU in the NS-user data
1622                            parameter of the N-CONNECT request primitive; or
1623
1624                         b) transmit the UN-TPDU (see ITU-T Rec. X.264 and
1625                            ISO/IEC 11570) followed by the NCM-TPDU in the
1626                            NS-user data parameter of the N-CONNECT request
1627                            primitive.
1628
1629                I don't know if this means that the user data field
1630                will contain a UN TPDU followed by an NCM TPDU or not.
1631
1632                X.264/ISO 11570 says that:
1633
1634                     When default identification is being used,
1635                     X.225/ISO 8073 COTP is identified.  No user data
1636                     is sent in the network-layer connection request.
1637
1638                     When explicit identification is being used,
1639                     the user data is a UN TPDU ("Use of network
1640                     connection TPDU"), which specifies the transport
1641                     protocol to use over this network connection.
1642                     It also says that the length of a UN TPDU shall
1643                     not exceed 32 octets, i.e. shall not exceed 0x20;
1644                     it says this is "due to the desire not to conflict
1645                     with the protocol identifier field carried by X.25
1646                     CALL REQUEST/INCOMING CALL packets", and says that
1647                     field has values specified in X.244.  X.244 has been
1648                     superseded by X.263/ISO 9577, so that presumably
1649                     means the goal is to allow a UN TPDU's length
1650                     field to be distinguished from an NLPID, allowing
1651                     you to tell whether X.264/ISO 11570 explicit
1652                     identification is being used or an NLPID is
1653                     being used as the SPI.
1654
1655                I read this as meaning that, if the ISO mechanisms are
1656                used to identify the protocol being carried over X.25:
1657
1658                     if there's no user data in the CALL REQUEST/
1659                     INCOMING CALL packet, it's COTP;
1660
1661                     if there is user data, then:
1662
1663                         if the first octet is less than or equal to
1664                         32, it might be a UN TPDU, and that identifies
1665                         the transport protocol being used, and
1666                         it may be followed by more data, such
1667                         as a COTP NCM TPDU if it's COTP;
1668
1669                         if the first octet is greater than 32, it's
1670                         an NLPID, *not* a TPDU length, and the
1671                         stuff following it is *not* a TPDU.
1672
1673                Figure A.2 of X.263/ISO 9577 seems to say that the
1674                first octet of the user data is a TPDU length field,
1675                in the range 0x03 through 0x82, and says they are
1676                for X.225/ISO 8073 Annex B or X.264/ISO 11570.
1677
1678                However, X.264/ISO 11570 seems to imply that the length
1679                field would be that of a UN TPDU, which must be less
1680                than or equal to 0x20, and X.225/ISO 8073 Annex B seems
1681                to indicate that the user data must begin with
1682                an X.264/ISO 11570 UN TPDU, so I'd say that A.2 should
1683                have said "in the range 0x03 through 0x20", instead
1684                (the length value doesn't include the length field,
1685                and the minimum UN TPDU has length, type, PRT-ID,
1686                and SHARE, so that's 3 bytes without the length). */
1687             spi = tvb_get_guint8(tvb, localoffset);
1688             if (spi > 32 || spi < 3) {
1689                 /* First octet is > 32, or < 3, so the user data isn't an
1690                    X.264/ISO 11570 UN TPDU */
1691                 is_x_264 = FALSE;
1692             } else {
1693                 /* First octet is >= 3 and <= 32, so the user data *might*
1694                    be an X.264/ISO 11570 UN TPDU.  Check whether we have
1695                    enough data to see if it is. */
1696                 if (tvb_bytes_exist(tvb, localoffset+1, 1)) {
1697                     /* We do; check whether the second octet is 1. */
1698                     if (tvb_get_guint8(tvb, localoffset+1) == 0x01) {
1699                         /* Yes, the second byte is 1, so it looks like
1700                            a UN TPDU. */
1701                         is_x_264 = TRUE;
1702                     } else {
1703                         /* No, the second byte is not 1, so it's not a
1704                            UN TPDU. */
1705                         is_x_264 = FALSE;
1706                     }
1707                 } else {
1708                     /* We can't see the second byte of the putative UN
1709                        TPDU, so we don't know if that's what it is. */
1710                     is_x_264 = -1;
1711                 }
1712             }
1713             if (is_x_264 == -1) {
1714                 /*
1715                  * We don't know what it is; just skip it.
1716                  */
1717                 localoffset = tvb_length(tvb);
1718             } else if (is_x_264) {
1719                 /* It looks like an X.264 UN TPDU, so show it as such. */
1720                 if (userdata_tree) {
1721                     proto_tree_add_text(userdata_tree, tvb, localoffset, 1,
1722                                         "X.264 length indicator: %u",
1723                                         spi);
1724                     proto_tree_add_text(userdata_tree, tvb, localoffset+1, 1,
1725                                         "X.264 UN TPDU identifier: 0x%02X",
1726                                         tvb_get_guint8(tvb, localoffset+1));
1727                 }
1728                 prt_id = tvb_get_guint8(tvb, localoffset+2);
1729                 if (userdata_tree) {
1730                     proto_tree_add_text(x25_tree, tvb, localoffset+2, 1,
1731                                         "X.264 protocol identifier: %s",
1732                                         val_to_str(prt_id, prt_id_vals,
1733                                                "Unknown (0x%02X)"));
1734                     proto_tree_add_text(x25_tree, tvb, localoffset+3, 1,
1735                                         "X.264 sharing strategy: %s",
1736                                         val_to_str(tvb_get_guint8(tvb, localoffset+3),
1737                                         sharing_strategy_vals, "Unknown (0x%02X)"));
1738                 }
1739
1740                 /* XXX - dissect the variable part? */
1741
1742                 /* The length doesn't include the length octet itself. */
1743                 localoffset += spi + 1;
1744
1745                 switch (prt_id) {
1746
1747                 case PRT_ID_ISO_8073:
1748                     /* ISO 8073 COTP */
1749                     x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1750                                              pinfo->fd->abs_usecs,
1751                                              ositp_handle);
1752                     /* XXX - disssect the rest of the user data as COTP?
1753                        That needs support for NCM TPDUs, etc. */
1754                     break;
1755
1756                 case PRT_ID_ISO_8602:
1757                     /* ISO 8602 CLTP */
1758                     x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1759                                              pinfo->fd->abs_usecs,
1760                                              ositp_handle);
1761                     break;
1762                 }
1763             } else if (is_x_264 == 0) {
1764                 /* It doesn't look like a UN TPDU, so compare the first
1765                    octet of the CALL REQUEST packet with various X.263/
1766                    ISO 9577 NLPIDs, as per Annex A of X.263/ISO 9577. */ 
1767
1768                 if (userdata_tree) {
1769                     proto_tree_add_text(userdata_tree, tvb, localoffset, 1,
1770                                         "X.263 secondary protocol ID: %s",
1771                                         val_to_str(spi, nlpid_vals, "Unknown (0x%02x)"));
1772                 }
1773                 localoffset++;
1774                 
1775                 /*
1776                  * What's the dissector handle for this SPI?
1777                  */
1778                 dissect = dissector_get_port_handle(x25_subdissector_table, spi);
1779                 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1780                                          pinfo->fd->abs_usecs, dissect);
1781             }
1782             if (localoffset < tvb_length(tvb)) {
1783                 if (userdata_tree) {
1784                     proto_tree_add_text(userdata_tree, tvb, localoffset,
1785                                 tvb_length(tvb)-localoffset, "Data");
1786                 }
1787                 localoffset = tvb_length(tvb);
1788             }
1789         }
1790         break;
1791     case X25_CALL_ACCEPTED:
1792         if(check_col(pinfo->fd, COL_INFO))
1793             col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1794                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call conn."
1795                                                                  : "Call acc." ,
1796                     vc);
1797         if (x25_tree) {
1798             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1799             proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1800                     X25_CALL_ACCEPTED,
1801                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call connected"
1802                                                                  : "Call accepted");
1803         }
1804         localoffset = 3;
1805         if (localoffset < x25_pkt_len) /* calling/called addresses */
1806             x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1807
1808         if (localoffset < x25_pkt_len) /* facilities */
1809             dump_facilities(x25_tree, &localoffset, tvb);
1810
1811         if (localoffset < tvb_reported_length(tvb)) { /* user data */
1812             if (x25_tree)
1813                 proto_tree_add_text(x25_tree, tvb, localoffset,
1814                                     tvb_reported_length(tvb)-localoffset, "Data");
1815             localoffset=tvb_reported_length(tvb);
1816         }
1817         break;
1818     case X25_CLEAR_REQUEST:
1819         if(check_col(pinfo->fd, COL_INFO)) {
1820             col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - %s",
1821                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear ind."
1822                                                                  : "Clear req." ,
1823                     vc, clear_code(tvb_get_guint8(tvb, 3)),
1824                     clear_diag(tvb_get_guint8(tvb, 4)));
1825         }
1826         x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1827         if (x25_tree) {
1828             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1829             proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb,
1830                     localoffset+2, 1, X25_CLEAR_REQUEST,
1831                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear indication"
1832                                                                  : "Clear request");
1833             proto_tree_add_text(x25_tree, tvb, 3, 1,
1834                     "Cause : %s", clear_code(tvb_get_guint8(tvb, 3)));
1835             proto_tree_add_text(x25_tree, tvb, 4, 1,
1836                     "Diagnostic : %s", clear_diag(tvb_get_guint8(tvb, 4)));
1837         }
1838         localoffset = x25_pkt_len;
1839         break;
1840     case X25_CLEAR_CONFIRMATION:
1841         if(check_col(pinfo->fd, COL_INFO))
1842             col_add_fstr(pinfo->fd, COL_INFO, "Clear Conf. VC:%d", vc);
1843         if (x25_tree) {
1844             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1845             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1846                     X25_CLEAR_CONFIRMATION);
1847         }
1848         localoffset = x25_pkt_len;
1849
1850         if (localoffset < tvb_reported_length(tvb)) /* extended clear conf format */
1851             x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1852
1853         if (localoffset < tvb_reported_length(tvb)) /* facilities */
1854             dump_facilities(x25_tree, &localoffset, tvb);
1855         break;
1856     case X25_DIAGNOSTIC:
1857         if(check_col(pinfo->fd, COL_INFO)) {
1858             col_add_fstr(pinfo->fd, COL_INFO, "Diag. %d",
1859                     (int)tvb_get_guint8(tvb, 3));
1860         }
1861         if (x25_tree) {
1862             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1863                     X25_DIAGNOSTIC);
1864             proto_tree_add_text(x25_tree, tvb, 3, 1,
1865                     "Diagnostic : %d", (int)tvb_get_guint8(tvb, 3));
1866         }
1867         localoffset = x25_pkt_len;
1868         break;
1869     case X25_INTERRUPT:
1870         if(check_col(pinfo->fd, COL_INFO))
1871             col_add_fstr(pinfo->fd, COL_INFO, "Interrupt VC:%d", vc);
1872         if (x25_tree) {
1873             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1874             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1875                     X25_INTERRUPT);
1876         }
1877         localoffset = x25_pkt_len;
1878         break;
1879     case X25_INTERRUPT_CONFIRMATION:
1880         if(check_col(pinfo->fd, COL_INFO))
1881             col_add_fstr(pinfo->fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
1882         if (x25_tree) {
1883             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1884             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1885                     X25_INTERRUPT_CONFIRMATION);
1886         }
1887         localoffset = x25_pkt_len;
1888         break;
1889     case X25_RESET_REQUEST:
1890         if(check_col(pinfo->fd, COL_INFO)) {
1891             col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
1892                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset ind."
1893                                                                  : "Reset req.",
1894                     vc, reset_code(tvb_get_guint8(tvb, 3)),
1895                     (int)tvb_get_guint8(tvb, 4));
1896         }
1897         x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1898         if (x25_tree) {
1899             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1900             proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1901                     X25_RESET_REQUEST,
1902                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset indication"
1903                                                                  : "Reset request");
1904             proto_tree_add_text(x25_tree, tvb, 3, 1,
1905                     "Cause : %s", reset_code(tvb_get_guint8(tvb, 3)));
1906             proto_tree_add_text(x25_tree, tvb, 4, 1,
1907                     "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1908         }
1909         localoffset = x25_pkt_len;
1910         break;
1911     case X25_RESET_CONFIRMATION:
1912         if(check_col(pinfo->fd, COL_INFO))
1913             col_add_fstr(pinfo->fd, COL_INFO, "Reset conf. VC:%d", vc);
1914         if (x25_tree) {
1915             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1916             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1917                     X25_RESET_CONFIRMATION);
1918         }
1919         localoffset = x25_pkt_len;
1920         break;
1921     case X25_RESTART_REQUEST:
1922         if(check_col(pinfo->fd, COL_INFO)) {
1923             col_add_fstr(pinfo->fd, COL_INFO, "%s %s - Diag.:%d",
1924                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart ind."
1925                                                                  : "Restart req.",
1926                     restart_code(tvb_get_guint8(tvb, 3)),
1927                     (int)tvb_get_guint8(tvb, 3));
1928         }
1929         if (x25_tree) {
1930             proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1931                     X25_RESTART_REQUEST,
1932                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart indication"
1933                                                                  : "Restart request");
1934             proto_tree_add_text(x25_tree, tvb, 3, 1,
1935                     "Cause : %s", restart_code(tvb_get_guint8(tvb, 3)));
1936             proto_tree_add_text(x25_tree, tvb, 4, 1,
1937                     "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1938         }
1939         localoffset = x25_pkt_len;
1940         break;
1941     case X25_RESTART_CONFIRMATION:
1942         if(check_col(pinfo->fd, COL_INFO))
1943             col_set_str(pinfo->fd, COL_INFO, "Restart conf.");
1944         if (x25_tree)
1945             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1946                     X25_RESTART_CONFIRMATION);
1947         localoffset = x25_pkt_len;
1948         break;
1949     case X25_REGISTRATION_REQUEST:
1950         if(check_col(pinfo->fd, COL_INFO))
1951             col_set_str(pinfo->fd, COL_INFO, "Registration req.");
1952         if (x25_tree)
1953             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1954                     X25_REGISTRATION_REQUEST);
1955         localoffset = 3;
1956         if (localoffset < x25_pkt_len)
1957             x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, FALSE);
1958
1959         if (x25_tree) {
1960             if (localoffset < x25_pkt_len)
1961                 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1962                         "Registration length: %d",
1963                         tvb_get_guint8(tvb, localoffset) & 0x7F);
1964             if (localoffset+1 < x25_pkt_len)
1965                 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1966                         tvb_get_guint8(tvb, localoffset) & 0x7F,
1967                         "Registration");
1968         }
1969         localoffset = tvb_reported_length(tvb);
1970         break;
1971     case X25_REGISTRATION_CONFIRMATION:
1972         if(check_col(pinfo->fd, COL_INFO))
1973             col_set_str(pinfo->fd, COL_INFO, "Registration conf.");
1974         if (x25_tree) {
1975             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1976                     X25_REGISTRATION_CONFIRMATION);
1977             proto_tree_add_text(x25_tree, tvb, 3, 1,
1978                     "Cause: %s", registration_code(tvb_get_guint8(tvb, 3)));
1979             proto_tree_add_text(x25_tree, tvb, 4, 1,
1980                     "Diagnostic: %s", registration_code(tvb_get_guint8(tvb, 4)));
1981         }
1982         localoffset = 5;
1983         if (localoffset < x25_pkt_len)
1984             x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, TRUE);
1985
1986         if (x25_tree) {
1987             if (localoffset < x25_pkt_len)
1988                 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1989                         "Registration length: %d",
1990                         tvb_get_guint8(tvb, localoffset) & 0x7F);
1991             if (localoffset+1 < x25_pkt_len)
1992                 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1993                         tvb_get_guint8(tvb, localoffset) & 0x7F,
1994                         "Registration");
1995         }
1996         localoffset = tvb_reported_length(tvb);
1997         break;
1998     default :
1999         localoffset = 2;
2000         if ((pkt_type & 0x01) == X25_DATA)
2001         {
2002             if(check_col(pinfo->fd, COL_INFO)) {
2003                 if (modulo == 8)
2004                     col_add_fstr(pinfo->fd, COL_INFO,
2005                             "Data VC:%d P(S):%d P(R):%d %s", vc,
2006                             (pkt_type >> 1) & 0x07,
2007                             (pkt_type >> 5) & 0x07,
2008                             ((pkt_type >> 4) & 0x01) ? " M" : "");
2009                 else
2010                     col_add_fstr(pinfo->fd, COL_INFO,
2011                             "Data VC:%d P(S):%d P(R):%d %s", vc,
2012                             tvb_get_guint8(tvb, localoffset+1) >> 1,
2013                             pkt_type >> 1,
2014                             (tvb_get_guint8(tvb, localoffset+1) & 0x01) ? " M" : "");
2015             }
2016             if (x25_tree) {
2017                 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
2018                         2, bytes0_1);
2019                 proto_tree_add_uint_hidden(x25_tree, hf_x25_type, tvb,
2020                         localoffset, 1, X25_DATA);
2021                 if (modulo == 8) {
2022                     proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
2023                             localoffset, 1, pkt_type);
2024                     if (pkt_type & 0x10)
2025                         proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod8, tvb,
2026                             localoffset, 1, pkt_type);
2027                     proto_tree_add_uint(x25_tree, hf_x25_p_s_mod8, tvb,
2028                             localoffset, 1, pkt_type);
2029                     proto_tree_add_text(x25_tree, tvb, localoffset, 1,
2030                             decode_boolean_bitfield(pkt_type, 0x01, 1*8,
2031                                 NULL, "DATA"));
2032                 }
2033                 else {
2034                     proto_tree_add_uint(x25_tree, hf_x25_p_r_mod128, tvb,
2035                             localoffset, 1, pkt_type);
2036                     proto_tree_add_uint(x25_tree, hf_x25_p_s_mod128, tvb,
2037                             localoffset+1, 1,
2038                             tvb_get_guint8(tvb, localoffset+1));
2039                     if (tvb_get_guint8(tvb, localoffset+1) & 0x01)
2040                         proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod128, tvb,
2041                                 localoffset+1, 1,
2042                                 tvb_get_guint8(tvb, localoffset+1));
2043                 }
2044             }
2045             localoffset += (modulo == 8) ? 1 : 2;
2046             break;
2047         }
2048         switch (pkt_type & 0x1F)
2049         {
2050         case X25_RR:
2051             if(check_col(pinfo->fd, COL_INFO)) {
2052                 if (modulo == 8)
2053                     col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
2054                             vc, (pkt_type >> 5) & 0x07);
2055                 else
2056                     col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
2057                             vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
2058             }
2059             if (x25_tree) {
2060                 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
2061                         2, bytes0_1);
2062                 if (modulo == 8) {
2063                     proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
2064                             localoffset, 1, pkt_type);
2065                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2066                             localoffset, 1, X25_RR);
2067                 }
2068                 else {
2069                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2070                             localoffset, 1, X25_RR);
2071                     proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
2072                             localoffset+1, 1, FALSE);
2073                 }
2074             }
2075             break;
2076
2077         case X25_RNR:
2078             if(check_col(pinfo->fd, COL_INFO)) {
2079                 if (modulo == 8)
2080                     col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
2081                             vc, (pkt_type >> 5) & 0x07);
2082                 else
2083                     col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
2084                             vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
2085             }
2086             if (x25_tree) {
2087                 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
2088                         2, bytes0_1);
2089                 if (modulo == 8) {
2090                     proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
2091                             localoffset, 1, pkt_type);
2092                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2093                             localoffset, 1, X25_RNR);
2094                 }
2095                 else {
2096                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2097                             localoffset, 1, X25_RNR);
2098                     proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
2099                             localoffset+1, 1, FALSE);
2100                 }
2101             }
2102             break;
2103
2104         case X25_REJ:
2105             if(check_col(pinfo->fd, COL_INFO)) {
2106                 if (modulo == 8)
2107                     col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
2108                             vc, (pkt_type >> 5) & 0x07);
2109                 else
2110                     col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
2111                             vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
2112             }
2113             if (x25_tree) {
2114                 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
2115                         2, bytes0_1);
2116                 if (modulo == 8) {
2117                     proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
2118                             localoffset, 1, pkt_type);
2119                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2120                             localoffset, 1, X25_REJ);
2121                 }
2122                 else {
2123                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
2124                             localoffset, 1, X25_REJ);
2125                     proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
2126                             localoffset+1, 1, FALSE);
2127                 }
2128             }
2129         }
2130         localoffset += (modulo == 8) ? 1 : 2;
2131     }
2132
2133     if (localoffset >= tvb_reported_length(tvb)) return;
2134
2135     next_tvb = tvb_new_subset(tvb, localoffset, -1, -1);
2136
2137     /* QLLC ? */
2138     if (q_bit_set) {
2139         call_dissector(qllc_handle, next_tvb, pinfo, tree);
2140         return;
2141     }
2142
2143     /* search the dissector in the hash table */
2144     if ((dissect = x25_hash_get_dissect(pinfo->fd->abs_secs, pinfo->fd->abs_usecs, vc))) {
2145         call_dissector(dissect, next_tvb, pinfo, tree);
2146     }
2147     else {
2148         /* Did the user suggest SNA-over-X.25? */
2149         if (non_q_bit_is_sna) {
2150             x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
2151                                      pinfo->fd->abs_usecs, sna_handle);
2152             call_dissector(sna_handle, next_tvb, pinfo, tree);
2153         }
2154         /* If the Call Req. has not been captured, and the payload begins
2155            with what appears to be an IP header, assume these packets carry
2156            IP */
2157         else if (tvb_get_guint8(tvb, localoffset) == 0x45) {
2158             x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
2159                                      pinfo->fd->abs_usecs, ip_handle);
2160             call_dissector(ip_handle, next_tvb, pinfo, tree);
2161         }
2162         else {
2163             call_dissector(data_handle,next_tvb, pinfo, tree);
2164         }
2165     }
2166 }
2167
2168 void
2169 proto_register_x25(void)
2170 {
2171     static hf_register_info hf[] = {
2172         { &hf_x25_gfi,
2173           { "GFI", "x.25.gfi", FT_UINT16, BASE_BIN, NULL, 0xF000,
2174                 "General format identifier", HFILL }},
2175         { &hf_x25_abit,
2176           { "A Bit", "x.25.a", FT_BOOLEAN, 16, NULL, 0x8000,
2177                 "Address Bit", HFILL }},
2178         { &hf_x25_qbit,
2179           { "Q Bit", "x.25.q", FT_BOOLEAN, 16, NULL, 0x8000,
2180                 "Qualifier Bit", HFILL }},
2181         { &hf_x25_dbit,
2182           { "D Bit", "x.25.d", FT_BOOLEAN, 16, NULL, 0x4000,
2183                 "Delivery Confirmation Bit", HFILL }},
2184         { &hf_x25_mod,
2185           { "Modulo", "x.25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
2186                 "Specifies whether the frame is modulo 8 or 128", HFILL }},
2187         { &hf_x25_lcn,
2188           { "Logical Channel", "x.25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
2189                 "Logical Channel Number", HFILL }},
2190         { &hf_x25_type,
2191           { "Packet Type", "x.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
2192                 "Packet Type", HFILL }},
2193         { &hf_x25_p_r_mod8,
2194           { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
2195                 "Packet Receive Sequence Number", HFILL }},
2196         { &hf_x25_p_r_mod128,
2197           { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
2198                 "Packet Receive Sequence Number", HFILL }},
2199         { &hf_x25_mbit_mod8,
2200           { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x10,
2201                 "More Bit", HFILL }},
2202         { &hf_x25_mbit_mod128,
2203           { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x01,
2204                 "More Bit", HFILL }},
2205         { &hf_x25_p_s_mod8,
2206           { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
2207                 "Packet Send Sequence Number", HFILL }},
2208         { &hf_x25_p_s_mod128,
2209           { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
2210                 "Packet Send Sequence Number", HFILL }},
2211     };
2212     static gint *ett[] = {
2213         &ett_x25,
2214         &ett_x25_gfi,
2215         &ett_x25_fac,
2216         &ett_x25_fac_unknown,
2217         &ett_x25_fac_mark,
2218         &ett_x25_fac_reverse,
2219         &ett_x25_fac_throughput,
2220         &ett_x25_fac_cug,
2221         &ett_x25_fac_called_modif,
2222         &ett_x25_fac_cug_outgoing_acc,
2223         &ett_x25_fac_throughput_min,
2224         &ett_x25_fac_express_data,
2225         &ett_x25_fac_bilateral_cug,
2226         &ett_x25_fac_packet_size,
2227         &ett_x25_fac_window_size,
2228         &ett_x25_fac_rpoa_selection,
2229         &ett_x25_fac_transit_delay,
2230         &ett_x25_fac_call_transfer,
2231         &ett_x25_fac_called_addr_ext,
2232         &ett_x25_fac_ete_transit_delay,
2233         &ett_x25_fac_calling_addr_ext,
2234         &ett_x25_fac_call_deflect,
2235         &ett_x25_fac_priority,
2236         &ett_x25_user_data
2237     };
2238     module_t *x25_module;
2239
2240     proto_x25 = proto_register_protocol ("X.25", "X.25", "x.25");
2241     proto_register_field_array (proto_x25, hf, array_length(hf));
2242     proto_register_subtree_array(ett, array_length(ett));
2243     register_init_routine(&reinit_x25_hashtable);
2244
2245     x25_subdissector_table = register_dissector_table("x.25.spi");
2246
2247     register_dissector("x.25", dissect_x25, proto_x25);
2248
2249     /* Preferences */
2250     x25_module = prefs_register_protocol(proto_x25, NULL);
2251     prefs_register_bool_preference(x25_module, "non_q_bit_is_sna",
2252             "When Q-bit is 0, payload is SNA", "When Q-bit is 0, payload is SNA",
2253             &non_q_bit_is_sna);
2254 }
2255
2256 void
2257 proto_reg_handoff_x25(void)
2258 {
2259     dissector_handle_t x25_handle;
2260
2261     /*
2262      * Get handles for various dissectors.
2263      */
2264     ip_handle = find_dissector("ip");
2265     ositp_handle = find_dissector("ositp");
2266     sna_handle = find_dissector("sna");
2267     qllc_handle = find_dissector("qllc");
2268     data_handle = find_dissector("data");
2269
2270     x25_handle = find_dissector("x.25");
2271     dissector_add("llc.dsap", SAP_X25, x25_handle);
2272 }