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