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