Cope with some of the *other* oddities that Linux ISDN appears to stick
[obnox/wireshark/wip.git] / packet-giop.c
1 /* packet-giop.c
2  * Routines for CORBA GIOP/IIOP packet disassembly
3  *
4  * Laurent Deniel <deniel@worldnet.fr>
5  *
6  * $Id: packet-giop.c,v 1.16 2000/08/07 03:20:34 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@zing.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  *
27  *
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
36 #endif
37
38 #include <string.h>
39 #include <ctype.h>
40 #include <glib.h>
41 #include "packet.h"
42
43 static int proto_giop = -1;
44 static int hf_giop_message_type = -1;
45 static int hf_giop_message_size = -1;
46
47 static gint ett_giop = -1;
48
49 /*
50  * GIOP / IIOP types definition - OMG CORBA 2.x / GIOP 1.[01]
51  * See OMG WEB site <http://www.omg.org> - CORBA+IIOP 2.2 (98-02-01.ps)
52  *
53  * Notes on mapping:
54  *
55  * <sequence> : unsigned int (# elts) + elements
56  * <string>   : unsigned int (string length) + length characters (with '\0')
57  * <enum>     : unsigned int (from 0 to n)
58  */
59
60 #define GIOP_MAGIC       "GIOP"
61 #define GIOP_MAJOR       1
62 #define GIOP_MINOR       1
63
64 #define GIOP_HEADER_SIZE 12
65
66 typedef struct OctetSequence{
67   u_int         sequence_length;
68   u_char        sequence_data[1];               /* of length bytes */
69 } OctetSequence;
70
71 typedef OctetSequence Principal;
72 typedef OctetSequence String;
73
74 /* 
75  * Some structures that contain sequences can not be directly used 
76  * (alignment problem on 64 bit architectures)
77  */
78
79 typedef struct ServiceContext {
80   u_int         context_id;
81   OctetSequence context_data;
82 } ServiceContext;
83
84 typedef struct ServiceContextList{
85   u_int           nr_context;
86   ServiceContext  service_context[1];           /* nr_context elements */
87 } ServiceContextList;
88
89 typedef enum MsgType {
90   Request,
91   Reply,
92   CancelRequest, 
93   LocateRequest,
94   LocateReply, 
95   CloseConnection,
96   MessageError,
97   Fragment                                      /* GIOP 1.1 only */
98 } MsgType;
99
100 typedef struct Version {
101   u_char        major;
102   u_char        minor;
103 } Version;
104
105 typedef struct MessageHeader {
106   char          magic[4];
107   Version       GIOP_version;
108   u_char        flags;                          /* byte_order in 1.0 */
109   u_char        message_type;
110   u_int         message_size;
111 } MessageHeader;
112
113 typedef struct RequestHeader_1_0 {
114   /* ServiceContextList service_context;*/
115   u_int         request_id;
116   u_char        response_expected;
117   OctetSequence object_key;
118   /* String     operation;              */
119   /* Principal  requesting_principal;   */
120 } RequestHeader_1_0;
121
122 typedef struct RequestHeader_1_1 {
123   /* ServiceContextList service_context;*/
124   u_int         request_id;
125   u_char        response_expected;
126   u_char        reserved[3];
127   OctetSequence object_key;
128   /* String     operation;              */
129   /* Principal  requesting_principal;   */
130 } RequestHeader_1_1;
131
132 typedef enum ReplyStatusType {
133   NO_EXCEPTION, 
134   USER_EXCEPTION, 
135   SYSTEM_EXCEPTION, 
136   LOCATION_FORWARD
137 } ReplyStatusType;
138
139 typedef struct ReplyHeader {
140   /* ServiceContext service_context;    */
141   u_int         request_id;
142   u_int         reply_status;
143 } ReplyHeader;
144
145 typedef struct SystemExceptionReplyBody {
146   String        exception_id; 
147   u_int         minor_code_value;
148   u_int         completion_status;
149 } SystemExceptionReplyBody;
150
151 typedef struct CancelRequestHeader {
152   u_int         request_id;
153 } CancelRequestHeader;
154
155 typedef struct LocateRequestHeader {
156   u_int         request_id;
157   OctetSequence object_key;
158 } LocateRequestHeader;
159
160 typedef enum LocateStatusType {
161   UNKNOWN_OBJECT, 
162   OBJECT_HERE, 
163   OBJECT_FORWARD
164 } LocateStatusType;
165
166 typedef struct LocateReplyHeader {
167   u_int         request_id;
168   u_int         locate_status;
169 } LocateReplyHeader;
170
171
172 static u_char *print_object_key(int length, u_char *from) 
173 {
174 #define MAX_OBJECT_KEY_LENGTH 64
175   static u_char buffer[MAX_OBJECT_KEY_LENGTH];
176   u_char *to = buffer;
177   int i = 0;
178   length = MIN(MAX_OBJECT_KEY_LENGTH - 3, length);
179   *to++ = '"';
180   while(i++ < length) {
181     *to = (isprint(*from)) ? *from : '.'; 
182     to++;
183     from++;
184   }  
185   *to++ = '"';
186   *to = '\0';
187   return buffer;
188 }
189
190 /* main entry point */
191
192 static gboolean
193 dissect_giop(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) 
194 {
195
196   MessageHeader header;
197   proto_tree *clnp_tree = NULL;
198   proto_item *ti;
199   u_char response_expected = 0;
200   u_int first_offset = offset;
201   u_int big_endian = FALSE;
202   u_int request_id = 0;
203   u_int message_size;
204   u_int minor_version;
205   u_int context_id;
206   u_int reply_status;
207   u_int locate_status;
208   u_int sequence_length;
209   u_int nr_seq;
210   RequestHeader_1_1 request_1_1;
211   RequestHeader_1_0 request_1_0;
212   ReplyHeader reply;
213   LocateReplyHeader locate_rep;
214   LocateRequestHeader locate_req;
215   int i;
216
217 #define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE)
218
219   if (!BYTES_ARE_IN_FRAME(offset, GIOP_HEADER_SIZE)) {
220     /* Not enough data, or not enough captured data; perhaps it was
221        a GIOP message, but we can't tell. */
222     return FALSE;
223   }
224
225   /* avoid alignment problem */
226
227   memcpy(&header, &pd[offset], sizeof(header));
228
229   /* check magic number and version */
230
231   if (memcmp(header.magic, GIOP_MAGIC, sizeof(header.magic)) != 0) {
232     /* Not a GIOP message. */
233     return FALSE;
234   }
235
236   if (check_col(fd, COL_PROTOCOL)) {
237     col_add_str(fd, COL_PROTOCOL, "GIOP");
238   }
239
240
241   if (header.GIOP_version.major != GIOP_MAJOR ||
242       ((minor_version = header.GIOP_version.minor) >  GIOP_MINOR)) {
243     /* Bad version number; should we note that and dissect the rest
244        as data, or should we return FALSE on the theory that it
245        might have been some other packet that happened to begin with
246        "GIOP"? */
247     if (check_col(fd, COL_INFO)) {
248       col_add_fstr(fd, COL_INFO, "Version %d.%d",
249                 header.GIOP_version.major, header.GIOP_version.minor);
250     }
251     if (tree) {
252       ti = proto_tree_add_item(tree, proto_giop, NullTVB, offset, 
253                           GIOP_HEADER_SIZE, FALSE);
254       clnp_tree = proto_item_add_subtree(ti, ett_giop);
255       proto_tree_add_text(clnp_tree, NullTVB, offset, GIOP_HEADER_SIZE,
256                 "Version %d.%d not supported", 
257                 header.GIOP_version.major, header.GIOP_version.minor);
258     }
259     old_dissect_data(pd, offset + GIOP_HEADER_SIZE, fd, tree);
260     return TRUE;
261   }
262
263   switch(minor_version) {
264     case 1  :
265       if (header.flags & 0x01)
266         big_endian = FALSE;
267       else
268         big_endian = TRUE;
269       break;
270     case 0  :
271       if (header.flags)
272         big_endian = FALSE;
273       else
274         big_endian = TRUE;
275       break;
276     default :
277       break;
278   }
279   
280   if (big_endian)
281     message_size = pntohl(&header.message_size);
282   else
283     message_size = pletohl(&header.message_size);
284
285   if (tree) {
286     ti = proto_tree_add_item(tree, proto_giop, NullTVB, offset, 
287                           GIOP_HEADER_SIZE + message_size, FALSE);
288     clnp_tree = proto_item_add_subtree(ti, ett_giop);
289     proto_tree_add_text(clnp_tree, NullTVB, offset,      4,
290                      "Magic number: %s", GIOP_MAGIC);
291     proto_tree_add_text(clnp_tree, NullTVB, offset +  4, 2, 
292                      "Version: %d.%d", 
293                      header.GIOP_version.major,
294                      header.GIOP_version.minor);
295     switch(minor_version) {
296       case 1  :
297         proto_tree_add_text(clnp_tree, NullTVB, offset +  6, 1, 
298                          "Flags: 0x%02x (%s%s)", 
299                          header.flags,
300                          (big_endian) ? "little" : "big",
301                          (header.flags & 0x02) ? " fragment" : "");
302         break;
303       case 0  :
304         proto_tree_add_text(clnp_tree, NullTVB, offset +  6, 1, 
305                          "Byte ordering: %s endian",
306                          (big_endian) ? "little" : "big");
307         break;
308       default :
309         break;
310     } /* minor_version */
311
312     proto_tree_add_uint_format(clnp_tree, 
313                                hf_giop_message_type,
314                                NullTVB, offset +  7, 1, 
315                                header.message_type,
316                                "Message type: %s",
317                                (header.message_type == Request) ? "Request" :
318                                (header.message_type == Reply) ? "Reply" :
319                                (header.message_type == CancelRequest) ? "CancelRequest" :
320                                (header.message_type == LocateRequest) ? "LocateRequest" :
321                                (header.message_type == LocateReply) ? "LocateReply" :
322                                (header.message_type == CloseConnection) ? "CloseConnection" :
323                                (header.message_type == MessageError) ? "MessageError" :
324                                (header.message_type == Fragment) ? "Fragment" : "?");
325
326     proto_tree_add_uint(clnp_tree, 
327                         hf_giop_message_size,
328                         NullTVB, offset +  8, 4, 
329                         message_size);
330
331   } /* tree */
332
333   offset += GIOP_HEADER_SIZE;
334
335   if (!BYTES_ARE_IN_FRAME(offset, message_size)) {
336     old_dissect_data(pd, offset, fd, tree);
337     return TRUE;
338   }
339
340   /* skip service_context in Request/Reply messages */
341
342   switch(header.message_type) {
343
344     case Request:
345     case Reply :
346
347       nr_seq = (big_endian) ? pntohl(&pd[offset]) : pletohl(&pd[offset]);
348
349       offset += sizeof(nr_seq);
350
351       for (i = 0 ; i < nr_seq ; i++) {
352
353         if (big_endian) {       
354           context_id = pntohl(&pd[offset]);
355           sequence_length = pntohl(&pd[offset + sizeof(context_id)]);
356         }
357         else {
358           context_id = pletohl(&pd[offset]);
359           sequence_length = pletohl(&pd[offset + sizeof(context_id)]);
360         }
361
362         if (tree) {
363           proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(context_id),
364                            "Context id: %d", context_id);
365           proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(context_id),
366                            sizeof(sequence_length),
367                            "Sequence length: %d", sequence_length);
368           proto_tree_add_text(clnp_tree, NullTVB,
369                            offset + 
370                            sizeof(context_id) + sizeof(sequence_length),
371                            sequence_length,
372                            "Sequence data: <not shown>");
373         }
374
375         offset += sizeof(context_id) + sizeof(sequence_length) + sequence_length;
376         offset += (sequence_length %4) ? 4 - (sequence_length%4) : 0 ;
377
378       } /* for */
379
380     default :
381       break;
382
383   } /* switch message_type */
384
385   /* decode next parts according to message type */
386
387   switch(header.message_type) {
388
389     case Request:
390
391       switch(minor_version) {
392         case 1  :
393           memcpy(&request_1_1, &pd[offset], sizeof(request_1_1));
394           response_expected = request_1_1.response_expected;
395           request_id = (big_endian)? pntohl(&request_1_1.request_id) :
396             pletohl(&request_1_1.request_id);
397           if (tree) {
398             proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
399                              "Request id: %d", request_id);
400             proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id),
401                              sizeof(request_1_1.response_expected),
402                              "Response expected: %d", 
403                              response_expected);
404             proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id) +
405                              sizeof(request_1_1.response_expected),
406                              3,
407                              "Reserved");
408           }
409           offset += sizeof(request_id) + 
410             sizeof(request_1_1.response_expected) + 3;
411           break;
412         case 0  :
413           memcpy(&request_1_0, &pd[offset], sizeof(request_1_0));
414           response_expected = request_1_0.response_expected;
415           request_id = (big_endian)? pntohl(&request_1_0.request_id) :
416             pletohl(&request_1_0.request_id);
417           if (tree) {
418             proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
419                              "Request id: %d", request_id);
420             proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id),
421                              sizeof(request_1_0.response_expected),
422                              "Response expected: %d", 
423                              response_expected);
424           }
425
426           offset += sizeof(request_id) + 
427             sizeof(request_1_0.response_expected);
428           break;
429         default :
430           break;
431       }
432
433       /* strange thing here with some ORBs/IIOP1.0 ? */
434       if ((offset - first_offset) % 4)
435         offset += 4 - (offset - first_offset)%4;
436
437       /* object_key */
438
439       sequence_length = (big_endian) ? 
440         pntohl(&pd[offset]) : pletohl(&pd[offset]);
441
442       if (tree) {
443         proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(sequence_length),
444                          "Object key length: %d", sequence_length);
445         proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(sequence_length),
446                          sequence_length,
447                          "Object key: %s",
448                          print_object_key(sequence_length, 
449                            (u_char *)&pd[offset + sizeof(sequence_length)]));
450       }
451
452       /* operation & requesting_principal */
453
454       offset += sizeof(sequence_length) + sequence_length;
455       offset += (sequence_length %4) ? 4 - (sequence_length%4) : 0 ;
456
457       sequence_length = (big_endian) ? 
458         pntohl(&pd[offset]) : pletohl(&pd[offset]);
459
460       if (sequence_length > message_size) {
461         old_dissect_data(pd, offset, fd, tree);
462         return TRUE;
463       }
464        
465       if (tree) {
466         proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(sequence_length),
467                          "Operation length: %d", sequence_length);
468         proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(sequence_length), 
469                          sequence_length,
470                          "Operation: %s",
471                          &pd[offset+sizeof(sequence_length)]);
472         proto_tree_add_text(clnp_tree, NullTVB, offset +
473                          sizeof(sequence_length)+ sequence_length,
474                          message_size - END_OF_GIOP_MESSAGE - 
475                          sizeof(sequence_length) - sequence_length,
476                          "Requesting principal: <not shown>");
477       }
478
479       if (check_col(fd, COL_INFO)) {
480         col_add_fstr(fd, COL_INFO, "Request %s %d: %s",
481                 response_expected ? "two-way" : "one-way" ,
482                 request_id,
483                 &pd[offset+sizeof(sequence_length)]);
484       }
485
486       break;
487
488     case Reply :
489
490       memcpy(&reply, &pd[offset], sizeof(reply));
491       request_id =  (big_endian) ? 
492         pntohl(&reply.request_id) : pletohl(&reply.request_id);
493       reply_status = (big_endian) ? 
494         pntohl(&reply.reply_status) : pletohl(&reply.reply_status);
495
496       if (tree) {
497         proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
498                          "Request id: %d", request_id);
499         proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id), 
500                          sizeof(reply_status),
501                          "Reply status: %s",
502                          reply_status == NO_EXCEPTION ? "no exception" :
503                          reply_status == USER_EXCEPTION ? "user exception" :
504                          reply_status == SYSTEM_EXCEPTION ? "system exception" :
505                          reply_status == LOCATION_FORWARD ? "location forward" :
506                          "?");
507       }
508
509       if (check_col(fd, COL_INFO)) {
510         col_add_fstr(fd, COL_INFO, "Reply %d: %s",
511                 request_id,
512                 reply_status == NO_EXCEPTION ? "no exception" :
513                 reply_status == USER_EXCEPTION ? "user exception" :
514                 reply_status == SYSTEM_EXCEPTION ? "system exception" :
515                 reply_status == LOCATION_FORWARD ? "location forward" :
516                 "?");
517       }
518
519       offset += sizeof(request_id) + sizeof(reply_status);
520
521       if (reply_status == SYSTEM_EXCEPTION) {
522
523         u_int minor_code_value;
524         u_int completion_status;
525
526         sequence_length = (big_endian) ? 
527           pntohl(&pd[offset]) : pletohl(&pd[offset]);
528
529         if (sequence_length > message_size) {
530           old_dissect_data(pd, offset, fd, tree);
531           return TRUE;
532         }
533
534         if (tree) {
535           proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(sequence_length),
536                            "Exception length: %d", sequence_length);
537           proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(sequence_length), 
538                            sequence_length,
539                            "Exception id: %s",
540                            &pd[offset+sizeof(sequence_length)]);
541
542         }
543
544         offset += sizeof(sequence_length) + sequence_length;
545
546         minor_code_value = (big_endian) ? 
547           pntohl(&pd[offset]) : pletohl(&pd[offset]);
548         completion_status = (big_endian) ? 
549           pntohl(&pd[offset+sizeof(minor_code_value)]) :
550           pletohl(&pd[offset+sizeof(minor_code_value)]);
551         
552         if (tree) {
553           proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(minor_code_value),
554                            "Minor code value: %d", minor_code_value);
555           proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(minor_code_value),
556                            sizeof(completion_status),
557                            "Completion Status: %d",
558                            completion_status);
559           
560         }
561
562       }
563       else if (reply_status == USER_EXCEPTION) {
564
565         sequence_length = (big_endian) ? 
566           pntohl(&pd[offset]) : pletohl(&pd[offset]);
567
568         if (sequence_length > message_size) {
569           old_dissect_data(pd, offset, fd, tree);
570           return TRUE;
571         }
572
573         if (tree) {
574           proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(sequence_length),
575                            "Exception length: %d", sequence_length);
576           proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(sequence_length), 
577                            sequence_length,
578                            "Exception id: %s",
579                            &pd[offset+sizeof(sequence_length)]);
580
581         }
582
583         offset += sizeof(sequence_length) + sequence_length;
584
585         sequence_length = (big_endian) ? 
586           pntohl(&pd[offset]) : pletohl(&pd[offset]);
587
588         if (sequence_length > message_size) {
589           old_dissect_data(pd, offset, fd, tree);
590           return TRUE;
591         }
592
593         if (tree && sequence_length) {
594           proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(sequence_length),
595                            "Exception member length: %d", sequence_length);
596           proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(sequence_length), 
597                            sequence_length,
598                            "Exception member: %s",
599                            &pd[offset+sizeof(sequence_length)]);
600         }
601
602         offset += sizeof(sequence_length) + sequence_length;
603
604       }
605       else {
606         
607         if (tree) {
608           proto_tree_add_text(clnp_tree, NullTVB, offset,
609                            message_size - END_OF_GIOP_MESSAGE,
610                            "Reply body: <not shown>");
611         }
612
613       } /* reply_status */
614
615       break;
616
617     case LocateRequest :
618
619       memcpy(&locate_req, &pd[offset], sizeof(locate_req));
620       request_id =  (big_endian) ? 
621         pntohl(&locate_req.request_id) : pletohl(&locate_req.request_id);
622
623       sequence_length = (big_endian) ? 
624         pntohl(&pd[offset+sizeof(request_id)]) : 
625         pletohl(&pd[offset+sizeof(request_id)]);
626
627       if (tree) {
628         proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
629                          "Request id: %d", request_id);
630         proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id), 
631                          sizeof(sequence_length),
632                          "Object key length: %d", sequence_length);
633         offset += sizeof(request_id) + sizeof(sequence_length);
634         proto_tree_add_text(clnp_tree, NullTVB,
635                          offset,
636                          sequence_length,
637                          "Object key: %s", 
638                          print_object_key(sequence_length, 
639                                           (u_char *)&pd[offset]));
640       }
641
642       if (check_col(fd, COL_INFO)) {
643         col_add_fstr(fd, COL_INFO, "LocateRequest %d", request_id);
644       }
645
646       break;
647
648     case LocateReply :
649
650       memcpy(&locate_rep, &pd[offset], sizeof(locate_rep));
651       request_id =  (big_endian) ? 
652         pntohl(&locate_rep.request_id) : pletohl(&locate_rep.request_id);
653       locate_status = (big_endian) ? 
654         pntohl(&locate_rep.locate_status) : pletohl(&locate_rep.locate_status);
655
656       if (tree) {
657         proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
658                          "Request id: %d", request_id);
659         proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id), 
660                          sizeof(locate_status),
661                          "Locate status: %d", locate_status);
662         offset += sizeof(request_id) + sizeof(locate_status);
663         if (locate_status == OBJECT_FORWARD) {
664           proto_tree_add_text(clnp_tree, NullTVB, offset,
665                            message_size - END_OF_GIOP_MESSAGE,
666                            "Locate reply body: <not shown>");
667         }
668       }
669
670       if (check_col(fd, COL_INFO)) {
671         col_add_fstr(fd, COL_INFO, "LocateReply %d: %s",
672                 request_id, 
673                 (locate_status == UNKNOWN_OBJECT) ? "Unknown object" :
674                 (locate_status == OBJECT_HERE) ? "Object here" :
675                 (locate_status == OBJECT_FORWARD) ? "Object forward" : "?");
676       }
677
678       break;
679
680     case CancelRequest :
681
682       request_id =  (big_endian) ? 
683         pntohl(&pd[offset]) : pletohl(&pd[offset]);
684
685       if (tree) {
686         proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
687                          "Request id: %d", request_id);
688       }
689
690       if (check_col(fd, COL_INFO)) {
691         col_add_fstr(fd, COL_INFO, "CancelRequest %d", request_id);
692       }
693
694       break;
695
696     case CloseConnection :
697       if (check_col(fd, COL_INFO)) {
698         col_add_str(fd, COL_INFO, "CloseConnection");
699       }
700       break;
701
702     case MessageError :
703       if (check_col(fd, COL_INFO)) {
704         col_add_str(fd, COL_INFO, "MessageError");
705       }
706       break;
707
708     case Fragment :
709       if (check_col(fd, COL_INFO)) {
710         col_add_str(fd, COL_INFO, "Fragment");
711       }
712       break;
713
714     default :
715       break;
716
717   } /* switch message_type */
718
719
720   offset = first_offset + GIOP_HEADER_SIZE + message_size;
721
722   if (IS_DATA_IN_FRAME(offset)) {
723     old_dissect_data(pd, offset, fd, tree);
724   }
725
726   return TRUE;
727 } /* dissect_giop */
728
729 void 
730 proto_register_giop(void)
731 {
732   static hf_register_info hf[] = {
733     { &hf_giop_message_type,
734       { "Message type",         "giop.type",    FT_UINT8,       BASE_DEC, NULL, 0x0,
735         "" }},
736     { &hf_giop_message_size,
737       { "Message size",         "giop.len",     FT_UINT32,      BASE_DEC, NULL, 0x0,
738         "" }},
739   };
740   static gint *ett[] = {
741     &ett_giop,
742   };
743
744   proto_giop = proto_register_protocol("General Inter-ORB Protocol", "giop");
745   proto_register_field_array(proto_giop, hf, array_length(hf));
746   proto_register_subtree_array(ett, array_length(ett));
747 }
748
749 void
750 proto_reg_handoff_giop(void)
751 {
752   old_heur_dissector_add("tcp", dissect_giop);
753 }