2 * Routines for CORBA GIOP/IIOP packet disassembly
4 * Laurent Deniel <deniel@worldnet.fr>
6 * $Id: packet-giop.c,v 1.16 2000/08/07 03:20:34 guy 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 #define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE)
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. */
225 /* avoid alignment problem */
227 memcpy(&header, &pd[offset], sizeof(header));
229 /* check magic number and version */
231 if (memcmp(header.magic, GIOP_MAGIC, sizeof(header.magic)) != 0) {
232 /* Not a GIOP message. */
236 if (check_col(fd, COL_PROTOCOL)) {
237 col_add_str(fd, COL_PROTOCOL, "GIOP");
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
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);
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);
259 old_dissect_data(pd, offset + GIOP_HEADER_SIZE, fd, tree);
263 switch(minor_version) {
265 if (header.flags & 0x01)
281 message_size = pntohl(&header.message_size);
283 message_size = pletohl(&header.message_size);
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,
293 header.GIOP_version.major,
294 header.GIOP_version.minor);
295 switch(minor_version) {
297 proto_tree_add_text(clnp_tree, NullTVB, offset + 6, 1,
298 "Flags: 0x%02x (%s%s)",
300 (big_endian) ? "little" : "big",
301 (header.flags & 0x02) ? " fragment" : "");
304 proto_tree_add_text(clnp_tree, NullTVB, offset + 6, 1,
305 "Byte ordering: %s endian",
306 (big_endian) ? "little" : "big");
310 } /* minor_version */
312 proto_tree_add_uint_format(clnp_tree,
313 hf_giop_message_type,
314 NullTVB, offset + 7, 1,
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" : "?");
326 proto_tree_add_uint(clnp_tree,
327 hf_giop_message_size,
328 NullTVB, offset + 8, 4,
333 offset += GIOP_HEADER_SIZE;
335 if (!BYTES_ARE_IN_FRAME(offset, message_size)) {
336 old_dissect_data(pd, offset, fd, tree);
340 /* skip service_context in Request/Reply messages */
342 switch(header.message_type) {
347 nr_seq = (big_endian) ? pntohl(&pd[offset]) : pletohl(&pd[offset]);
349 offset += sizeof(nr_seq);
351 for (i = 0 ; i < nr_seq ; i++) {
354 context_id = pntohl(&pd[offset]);
355 sequence_length = pntohl(&pd[offset + sizeof(context_id)]);
358 context_id = pletohl(&pd[offset]);
359 sequence_length = pletohl(&pd[offset + sizeof(context_id)]);
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,
370 sizeof(context_id) + sizeof(sequence_length),
372 "Sequence data: <not shown>");
375 offset += sizeof(context_id) + sizeof(sequence_length) + sequence_length;
376 offset += (sequence_length %4) ? 4 - (sequence_length%4) : 0 ;
383 } /* switch message_type */
385 /* decode next parts according to message type */
387 switch(header.message_type) {
391 switch(minor_version) {
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);
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",
404 proto_tree_add_text(clnp_tree, NullTVB, offset + sizeof(request_id) +
405 sizeof(request_1_1.response_expected),
409 offset += sizeof(request_id) +
410 sizeof(request_1_1.response_expected) + 3;
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);
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",
426 offset += sizeof(request_id) +
427 sizeof(request_1_0.response_expected);
433 /* strange thing here with some ORBs/IIOP1.0 ? */
434 if ((offset - first_offset) % 4)
435 offset += 4 - (offset - first_offset)%4;
439 sequence_length = (big_endian) ?
440 pntohl(&pd[offset]) : pletohl(&pd[offset]);
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),
448 print_object_key(sequence_length,
449 (u_char *)&pd[offset + sizeof(sequence_length)]));
452 /* operation & requesting_principal */
454 offset += sizeof(sequence_length) + sequence_length;
455 offset += (sequence_length %4) ? 4 - (sequence_length%4) : 0 ;
457 sequence_length = (big_endian) ?
458 pntohl(&pd[offset]) : pletohl(&pd[offset]);
460 if (sequence_length > message_size) {
461 old_dissect_data(pd, offset, fd, 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),
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>");
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" ,
483 &pd[offset+sizeof(sequence_length)]);
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);
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),
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" :
509 if (check_col(fd, COL_INFO)) {
510 col_add_fstr(fd, COL_INFO, "Reply %d: %s",
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" :
519 offset += sizeof(request_id) + sizeof(reply_status);
521 if (reply_status == SYSTEM_EXCEPTION) {
523 u_int minor_code_value;
524 u_int completion_status;
526 sequence_length = (big_endian) ?
527 pntohl(&pd[offset]) : pletohl(&pd[offset]);
529 if (sequence_length > message_size) {
530 old_dissect_data(pd, offset, fd, 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),
540 &pd[offset+sizeof(sequence_length)]);
544 offset += sizeof(sequence_length) + sequence_length;
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)]);
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",
563 else if (reply_status == USER_EXCEPTION) {
565 sequence_length = (big_endian) ?
566 pntohl(&pd[offset]) : pletohl(&pd[offset]);
568 if (sequence_length > message_size) {
569 old_dissect_data(pd, offset, fd, 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),
579 &pd[offset+sizeof(sequence_length)]);
583 offset += sizeof(sequence_length) + sequence_length;
585 sequence_length = (big_endian) ?
586 pntohl(&pd[offset]) : pletohl(&pd[offset]);
588 if (sequence_length > message_size) {
589 old_dissect_data(pd, offset, fd, tree);
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),
598 "Exception member: %s",
599 &pd[offset+sizeof(sequence_length)]);
602 offset += sizeof(sequence_length) + sequence_length;
608 proto_tree_add_text(clnp_tree, NullTVB, offset,
609 message_size - END_OF_GIOP_MESSAGE,
610 "Reply body: <not shown>");
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);
623 sequence_length = (big_endian) ?
624 pntohl(&pd[offset+sizeof(request_id)]) :
625 pletohl(&pd[offset+sizeof(request_id)]);
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,
638 print_object_key(sequence_length,
639 (u_char *)&pd[offset]));
642 if (check_col(fd, COL_INFO)) {
643 col_add_fstr(fd, COL_INFO, "LocateRequest %d", request_id);
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);
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>");
670 if (check_col(fd, COL_INFO)) {
671 col_add_fstr(fd, COL_INFO, "LocateReply %d: %s",
673 (locate_status == UNKNOWN_OBJECT) ? "Unknown object" :
674 (locate_status == OBJECT_HERE) ? "Object here" :
675 (locate_status == OBJECT_FORWARD) ? "Object forward" : "?");
682 request_id = (big_endian) ?
683 pntohl(&pd[offset]) : pletohl(&pd[offset]);
686 proto_tree_add_text(clnp_tree, NullTVB, offset, sizeof(request_id),
687 "Request id: %d", request_id);
690 if (check_col(fd, COL_INFO)) {
691 col_add_fstr(fd, COL_INFO, "CancelRequest %d", request_id);
696 case CloseConnection :
697 if (check_col(fd, COL_INFO)) {
698 col_add_str(fd, COL_INFO, "CloseConnection");
703 if (check_col(fd, COL_INFO)) {
704 col_add_str(fd, COL_INFO, "MessageError");
709 if (check_col(fd, COL_INFO)) {
710 col_add_str(fd, COL_INFO, "Fragment");
717 } /* switch message_type */
720 offset = first_offset + GIOP_HEADER_SIZE + message_size;
722 if (IS_DATA_IN_FRAME(offset)) {
723 old_dissect_data(pd, offset, fd, tree);
730 proto_register_giop(void)
732 static hf_register_info hf[] = {
733 { &hf_giop_message_type,
734 { "Message type", "giop.type", FT_UINT8, BASE_DEC, NULL, 0x0,
736 { &hf_giop_message_size,
737 { "Message size", "giop.len", FT_UINT32, BASE_DEC, NULL, 0x0,
740 static gint *ett[] = {
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));
750 proto_reg_handoff_giop(void)
752 old_heur_dissector_add("tcp", dissect_giop);