2 * Routines for CORBA GIOP/IIOP packet disassembly
4 * Laurent Deniel <deniel@worldnet.fr>
6 * $Id: packet-giop.c,v 1.10 1999/11/16 11:42:30 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 */
192 void dissect_giop(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
195 MessageHeader header;
196 proto_tree *clnp_tree = NULL;
198 u_char response_expected = 0;
199 u_int first_offset = offset;
200 u_int big_endian = FALSE;
201 u_int request_id = 0;
207 u_int sequence_length;
209 RequestHeader_1_1 request_1_1;
210 RequestHeader_1_0 request_1_0;
212 LocateReplyHeader locate_rep;
213 LocateRequestHeader locate_req;
216 #define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE)
218 if (!BYTES_ARE_IN_FRAME(offset, GIOP_HEADER_SIZE)) {
219 dissect_data(pd, offset, fd, tree);
223 /* avoid alignment problem */
225 memcpy(&header, &pd[offset], sizeof(header));
227 /* check magic number and version */
229 if (memcmp(header.magic, GIOP_MAGIC, sizeof(header.magic)) != 0) {
230 dissect_data(pd, offset, fd, tree);
234 if (header.GIOP_version.major != GIOP_MAJOR ||
235 ((minor_version = header.GIOP_version.minor) > GIOP_MINOR)) {
236 dissect_data(pd, offset, fd, tree);
240 switch(minor_version) {
242 if (header.flags & 0x01)
258 message_size = pntohl(&header.message_size);
260 message_size = pletohl(&header.message_size);
262 if (check_col(fd, COL_PROTOCOL)) {
263 col_add_str(fd, COL_PROTOCOL, "GIOP");
267 ti = proto_tree_add_item(tree, proto_giop, offset,
268 GIOP_HEADER_SIZE + message_size, NULL);
269 clnp_tree = proto_item_add_subtree(ti, ett_giop);
270 proto_tree_add_text(clnp_tree, offset, 4,
271 "Magic number: %s", GIOP_MAGIC);
272 proto_tree_add_text(clnp_tree, offset + 4, 2,
274 header.GIOP_version.major,
275 header.GIOP_version.minor);
276 switch(minor_version) {
278 proto_tree_add_text(clnp_tree, offset + 6, 1,
279 "Flags: 0x%02x (%s%s)",
281 (big_endian) ? "little" : "big",
282 (header.flags & 0x02) ? " fragment" : "");
285 proto_tree_add_text(clnp_tree, offset + 6, 1,
286 "Byte ordering: %s endian",
287 (big_endian) ? "little" : "big");
291 } /* minor_version */
293 proto_tree_add_item_format(clnp_tree,
294 hf_giop_message_type,
298 (header.message_type == Request) ? "Request" :
299 (header.message_type == Reply) ? "Reply" :
300 (header.message_type == CancelRequest) ? "CancelRequest" :
301 (header.message_type == LocateRequest) ? "LocateRequest" :
302 (header.message_type == LocateReply) ? "LocateReply" :
303 (header.message_type == CloseConnection) ? "CloseConnection" :
304 (header.message_type == MessageError) ? "MessageError" :
305 (header.message_type == Fragment) ? "Fragment" : "?");
307 proto_tree_add_item(clnp_tree,
308 hf_giop_message_size,
314 offset += GIOP_HEADER_SIZE;
316 if (!BYTES_ARE_IN_FRAME(offset, message_size)) {
317 dissect_data(pd, offset, fd, tree);
321 /* skip service_context in Request/Reply messages */
323 switch(header.message_type) {
328 nr_seq = (big_endian) ? pntohl(&pd[offset]) : pletohl(&pd[offset]);
330 offset += sizeof(nr_seq);
332 for (i = 0 ; i < nr_seq ; i++) {
335 context_id = pntohl(&pd[offset]);
336 sequence_length = pntohl(&pd[offset + sizeof(context_id)]);
339 context_id = pletohl(&pd[offset]);
340 sequence_length = pletohl(&pd[offset + sizeof(context_id)]);
344 proto_tree_add_text(clnp_tree, offset, sizeof(context_id),
345 "Context id: %d", context_id);
346 proto_tree_add_text(clnp_tree, offset + sizeof(context_id),
347 sizeof(sequence_length),
348 "Sequence length: %d", sequence_length);
349 proto_tree_add_text(clnp_tree,
351 sizeof(context_id) + sizeof(sequence_length),
353 "Sequence data: <not shown>");
356 offset += sizeof(context_id) + sizeof(sequence_length) + sequence_length;
357 offset += (sequence_length %4) ? 4 - (sequence_length%4) : 0 ;
364 } /* switch message_type */
366 /* decode next parts according to message type */
368 switch(header.message_type) {
372 switch(minor_version) {
374 memcpy(&request_1_1, &pd[offset], sizeof(request_1_1));
375 response_expected = request_1_1.response_expected;
376 request_id = (big_endian)? pntohl(&request_1_1.request_id) :
377 pletohl(&request_1_1.request_id);
379 proto_tree_add_text(clnp_tree, offset, sizeof(request_id),
380 "Request id: %d", request_id);
381 proto_tree_add_text(clnp_tree, offset + sizeof(request_id),
382 sizeof(request_1_1.response_expected),
383 "Response expected: %d",
385 proto_tree_add_text(clnp_tree, offset + sizeof(request_id) +
386 sizeof(request_1_1.response_expected),
390 offset += sizeof(request_id) +
391 sizeof(request_1_1.response_expected) + 3;
394 memcpy(&request_1_0, &pd[offset], sizeof(request_1_0));
395 response_expected = request_1_0.response_expected;
396 request_id = (big_endian)? pntohl(&request_1_0.request_id) :
397 pletohl(&request_1_0.request_id);
399 proto_tree_add_text(clnp_tree, offset, sizeof(request_id),
400 "Request id: %d", request_id);
401 proto_tree_add_text(clnp_tree, offset + sizeof(request_id),
402 sizeof(request_1_0.response_expected),
403 "Response expected: %d",
407 offset += sizeof(request_id) +
408 sizeof(request_1_0.response_expected);
414 /* strange thing here with some ORBs/IIOP1.0 ? */
415 if ((offset - first_offset) % 4)
416 offset += 4 - (offset - first_offset)%4;
420 sequence_length = (big_endian) ?
421 pntohl(&pd[offset]) : pletohl(&pd[offset]);
424 proto_tree_add_text(clnp_tree, offset, sizeof(sequence_length),
425 "Object key length: %d", sequence_length);
426 proto_tree_add_text(clnp_tree, offset + sizeof(sequence_length),
429 print_object_key(sequence_length,
430 (u_char *)&pd[offset + sizeof(sequence_length)]));
433 /* operation & requesting_principal */
435 offset += sizeof(sequence_length) + sequence_length;
436 offset += (sequence_length %4) ? 4 - (sequence_length%4) : 0 ;
438 sequence_length = (big_endian) ?
439 pntohl(&pd[offset]) : pletohl(&pd[offset]);
441 if (sequence_length > message_size) {
442 dissect_data(pd, offset, fd, tree);
447 proto_tree_add_text(clnp_tree, offset, sizeof(sequence_length),
448 "Operation length: %d", sequence_length);
449 proto_tree_add_text(clnp_tree, offset + sizeof(sequence_length),
452 &pd[offset+sizeof(sequence_length)]);
453 proto_tree_add_text(clnp_tree, offset +
454 sizeof(sequence_length)+ sequence_length,
455 message_size - END_OF_GIOP_MESSAGE -
456 sizeof(sequence_length) - sequence_length,
457 "Requesting principal: <not shown>");
460 if (check_col(fd, COL_INFO)) {
461 col_add_fstr(fd, COL_INFO, "Request %s %d: %s",
462 response_expected ? "two-way" : "one-way" ,
464 &pd[offset+sizeof(sequence_length)]);
471 memcpy(&reply, &pd[offset], sizeof(reply));
472 request_id = (big_endian) ?
473 pntohl(&reply.request_id) : pletohl(&reply.request_id);
474 reply_status = (big_endian) ?
475 pntohl(&reply.reply_status) : pletohl(&reply.reply_status);
478 proto_tree_add_text(clnp_tree, offset, sizeof(request_id),
479 "Request id: %d", request_id);
480 proto_tree_add_text(clnp_tree, offset + sizeof(request_id),
481 sizeof(reply_status),
483 reply_status == NO_EXCEPTION ? "no exception" :
484 reply_status == USER_EXCEPTION ? "user exception" :
485 reply_status == SYSTEM_EXCEPTION ? "system exception" :
486 reply_status == LOCATION_FORWARD ? "location forward" :
490 if (check_col(fd, COL_INFO)) {
491 col_add_fstr(fd, COL_INFO, "Reply %d: %s",
493 reply_status == NO_EXCEPTION ? "no exception" :
494 reply_status == USER_EXCEPTION ? "user exception" :
495 reply_status == SYSTEM_EXCEPTION ? "system exception" :
496 reply_status == LOCATION_FORWARD ? "location forward" :
500 offset += sizeof(request_id) + sizeof(reply_status);
502 if (reply_status == SYSTEM_EXCEPTION) {
504 u_int minor_code_value;
505 u_int completion_status;
507 sequence_length = (big_endian) ?
508 pntohl(&pd[offset]) : pletohl(&pd[offset]);
510 if (sequence_length > message_size) {
511 dissect_data(pd, offset, fd, tree);
516 proto_tree_add_text(clnp_tree, offset, sizeof(sequence_length),
517 "Exception length: %d", sequence_length);
518 proto_tree_add_text(clnp_tree, offset + sizeof(sequence_length),
521 &pd[offset+sizeof(sequence_length)]);
525 offset += sizeof(sequence_length) + sequence_length;
527 minor_code_value = (big_endian) ?
528 pntohl(&pd[offset]) : pletohl(&pd[offset]);
529 completion_status = (big_endian) ?
530 pntohl(&pd[offset+sizeof(minor_code_value)]) :
531 pletohl(&pd[offset+sizeof(minor_code_value)]);
534 proto_tree_add_text(clnp_tree, offset, sizeof(minor_code_value),
535 "Minor code value: %d", minor_code_value);
536 proto_tree_add_text(clnp_tree, offset + sizeof(minor_code_value),
537 sizeof(completion_status),
538 "Completion Status: %d",
544 else if (reply_status == USER_EXCEPTION) {
546 sequence_length = (big_endian) ?
547 pntohl(&pd[offset]) : pletohl(&pd[offset]);
549 if (sequence_length > message_size) {
550 dissect_data(pd, offset, fd, tree);
555 proto_tree_add_text(clnp_tree, offset, sizeof(sequence_length),
556 "Exception length: %d", sequence_length);
557 proto_tree_add_text(clnp_tree, offset + sizeof(sequence_length),
560 &pd[offset+sizeof(sequence_length)]);
564 offset += sizeof(sequence_length) + sequence_length;
566 sequence_length = (big_endian) ?
567 pntohl(&pd[offset]) : pletohl(&pd[offset]);
569 if (sequence_length > message_size) {
570 dissect_data(pd, offset, fd, tree);
574 if (tree && sequence_length) {
575 proto_tree_add_text(clnp_tree, offset, sizeof(sequence_length),
576 "Exception member length: %d", sequence_length);
577 proto_tree_add_text(clnp_tree, offset + sizeof(sequence_length),
579 "Exception member: %s",
580 &pd[offset+sizeof(sequence_length)]);
583 offset += sizeof(sequence_length) + sequence_length;
589 proto_tree_add_text(clnp_tree, offset,
590 message_size - END_OF_GIOP_MESSAGE,
591 "Reply body: <not shown>");
600 memcpy(&locate_req, &pd[offset], sizeof(locate_req));
601 request_id = (big_endian) ?
602 pntohl(&locate_req.request_id) : pletohl(&locate_req.request_id);
604 sequence_length = (big_endian) ?
605 pntohl(&pd[offset+sizeof(request_id)]) :
606 pletohl(&pd[offset+sizeof(request_id)]);
609 proto_tree_add_text(clnp_tree, offset, sizeof(request_id),
610 "Request id: %d", request_id);
611 proto_tree_add_text(clnp_tree, offset + sizeof(request_id),
612 sizeof(sequence_length),
613 "Object key length: %d", sequence_length);
614 offset += sizeof(request_id) + sizeof(sequence_length);
615 proto_tree_add_text(clnp_tree,
619 print_object_key(sequence_length,
620 (u_char *)&pd[offset]));
623 if (check_col(fd, COL_INFO)) {
624 col_add_fstr(fd, COL_INFO, "LocateRequest %d", request_id);
631 memcpy(&locate_rep, &pd[offset], sizeof(locate_rep));
632 request_id = (big_endian) ?
633 pntohl(&locate_rep.request_id) : pletohl(&locate_rep.request_id);
634 locate_status = (big_endian) ?
635 pntohl(&locate_rep.locate_status) : pletohl(&locate_rep.locate_status);
638 proto_tree_add_text(clnp_tree, offset, sizeof(request_id),
639 "Request id: %d", request_id);
640 proto_tree_add_text(clnp_tree, offset + sizeof(request_id),
641 sizeof(locate_status),
642 "Locate status: %d", locate_status);
643 offset += sizeof(request_id) + sizeof(locate_status);
644 if (locate_status == OBJECT_FORWARD) {
645 proto_tree_add_text(clnp_tree, offset,
646 message_size - END_OF_GIOP_MESSAGE,
647 "Locate reply body: <not shown>");
651 if (check_col(fd, COL_INFO)) {
652 col_add_fstr(fd, COL_INFO, "LocateReply %d: %s",
654 (locate_status == UNKNOWN_OBJECT) ? "Unknown object" :
655 (locate_status == OBJECT_HERE) ? "Object here" :
656 (locate_status == OBJECT_FORWARD) ? "Object forward" : "?");
663 request_id = (big_endian) ?
664 pntohl(&pd[offset]) : pletohl(&pd[offset]);
667 proto_tree_add_text(clnp_tree, offset, sizeof(request_id),
668 "Request id: %d", request_id);
671 if (check_col(fd, COL_INFO)) {
672 col_add_fstr(fd, COL_INFO, "CancelRequest %d", request_id);
677 case CloseConnection :
678 if (check_col(fd, COL_INFO)) {
679 col_add_str(fd, COL_INFO, "CloseConnection");
684 if (check_col(fd, COL_INFO)) {
685 col_add_str(fd, COL_INFO, "MessageError");
690 if (check_col(fd, COL_INFO)) {
691 col_add_str(fd, COL_INFO, "Fragment");
698 } /* switch message_type */
701 offset = first_offset + GIOP_HEADER_SIZE + message_size;
703 if (IS_DATA_IN_FRAME(offset)) {
704 dissect_data(pd, offset, fd, tree);
710 proto_register_giop(void)
712 static hf_register_info hf[] = {
713 { &hf_giop_message_type,
714 { "Message type", "giop.type", FT_UINT8, BASE_DEC, NULL, 0x0,
716 { &hf_giop_message_size,
717 { "Message size", "giop.len", FT_UINT32, BASE_DEC, NULL, 0x0,
720 static gint *ett[] = {
724 proto_giop = proto_register_protocol("General Inter-ORB Protocol", "giop");
725 proto_register_field_array(proto_giop, hf, array_length(hf));
726 proto_register_subtree_array(ett, array_length(ett));