2 * Routines for rpc dissection
3 * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
5 * $Id: packet-rpc.c,v 1.12 1999/11/15 14:17:19 nneul Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@unicom.net>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-smb.c
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.
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
40 #include "conversation.h"
41 #include "packet-rpc.h"
44 const value_string rpc_msg_type[3] = {
46 { RPC_REPLY, "Reply" },
50 const value_string rpc_reply_state[3] = {
51 { MSG_ACCEPTED, "accepted" },
52 { MSG_DENIED, "denied" },
56 const value_string rpc_auth_flavor[5] = {
57 { AUTH_NULL, "AUTH_NULL" },
58 { AUTH_UNIX, "AUTH_UNIX" },
59 { AUTH_SHORT, "AUTH_SHORT" },
60 { AUTH_DES, "AUTH_DES" },
64 const value_string rpc_accept_state[6] = {
65 { SUCCESS, "RPC executed successfully" },
66 { PROG_UNAVAIL, "remote hasn't exported program" },
67 { PROG_MISMATCH, "remote can't support version #" },
68 { PROC_UNAVAIL, "program can't support procedure" },
69 { GARBAGE_ARGS, "procedure can't decode params" },
73 const value_string rpc_reject_state[3] = {
74 { RPC_MISMATCH, "RPC_MISMATCH" },
75 { AUTH_ERROR, "AUTH_ERROR" },
79 const value_string rpc_auth_state[6] = {
80 { AUTH_BADCRED, "bad credential (seal broken)" },
81 { AUTH_REJECTEDCRED, "client must begin new session" },
82 { AUTH_BADVERF, "bad verifier (seal broken)" },
83 { AUTH_REJECTEDVERF, "verifier expired or replayed" },
84 { AUTH_TOOWEAK, "rejected for security reasons" },
89 /* the protocol number */
90 static int proto_rpc = -1;
93 /* Hash table with info on RPC program numbers */
94 GHashTable *rpc_progs;
96 /* Hash table with info on RPC procedure numbers */
97 GHashTable *rpc_procs;
100 /***********************************/
101 /* Hash array with procedure names */
102 /***********************************/
106 rpc_proc_equal(gconstpointer k1, gconstpointer k2)
108 rpc_proc_info_key* key1 = (rpc_proc_info_key*) k1;
109 rpc_proc_info_key* key2 = (rpc_proc_info_key*) k2;
111 return ((key1->prog == key2->prog &&
112 key1->vers == key2->vers &&
113 key1->proc == key2->proc) ?
117 /* calculate a hash key */
119 rpc_proc_hash(gconstpointer k)
121 rpc_proc_info_key* key = (rpc_proc_info_key*) k;
123 return (key->prog ^ (key->vers<<16) ^ (key->proc<<24));
127 /* insert some entries */
129 rpc_init_proc_table(guint prog, guint vers, const vsff *proc_table)
133 for (proc = proc_table ; proc->strptr!=NULL; proc++) {
134 rpc_proc_info_key *key;
135 rpc_proc_info_value *value;
137 key = (rpc_proc_info_key *) g_malloc(sizeof(rpc_proc_info_key));
140 key->proc = proc->value;
142 value = (rpc_proc_info_value *) g_malloc(sizeof(rpc_proc_info_value));
143 value->name = proc->strptr;
144 value->dissect_call = proc->dissect_call;
145 value->dissect_reply = proc->dissect_reply;
147 g_hash_table_insert(rpc_procs,key,value);
151 /*----------------------------------------*/
152 /* end of Hash array with procedure names */
153 /*----------------------------------------*/
156 /*********************************/
157 /* Hash array with program names */
158 /*********************************/
162 rpc_prog_equal(gconstpointer k1, gconstpointer k2)
164 rpc_prog_info_key* key1 = (rpc_prog_info_key*) k1;
165 rpc_prog_info_key* key2 = (rpc_prog_info_key*) k2;
167 return ((key1->prog == key2->prog) ?
172 /* calculate a hash key */
174 rpc_prog_hash(gconstpointer k)
176 rpc_prog_info_key* key = (rpc_prog_info_key*) k;
183 rpc_init_prog(int proto, guint32 prog, int ett)
185 rpc_prog_info_key *key;
186 rpc_prog_info_value *value;
188 key = (rpc_prog_info_key *) g_malloc(sizeof(rpc_prog_info_key));
191 value = (rpc_prog_info_value *) g_malloc(sizeof(rpc_prog_info_value));
192 value->proto = proto;
194 value->progname = proto_registrar_get_abbrev(proto);
196 g_hash_table_insert(rpc_progs,key,value);
199 /* return the name associated with a previously registered program. This
200 should probably eventually be expanded to use the rpc YP/NIS map
201 so that it can give names for programs not handled by ethereal */
202 char *rpc_prog_name(guint32 prog)
204 char *progname = NULL;
205 rpc_prog_info_key rpc_prog_key;
206 rpc_prog_info_value *rpc_prog;
208 rpc_prog_key.prog = prog;
209 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
210 progname = "Unknown";
213 progname = rpc_prog->progname;
219 /*--------------------------------------*/
220 /* end of Hash array with program names */
221 /*--------------------------------------*/
225 * Init the hash tables. It will be called from ethereal_proto_init().
226 * ethereal_proto_init() calls later proto_init(), which calls
227 * register_all_protocols().
228 * The proto_register_<some rpc program> functions use these hash tables
229 * here, so we need this order!
234 rpc_progs = g_hash_table_new(rpc_prog_hash, rpc_prog_equal);
235 rpc_procs = g_hash_table_new(rpc_proc_hash, rpc_proc_equal);
239 /* static array, first quick implementation, I'll switch over to GList soon */
240 rpc_call_info rpc_call_table[RPC_CALL_TABLE_LENGTH];
241 guint32 rpc_call_index = 0;
242 guint32 rpc_call_firstfree = 0;
245 rpc_call_insert(rpc_call_info *call)
247 /* some space left? */
248 if (rpc_call_firstfree<RPC_CALL_TABLE_LENGTH) {
249 /* some space left */
250 /* take the first free entry */
251 rpc_call_index = rpc_call_firstfree;
252 /* increase this limit */
253 rpc_call_firstfree++;
254 /* rpc_call_firstfree may now be RPC_CALL_TABLE_LENGTH */
258 /* the next entry, with wrap around */
259 rpc_call_index = (rpc_call_index+1) % rpc_call_firstfree;
262 /* put the entry in */
263 memcpy(&rpc_call_table[rpc_call_index],call,sizeof(*call));
269 rpc_call_lookup(rpc_call_info *call)
276 rpc_call_table[i].xid == call->xid &&
277 rpc_call_table[i].conversation == call->conversation
279 return &rpc_call_table[i];
281 if (rpc_call_firstfree) {
282 /* decrement by one, go to rpc_call_firstfree-1
283 at the start of the list */
284 i = (i-1+rpc_call_firstfree) % rpc_call_firstfree;
286 } while (i!=rpc_call_index);
292 rpc_roundup(unsigned int a)
294 unsigned int mod = a % 4;
295 return a + ((mod)? 4-mod : 0);
300 dissect_rpc_uint32(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
301 char* name, char* type)
305 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
306 value = EXTRACT_UINT(pd, offset+0);
309 proto_tree_add_text(tree, offset, 4,
310 "%s: %u", name, value);
319 dissect_rpc_uint64(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
320 char* name, char* type)
325 if (!BYTES_ARE_IN_FRAME(offset,8)) return offset;
326 value_high = EXTRACT_UINT(pd, offset+0);
327 value_low = EXTRACT_UINT(pd, offset+4);
331 proto_tree_add_text(tree, offset, 8,
332 "%s: %x%08x", name, value_high, value_low);
334 proto_tree_add_text(tree, offset, 8,
335 "%s: %u", name, value_low);
344 /* arbitrary limit */
345 #define RPC_STRING_MAXBUF 2048
348 dissect_rpc_string(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, char* name)
350 proto_item *string_item;
351 proto_tree *string_tree = NULL;
353 guint32 string_length;
355 guint32 string_length_full;
356 char string_buffer[RPC_STRING_MAXBUF];
358 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
359 string_length = EXTRACT_UINT(pd,offset+0);
360 string_length_full = rpc_roundup(string_length);
361 string_fill = string_length_full - string_length;
362 if (!BYTES_ARE_IN_FRAME(offset+4,string_length_full)) return offset;
363 if (string_length>=sizeof(string_buffer)) return offset;
364 memcpy(string_buffer,pd+offset+4,string_length);
365 string_buffer[string_length] = '\0';
367 string_item = proto_tree_add_text(tree,offset+0,
368 4+string_length_full,
369 "%s: %s", name, string_buffer);
371 string_tree = proto_item_add_subtree(string_item, ETT_RPC_STRING);
375 proto_tree_add_text(string_tree,offset+0,4,
376 "length: %u", string_length);
377 proto_tree_add_text(string_tree,offset+4,string_length,
378 "text: %s", string_buffer);
380 proto_tree_add_text(string_tree,offset+4+string_length,string_fill,
381 "fill bytes: opaque data");
384 offset += 4 + string_length_full;
389 dissect_rpc_string_item(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int hfindex)
391 proto_item *string_item;
392 proto_tree *string_tree = NULL;
394 guint32 string_length;
396 guint32 string_length_full;
397 char string_buffer[RPC_STRING_MAXBUF];
399 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
400 string_length = EXTRACT_UINT(pd,offset+0);
401 string_length_full = rpc_roundup(string_length);
402 string_fill = string_length_full - string_length;
403 if (!BYTES_ARE_IN_FRAME(offset+4,string_length_full)) return offset;
404 if (string_length>=sizeof(string_buffer)) return offset;
405 memcpy(string_buffer,pd+offset+4,string_length);
406 string_buffer[string_length] = '\0';
408 string_item = proto_tree_add_text(tree,offset+0,
409 4+string_length_full,
410 "%s: %s", proto_registrar_get_name(hfindex), string_buffer);
411 proto_tree_add_item_hidden(tree, hfindex, offset+4,
412 string_length, string_buffer);
414 string_tree = proto_item_add_subtree(string_item, ETT_RPC_STRING);
418 proto_tree_add_text(string_tree,offset+0,4,
419 "length: %u", string_length);
420 proto_tree_add_text(string_tree,offset+4,string_length,
421 "text: %s", string_buffer);
423 proto_tree_add_text(string_tree,offset+4+string_length,string_fill,
424 "fill bytes: opaque data");
427 offset += 4 + string_length_full;
433 dissect_rpc_auth( const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
439 /* both checks are made outside */
440 /* if (!BYTES_ARE_IN_FRAME(offset,8)) return; */
441 flavor = EXTRACT_UINT(pd,offset+0);
442 length = EXTRACT_UINT(pd,offset+4);
443 length_full = rpc_roundup(length);
444 /* if (!BYTES_ARE_IN_FRAME(offset+8,full_length)) return; */
447 proto_tree_add_text(tree,offset+0,4,
448 "Flavor: %s (%u)", val_to_str(flavor,rpc_auth_flavor,"Unknown"),flavor);
449 proto_tree_add_text(tree,offset+4,4,
450 "Length: %u", length);
464 proto_tree *gtree = NULL;
466 if (!BYTES_ARE_IN_FRAME(offset,4)) return;
467 stamp = EXTRACT_UINT(pd,offset+0);
469 proto_tree_add_text(tree,offset+0,4,
470 "stamp: 0x%08x", stamp);
473 offset = dissect_rpc_string(pd,offset,fd,tree,"machinename");
475 if (!BYTES_ARE_IN_FRAME(offset,4)) return;
476 uid = EXTRACT_UINT(pd,offset+0);
478 proto_tree_add_text(tree,offset+0,4,
482 if (!BYTES_ARE_IN_FRAME(offset,4)) return;
483 gid = EXTRACT_UINT(pd,offset+0);
485 proto_tree_add_text(tree,offset+0,4,
489 if (!BYTES_ARE_IN_FRAME(offset,4)) return;
490 gids_count = EXTRACT_UINT(pd,offset+0);
492 gitem = proto_tree_add_text(tree, offset, 4+gids_count*4,
494 gtree = proto_item_add_subtree(gitem, ETT_RPC_GIDS);
497 if (!BYTES_ARE_IN_FRAME(offset,4*gids_count)) return;
498 for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
499 gids_entry = EXTRACT_UINT(pd,offset+0);
501 proto_tree_add_text(gtree, offset, 4,
505 /* how can I NOW change the gitem to print a list with
506 the first 16 gids? */
514 /* I have no tcpdump file with such a packet to verify the
515 info from the RFC 1050 */
524 proto_tree_add_text(tree,offset,
525 length_full, "opaque data");
531 dissect_rpc_cred( const u_char *pd, int offset, frame_data *fd, proto_tree *tree )
538 if (!BYTES_ARE_IN_FRAME(offset,8)) return offset;
539 length = EXTRACT_UINT(pd,offset+4);
540 length_full = rpc_roundup(length);
541 if (!BYTES_ARE_IN_FRAME(offset+8,length_full)) return offset;
544 citem = proto_tree_add_text(tree, offset, 8+length_full,
546 ctree = proto_item_add_subtree(citem, ETT_RPC_CRED);
547 dissect_rpc_auth(pd, offset, fd, ctree);
549 offset += 8 + length_full;
556 dissect_rpc_verf( const u_char *pd, int offset, frame_data *fd, proto_tree *tree )
559 unsigned int length_full;
563 if (!BYTES_ARE_IN_FRAME(offset,8)) return offset;
564 length = EXTRACT_UINT(pd,offset+4);
565 length_full = rpc_roundup(length);
566 if (!BYTES_ARE_IN_FRAME(offset+8,length_full)) return offset;
569 vitem = proto_tree_add_text(tree, offset, 8+length_full,
571 vtree = proto_item_add_subtree(vitem, ETT_RPC_VERF);
572 dissect_rpc_auth(pd, offset, fd, vtree);
574 offset += 8 + length_full;
581 dissect_rpc( const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
584 rpc_call_info rpc_key;
585 rpc_call_info *rpc_call = NULL;
586 rpc_prog_info_value *rpc_prog = NULL;
587 rpc_prog_info_key rpc_prog_key;
590 unsigned int rpcvers;
592 unsigned int vers = 0;
593 unsigned int proc = 0;
597 unsigned int reply_state;
598 unsigned int accept_state;
599 unsigned int reject_state;
601 char *msg_type_name = NULL;
603 char *procname = NULL;
604 static char procname_static[20];
606 unsigned int vers_low;
607 unsigned int vers_high;
609 unsigned int auth_state;
611 proto_item *rpc_item=NULL;
612 proto_tree *rpc_tree = NULL;
614 proto_item *pitem=NULL;
615 proto_tree *ptree = NULL;
616 int offset_old = offset;
618 rpc_call_info rpc_call_msg;
619 rpc_proc_info_key key;
620 rpc_proc_info_value *value = NULL;
621 conversation_t* conversation;
622 static address null_address = { AT_NONE, 0, NULL };
624 dissect_function_t *dissect_function = NULL;
627 * Check to see whether this looks like an RPC call or reply.
629 if (!BYTES_ARE_IN_FRAME(offset,8)) {
630 /* Captured data in packet isn't enough to let us tell. */
634 /* both directions need at least this */
635 msg_type = EXTRACT_UINT(pd,offset+4);
640 /* check for RPC call */
641 if (!BYTES_ARE_IN_FRAME(offset,16)) {
642 /* Captured data in packet isn't enough to let us
647 /* XID can be anything, we don't check it.
648 We already have the message type.
649 Check whether an RPC version number of 2 is in the
650 location where it would be, and that an RPC program
651 number we know about is in the locaton where it would be. */
652 rpc_prog_key.prog = EXTRACT_UINT(pd,offset+12);
653 if (EXTRACT_UINT(pd,offset+8) != 2 ||
654 ((rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key))
656 /* They're not, so it's probably not an RPC call. */
662 /* Check for RPC reply. A reply must match a call that
663 we've seen, and the reply must be sent to the same
664 port and address that the call came from, and must
665 come from the port to which the call was sent. (We
666 don't worry about the address to which the call was
667 sent and from which the reply was sent, because there's
668 no guarantee that the reply will come from the address
669 to which the call was sent.) */
670 conversation = find_conversation(&null_address, &pi.dst,
671 pi.ptype, pi.srcport, pi.destport);
672 if (conversation == NULL) {
673 /* We haven't seen an RPC call for that conversation,
674 so we can't check for a reply to that call. */
678 /* The XIDs of the call and reply must match. */
679 rpc_key.xid = EXTRACT_UINT(pd,offset+0);
680 rpc_key.conversation = conversation;
681 if ((rpc_call = rpc_call_lookup(&rpc_key)) == NULL) {
682 /* The XID doesn't match a call from that
683 conversation, so it's probably not an RPC reply. */
689 /* The putative message type field contains neither
690 RPC_CALL nor RPC_REPLY, so it's not an RPC call or
695 if (check_col(fd, COL_PROTOCOL))
696 col_add_str(fd, COL_PROTOCOL, "RPC");
699 rpc_item = proto_tree_add_item(tree, proto_rpc, offset, END_OF_FRAME, NULL);
701 rpc_tree = proto_item_add_subtree(rpc_item, ETT_RPC);
705 xid = EXTRACT_UINT(pd,offset+0);
707 proto_tree_add_text(rpc_tree,offset+0,4,
708 "XID: 0x%x (%u)", xid, xid);
711 msg_type_name = val_to_str(msg_type,rpc_msg_type,"%u");
713 proto_tree_add_text(rpc_tree,offset+4,4,
715 msg_type_name, msg_type);
720 if (msg_type==RPC_CALL) {
721 /* we know already the proto-entry, the ETT-const,
723 proto = rpc_prog->proto;
725 progname = rpc_prog->progname;
727 rpcvers = EXTRACT_UINT(pd,offset+0);
729 proto_tree_add_text(rpc_tree,offset+0,4,
730 "RPC Version: %u", rpcvers);
733 prog = EXTRACT_UINT(pd,offset+4);
736 proto_tree_add_text(rpc_tree,offset+4,4,
737 "Program: %s (%u)", progname, prog);
740 if (check_col(fd, COL_PROTOCOL)) {
741 /* Set the protocol name to the underlying
743 col_add_fstr(fd, COL_PROTOCOL, "%s", progname);
746 if (!BYTES_ARE_IN_FRAME(offset+8,4))
748 vers = EXTRACT_UINT(pd,offset+8);
750 proto_tree_add_text(rpc_tree,offset+8,4,
751 "Program Version: %u",vers);
754 if (!BYTES_ARE_IN_FRAME(offset+12,4))
756 proc = EXTRACT_UINT(pd,offset+12);
762 value = g_hash_table_lookup(rpc_procs,&key);
764 dissect_function = value->dissect_call;
765 procname = value->name;
768 /* happens only with strange program versions or
769 non-existing dissectors */
770 dissect_function = NULL;
771 sprintf(procname_static, "proc-%u", proc);
772 procname = procname_static;
775 proto_tree_add_text(rpc_tree,offset+12,4,
776 "Procedure: %s (%u)", procname, proc);
779 if (check_col(fd, COL_INFO)) {
780 col_add_fstr(fd, COL_INFO,"V%u %s %s XID 0x%x",
787 /* Keep track of the address and port whence the call came,
788 and the port to which the call is being sent, so that
789 we can match up calls wityh replies. (We don't worry
790 about the address to which the call was sent and from
791 which the reply was sent, because there's no
792 guarantee that the reply will come from the address
793 to which the call was sent.) */
794 conversation = find_conversation(&pi.src, &null_address,
795 pi.ptype, pi.srcport, pi.destport);
796 if (conversation == NULL) {
797 /* It's not part of any conversation - create a new one. */
798 conversation = conversation_new(&pi.src, &null_address,
799 pi.ptype, pi.srcport, pi.destport, NULL);
802 /* prepare the key data */
803 rpc_call_msg.xid = xid;
804 rpc_call_msg.conversation = conversation;
806 /* look up the request */
807 if (rpc_call_lookup(&rpc_call_msg)) {
808 /* duplicate request */
809 if (check_col(fd, COL_INFO)) {
810 col_append_fstr(fd, COL_INFO, " dup XID 0x%x", xid);
814 /* prepare the value data */
815 rpc_call_msg.replies = 0;
816 rpc_call_msg.prog = prog;
817 rpc_call_msg.vers = vers;
818 rpc_call_msg.proc = proc;
819 rpc_call_msg.proc_info = value;
821 rpc_call_insert(&rpc_call_msg);
826 offset = dissect_rpc_cred(pd, offset, fd, rpc_tree);
827 offset = dissect_rpc_verf(pd, offset, fd, rpc_tree);
829 /* go to the next dissector */
830 /* goto dissect_rpc_prog; */
832 } /* end of RPC call */
833 else if (msg_type == RPC_REPLY)
835 /* we know already the type from the calling routine,
836 and we already have "rpc_call" set above. */
837 prog = rpc_call->prog;
838 vers = rpc_call->vers;
839 proc = rpc_call->proc;
840 if (rpc_call->proc_info != NULL) {
841 dissect_function = rpc_call->proc_info->dissect_reply;
842 if (rpc_call->proc_info->name != NULL) {
843 procname = rpc_call->proc_info->name;
846 sprintf(procname_static, "proc-%u", proc);
847 procname = procname_static;
851 dissect_function = NULL;
852 sprintf(procname_static, "proc-%u", proc);
853 procname = procname_static;
857 rpc_prog_key.prog = prog;
858 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
861 progname = "Unknown";
864 proto = rpc_prog->proto;
866 progname = rpc_prog->progname;
868 if (check_col(fd, COL_PROTOCOL)) {
869 /* Set the protocol name to the underlying
871 col_add_fstr(fd, COL_PROTOCOL, "%s",
876 if (check_col(fd, COL_INFO)) {
877 col_add_fstr(fd, COL_INFO,"V%u %s %s XID 0x%x",
885 proto_tree_add_text(rpc_tree,0,0,
888 proto_tree_add_text(rpc_tree,0,0,
889 "Program Version: %u", vers);
890 proto_tree_add_text(rpc_tree,0,0,
891 "Procedure: %s (%u)", procname, proc);
894 if (rpc_call->replies>1) {
895 if (check_col(fd, COL_INFO)) {
896 col_append_fstr(fd, COL_INFO, " dup XID 0x%x", xid);
900 if (!BYTES_ARE_IN_FRAME(offset,4))
902 reply_state = EXTRACT_UINT(pd,offset+0);
904 proto_tree_add_text(rpc_tree,offset+0, 4,
905 "Reply State: %s (%u)",
906 val_to_str(reply_state,rpc_reply_state,"Unknown"),
911 if (reply_state == MSG_ACCEPTED) {
912 offset = dissect_rpc_verf(pd, offset, fd, rpc_tree);
913 if (!BYTES_ARE_IN_FRAME(offset,4))
915 accept_state = EXTRACT_UINT(pd,offset+0);
917 proto_tree_add_text(rpc_tree,offset+0, 4,
918 "Accept State: %s (%u)",
919 val_to_str(accept_state,rpc_accept_state,"Unknown"),
923 switch (accept_state) {
925 /* now goto the lower protocol */
926 goto dissect_rpc_prog;
929 if (!BYTES_ARE_IN_FRAME(offset,8))
931 vers_low = EXTRACT_UINT(pd,offset+0);
932 vers_high = EXTRACT_UINT(pd,offset+4);
934 proto_tree_add_text(rpc_tree,
936 "min. Program Version: %u",
938 proto_tree_add_text(rpc_tree,
940 "max. Program Version: %u",
949 } else if (reply_state == MSG_DENIED) {
950 if (!BYTES_ARE_IN_FRAME(offset,4))
952 reject_state = EXTRACT_UINT(pd,offset+0);
954 proto_tree_add_text(rpc_tree, offset+0, 4,
955 "Reject State: %s (%u)",
956 val_to_str(reject_state,rpc_reject_state,"Unknown"),
961 if (reject_state==RPC_MISMATCH) {
962 if (!BYTES_ARE_IN_FRAME(offset,8))
964 vers_low = EXTRACT_UINT(pd,offset+0);
965 vers_high = EXTRACT_UINT(pd,offset+4);
967 proto_tree_add_text(rpc_tree,
969 "min. RPC Version: %u",
971 proto_tree_add_text(rpc_tree,
973 "max. RPC Version: %u",
977 } else if (reject_state==AUTH_ERROR) {
978 if (!BYTES_ARE_IN_FRAME(offset,4))
980 auth_state = EXTRACT_UINT(pd,offset+0);
982 proto_tree_add_text(rpc_tree,
984 "Authentication error: %s (%u)",
985 val_to_str(auth_state,rpc_auth_state,"Unknown"),
991 } /* end of RPC reply */
994 /* I know, goto is evil but it works as it is. */
996 /* now we know, that RPC was shorter */
998 proto_item_set_len(rpc_item, offset - offset_old);
1001 /* create here the program specific sub-tree */
1003 pitem = proto_tree_add_item(tree, proto, offset, END_OF_FRAME);
1005 ptree = proto_item_add_subtree(pitem, ett);
1008 /* call a specific dissection */
1009 if (dissect_function != NULL) {
1010 offset = dissect_function(pd, offset, fd, ptree);
1013 /* dissect any remaining bytes (incomplete dissection) as pure data in
1015 dissect_data(pd, offset, fd, ptree);
1020 /* will be called from file.c on every new file open */
1022 rpc_init_protocol(void)
1025 rpc_call_firstfree = 0;
1029 /* will be called once from register.c at startup time */
1031 proto_register_rpc(void)
1033 proto_rpc = proto_register_protocol("Remote Procedure Call", "rpc");