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