Add "register-static.c" to the list of files to ignore in CVS.
[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.50 2001/07/05 22:10:09 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 == 0x09)
379         return "Out Of Order";
380     if (code == 0x11)
381         return "Remote Procedure Error";
382     if (code == 0x19)
383         return "Reverse Charging Acceptance Not Subscribed";
384     if (code == 0x21)
385         return "Incompatible Destination";
386     if (code == 0x29)
387         return "Fast Select Acceptance Not Subscribed";
388     if (code == 0x39)
389         return "Destination Absent";
390     if (code == 0x03)
391         return "Invalid Facility Requested";
392     if (code == 0x0B)
393         return "Access Barred";
394     if (code == 0x13)
395         return "Local Procedure Error";
396     if (code == 0x05)
397         return "Network Congestion";
398     if (code == 0x0D)
399         return "Not Obtainable";
400     if (code == 0x15)
401         return "RPOA Out Of Order";
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
549     sprintf(buffer, "Unknown %d", code);
550
551     return buffer;
552 }
553
554 static char *reset_code(unsigned char code)
555 {
556     static char buffer[25];
557
558     if (code == 0x00 || (code & 0x80) == 0x80)
559         return "DTE Originated";
560     if (code == 0x01)
561         return "Out of order";
562     if (code == 0x03)
563         return "Remote Procedure Error";
564     if (code == 0x05)
565         return "Local Procedure Error";
566     if (code == 0x07)
567         return "Network Congestion";
568     if (code == 0x09)
569         return "Remote DTE operational";
570     if (code == 0x0F)
571         return "Network operational";
572     if (code == 0x11)
573         return "Incompatible Destination";
574     if (code == 0x1D)
575         return "Network out of order";
576
577     sprintf(buffer, "Unknown %02X", code);
578
579     return buffer;
580 }
581
582 static char *restart_code(unsigned char code)
583 {
584     static char buffer[25];
585
586     if (code == 0x00 || (code & 0x80) == 0x80)
587         return "DTE Originated";
588     if (code == 0x01)
589         return "Local Procedure Error";
590     if (code == 0x03)
591         return "Network Congestion";
592     if (code == 0x07)
593         return "Network Operational";
594     if (code == 0x7F)
595         return "Registration/cancellation confirmed";
596
597     sprintf(buffer, "Unknown %02X", code);
598
599     return buffer;
600 }
601
602 static char *registration_code(unsigned char code)
603 {
604     static char buffer[25];
605
606     if (code == 0x03)
607         return "Invalid facility request";
608     if (code == 0x05)
609         return "Network congestion";
610     if (code == 0x13)
611         return "Local procedure error";
612     if (code == 0x7F)
613         return "Registration/cancellation confirmed";
614
615     sprintf(buffer, "Unknown %02X", code);
616
617     return buffer;
618 }
619
620 static void
621 dump_facilities(proto_tree *tree, int *offset, tvbuff_t *tvb)
622 {
623     guint8 fac, byte1, byte2, byte3;
624     guint32 len;      /* facilities length */
625     proto_item *ti=0;
626     proto_tree *fac_tree = 0;
627     proto_tree *fac_subtree;
628
629     len = tvb_get_guint8(tvb, *offset);
630     if (len && tree) {
631         ti = proto_tree_add_text(tree, tvb, *offset, len + 1,
632                                  "Facilities");
633         fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
634         proto_tree_add_text(fac_tree, tvb, *offset, 1,
635                             "Facilities length: %d", len);
636     }
637     (*offset)++;
638
639     while (len > 0) {
640         fac = tvb_get_guint8(tvb, *offset);
641         switch(fac & X25_FAC_CLASS_MASK) {
642         case X25_FAC_CLASS_A:
643             switch (fac) {
644             case X25_FAC_COMP_MARK:
645                 if (fac_tree)
646                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
647                             "Code : 00 (Marker)");
648                 switch (tvb_get_guint8(tvb, *offset + 1)) {
649                 case 0x00:
650                     if (fac_tree) {
651                         fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
652                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
653                                             "Parameter : 00 (Network complementary "
654                                             "services - calling DTE)");
655                     }
656                     break;
657                 case 0xFF:
658                     if (fac_tree) {
659                         fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
660                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
661                                             "Parameter : FF (Network complementary "
662                                             "services - called DTE)");
663                     }
664                     break;
665                 case 0x0F:
666                     if (fac_tree) {
667                         fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
668                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
669                                             "Parameter : 0F (DTE complementary "
670                                             "services)");
671                     }
672                     break;
673                 default:
674                     if (fac_tree) {
675                         fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
676                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
677                                             "Parameter : %02X (Unknown marker)",
678                                             tvb_get_guint8(tvb, *offset+1));
679                     }
680                     break;
681                 }
682                 break;
683             case X25_FAC_REVERSE:
684                 if (fac_tree) {
685                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
686                             "(Reverse charging / Fast select)", fac);
687                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
688                     byte1 = tvb_get_guint8(tvb, *offset + 1);
689                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
690                             "Parameter : %02X", byte1);
691                     if (byte1 & 0xC0)
692                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
693                                 "11.. .... = Fast select with restriction");
694                     else if (byte1 & 0x80)
695                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
696                                 "10.. .... = Fast select - no restriction");
697                     else
698                         proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
699                                 "00.. .... = Fast select not requested");
700                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
701                             decode_boolean_bitfield(byte1, 0x01, 1*8,
702                                 "Reverse charging requested",
703                                 "Reverse charging not requested"));
704                 }
705                 break;
706             case X25_FAC_THROUGHPUT:
707                 if (fac_tree) {
708                     char tmpbuf[80];
709
710                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
711                             "(Throughput class negociation)", fac);
712                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
713                     byte1 = tvb_get_guint8(tvb, *offset + 1);
714                     switch (byte1 >> 4)
715                     {
716                     case 3:
717                     case 4:
718                     case 5:
719                     case 6:
720                     case 7:
721                     case 8:
722                     case 9:
723                     case 10:
724                     case 11:
725                         sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
726                                 75*(1<<((byte1 >> 4)-3)));
727                         break;
728                     case 12:
729                         sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
730                         break;
731                     case 13:
732                         sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
733                         break;
734                     default:
735                         sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
736                     }
737                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
738                             decode_numeric_bitfield(byte1, 0xF0, 1*8, tmpbuf));
739                     switch (byte1 & 0x0F)
740                     {
741                     case 3:
742                     case 4:
743                     case 5:
744                     case 6:
745                     case 7:
746                     case 8:
747                     case 9:
748                     case 10:
749                     case 11:
750                         sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
751                                 75*(1<<((byte1 & 0x0F)-3)));
752                         break;
753                     case 12:
754                         sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
755                         break;
756                     case 13:
757                         sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
758                         break;
759                     default:
760                         sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
761                     }
762                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
763                             decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
764                 }
765                 break;
766             case X25_FAC_CUG:
767                 if (fac_tree) {
768                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
769                             "(Closed user group selection)", fac);
770                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
771                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
772                             "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
773                 }
774                 break;
775             case X25_FAC_CALLED_MODIF:
776                 if (fac_tree) {
777                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
778                             "(Called address modified)", fac);
779                     fac_subtree = proto_item_add_subtree(ti,
780                             ett_x25_fac_called_modif);
781                     proto_tree_add_text(fac_tree, tvb, *offset+1, 1,
782                             "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
783                 }
784                 break;
785             case X25_FAC_CUG_OUTGOING_ACC:
786                 if (fac_tree) {
787                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
788                             "(Closed user group with outgoing access selection)",
789                             fac);
790                     fac_subtree = proto_item_add_subtree(ti,
791                             ett_x25_fac_cug_outgoing_acc);
792                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
793                             "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
794                 }
795                 break;
796             case X25_FAC_THROUGHPUT_MIN:
797                 if (fac_tree) {
798                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
799                             "(Minimum throughput class)", fac);
800                     fac_subtree = proto_item_add_subtree(ti,
801                             ett_x25_fac_throughput_min);
802                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
803                             "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
804                 }
805                 break;
806             case X25_FAC_EXPRESS_DATA:
807                 if (fac_tree) {
808                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
809                             "(Negociation of express data)", fac);
810                     fac_subtree = proto_item_add_subtree(ti,
811                             ett_x25_fac_express_data);
812                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
813                             "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
814                 }
815                 break;
816             default:
817                 if (fac_tree) {
818                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
819                             "Code : %02X (Unknown class A)", fac);
820                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
821                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
822                             "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
823                 }
824                 break;
825             }
826             (*offset) += 2;
827             len -= 2;
828             break;
829         case X25_FAC_CLASS_B:
830             switch (fac) {
831             case X25_FAC_BILATERAL_CUG:
832                 if (fac_tree) {
833                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
834                             "(Bilateral closed user group selection)", fac);
835                     fac_subtree = proto_item_add_subtree(ti,
836                             ett_x25_fac_bilateral_cug);
837                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
838                                         "Bilateral CUG: %04X",
839                                         tvb_get_ntohs(tvb, *offset+1));
840                 }
841                 break;
842             case X25_FAC_PACKET_SIZE:
843                 if (fac_tree)
844                 {
845                     char tmpbuf[80];
846
847                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
848                             "(Packet size)", fac);
849                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
850                     byte1 = tvb_get_guint8(tvb, *offset + 1);
851                     switch (byte1)
852                     {
853                     case 0x04:
854                         sprintf(tmpbuf, "From the called DTE : %%u (16)");
855                         break;
856                     case 0x05:
857                         sprintf(tmpbuf, "From the called DTE : %%u (32)");
858                         break;
859                     case 0x06:
860                         sprintf(tmpbuf, "From the called DTE : %%u (64)");
861                         break;
862                     case 0x07:
863                         sprintf(tmpbuf, "From the called DTE : %%u (128)");
864                         break;
865                     case 0x08:
866                         sprintf(tmpbuf, "From the called DTE : %%u (256)");
867                         break;
868                     case 0x0D:
869                         sprintf(tmpbuf, "From the called DTE : %%u (512)");
870                         break;
871                     case 0x0C:
872                         sprintf(tmpbuf, "From the called DTE : %%u (1024)");
873                         break;
874                     case 0x0E:
875                         sprintf(tmpbuf, "From the called DTE : %%u (2048)");
876                         break;
877                     case 0x0F:
878                         sprintf(tmpbuf, "From the called DTE : %%u (4096)");
879                         break;
880                     default:
881                         sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
882                         break;
883                     }
884                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
885                             decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
886
887                     byte2 = tvb_get_guint8(tvb, *offset + 1);
888                     switch (byte2)
889                     {
890                     case 0x04:
891                         sprintf(tmpbuf, "From the calling DTE : %%u (16)");
892                         break;
893                     case 0x05:
894                         sprintf(tmpbuf, "From the calling DTE : %%u (32)");
895                         break;
896                     case 0x06:
897                         sprintf(tmpbuf, "From the calling DTE : %%u (64)");
898                         break;
899                     case 0x07:
900                         sprintf(tmpbuf, "From the calling DTE : %%u (128)");
901                         break;
902                     case 0x08:
903                         sprintf(tmpbuf, "From the calling DTE : %%u (256)");
904                         break;
905                     case 0x0D:
906                         sprintf(tmpbuf, "From the calling DTE : %%u (512)");
907                         break;
908                     case 0x0C:
909                         sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
910                         break;
911                     case 0x0E:
912                         sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
913                         break;
914                     case 0x0F:
915                         sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
916                         break;
917                     default:
918                         sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
919                         break;
920                     }
921                     proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
922                             decode_numeric_bitfield(byte2, 0x0F, 1*8, tmpbuf));
923                 }
924                 break;
925             case X25_FAC_WINDOW_SIZE:
926                 if (fac_tree) {
927                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
928                             "(Window size)", fac);
929                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
930                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
931                             decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+1),
932                                 0x7F, 1*8, "From the called DTE: %u"));
933                     proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
934                             decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+2),
935                                 0x7F, 1*8, "From the calling DTE: %u"));
936                 }
937                 break;
938             case X25_FAC_RPOA_SELECTION:
939                 if (fac_tree) {
940                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
941                             "(RPOA selection)", fac);
942                     fac_subtree = proto_item_add_subtree(ti,
943                             ett_x25_fac_rpoa_selection);
944                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
945                                         "Data network identification code : %04X",
946                                         tvb_get_ntohs(tvb, *offset+1));
947                 }
948                 break;
949             case X25_FAC_TRANSIT_DELAY:
950                 if (fac_tree) {
951                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
952                             "(Transit delay selection and indication)", fac);
953                     fac_subtree = proto_item_add_subtree(ti,
954                             ett_x25_fac_transit_delay);
955                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
956                                         "Transit delay: %d ms",
957                                         tvb_get_ntohs(tvb, *offset+1));
958                 }
959                 break;
960             default:
961                 if (fac_tree) {
962                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
963                             "Code : %02X (Unknown class B)", fac);
964                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
965                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
966                             "Parameter %04X", tvb_get_ntohs(tvb, *offset+1));
967                 }
968                 break;
969             }
970             (*offset) += 3;
971             len -= 3;
972             break;
973         case X25_FAC_CLASS_C:
974             if (fac_tree) {
975                 ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
976                         "Code : %02X (Unknown class C)", fac);
977                 fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
978                 proto_tree_add_text(fac_subtree, tvb, *offset+1, 3,
979                         "Parameter %06X",
980                         tvb_get_ntoh24(tvb, *offset+1));
981             }
982             (*offset) += 4;
983             len -= 4;
984             break;
985         case X25_FAC_CLASS_D:
986             switch (fac) {
987             case X25_FAC_CALL_TRANSFER:
988                 if (fac_tree) {
989                     int i;
990                     char tmpbuf[256];
991
992                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
993                             "(Call redirection or deflection notification)", fac);
994                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
995                     byte1 = tvb_get_guint8(tvb, *offset+1);
996                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
997                             "Length : %u", byte1);
998                     byte2 = tvb_get_guint8(tvb, *offset+2);
999                     if ((byte2 & 0xC0) == 0xC0) {
1000                         proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1001                                 "Reason : call deflection by the originally "
1002                                 "called DTE address");
1003                     }
1004                     else {
1005                         switch (byte2) {
1006                         case 0x01:
1007                             proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1008                                     "Reason : originally called DTE busy");
1009                             break;
1010                         case 0x07:
1011                             proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1012                                     "Reason : call dist. within a hunt group");
1013                             break;
1014                         case 0x09:
1015                             proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1016                                     "Reason : originally called DTE out of order");
1017                             break;
1018                         case 0x0F:
1019                             proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1020                                     "Reason : systematic call redirection");
1021                             break;
1022                         default:
1023                             proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1024                                     "Reason : unknown");
1025                             break;
1026                         }
1027                     }
1028                     byte3 = tvb_get_guint8(tvb, *offset+3);
1029                     proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1030                             "Number of semi-octets in DTE address : %u",
1031                             byte3);
1032                     for (i = 0; i < byte3; i++) {
1033                         if (i % 2 == 0) {
1034                             tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1035                                     & 0x0F) + '0';
1036                             /* if > 9, convert to the right hexadecimal letter */
1037                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1038                         } else {
1039                             tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1040                                     & 0x0F) + '0';
1041                             /* if > 9, convert to the right hexadecimal letter */
1042                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1043                         }
1044                     }
1045                     tmpbuf[i] = 0;
1046                     proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1047                             "DTE address : %s", tmpbuf);
1048                 }
1049                 break;
1050             case X25_FAC_CALLING_ADDR_EXT:
1051                 if (fac_tree) {
1052                     int i;
1053                     char tmpbuf[256];
1054
1055                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1056                             "(Calling address extension)", fac);
1057                     fac_subtree = proto_item_add_subtree(ti,
1058                             ett_x25_fac_calling_addr_ext);
1059                     byte1 = tvb_get_guint8(tvb, *offset+1);
1060                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1061                             "Length : %u", byte1);
1062                     byte2 = tvb_get_guint8(tvb, *offset+2);
1063                     proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1064                             "Number of semi-octets in DTE address : %u", byte2);
1065                     for (i = 0; i < byte2; i++) {
1066                         if (i % 2 == 0) {
1067                             tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1068                                     & 0x0F) + '0';
1069                             /* if > 9, convert to the right hexadecimal letter */
1070                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1071                         } else {
1072                             tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1073                                     & 0x0F) + '0';
1074                             /* if > 9, convert to the right hexadecimal letter */
1075                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1076                         }
1077                     }
1078                     tmpbuf[i] = 0;
1079                     proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1080                             "DTE address : %s", tmpbuf);
1081                 }
1082                 break;
1083             case X25_FAC_CALLED_ADDR_EXT:
1084                 if (fac_tree) {
1085                     int i;
1086                     char tmpbuf[256];
1087
1088                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1089                             "(Called address extension)", fac);
1090                     fac_subtree = proto_item_add_subtree(ti,
1091                             ett_x25_fac_called_addr_ext);
1092                     byte1 = tvb_get_guint8(tvb, *offset+1);
1093                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1094                             "Length : %u", byte1);
1095                     byte2 = tvb_get_guint8(tvb, *offset+2);
1096                     proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1097                             "Number of semi-octets in DTE address : %u", byte2);
1098                     for (i = 0; i < byte2; i++) {
1099                         if (i % 2 == 0) {
1100                             tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
1101                                     & 0x0F) + '0';
1102                             /* if > 9, convert to the right hexadecimal letter */
1103                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1104                         } else {
1105                             tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
1106                                     & 0x0F) + '0';
1107                             /* if > 9, convert to the right hexadecimal letter */
1108                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1109                         }
1110                     }
1111                     tmpbuf[i] = 0;
1112                     proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
1113                             "DTE address : %s", tmpbuf);
1114                 }
1115                 break;
1116             case X25_FAC_ETE_TRANSIT_DELAY:
1117                 if (fac_tree) {
1118                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1119                             "(End to end transit delay)", fac);
1120                     fac_subtree = proto_item_add_subtree(ti,
1121                             ett_x25_fac_ete_transit_delay);
1122                     byte1 = tvb_get_guint8(tvb, *offset+1);
1123                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1124                             "Length : %u", byte1);
1125                     proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1126                 }
1127                 break;
1128             case X25_FAC_CALL_DEFLECT:
1129                 if (fac_tree) {
1130                     int i;
1131                     char tmpbuf[256];
1132
1133                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
1134                             "(Call deflection selection)", fac);
1135                     fac_subtree = proto_item_add_subtree(ti,
1136                             ett_x25_fac_call_deflect);
1137                     byte1 = tvb_get_guint8(tvb, *offset+1);
1138                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1139                             "Length : %u", byte1);
1140                     byte2 = tvb_get_guint8(tvb, *offset+2);
1141                     if ((byte2 & 0xC0) == 0xC0)
1142                         proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1143                                 "Reason : call DTE originated");
1144                     else
1145                         proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
1146                                 "Reason : unknown");
1147                     byte3 = tvb_get_guint8(tvb, *offset+3);
1148                     proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
1149                             "Number of semi-octets in the alternative DTE address : %u",
1150                             byte3);
1151                     for (i = 0; i < byte3; i++) {
1152                         if (i % 2 == 0) {
1153                             tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
1154                                     & 0x0F) + '0';
1155                             /* if > 9, convert to the right hexadecimal letter */
1156                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1157                         } else {
1158                             tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
1159                                     & 0x0F) + '0';
1160                             /* if > 9, convert to the right hexadecimal letter */
1161                             if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
1162                         }
1163                     }
1164                     tmpbuf[i] = 0;
1165                     proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
1166                             "Alternative DTE address : %s", tmpbuf);
1167                 }
1168                 break;
1169             case X25_FAC_PRIORITY:
1170                 if (fac_tree) {
1171                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1172                             "Code : %02X (Priority)", fac);
1173                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
1174                     byte1 = tvb_get_guint8(tvb, *offset+1);
1175                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1176                             "Length : %u", byte1);
1177                     proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1178                 }
1179                 break;
1180             default:
1181                 if (fac_tree) {
1182                     ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
1183                             "Code : %02X (Unknown class D)", fac);
1184                     fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
1185                     byte1 = tvb_get_guint8(tvb, *offset+1);
1186                     proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
1187                             "Length : %u", byte1);
1188                     proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
1189                 }
1190             }
1191             byte1 = tvb_get_guint8(tvb, *offset+1);
1192             (*offset) += byte1+2;
1193             len -= byte1+2;
1194             break;
1195         }
1196     }
1197 }
1198
1199 static void
1200 x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
1201          frame_data *fd, gboolean toa)
1202 {
1203     int len1, len2;
1204     int i;
1205     char addr1[16], addr2[16];
1206     char *first, *second;
1207     guint8 byte;
1208     int localoffset;
1209
1210     byte = tvb_get_guint8(tvb, *offset);
1211     len1 = (byte >> 4) & 0x0F;
1212     len2 = (byte >> 0) & 0x0F;
1213     if (tree) {
1214         proto_tree_add_text(tree, tvb, *offset, 1,
1215                 decode_numeric_bitfield(byte, 0xF0, 1*8,
1216                     toa ? "Called address length : %u" :
1217                           "Calling address length : %u"));
1218         proto_tree_add_text(tree, tvb, *offset, 1,
1219                 decode_numeric_bitfield(byte, 0x0F, 1*8,
1220                     toa ? "Calling address length : %u" :
1221                           "Called address length : %u"));
1222     }
1223     (*offset)++;
1224
1225     localoffset = *offset;
1226     byte = tvb_get_guint8(tvb, localoffset);
1227
1228     first=addr1;
1229     second=addr2;
1230     for (i = 0; i < (len1 + len2); i++) {
1231         if (i < len1) {
1232             if (i % 2 != 0) {
1233                 *first++ = ((byte >> 0) & 0x0F) + '0';
1234                 localoffset++;
1235                 byte = tvb_get_guint8(tvb, localoffset);
1236             } else {
1237                 *first++ = ((byte >> 4) & 0x0F) + '0';
1238             }
1239         } else {
1240             if (i % 2 != 0) {
1241                 *second++ = ((byte >> 0) & 0x0F) + '0';
1242                 localoffset++;
1243                 byte = tvb_get_guint8(tvb, localoffset);
1244             } else {
1245                 *second++ = ((byte >> 4) & 0x0F) + '0';
1246             }
1247         }
1248     }
1249
1250     *first  = '\0';
1251     *second = '\0';
1252
1253     if (len1) {
1254         if (toa) {
1255             if (check_col(fd, COL_RES_DL_DST))
1256                 col_add_str(fd, COL_RES_DL_DST, addr1);
1257         }
1258         else {
1259             if(check_col(fd, COL_RES_DL_SRC))
1260                 col_add_str(fd, COL_RES_DL_SRC, addr1);
1261         }
1262         if (tree)
1263             proto_tree_add_text(tree, tvb, *offset,
1264                                 (len1 + 1) / 2,
1265                                 "%s address : %s",
1266                                 toa ? "Called" : "Calling",
1267                                 addr1);
1268     }
1269     if (len2) {
1270         if (toa) {
1271             if (check_col(fd, COL_RES_DL_SRC))
1272                 col_add_str(fd, COL_RES_DL_SRC, addr2);
1273         }
1274         else {
1275             if(check_col(fd, COL_RES_DL_DST))
1276                 col_add_str(fd, COL_RES_DL_DST, addr2);
1277         }
1278         if (tree)
1279             proto_tree_add_text(tree, tvb, *offset + len1/2,
1280                                 (len2+1)/2+(len1%2+(len2+1)%2)/2,
1281                                 "%s address : %s",
1282                                 toa ? "Calling" : "Called",
1283                                 addr2);
1284     }
1285     (*offset) += ((len1 + len2 + 1) / 2);
1286 }
1287
1288 static int
1289 get_x25_pkt_len(tvbuff_t *tvb)
1290 {
1291     guint length, called_len, calling_len, dte_len, dce_len;
1292     guint8 byte2, bytex;
1293
1294     byte2 = tvb_get_guint8(tvb, 2);
1295     switch (byte2)
1296     {
1297     case X25_CALL_REQUEST:
1298         bytex = tvb_get_guint8(tvb, 3);
1299         called_len  = (bytex >> 0) & 0x0F;
1300         calling_len = (bytex >> 4) & 0x0F;
1301         length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1302         if (length < tvb_reported_length(tvb))
1303             length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1304
1305         return MIN(tvb_reported_length(tvb),length);
1306
1307     case X25_CALL_ACCEPTED:
1308         bytex = tvb_get_guint8(tvb, 3);
1309         called_len  = (bytex >> 0) & 0x0F;
1310         calling_len = (bytex >> 4) & 0x0F;
1311         length = 4 + (called_len + calling_len + 1) / 2; /* addr */
1312         if (length < tvb_reported_length(tvb))
1313             length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
1314
1315         return MIN(tvb_reported_length(tvb),length);
1316
1317     case X25_CLEAR_REQUEST:
1318     case X25_RESET_REQUEST:
1319     case X25_RESTART_REQUEST:
1320         return MIN(tvb_reported_length(tvb),5);
1321
1322     case X25_DIAGNOSTIC:
1323         return MIN(tvb_reported_length(tvb),4);
1324
1325     case X25_CLEAR_CONFIRMATION:
1326     case X25_INTERRUPT:
1327     case X25_INTERRUPT_CONFIRMATION:
1328     case X25_RESET_CONFIRMATION:
1329     case X25_RESTART_CONFIRMATION:
1330         return MIN(tvb_reported_length(tvb),3);
1331
1332     case X25_REGISTRATION_REQUEST:
1333         bytex = tvb_get_guint8(tvb, 3);
1334         dce_len = (bytex >> 0) & 0x0F;
1335         dte_len = (bytex >> 4) & 0x0F;
1336         length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
1337         if (length < tvb_reported_length(tvb))
1338             length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1339
1340         return MIN(tvb_reported_length(tvb),length);
1341
1342     case X25_REGISTRATION_CONFIRMATION:
1343         bytex = tvb_get_guint8(tvb, 5);
1344         dce_len = (bytex >> 0) & 0x0F;
1345         dte_len = (bytex >> 4) & 0x0F;
1346         length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
1347         if (length < tvb_reported_length(tvb))
1348             length += (1 + tvb_get_guint8(tvb, length)); /* registration */
1349
1350         return MIN(tvb_reported_length(tvb),length);
1351     }
1352
1353     if ((byte2 & 0x01) == X25_DATA) return MIN(tvb_reported_length(tvb),3);
1354
1355     switch (byte2 & 0x1F)
1356     {
1357     case X25_RR:
1358         return MIN(tvb_reported_length(tvb),3);
1359
1360     case X25_RNR:
1361         return MIN(tvb_reported_length(tvb),3);
1362
1363     case X25_REJ:
1364         return MIN(tvb_reported_length(tvb),3);
1365     }
1366
1367     return 0;
1368 }
1369
1370 #define PRT_ID_ISO_8073 0x01
1371
1372 static const value_string prt_id_vals[] = {
1373         {PRT_ID_ISO_8073, "ISO 8073 COTP"},
1374         {0x02,            "ISO 8602"},
1375         {0x03,            "ISO 10732 in conjunction with ISO 8073"},
1376         {0x04,            "ISO 10736 in conjunction with ISO 8602"},
1377         {0x00,            NULL}
1378 };
1379
1380 static const value_string sharing_strategy_vals[] = {
1381         {0x00,            "No sharing"},
1382         {0x00,            NULL}
1383 };
1384
1385 static void
1386 dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1387 {
1388     proto_tree *x25_tree=0, *gfi_tree=0;
1389     proto_item *ti;
1390     guint localoffset=0;
1391     guint x25_pkt_len;
1392     int modulo;
1393     guint16 vc;
1394     dissector_handle_t dissect;
1395     gboolean toa;         /* TOA/NPI address format */
1396     guint16 bytes0_1;
1397     guint8 pkt_type;
1398     tvbuff_t *next_tvb;
1399
1400     if (check_col(pinfo->fd, COL_PROTOCOL))
1401         col_set_str(pinfo->fd, COL_PROTOCOL, "X.25");
1402
1403     bytes0_1 = tvb_get_ntohs(tvb, 0);
1404
1405     modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
1406     vc     = (int)(bytes0_1 & 0x0FFF);
1407
1408     if (bytes0_1 & 0x8000) toa = TRUE;
1409     else toa = FALSE;
1410
1411     x25_pkt_len = get_x25_pkt_len(tvb);
1412     if (x25_pkt_len < 3) /* packet too short */
1413     {
1414         if (check_col(pinfo->fd, COL_INFO))
1415             col_set_str(pinfo->fd, COL_INFO, "Invalid/short X.25 packet");
1416         if (tree)
1417             proto_tree_add_protocol_format(tree, proto_x25, tvb, 0,
1418                     tvb_length(tvb), "Invalid/short X.25 packet");
1419         return;
1420     }
1421
1422     pkt_type = tvb_get_guint8(tvb, 2);
1423
1424     if (tree) {
1425         ti = proto_tree_add_item(tree, proto_x25, tvb, 0, x25_pkt_len, FALSE);
1426         x25_tree = proto_item_add_subtree(ti, ett_x25);
1427         ti = proto_tree_add_item(x25_tree, hf_x25_gfi, tvb, 0, 2, FALSE);
1428         gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
1429         if ((pkt_type & 0x01) == X25_DATA)
1430             proto_tree_add_boolean(gfi_tree, hf_x25_qbit, tvb, 0, 2,
1431                     bytes0_1);
1432         else if (pkt_type == X25_CALL_REQUEST ||
1433                 pkt_type == X25_CALL_ACCEPTED ||
1434                 pkt_type == X25_CLEAR_REQUEST ||
1435                 pkt_type == X25_CLEAR_CONFIRMATION)
1436             proto_tree_add_boolean(gfi_tree, hf_x25_abit, tvb, 0, 2,
1437                     bytes0_1);
1438         if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
1439                 (pkt_type & 0x01) == X25_DATA)
1440             proto_tree_add_boolean(gfi_tree, hf_x25_dbit, tvb, 0, 2,
1441                     bytes0_1);
1442         proto_tree_add_uint(gfi_tree, hf_x25_mod, tvb, 0, 2, bytes0_1);
1443     }
1444
1445     switch (pkt_type) {
1446     case X25_CALL_REQUEST:
1447         if (check_col(pinfo->fd, COL_INFO))
1448             col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1449                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Inc. call"
1450                                                                  : "Call req." ,
1451                     vc);
1452         if (x25_tree) {
1453             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb,
1454                     0, 2, bytes0_1);
1455             proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1456                     X25_CALL_REQUEST,
1457                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Incoming call"
1458                                                                  : "Call request");
1459         }
1460         localoffset = 3;
1461         if (localoffset < x25_pkt_len) /* calling/called addresses */
1462             x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1463
1464         if (localoffset < x25_pkt_len) /* facilities */
1465             dump_facilities(x25_tree, &localoffset, tvb);
1466
1467         if (localoffset < tvb_reported_length(tvb)) /* user data */
1468         {
1469             guint8 spi;
1470             guint8 prt_id;
1471
1472             /* Compare the first octet of the CALL REQUEST packet with
1473                various ISO 9577 NLPIDs, as per Annex A of ISO 9577. */
1474             spi = tvb_get_guint8(tvb, localoffset);
1475             switch (spi) {
1476
1477             /*
1478              * XXX - handle other NLPIDs, e.g. PPP?
1479              * See RFC 1356 for information on at least some other
1480              * ways of running other protocols atop X.25.
1481              */
1482             case NLPID_IP:
1483                 x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1484                                          pinfo->fd->abs_usecs, ip_handle);
1485                 if (x25_tree)
1486                     proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1487                                         "X.224 secondary protocol ID: IP");
1488                 localoffset++;
1489                 break;
1490
1491             default:
1492                 if ((spi >= 0x03 && spi <= 0x82)
1493                     && tvb_get_guint8(tvb, localoffset+1) == 0x01) {
1494                     /* ISO 9577 claims that a SPI in that range is a
1495                        length field for X.224/ISO 8073 or X.264/ISO 11570;
1496                        however, some of them collide with NLPIDs such
1497                        as 0x81 for ISO 8473 CLNP or ISO 8542 ESIS, so
1498                        I don't know how you run those over X.25, assuming
1499                        you do.
1500
1501                        I'm also not sure what the "or" means there; it
1502                        looks as if X.264 specifies the layout of a
1503                        "UN TPDU" ("Use of network connection TPDU"),
1504                        which specifies the transport protocol to use
1505                        over this network connection, and 0x03 0x01 0x01
1506                        0x00 is such a TPDU, with a length of 3, a UN
1507                        field of 1 (as is required), a PRT-ID ("protocol
1508                        identifier") field of 1 (X.224/ISO 8073, a/k/a
1509                        COTP service), and a SHARE ("sharing strategy")
1510                        field of 0 ("no sharing", which is the only one
1511                        allowed).
1512
1513                        So we'll assume that's what it is, as the SPI
1514                        is in the right range for a length, and the UN
1515                        field is 0x01. */
1516                     prt_id = tvb_get_guint8(tvb, localoffset+2);
1517                     if (x25_tree) {
1518                         proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1519                                         "X.264 length indicator: %u",
1520                                         spi);
1521                         proto_tree_add_text(x25_tree, tvb, localoffset+1, 1,
1522                                         "X.264 UN TPDU identifier: 0x%02X",
1523                                         tvb_get_guint8(tvb, localoffset+1));
1524                         proto_tree_add_text(x25_tree, tvb, localoffset+2, 1,
1525                                         "X.264 protocol identifier: %s",
1526                                         val_to_str(prt_id, prt_id_vals,
1527                                             "Unknown (0x%02X)"));
1528                         proto_tree_add_text(x25_tree, tvb, localoffset+3, 1,
1529                                         "X.264 sharing strategy: %s",
1530                                         val_to_str(tvb_get_guint8(tvb, localoffset+3),
1531                                             sharing_strategy_vals, "Unknown (0x%02X)"));
1532                     }
1533
1534                     /* XXX - dissect the variable part? */
1535
1536                     /* The length doesn't include the length octet itself. */
1537                     localoffset += spi + 1;
1538
1539                     switch (prt_id) {
1540
1541                     case PRT_ID_ISO_8073:
1542                         /* ISO 8073 COTP */
1543                         x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1544                                          pinfo->fd->abs_usecs, ositp_handle);
1545                         break;
1546
1547                     default:
1548                         goto unknown;
1549                     }
1550                 } else {
1551                 unknown:
1552                     if (x25_tree) {
1553                         proto_tree_add_text(x25_tree, tvb, localoffset,
1554                                 tvb_reported_length(tvb)-localoffset, "Data");
1555                     }
1556                     localoffset = tvb_reported_length(tvb);
1557                 }
1558             }
1559         }
1560         break;
1561     case X25_CALL_ACCEPTED:
1562         if(check_col(pinfo->fd, COL_INFO))
1563             col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d",
1564                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call conn."
1565                                                                  : "Call acc." ,
1566                     vc);
1567         if (x25_tree) {
1568             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1569             proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1570                     X25_CALL_ACCEPTED,
1571                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Call connected"
1572                                                                  : "Call accepted");
1573         }
1574         localoffset = 3;
1575         if (localoffset < x25_pkt_len) /* calling/called addresses */
1576             x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1577
1578         if (localoffset < x25_pkt_len) /* facilities */
1579             dump_facilities(x25_tree, &localoffset, tvb);
1580
1581         if (localoffset < tvb_reported_length(tvb)) { /* user data */
1582             if (x25_tree)
1583                 proto_tree_add_text(x25_tree, tvb, localoffset,
1584                                     tvb_reported_length(tvb)-localoffset, "Data");
1585             localoffset=tvb_reported_length(tvb);
1586         }
1587         break;
1588     case X25_CLEAR_REQUEST:
1589         if(check_col(pinfo->fd, COL_INFO)) {
1590             col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - %s",
1591                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear ind."
1592                                                                  : "Clear req." ,
1593                     vc, clear_code(tvb_get_guint8(tvb, 3)),
1594                     clear_diag(tvb_get_guint8(tvb, 4)));
1595         }
1596         x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1597         if (x25_tree) {
1598             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1599             proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb,
1600                     localoffset+2, 1, X25_CLEAR_REQUEST,
1601                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Clear indication"
1602                                                                  : "Clear request");
1603             proto_tree_add_text(x25_tree, tvb, 3, 1,
1604                     "Cause : %s", clear_code(tvb_get_guint8(tvb, 3)));
1605             proto_tree_add_text(x25_tree, tvb, 4, 1,
1606                     "Diagnostic : %s", clear_diag(tvb_get_guint8(tvb, 4)));
1607         }
1608         localoffset = x25_pkt_len;
1609         break;
1610     case X25_CLEAR_CONFIRMATION:
1611         if(check_col(pinfo->fd, COL_INFO))
1612             col_add_fstr(pinfo->fd, COL_INFO, "Clear Conf. VC:%d", vc);
1613         if (x25_tree) {
1614             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1615             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1616                     X25_CLEAR_CONFIRMATION);
1617         }
1618         localoffset = x25_pkt_len;
1619
1620         if (localoffset < tvb_reported_length(tvb)) /* extended clear conf format */
1621             x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, toa);
1622
1623         if (localoffset < tvb_reported_length(tvb)) /* facilities */
1624             dump_facilities(x25_tree, &localoffset, tvb);
1625         break;
1626     case X25_DIAGNOSTIC:
1627         if(check_col(pinfo->fd, COL_INFO)) {
1628             col_add_fstr(pinfo->fd, COL_INFO, "Diag. %d",
1629                     (int)tvb_get_guint8(tvb, 3));
1630         }
1631         if (x25_tree) {
1632             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1633                     X25_DIAGNOSTIC);
1634             proto_tree_add_text(x25_tree, tvb, 3, 1,
1635                     "Diagnostic : %d", (int)tvb_get_guint8(tvb, 3));
1636         }
1637         localoffset = x25_pkt_len;
1638         break;
1639     case X25_INTERRUPT:
1640         if(check_col(pinfo->fd, COL_INFO))
1641             col_add_fstr(pinfo->fd, COL_INFO, "Interrupt VC:%d", vc);
1642         if (x25_tree) {
1643             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1644             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1645                     X25_INTERRUPT);
1646         }
1647         localoffset = x25_pkt_len;
1648         break;
1649     case X25_INTERRUPT_CONFIRMATION:
1650         if(check_col(pinfo->fd, COL_INFO))
1651             col_add_fstr(pinfo->fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
1652         if (x25_tree) {
1653             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1654             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1655                     X25_INTERRUPT_CONFIRMATION);
1656         }
1657         localoffset = x25_pkt_len;
1658         break;
1659     case X25_RESET_REQUEST:
1660         if(check_col(pinfo->fd, COL_INFO)) {
1661             col_add_fstr(pinfo->fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
1662                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset ind."
1663                                                                  : "Reset req.",
1664                     vc, reset_code(tvb_get_guint8(tvb, 3)),
1665                     (int)tvb_get_guint8(tvb, 4));
1666         }
1667         x25_hash_add_proto_end(vc, pinfo->fd->abs_secs, pinfo->fd->abs_usecs);
1668         if (x25_tree) {
1669             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1670             proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1671                     X25_RESET_REQUEST,
1672                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Reset indication"
1673                                                                  : "Reset request");
1674             proto_tree_add_text(x25_tree, tvb, 3, 1,
1675                     "Cause : %s", reset_code(tvb_get_guint8(tvb, 3)));
1676             proto_tree_add_text(x25_tree, tvb, 4, 1,
1677                     "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1678         }
1679         localoffset = x25_pkt_len;
1680         break;
1681     case X25_RESET_CONFIRMATION:
1682         if(check_col(pinfo->fd, COL_INFO))
1683             col_add_fstr(pinfo->fd, COL_INFO, "Reset conf. VC:%d", vc);
1684         if (x25_tree) {
1685             proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
1686             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1687                     X25_RESET_CONFIRMATION);
1688         }
1689         localoffset = x25_pkt_len;
1690         break;
1691     case X25_RESTART_REQUEST:
1692         if(check_col(pinfo->fd, COL_INFO)) {
1693             col_add_fstr(pinfo->fd, COL_INFO, "%s %s - Diag.:%d",
1694                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart ind."
1695                                                                  : "Restart req.",
1696                     restart_code(tvb_get_guint8(tvb, 3)),
1697                     (int)tvb_get_guint8(tvb, 3));
1698         }
1699         if (x25_tree) {
1700             proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
1701                     X25_RESTART_REQUEST,
1702                     (pinfo->pseudo_header->x25.flags & FROM_DCE) ? "Restart indication"
1703                                                                  : "Restart request");
1704             proto_tree_add_text(x25_tree, tvb, 3, 1,
1705                     "Cause : %s", restart_code(tvb_get_guint8(tvb, 3)));
1706             proto_tree_add_text(x25_tree, tvb, 4, 1,
1707                     "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
1708         }
1709         localoffset = x25_pkt_len;
1710         break;
1711     case X25_RESTART_CONFIRMATION:
1712         if(check_col(pinfo->fd, COL_INFO))
1713             col_set_str(pinfo->fd, COL_INFO, "Restart conf.");
1714         if (x25_tree)
1715             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1716                     X25_RESTART_CONFIRMATION);
1717         localoffset = x25_pkt_len;
1718         break;
1719     case X25_REGISTRATION_REQUEST:
1720         if(check_col(pinfo->fd, COL_INFO))
1721             col_set_str(pinfo->fd, COL_INFO, "Registration req.");
1722         if (x25_tree)
1723             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1724                     X25_REGISTRATION_REQUEST);
1725         localoffset = 3;
1726         if (localoffset < x25_pkt_len)
1727             x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, FALSE);
1728
1729         if (x25_tree) {
1730             if (localoffset < x25_pkt_len)
1731                 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1732                         "Registration length: %d",
1733                         tvb_get_guint8(tvb, localoffset) & 0x7F);
1734             if (localoffset+1 < x25_pkt_len)
1735                 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1736                         tvb_get_guint8(tvb, localoffset) & 0x7F,
1737                         "Registration");
1738         }
1739         localoffset = tvb_reported_length(tvb);
1740         break;
1741     case X25_REGISTRATION_CONFIRMATION:
1742         if(check_col(pinfo->fd, COL_INFO))
1743             col_set_str(pinfo->fd, COL_INFO, "Registration conf.");
1744         if (x25_tree) {
1745             proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
1746                     X25_REGISTRATION_CONFIRMATION);
1747             proto_tree_add_text(x25_tree, tvb, 3, 1,
1748                     "Cause: %s", registration_code(tvb_get_guint8(tvb, 3)));
1749             proto_tree_add_text(x25_tree, tvb, 4, 1,
1750                     "Diagnostic: %s", registration_code(tvb_get_guint8(tvb, 4)));
1751         }
1752         localoffset = 5;
1753         if (localoffset < x25_pkt_len)
1754             x25_ntoa(x25_tree, &localoffset, tvb, pinfo->fd, TRUE);
1755
1756         if (x25_tree) {
1757             if (localoffset < x25_pkt_len)
1758                 proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1759                         "Registration length: %d",
1760                         tvb_get_guint8(tvb, localoffset) & 0x7F);
1761             if (localoffset+1 < x25_pkt_len)
1762                 proto_tree_add_text(x25_tree, tvb, localoffset+1,
1763                         tvb_get_guint8(tvb, localoffset) & 0x7F,
1764                         "Registration");
1765         }
1766         localoffset = tvb_reported_length(tvb);
1767         break;
1768     default :
1769         localoffset = 2;
1770         if ((pkt_type & 0x01) == X25_DATA)
1771         {
1772             if(check_col(pinfo->fd, COL_INFO)) {
1773                 if (modulo == 8)
1774                     col_add_fstr(pinfo->fd, COL_INFO,
1775                             "Data VC:%d P(S):%d P(R):%d %s", vc,
1776                             (pkt_type >> 1) & 0x07,
1777                             (pkt_type >> 5) & 0x07,
1778                             ((pkt_type >> 4) & 0x01) ? " M" : "");
1779                 else
1780                     col_add_fstr(pinfo->fd, COL_INFO,
1781                             "Data VC:%d P(S):%d P(R):%d %s", vc,
1782                             tvb_get_guint8(tvb, localoffset+1) >> 1,
1783                             pkt_type >> 1,
1784                             (tvb_get_guint8(tvb, localoffset+1) & 0x01) ? " M" : "");
1785             }
1786             if (x25_tree) {
1787                 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1788                         2, bytes0_1);
1789                 proto_tree_add_uint_hidden(x25_tree, hf_x25_type, tvb,
1790                         localoffset, 1, X25_DATA);
1791                 if (modulo == 8) {
1792                     proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1793                             localoffset, 1, pkt_type);
1794                     if (pkt_type & 0x10)
1795                         proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod8, tvb,
1796                             localoffset, 1, pkt_type);
1797                     proto_tree_add_uint(x25_tree, hf_x25_p_s_mod8, tvb,
1798                             localoffset, 1, pkt_type);
1799                     proto_tree_add_text(x25_tree, tvb, localoffset, 1,
1800                             decode_boolean_bitfield(pkt_type, 0x01, 1*8,
1801                                 NULL, "DATA"));
1802                 }
1803                 else {
1804                     proto_tree_add_uint(x25_tree, hf_x25_p_r_mod128, tvb,
1805                             localoffset, 1, pkt_type);
1806                     proto_tree_add_uint(x25_tree, hf_x25_p_s_mod128, tvb,
1807                             localoffset+1, 1,
1808                             tvb_get_guint8(tvb, localoffset+1));
1809                     if (tvb_get_guint8(tvb, localoffset+1) & 0x01)
1810                         proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod128, tvb,
1811                                 localoffset+1, 1,
1812                                 tvb_get_guint8(tvb, localoffset+1));
1813                 }
1814             }
1815             localoffset += (modulo == 8) ? 1 : 2;
1816             break;
1817         }
1818         switch (pkt_type & 0x1F)
1819         {
1820         case X25_RR:
1821             if(check_col(pinfo->fd, COL_INFO)) {
1822                 if (modulo == 8)
1823                     col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
1824                             vc, (pkt_type >> 5) & 0x07);
1825                 else
1826                     col_add_fstr(pinfo->fd, COL_INFO, "RR VC:%d P(R):%d",
1827                             vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1828             }
1829             if (x25_tree) {
1830                 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1831                         2, bytes0_1);
1832                 if (modulo == 8) {
1833                     proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1834                             localoffset, 1, pkt_type);
1835                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1836                             localoffset, 1, X25_RR);
1837                 }
1838                 else {
1839                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1840                             localoffset, 1, X25_RR);
1841                     proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
1842                             localoffset+1, 1, FALSE);
1843                 }
1844             }
1845             break;
1846
1847         case X25_RNR:
1848             if(check_col(pinfo->fd, COL_INFO)) {
1849                 if (modulo == 8)
1850                     col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
1851                             vc, (pkt_type >> 5) & 0x07);
1852                 else
1853                     col_add_fstr(pinfo->fd, COL_INFO, "RNR VC:%d P(R):%d",
1854                             vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1855             }
1856             if (x25_tree) {
1857                 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1858                         2, bytes0_1);
1859                 if (modulo == 8) {
1860                     proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1861                             localoffset, 1, pkt_type);
1862                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1863                             localoffset, 1, X25_RNR);
1864                 }
1865                 else {
1866                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1867                             localoffset, 1, X25_RNR);
1868                     proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
1869                             localoffset+1, 1, FALSE);
1870                 }
1871             }
1872             break;
1873
1874         case X25_REJ:
1875             if(check_col(pinfo->fd, COL_INFO)) {
1876                 if (modulo == 8)
1877                     col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
1878                             vc, (pkt_type >> 5) & 0x07);
1879                 else
1880                     col_add_fstr(pinfo->fd, COL_INFO, "REJ VC:%d P(R):%d",
1881                             vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
1882             }
1883             if (x25_tree) {
1884                 proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
1885                         2, bytes0_1);
1886                 if (modulo == 8) {
1887                     proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
1888                             localoffset, 1, pkt_type);
1889                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1890                             localoffset, 1, X25_REJ);
1891                 }
1892                 else {
1893                     proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
1894                             localoffset, 1, X25_REJ);
1895                     proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
1896                             localoffset+1, 1, FALSE);
1897                 }
1898             }
1899         }
1900         localoffset += (modulo == 8) ? 1 : 2;
1901     }
1902
1903     if (localoffset >= tvb_reported_length(tvb)) return;
1904
1905     next_tvb = tvb_new_subset(tvb, localoffset, -1, -1);
1906     /* search the dissector in the hash table */
1907     if ((dissect = x25_hash_get_dissect(pinfo->fd->abs_secs, pinfo->fd->abs_usecs, vc)))
1908         call_dissector(dissect, next_tvb, pinfo, tree);
1909     else {
1910         /* If the Call Req. has not been captured, assume these packets carry IP */
1911         if (tvb_get_guint8(tvb, localoffset) == 0x45) {
1912             x25_hash_add_proto_start(vc, pinfo->fd->abs_secs,
1913                     pinfo->fd->abs_usecs, ip_handle);
1914             call_dissector(ip_handle, next_tvb, pinfo, tree);
1915         }
1916         else {
1917             dissect_data(next_tvb, 0, pinfo, tree);
1918         }
1919     }
1920 }
1921
1922 void
1923 proto_register_x25(void)
1924 {
1925     static hf_register_info hf[] = {
1926         { &hf_x25_gfi,
1927           { "GFI", "x.25.gfi", FT_UINT16, BASE_BIN, NULL, 0xF000,
1928                 "General format identifier", HFILL }},
1929         { &hf_x25_abit,
1930           { "A Bit", "x.25.a", FT_BOOLEAN, 16, NULL, 0x8000,
1931                 "Address Bit", HFILL }},
1932         { &hf_x25_qbit,
1933           { "Q Bit", "x.25.q", FT_BOOLEAN, 16, NULL, 0x8000,
1934                 "Qualifier Bit", HFILL }},
1935         { &hf_x25_dbit,
1936           { "D Bit", "x.25.d", FT_BOOLEAN, 16, NULL, 0x4000,
1937                 "Delivery Confirmation Bit", HFILL }},
1938         { &hf_x25_mod,
1939           { "Modulo", "x.25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
1940                 "Specifies whether the frame is modulo 8 or 128", HFILL }},
1941         { &hf_x25_lcn,
1942           { "Logical Channel", "x.25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
1943                 "Logical Channel Number", HFILL }},
1944         { &hf_x25_type,
1945           { "Packet Type", "x.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
1946                 "Packet Type", HFILL }},
1947         { &hf_x25_p_r_mod8,
1948           { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
1949                 "Packet Receive Sequence Number", HFILL }},
1950         { &hf_x25_p_r_mod128,
1951           { "P(R)", "x.25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
1952                 "Packet Receive Sequence Number", HFILL }},
1953         { &hf_x25_mbit_mod8,
1954           { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x10,
1955                 "More Bit", HFILL }},
1956         { &hf_x25_mbit_mod128,
1957           { "M Bit", "x.25.m", FT_BOOLEAN, 8, NULL, 0x01,
1958                 "More Bit", HFILL }},
1959         { &hf_x25_p_s_mod8,
1960           { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
1961                 "Packet Send Sequence Number", HFILL }},
1962         { &hf_x25_p_s_mod128,
1963           { "P(S)", "x.25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
1964                 "Packet Send Sequence Number", HFILL }},
1965     };
1966     static gint *ett[] = {
1967         &ett_x25,
1968         &ett_x25_gfi,
1969         &ett_x25_fac,
1970         &ett_x25_fac_unknown,
1971         &ett_x25_fac_mark,
1972         &ett_x25_fac_reverse,
1973         &ett_x25_fac_throughput,
1974         &ett_x25_fac_cug,
1975         &ett_x25_fac_called_modif,
1976         &ett_x25_fac_cug_outgoing_acc,
1977         &ett_x25_fac_throughput_min,
1978         &ett_x25_fac_express_data,
1979         &ett_x25_fac_bilateral_cug,
1980         &ett_x25_fac_packet_size,
1981         &ett_x25_fac_window_size,
1982         &ett_x25_fac_rpoa_selection,
1983         &ett_x25_fac_transit_delay,
1984         &ett_x25_fac_call_transfer,
1985         &ett_x25_fac_called_addr_ext,
1986         &ett_x25_fac_ete_transit_delay,
1987         &ett_x25_fac_calling_addr_ext,
1988         &ett_x25_fac_call_deflect,
1989         &ett_x25_fac_priority
1990     };
1991
1992     proto_x25 = proto_register_protocol ("X.25", "X.25", "x.25");
1993     proto_register_field_array (proto_x25, hf, array_length(hf));
1994     proto_register_subtree_array(ett, array_length(ett));
1995     register_init_routine(&reinit_x25_hashtable);
1996
1997     register_dissector("x.25", dissect_x25, proto_x25);
1998 }
1999
2000 void
2001 proto_reg_handoff_x25(void)
2002 {
2003     /*
2004      * Get handles for the IP and OSI TP (COTP/CLTP) dissectors.
2005      */
2006     ip_handle = find_dissector("ip");
2007     ositp_handle = find_dissector("ositp");
2008
2009     dissector_add("llc.dsap", SAP_X25, dissect_x25, proto_x25);
2010 }