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