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