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