2 * Routines for CORBA GIOP/IIOP packet disassembly
4 * Laurent Deniel <deniel@worldnet.fr>
6 * $Id: packet-giop.c,v 1.17 2000/08/13 14:08:11 deniel Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@zing.org>
10 * Copyright 1998 Gerald Combs
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.
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.
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.
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
43 static int proto_giop = -1;
44 static int hf_giop_message_type = -1;
45 static int hf_giop_message_size = -1;
47 static gint ett_giop = -1;
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)
55 * <sequence> : unsigned int (# elts) + elements
56 * <string> : unsigned int (string length) + length characters (with '\0')
57 * <enum> : unsigned int (from 0 to n)
60 #define GIOP_MAGIC "GIOP"
64 #define GIOP_HEADER_SIZE 12
66 typedef struct OctetSequence{
67 u_int sequence_length;
68 u_char sequence_data[1]; /* of length bytes */
71 typedef OctetSequence Principal;
72 typedef OctetSequence String;
75 * Some structures that contain sequences can not be directly used
76 * (alignment problem on 64 bit architectures)
79 typedef struct ServiceContext {
81 OctetSequence context_data;
84 typedef struct ServiceContextList{
86 ServiceContext service_context[1]; /* nr_context elements */
89 typedef enum MsgType {
97 Fragment /* GIOP 1.1 only */
100 typedef struct Version {
105 typedef struct MessageHeader {
107 Version GIOP_version;
108 u_char flags; /* byte_order in 1.0 */
113 typedef struct RequestHeader_1_0 {
114 /* ServiceContextList service_context;*/
116 u_char response_expected;
117 OctetSequence object_key;
118 /* String operation; */
119 /* Principal requesting_principal; */
122 typedef struct RequestHeader_1_1 {
123 /* ServiceContextList service_context;*/
125 u_char response_expected;
127 OctetSequence object_key;
128 /* String operation; */
129 /* Principal requesting_principal; */
132 typedef enum ReplyStatusType {
139 typedef struct ReplyHeader {
140 /* ServiceContext service_context; */
145 typedef struct SystemExceptionReplyBody {
147 u_int minor_code_value;
148 u_int completion_status;
149 } SystemExceptionReplyBody;
151 typedef struct CancelRequestHeader {
153 } CancelRequestHeader;
155 typedef struct LocateRequestHeader {
157 OctetSequence object_key;
158 } LocateRequestHeader;
160 typedef enum LocateStatusType {
166 typedef struct LocateReplyHeader {
172 static u_char *print_object_key(int length, u_char *from)
174 #define MAX_OBJECT_KEY_LENGTH 64
175 static u_char buffer[MAX_OBJECT_KEY_LENGTH];
178 length = MIN(MAX_OBJECT_KEY_LENGTH - 3, length);
180 while(i++ < length) {
181 *to = (isprint(*from)) ? *from : '.';
190 /* main entry point */
193 dissect_giop(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
196 MessageHeader header;
197 proto_tree *clnp_tree = NULL;
199 u_char response_expected = 0;
200 u_int first_offset = offset;
201 u_int big_endian = FALSE;
202 u_int request_id = 0;
208 u_int sequence_length;
210 RequestHeader_1_1 request_1_1;
211 RequestHeader_1_0 request_1_0;
213 LocateReplyHeader locate_rep;
214 LocateRequestHeader locate_req;
217 if (!proto_is_protocol_enabled(proto_giop))
220 #define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE)
222 if (!BYTES_ARE_IN_FRAME(offset, GIOP_HEADER_SIZE)) {
223 /* Not enough data, or not enough captured data; perhaps it was
224 a GIOP message, but we can't tell. */
228 /* avoid alignment problem */
230 memcpy(&header, &pd[offset], sizeof(header));
232 /* check magic number and version */
234 if (memcmp(header.magic, GIOP_MAGIC, sizeof(header.magic)) != 0) {
235 /* Not a GIOP message. */
239 if (check_col(fd, COL_PROTOCOL)) {
240 col_add_str(fd, COL_PROTOCOL, "GIOP");
244 if (header.GIOP_version.major != GIOP_MAJOR ||
245 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR)) {
246 /* Bad version number; should we note that and dissect the rest
247 as data, or should we return FALSE on the theory that it
248 might have been some other packet that happened to begin with
250 if (check_col(fd, COL_INFO)) {
251 col_add_fstr(fd, COL_INFO, "Version %d.%d",
252 header.GIOP_version.major, header.GIOP_version.minor);
255 ti = proto_tree_add_item(tree, proto_giop, NullTVB, offset,
256 GIOP_HEADER_SIZE, FALSE);
257 clnp_tree = proto_item_add_subtree(ti, ett_giop);
258 proto_tree_add_text(clnp_tree, NullTVB, offset, GIOP_HEADER_SIZE,
259 "Version %d.%d not supported",
260 header.GIOP_version.major, header.GIOP_version.minor);
262 old_dissect_data(pd, offset + GIOP_HEADER_SIZE, fd, tree);
266 switch(minor_version) {
268 if (header.flags & 0x01)
284 message_size = pntohl(&header.message_size);
286 message_size = pletohl(&header.message_size);
289 ti = proto_tree_add_item(tree, proto_giop, NullTVB, offset,
290 GIOP_HEADER_SIZE + message_size, FALSE);
291 clnp_tree = proto_item_add_subtree(ti, ett_giop);
292 proto_tree_add_text(clnp_tree, NullTVB, offset, 4,
293 "Magic number: %s", GIOP_MAGIC);
294 proto_tree_add_text(clnp_tree, NullTVB, offset + 4, 2,
296 header.GIOP_version.major,
297 header.GIOP_version.minor);
298 switch(minor_version) {
300 proto_tree_add_text(clnp_tree, NullTVB, offset + 6, 1,
301 "Flags: 0x%02x (%s%s)",
303 (big_endian) ? "little" : "big",
304 (header.flags & 0x02) ? " fragment" : "");
307 proto_tree_add_text(clnp_tree, NullTVB, offset + 6, 1,
308 "Byte ordering: %s endian",
309 (big_endian) ? "little" : "big");
313 } /* minor_version */
315 proto_tree_add_uint_format(clnp_tree,
316 hf_giop_message_type,
317 NullTVB, offset + 7, 1,
320 (header.message_type == Request) ? "Request" :
321 (header.message_type == Reply) ? "Reply" :
322 (header.message_type == CancelRequest) ? "CancelRequest" :
323 (header.message_type == LocateRequest) ? "LocateRequest" :
324 (header.message_type == LocateReply) ? "LocateReply" :
325 (header.message_type == CloseConnection) ? "CloseConnection" :
326 (header.message_type == MessageError) ? "MessageError" :
327 (header.message_type == Fragment) ? "Fragment" : "?");
329 proto_tree_add_uint(clnp_tree,
330 hf_giop_message_size,
331 NullTVB, offset + 8, 4,
336 offset += GIOP_HEADER_SIZE;
338 if (!BYTES_ARE_IN_FRAME(offset, message_size)) {
339 old_dissect_data(pd, offset, fd, tree);
343 /* skip service_context in Request/Reply messages */
345 switch(header.message_type) {
350 nr_seq = (big_endian) ? pntohl(&pd[offset]) : pletohl(&pd[offset]);
352 offset += sizeof(nr_seq);
354 for (i = 0 ; i < nr_seq ; i++) {
357 context_id = pntohl(&pd[offset]);
358 sequence_length = pntohl(&pd[offset + sizeof(context_id)]);
361 context_id = pletohl(&pd[offset]);
362 sequence_length = pletohl(&pd[offset + sizeof(context_id)]);
366 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(context_id),
367 "Context id: %d", context_id);
368 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(context_id),
369 sizeof(sequence_length),
370 "Sequence length: %d", sequence_length);
371 proto_tree_add_text(clnp_tree, NullTVB,
373 sizeof(context_id) + sizeof(sequence_length),
375 "Sequence data: <not shown>");
378 offset += sizeof(context_id) + sizeof(sequence_length) + sequence_length;
379 offset += (sequence_length %4) ? 4 - (sequence_length%4) : 0 ;
386 } /* switch message_type */
388 /* decode next parts according to message type */
390 switch(header.message_type) {
394 switch(minor_version) {
396 memcpy(&request_1_1, &pd[offset], sizeof(request_1_1));
397 response_expected = request_1_1.response_expected;
398 request_id = (big_endian)? pntohl(&request_1_1.request_id) :
399 pletohl(&request_1_1.request_id);
401 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
402 "Request id: %d", request_id);
403 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id),
404 sizeof(request_1_1.response_expected),
405 "Response expected: %d",
407 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id) +
408 sizeof(request_1_1.response_expected),
412 offset += sizeof(request_id) +
413 sizeof(request_1_1.response_expected) + 3;
416 memcpy(&request_1_0, &pd[offset], sizeof(request_1_0));
417 response_expected = request_1_0.response_expected;
418 request_id = (big_endian)? pntohl(&request_1_0.request_id) :
419 pletohl(&request_1_0.request_id);
421 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
422 "Request id: %d", request_id);
423 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id),
424 sizeof(request_1_0.response_expected),
425 "Response expected: %d",
429 offset += sizeof(request_id) +
430 sizeof(request_1_0.response_expected);
436 /* strange thing here with some ORBs/IIOP1.0 ? */
437 if ((offset - first_offset) % 4)
438 offset += 4 - (offset - first_offset)%4;
442 sequence_length = (big_endian) ?
443 pntohl(&pd[offset]) : pletohl(&pd[offset]);
446 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(sequence_length),
447 "Object key length: %d", sequence_length);
448 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(sequence_length),
451 print_object_key(sequence_length,
452 (u_char *)&pd[offset + sizeof(sequence_length)]));
455 /* operation & requesting_principal */
457 offset += sizeof(sequence_length) + sequence_length;
458 offset += (sequence_length %4) ? 4 - (sequence_length%4) : 0 ;
460 sequence_length = (big_endian) ?
461 pntohl(&pd[offset]) : pletohl(&pd[offset]);
463 if (sequence_length > message_size) {
464 old_dissect_data(pd, offset, fd, tree);
469 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(sequence_length),
470 "Operation length: %d", sequence_length);
471 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(sequence_length),
474 &pd[offset+sizeof(sequence_length)]);
475 proto_tree_add_text(clnp_tree, NullTVB, offset +
476 sizeof(sequence_length)+ sequence_length,
477 message_size - END_OF_GIOP_MESSAGE -
478 sizeof(sequence_length) - sequence_length,
479 "Requesting principal: <not shown>");
482 if (check_col(fd, COL_INFO)) {
483 col_add_fstr(fd, COL_INFO, "Request %s %d: %s",
484 response_expected ? "two-way" : "one-way" ,
486 &pd[offset+sizeof(sequence_length)]);
493 memcpy(&reply, &pd[offset], sizeof(reply));
494 request_id = (big_endian) ?
495 pntohl(&reply.request_id) : pletohl(&reply.request_id);
496 reply_status = (big_endian) ?
497 pntohl(&reply.reply_status) : pletohl(&reply.reply_status);
500 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
501 "Request id: %d", request_id);
502 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id),
503 sizeof(reply_status),
505 reply_status == NO_EXCEPTION ? "no exception" :
506 reply_status == USER_EXCEPTION ? "user exception" :
507 reply_status == SYSTEM_EXCEPTION ? "system exception" :
508 reply_status == LOCATION_FORWARD ? "location forward" :
512 if (check_col(fd, COL_INFO)) {
513 col_add_fstr(fd, COL_INFO, "Reply %d: %s",
515 reply_status == NO_EXCEPTION ? "no exception" :
516 reply_status == USER_EXCEPTION ? "user exception" :
517 reply_status == SYSTEM_EXCEPTION ? "system exception" :
518 reply_status == LOCATION_FORWARD ? "location forward" :
522 offset += sizeof(request_id) + sizeof(reply_status);
524 if (reply_status == SYSTEM_EXCEPTION) {
526 u_int minor_code_value;
527 u_int completion_status;
529 sequence_length = (big_endian) ?
530 pntohl(&pd[offset]) : pletohl(&pd[offset]);
532 if (sequence_length > message_size) {
533 old_dissect_data(pd, offset, fd, tree);
538 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(sequence_length),
539 "Exception length: %d", sequence_length);
540 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(sequence_length),
543 &pd[offset+sizeof(sequence_length)]);
547 offset += sizeof(sequence_length) + sequence_length;
549 minor_code_value = (big_endian) ?
550 pntohl(&pd[offset]) : pletohl(&pd[offset]);
551 completion_status = (big_endian) ?
552 pntohl(&pd[offset+sizeof(minor_code_value)]) :
553 pletohl(&pd[offset+sizeof(minor_code_value)]);
556 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(minor_code_value),
557 "Minor code value: %d", minor_code_value);
558 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(minor_code_value),
559 sizeof(completion_status),
560 "Completion Status: %d",
566 else if (reply_status == USER_EXCEPTION) {
568 sequence_length = (big_endian) ?
569 pntohl(&pd[offset]) : pletohl(&pd[offset]);
571 if (sequence_length > message_size) {
572 old_dissect_data(pd, offset, fd, tree);
577 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(sequence_length),
578 "Exception length: %d", sequence_length);
579 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(sequence_length),
582 &pd[offset+sizeof(sequence_length)]);
586 offset += sizeof(sequence_length) + sequence_length;
588 sequence_length = (big_endian) ?
589 pntohl(&pd[offset]) : pletohl(&pd[offset]);
591 if (sequence_length > message_size) {
592 old_dissect_data(pd, offset, fd, tree);
596 if (tree && sequence_length) {
597 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(sequence_length),
598 "Exception member length: %d", sequence_length);
599 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(sequence_length),
601 "Exception member: %s",
602 &pd[offset+sizeof(sequence_length)]);
605 offset += sizeof(sequence_length) + sequence_length;
611 proto_tree_add_text(clnp_tree, NullTVB, offset,
612 message_size - END_OF_GIOP_MESSAGE,
613 "Reply body: <not shown>");
622 memcpy(&locate_req, &pd[offset], sizeof(locate_req));
623 request_id = (big_endian) ?
624 pntohl(&locate_req.request_id) : pletohl(&locate_req.request_id);
626 sequence_length = (big_endian) ?
627 pntohl(&pd[offset+sizeof(request_id)]) :
628 pletohl(&pd[offset+sizeof(request_id)]);
631 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
632 "Request id: %d", request_id);
633 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id),
634 sizeof(sequence_length),
635 "Object key length: %d", sequence_length);
636 offset += sizeof(request_id) + sizeof(sequence_length);
637 proto_tree_add_text(clnp_tree, NullTVB,
641 print_object_key(sequence_length,
642 (u_char *)&pd[offset]));
645 if (check_col(fd, COL_INFO)) {
646 col_add_fstr(fd, COL_INFO, "LocateRequest %d", request_id);
653 memcpy(&locate_rep, &pd[offset], sizeof(locate_rep));
654 request_id = (big_endian) ?
655 pntohl(&locate_rep.request_id) : pletohl(&locate_rep.request_id);
656 locate_status = (big_endian) ?
657 pntohl(&locate_rep.locate_status) : pletohl(&locate_rep.locate_status);
660 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
661 "Request id: %d", request_id);
662 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id),
663 sizeof(locate_status),
664 "Locate status: %d", locate_status);
665 offset += sizeof(request_id) + sizeof(locate_status);
666 if (locate_status == OBJECT_FORWARD) {
667 proto_tree_add_text(clnp_tree, NullTVB, offset,
668 message_size - END_OF_GIOP_MESSAGE,
669 "Locate reply body: <not shown>");
673 if (check_col(fd, COL_INFO)) {
674 col_add_fstr(fd, COL_INFO, "LocateReply %d: %s",
676 (locate_status == UNKNOWN_OBJECT) ? "Unknown object" :
677 (locate_status == OBJECT_HERE) ? "Object here" :
678 (locate_status == OBJECT_FORWARD) ? "Object forward" : "?");
685 request_id = (big_endian) ?
686 pntohl(&pd[offset]) : pletohl(&pd[offset]);
689 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
690 "Request id: %d", request_id);
693 if (check_col(fd, COL_INFO)) {
694 col_add_fstr(fd, COL_INFO, "CancelRequest %d", request_id);
699 case CloseConnection :
700 if (check_col(fd, COL_INFO)) {
701 col_add_str(fd, COL_INFO, "CloseConnection");
706 if (check_col(fd, COL_INFO)) {
707 col_add_str(fd, COL_INFO, "MessageError");
712 if (check_col(fd, COL_INFO)) {
713 col_add_str(fd, COL_INFO, "Fragment");
720 } /* switch message_type */
723 offset = first_offset + GIOP_HEADER_SIZE + message_size;
725 if (IS_DATA_IN_FRAME(offset)) {
726 old_dissect_data(pd, offset, fd, tree);
733 proto_register_giop(void)
735 static hf_register_info hf[] = {
736 { &hf_giop_message_type,
737 { "Message type", "giop.type", FT_UINT8, BASE_DEC, NULL, 0x0,
739 { &hf_giop_message_size,
740 { "Message size", "giop.len", FT_UINT32, BASE_DEC, NULL, 0x0,
743 static gint *ett[] = {
747 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "giop");
748 proto_register_field_array(proto_giop, hf, array_length(hf));
749 proto_register_subtree_array(ett, array_length(ett));
753 proto_reg_handoff_giop(void)
755 old_heur_dissector_add("tcp", dissect_giop);