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