2 * Routines for rpc dissection
3 * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
5 * $Id: packet-rpc.c,v 1.40 2000/08/24 22:58:55 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
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>
41 #include "conversation.h"
42 #include "packet-rpc.h"
45 #define RPC_RM_FRAGLEN 0x7fffffffL
47 static struct true_false_string yesno = { "Yes", "No" };
50 static const value_string rpc_msg_type[] = {
52 { RPC_REPLY, "Reply" },
56 static const value_string rpc_reply_state[] = {
57 { MSG_ACCEPTED, "accepted" },
58 { MSG_DENIED, "denied" },
62 const value_string rpc_auth_flavor[] = {
63 { AUTH_NULL, "AUTH_NULL" },
64 { AUTH_UNIX, "AUTH_UNIX" },
65 { AUTH_SHORT, "AUTH_SHORT" },
66 { AUTH_DES, "AUTH_DES" },
67 { RPCSEC_GSS, "RPCSEC_GSS" },
71 static const value_string rpc_authgss_proc[] = {
72 { RPCSEC_GSS_DATA, "RPCSEC_GSS_DATA" },
73 { RPCSEC_GSS_INIT, "RPCSEC_GSS_INIT" },
74 { RPCSEC_GSS_CONTINUE_INIT, "RPCSEC_GSS_CONTINUE_INIT" },
75 { RPCSEC_GSS_DESTROY, "RPCSEC_GSS_DESTROY" },
79 static const value_string rpc_authgss_svc[] = {
80 { RPCSEC_GSS_SVC_NONE, "rpcsec_gss_svc_none" },
81 { RPCSEC_GSS_SVC_INTEGRITY, "rpcsec_gss_svc_integrity" },
82 { RPCSEC_GSS_SVC_PRIVACY, "rpcsec_gss_svc_privacy" },
86 static const value_string rpc_accept_state[] = {
87 { SUCCESS, "RPC executed successfully" },
88 { PROG_UNAVAIL, "remote hasn't exported program" },
89 { PROG_MISMATCH, "remote can't support version #" },
90 { PROC_UNAVAIL, "program can't support procedure" },
91 { GARBAGE_ARGS, "procedure can't decode params" },
95 static const value_string rpc_reject_state[] = {
96 { RPC_MISMATCH, "RPC_MISMATCH" },
97 { AUTH_ERROR, "AUTH_ERROR" },
101 static const value_string rpc_auth_state[] = {
102 { AUTH_BADCRED, "bad credential (seal broken)" },
103 { AUTH_REJECTEDCRED, "client must begin new session" },
104 { AUTH_BADVERF, "bad verifier (seal broken)" },
105 { AUTH_REJECTEDVERF, "verifier expired or replayed" },
106 { AUTH_TOOWEAK, "rejected for security reasons" },
107 { RPCSEC_GSSCREDPROB, "GSS credential problem" },
108 { RPCSEC_GSSCTXPROB, "GSS context problem" },
113 /* the protocol number */
114 static int proto_rpc = -1;
115 static int hf_rpc_lastfrag = -1;
116 static int hf_rpc_fraglen = -1;
117 static int hf_rpc_xid = -1;
118 static int hf_rpc_msgtype = -1;
119 static int hf_rpc_version = -1;
120 static int hf_rpc_version_min = -1;
121 static int hf_rpc_version_max = -1;
122 static int hf_rpc_program = -1;
123 static int hf_rpc_programversion = -1;
124 static int hf_rpc_programversion_min = -1;
125 static int hf_rpc_programversion_max = -1;
126 static int hf_rpc_procedure = -1;
127 static int hf_rpc_auth_flavor = -1;
128 static int hf_rpc_auth_length = -1;
129 static int hf_rpc_auth_machinename = -1;
130 static int hf_rpc_auth_stamp = -1;
131 static int hf_rpc_auth_uid = -1;
132 static int hf_rpc_auth_gid = -1;
133 static int hf_rpc_authgss_v = -1;
134 static int hf_rpc_authgss_proc = -1;
135 static int hf_rpc_authgss_seq = -1;
136 static int hf_rpc_authgss_svc = -1;
137 static int hf_rpc_authgss_ctx = -1;
138 static int hf_rpc_authgss_major = -1;
139 static int hf_rpc_authgss_minor = -1;
140 static int hf_rpc_authgss_window = -1;
141 static int hf_rpc_authgss_token = -1;
142 static int hf_rpc_authgss_data_length = -1;
143 static int hf_rpc_authgss_data = -1;
144 static int hf_rpc_authgss_checksum = -1;
145 static int hf_rpc_state_accept = -1;
146 static int hf_rpc_state_reply = -1;
147 static int hf_rpc_state_reject = -1;
148 static int hf_rpc_state_auth = -1;
149 static int hf_rpc_dup = -1;
150 static int hf_rpc_call_dup = -1;
151 static int hf_rpc_reply_dup = -1;
152 static int hf_rpc_value_follows = -1;
154 static gint ett_rpc = -1;
155 static gint ett_rpc_string = -1;
156 static gint ett_rpc_cred = -1;
157 static gint ett_rpc_verf = -1;
158 static gint ett_rpc_gids = -1;
159 static gint ett_rpc_gss_data = -1;
161 /* Hash table with info on RPC program numbers */
162 static GHashTable *rpc_progs;
164 /* Hash table with info on RPC procedure numbers */
165 static GHashTable *rpc_procs;
168 /***********************************/
169 /* Hash array with procedure names */
170 /***********************************/
174 rpc_proc_equal(gconstpointer k1, gconstpointer k2)
176 rpc_proc_info_key* key1 = (rpc_proc_info_key*) k1;
177 rpc_proc_info_key* key2 = (rpc_proc_info_key*) k2;
179 return ((key1->prog == key2->prog &&
180 key1->vers == key2->vers &&
181 key1->proc == key2->proc) ?
185 /* calculate a hash key */
187 rpc_proc_hash(gconstpointer k)
189 rpc_proc_info_key* key = (rpc_proc_info_key*) k;
191 return (key->prog ^ (key->vers<<16) ^ (key->proc<<24));
195 /* insert some entries */
197 rpc_init_proc_table(guint prog, guint vers, const vsff *proc_table)
201 for (proc = proc_table ; proc->strptr!=NULL; proc++) {
202 rpc_proc_info_key *key;
203 rpc_proc_info_value *value;
205 key = (rpc_proc_info_key *) g_malloc(sizeof(rpc_proc_info_key));
208 key->proc = proc->value;
210 value = (rpc_proc_info_value *) g_malloc(sizeof(rpc_proc_info_value));
211 value->name = proc->strptr;
212 value->dissect_call = proc->dissect_call;
213 value->dissect_reply = proc->dissect_reply;
215 g_hash_table_insert(rpc_procs,key,value);
219 /*----------------------------------------*/
220 /* end of Hash array with procedure names */
221 /*----------------------------------------*/
224 /*********************************/
225 /* Hash array with program names */
226 /*********************************/
230 rpc_prog_equal(gconstpointer k1, gconstpointer k2)
232 rpc_prog_info_key* key1 = (rpc_prog_info_key*) k1;
233 rpc_prog_info_key* key2 = (rpc_prog_info_key*) k2;
235 return ((key1->prog == key2->prog) ?
240 /* calculate a hash key */
242 rpc_prog_hash(gconstpointer k)
244 rpc_prog_info_key* key = (rpc_prog_info_key*) k;
251 rpc_init_prog(int proto, guint32 prog, int ett)
253 rpc_prog_info_key *key;
254 rpc_prog_info_value *value;
255 char *uc_progname = NULL, *lc_progname = NULL;
257 key = (rpc_prog_info_key *) g_malloc(sizeof(rpc_prog_info_key));
260 value = (rpc_prog_info_value *) g_malloc(sizeof(rpc_prog_info_value));
261 value->proto = proto;
264 lc_progname = proto_registrar_get_abbrev(proto);
268 uc_progname = strdup(lc_progname);
269 for (i=0; i<strlen(uc_progname); i++)
271 uc_progname[i] = toupper(uc_progname[i]);
274 value->progname = uc_progname;
276 g_hash_table_insert(rpc_progs,key,value);
279 /* return the name associated with a previously registered program. This
280 should probably eventually be expanded to use the rpc YP/NIS map
281 so that it can give names for programs not handled by ethereal */
282 char *rpc_prog_name(guint32 prog)
284 char *progname = NULL;
285 rpc_prog_info_key rpc_prog_key;
286 rpc_prog_info_value *rpc_prog;
288 rpc_prog_key.prog = prog;
289 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
290 progname = "Unknown";
293 progname = rpc_prog->progname;
299 /*--------------------------------------*/
300 /* end of Hash array with program names */
301 /*--------------------------------------*/
303 /* static array, first quick implementation, I'll switch over to GList soon */
304 typedef struct _rpc_call_info {
306 conversation_t *conversation;
307 guint32 req_num; /* frame number of first request seen */
308 guint32 rep_num; /* frame number of first reply seen */
315 rpc_proc_info_value* proc_info;
318 #define RPC_CALL_TABLE_LENGTH 1000
320 rpc_call_info rpc_call_table[RPC_CALL_TABLE_LENGTH];
321 guint32 rpc_call_index = 0;
322 guint32 rpc_call_firstfree = 0;
325 rpc_call_insert(rpc_call_info *call)
327 /* some space left? */
328 if (rpc_call_firstfree<RPC_CALL_TABLE_LENGTH) {
329 /* some space left */
330 /* take the first free entry */
331 rpc_call_index = rpc_call_firstfree;
332 /* increase this limit */
333 rpc_call_firstfree++;
334 /* rpc_call_firstfree may now be RPC_CALL_TABLE_LENGTH */
338 /* the next entry, with wrap around */
339 rpc_call_index = (rpc_call_index+1) % rpc_call_firstfree;
342 /* put the entry in */
343 memcpy(&rpc_call_table[rpc_call_index],call,sizeof(*call));
348 static rpc_call_info*
349 rpc_call_lookup(rpc_call_info *call)
356 rpc_call_table[i].xid == call->xid &&
357 rpc_call_table[i].conversation == call->conversation
359 return &rpc_call_table[i];
361 if (rpc_call_firstfree) {
362 /* decrement by one, go to rpc_call_firstfree-1
363 at the start of the list */
364 i = (i-1+rpc_call_firstfree) % rpc_call_firstfree;
366 } while (i!=rpc_call_index);
372 rpc_roundup(unsigned int a)
374 unsigned int mod = a % 4;
375 return a + ((mod)? 4-mod : 0);
380 dissect_rpc_bool(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
385 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
386 value = EXTRACT_UINT(pd, offset+0);
388 proto_tree_add_boolean(tree, hfindex, NullTVB, offset, 4, value);
396 dissect_rpc_bool_tvb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
397 int hfindex, int offset)
400 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
406 dissect_rpc_uint32(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
411 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
412 value = EXTRACT_UINT(pd, offset+0);
415 proto_tree_add_text(tree, NullTVB, offset, 4,
416 "%s: %u", name, value);
425 dissect_rpc_uint32_tvb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
426 int hfindex, int offset)
429 proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
435 dissect_rpc_uint64(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
441 if (!BYTES_ARE_IN_FRAME(offset,8)) return offset;
442 value_high = EXTRACT_UINT(pd, offset+0);
443 value_low = EXTRACT_UINT(pd, offset+4);
447 proto_tree_add_text(tree, NullTVB, offset, 8,
448 "%s: 0x%x%08x", name, value_high, value_low);
450 proto_tree_add_text(tree, NullTVB, offset, 8,
451 "%s: %u", name, value_low);
460 dissect_rpc_uint64_tvb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
461 int hfindex, int offset)
466 value_high = tvb_get_ntohl(tvb, offset + 0);
467 value_low = tvb_get_ntohl(tvb, offset + 4);
471 proto_tree_add_text(tree, tvb, offset, 8,
472 "%s: 0x%x%08x", proto_registrar_get_name(hfindex), value_high, value_low);
474 proto_tree_add_uint(tree, hfindex, tvb, offset, 8, value_low);
482 dissect_rpc_opaque_data(const u_char *pd, int offset, frame_data *fd,
483 proto_tree *tree, int hfindex, gboolean string_data,
484 char **string_buffer_ret)
486 proto_item *string_item = NULL;
487 proto_tree *string_tree = NULL;
488 int old_offset = offset;
490 int length_truncated = 0;
492 int string_truncated = 0;
493 guint32 string_length = 0;
494 guint32 string_length_full;
495 guint32 string_length_packet;
496 guint32 string_length_copy = 0;
498 int fill_truncated = 0;
499 guint32 fill_length = 0;
500 guint32 fill_length_packet = 0;
501 guint32 fill_length_copy = 0;
503 char *string_buffer = NULL;
504 char *string_buffer_print = NULL;
506 if (BYTES_ARE_IN_FRAME(offset,4)) {
507 string_length = EXTRACT_UINT(pd,offset+0);
508 string_length_full = rpc_roundup(string_length);
509 string_length_packet = pi.captured_len - (offset + 4);
510 if (string_length_packet < string_length) {
511 /* truncated string */
512 string_truncated = 1;
513 string_length_copy = string_length_packet;
516 fill_length_packet = 0;
517 fill_length_copy = 0;
520 /* full string data */
521 string_truncated = 0;
522 string_length_copy = string_length;
523 fill_length = string_length_full - string_length;
524 fill_length_packet = pi.captured_len - (offset + 4 + string_length);
525 if (fill_length_packet < fill_length) {
526 /* truncated fill bytes */
527 fill_length_copy = fill_length_packet;
531 /* full fill bytes */
532 fill_length_copy = fill_length;
536 string_buffer = (char*)g_malloc(string_length_copy +
537 (string_data ? 1 : 0));
538 memcpy(string_buffer,pd+offset+4,string_length_copy);
540 string_buffer[string_length_copy] = '\0';
542 /* calculate a nice printable string */
544 if (string_length != string_length_copy) {
546 /* alloc maximum data area */
547 string_buffer_print = (char*)g_malloc(string_length_copy + 12 + 1);
548 /* copy over the data */
549 memcpy(string_buffer_print,string_buffer,string_length_copy);
550 /* append a 0 byte for sure printing */
551 string_buffer_print[string_length_copy] = '\0';
552 /* append <TRUNCATED> */
553 /* This way, we get the TRUNCATED even
554 in the case of totally wrong packets,
555 where \0 are inside the string.
556 TRUNCATED will appear at the
557 first \0 or at the end (where we
558 put the securing \0).
560 strcat(string_buffer_print,"<TRUNCATED>");
563 string_buffer_print = g_strdup("<DATA><TRUNCATED>");
568 string_buffer_print = g_strdup(string_buffer);
571 string_buffer_print = g_strdup("<DATA>");
576 string_buffer_print = g_strdup("<EMPTY>");
580 length_truncated = 1;
581 string_truncated = 2;
583 string_buffer = g_strdup("");
584 string_buffer_print = g_strdup("<TRUNCATED>");
588 string_item = proto_tree_add_text(tree, NullTVB,offset+0, END_OF_FRAME,
589 "%s: %s", proto_registrar_get_name(hfindex), string_buffer_print);
591 proto_tree_add_string_hidden(tree, hfindex, NullTVB, offset+4,
592 string_length_copy, string_buffer);
595 string_tree = proto_item_add_subtree(string_item, ett_rpc_string);
598 if (length_truncated) {
600 proto_tree_add_text(string_tree, NullTVB,
601 offset,pi.captured_len-offset,
602 "length: <TRUNCATED>");
603 offset = pi.captured_len;
606 proto_tree_add_text(string_tree, NullTVB,offset+0,4,
607 "length: %u", string_length);
611 proto_tree_add_text(string_tree, NullTVB,offset,string_length_copy,
612 "contents: %s", string_buffer_print);
613 offset += string_length_copy;
616 if (fill_truncated) {
617 proto_tree_add_text(string_tree, NullTVB,
618 offset,fill_length_copy,
619 "fill bytes: opaque data<TRUNCATED>");
622 proto_tree_add_text(string_tree, NullTVB,
623 offset,fill_length_copy,
624 "fill bytes: opaque data");
627 offset += fill_length_copy;
632 proto_item_set_len(string_item, offset - old_offset);
635 if (string_buffer != NULL) g_free (string_buffer );
636 if (string_buffer_print != NULL) {
637 if (string_buffer_ret != NULL)
638 *string_buffer_ret = string_buffer_print;
640 g_free (string_buffer_print);
647 dissect_rpc_string(const u_char *pd, int offset, frame_data *fd,
648 proto_tree *tree, int hfindex, char **string_buffer_ret)
650 offset = dissect_rpc_opaque_data(pd, offset, fd, tree, hfindex, TRUE,
658 dissect_rpc_string_tvb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int hfindex, int offset, char **string_buffer_ret)
662 int compat_offset_new;
664 tvb_compat(tvb, &pd, &compat_offset);
665 compat_offset += offset;
667 compat_offset_new = dissect_rpc_string(pd, compat_offset, pinfo->fd,
668 tree, hfindex, string_buffer_ret);
669 offset += (compat_offset_new - compat_offset);
675 dissect_rpc_data(const u_char *pd, int offset, frame_data *fd,
676 proto_tree *tree, int hfindex)
678 offset = dissect_rpc_opaque_data(pd, offset, fd, tree, hfindex, FALSE,
686 dissect_rpc_data_tvb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int hfindex, int offset)
690 int compat_offset_new;
692 tvb_compat(tvb, &pd, &compat_offset);
693 compat_offset += offset;
695 compat_offset_new = dissect_rpc_data(pd, compat_offset, pinfo->fd,
697 offset += (compat_offset_new - compat_offset);
703 dissect_rpc_list(const u_char *pd, int offset, frame_data *fd,
704 proto_tree *tree, dissect_function_t *rpc_list_dissector)
706 guint32 value_follows;
709 if (!BYTES_ARE_IN_FRAME(offset,4)) break;
710 value_follows = EXTRACT_UINT(pd, offset+0);
711 proto_tree_add_boolean(tree,hf_rpc_value_follows, NullTVB,
712 offset+0, 4, value_follows);
714 if (value_follows == 1) {
715 offset = rpc_list_dissector(pd, offset, fd, tree);
726 dissect_rpc_authunix_cred(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
735 proto_tree *gtree = NULL;
737 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
738 stamp = EXTRACT_UINT(pd,offset+0);
740 proto_tree_add_uint(tree, hf_rpc_auth_stamp, NullTVB,
744 offset = dissect_rpc_string(pd,offset,fd,
745 tree,hf_rpc_auth_machinename,NULL);
747 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
748 uid = EXTRACT_UINT(pd,offset+0);
750 proto_tree_add_uint(tree, hf_rpc_auth_uid, NullTVB,
754 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
755 gid = EXTRACT_UINT(pd,offset+0);
757 proto_tree_add_uint(tree, hf_rpc_auth_gid, NullTVB,
761 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
762 gids_count = EXTRACT_UINT(pd,offset+0);
764 gitem = proto_tree_add_text(tree, NullTVB, offset, 4+gids_count*4,
766 gtree = proto_item_add_subtree(gitem, ett_rpc_gids);
770 if (!BYTES_ARE_IN_FRAME(offset,4*gids_count)) return offset;
771 for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
772 gids_entry = EXTRACT_UINT(pd,offset+0);
774 proto_tree_add_uint(gtree, hf_rpc_auth_gid, NullTVB,
775 offset, 4, gids_entry);
778 /* how can I NOW change the gitem to print a list with
779 the first 16 gids? */
785 dissect_rpc_authgss_cred(const u_char *pd, int offset,
786 frame_data *fd, proto_tree *tree)
793 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
794 agc_v = EXTRACT_UINT(pd, offset+0);
796 proto_tree_add_uint(tree, hf_rpc_authgss_v,
797 NullTVB, offset+0, 4, agc_v);
800 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
801 agc_proc = EXTRACT_UINT(pd, offset+0);
803 proto_tree_add_uint(tree, hf_rpc_authgss_proc,
804 NullTVB, offset+0, 4, agc_proc);
807 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
808 agc_seq = EXTRACT_UINT(pd, offset+0);
810 proto_tree_add_uint(tree, hf_rpc_authgss_seq,
811 NullTVB, offset+0, 4, agc_seq);
814 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
815 agc_svc = EXTRACT_UINT(pd, offset+0);
817 proto_tree_add_uint(tree, hf_rpc_authgss_svc,
818 NullTVB, offset+0, 4, agc_svc);
821 offset = dissect_rpc_data(pd,offset,fd,tree,
828 dissect_rpc_cred( const u_char *pd, int offset, frame_data *fd, proto_tree *tree )
836 if (!BYTES_ARE_IN_FRAME(offset,8)) return offset;
837 flavor = EXTRACT_UINT(pd,offset+0);
838 length = EXTRACT_UINT(pd,offset+4);
839 length = rpc_roundup(length);
840 if (!BYTES_ARE_IN_FRAME(offset+8,length)) return offset;
843 citem = proto_tree_add_text(tree, NullTVB, offset,
844 8+length, "Credentials");
845 ctree = proto_item_add_subtree(citem, ett_rpc_cred);
846 proto_tree_add_uint(ctree, hf_rpc_auth_flavor, NullTVB,
847 offset+0, 4, flavor);
848 proto_tree_add_uint(ctree, hf_rpc_auth_length, NullTVB,
849 offset+4, 4, length);
853 dissect_rpc_authunix_cred(pd, offset+8, fd, ctree);
860 /* I have no tcpdump file with such a packet to verify the
861 info from the RFC 1050 */
868 dissect_rpc_authgss_cred(pd, offset+8, fd, ctree);
872 proto_tree_add_text(ctree, NullTVB, offset+8,
873 length,"opaque data");
877 offset += 8 + length;
883 dissect_rpc_verf( const u_char *pd, int offset, frame_data *fd, proto_tree *tree )
891 if (!BYTES_ARE_IN_FRAME(offset,8)) return offset;
892 flavor = EXTRACT_UINT(pd,offset+0);
893 length = EXTRACT_UINT(pd,offset+4);
894 length = rpc_roundup(length);
895 if (!BYTES_ARE_IN_FRAME(offset+8,length)) return offset;
898 vitem = proto_tree_add_text(tree, NullTVB, offset,
899 8+length, "Verifier");
900 vtree = proto_item_add_subtree(vitem, ett_rpc_verf);
901 proto_tree_add_uint(vtree, hf_rpc_auth_flavor, NullTVB,
902 offset+0, 4, flavor);
906 proto_tree_add_uint(vtree, hf_rpc_auth_length, NullTVB,
907 offset+4, 4, length);
908 dissect_rpc_authunix_cred(pd, offset+8, fd, vtree);
911 dissect_rpc_data(pd, offset+4, fd, vtree,
912 hf_rpc_authgss_checksum);
915 proto_tree_add_uint(vtree, hf_rpc_auth_length, NullTVB,
916 offset+4, 4, length);
918 proto_tree_add_text(vtree, NullTVB, offset+8,
919 length, "opaque data");
923 offset += 8 + length;
929 dissect_rpc_authgss_initarg(const u_char *pd, int offset,
930 frame_data *fd, proto_tree *tree)
932 offset = dissect_rpc_data(pd, offset, fd, tree, hf_rpc_authgss_token);
937 dissect_rpc_authgss_initres(const u_char *pd, int offset,
938 frame_data *fd, proto_tree *tree)
940 int major, minor, window;
942 offset = dissect_rpc_data(pd, offset, fd, tree, hf_rpc_authgss_ctx);
944 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
945 major = EXTRACT_UINT(pd,offset+0);
947 proto_tree_add_uint(tree, hf_rpc_authgss_major, NullTVB,
951 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
952 minor = EXTRACT_UINT(pd,offset+0);
954 proto_tree_add_uint(tree, hf_rpc_authgss_minor, NullTVB,
958 if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
959 window = EXTRACT_UINT(pd,offset+0);
961 proto_tree_add_uint(tree, hf_rpc_authgss_window, NullTVB,
962 offset+0, 4, window);
965 offset = dissect_rpc_data(pd, offset, fd, tree, hf_rpc_authgss_token);
971 dissect_rpc_authgss_integ_data(const u_char *pd, int offset,
972 frame_data *fd, proto_tree *tree,
973 dissect_function_t *dissect_function)
980 if (!BYTES_ARE_IN_FRAME(offset, 8)) return offset;
981 length = EXTRACT_UINT(pd, offset+0);
982 length = rpc_roundup(length);
983 seq = EXTRACT_UINT(pd,offset+4);
986 gitem = proto_tree_add_text(tree, NullTVB, offset,
987 4+length, "GSS Data");
988 gtree = proto_item_add_subtree(gitem, ett_rpc_gss_data);
989 proto_tree_add_uint(gtree, hf_rpc_authgss_data_length,
990 NullTVB, offset+0, 4, length);
991 proto_tree_add_uint(gtree, hf_rpc_authgss_seq,
992 NullTVB, offset+4, 4, seq);
993 if (dissect_function != NULL)
994 offset = dissect_function(pd, offset, fd, gtree);
996 offset += 8 + length;
997 offset = dissect_rpc_data(pd, offset, fd, tree, hf_rpc_authgss_checksum);
1002 dissect_rpc_authgss_priv_data(const u_char *pd, int offset,
1003 frame_data *fd, proto_tree *tree)
1005 offset = dissect_rpc_data(pd, offset, fd, tree, hf_rpc_authgss_data);
1010 dissect_rpc( const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1013 rpc_call_info rpc_key;
1014 rpc_call_info *rpc_call = NULL;
1015 rpc_prog_info_value *rpc_prog = NULL;
1016 rpc_prog_info_key rpc_prog_key;
1019 unsigned int rpcvers;
1020 unsigned int prog = 0;
1021 unsigned int vers = 0;
1022 unsigned int proc = 0;
1023 unsigned int flavor = 0;
1024 unsigned int gss_proc = 0;
1025 unsigned int gss_svc = 0;
1029 unsigned int reply_state;
1030 unsigned int accept_state;
1031 unsigned int reject_state;
1033 char *msg_type_name = NULL;
1035 char *procname = NULL;
1036 static char procname_static[20];
1038 unsigned int vers_low;
1039 unsigned int vers_high;
1041 unsigned int auth_state;
1043 proto_item *rpc_item=NULL;
1044 proto_tree *rpc_tree = NULL;
1046 proto_item *pitem=NULL;
1047 proto_tree *ptree = NULL;
1048 int offset_old = offset;
1053 rpc_call_info rpc_call_msg;
1054 rpc_proc_info_key key;
1055 rpc_proc_info_value *value = NULL;
1056 conversation_t* conversation;
1057 static address null_address = { AT_NONE, 0, NULL };
1059 dissect_function_t *dissect_function = NULL;
1061 if (!proto_is_protocol_enabled(proto_rpc))
1064 /* TCP uses record marking */
1065 use_rm = (pi.ptype == PT_TCP);
1067 /* the first 4 bytes are special in "record marking mode" */
1069 if (!BYTES_ARE_IN_FRAME(offset,4))
1071 rpc_rm = EXTRACT_UINT(pd,offset);
1076 * Check to see whether this looks like an RPC call or reply.
1078 if (!BYTES_ARE_IN_FRAME(offset,8)) {
1079 /* Captured data in packet isn't enough to let us tell. */
1083 /* both directions need at least this */
1084 msg_type = EXTRACT_UINT(pd,offset+4);
1089 /* check for RPC call */
1090 if (!BYTES_ARE_IN_FRAME(offset,16)) {
1091 /* Captured data in packet isn't enough to let us
1096 /* XID can be anything, we don't check it.
1097 We already have the message type.
1098 Check whether an RPC version number of 2 is in the
1099 location where it would be, and that an RPC program
1100 number we know about is in the locaton where it would be. */
1101 rpc_prog_key.prog = EXTRACT_UINT(pd,offset+12);
1102 if (EXTRACT_UINT(pd,offset+8) != 2 ||
1103 ((rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key))
1105 /* They're not, so it's probably not an RPC call. */
1111 /* Check for RPC reply. A reply must match a call that
1112 we've seen, and the reply must be sent to the same
1113 port and address that the call came from, and must
1114 come from the port to which the call was sent. (We
1115 don't worry about the address to which the call was
1116 sent and from which the reply was sent, because there's
1117 no guarantee that the reply will come from the address
1118 to which the call was sent.) */
1119 conversation = find_conversation(&null_address, &pi.dst,
1120 pi.ptype, pi.srcport, pi.destport);
1121 if (conversation == NULL) {
1122 /* We haven't seen an RPC call for that conversation,
1123 so we can't check for a reply to that call. */
1127 /* The XIDs of the call and reply must match. */
1128 rpc_key.xid = EXTRACT_UINT(pd,offset+0);
1129 rpc_key.conversation = conversation;
1130 if ((rpc_call = rpc_call_lookup(&rpc_key)) == NULL) {
1131 /* The XID doesn't match a call from that
1132 conversation, so it's probably not an RPC reply. */
1138 /* The putative message type field contains neither
1139 RPC_CALL nor RPC_REPLY, so it's not an RPC call or
1144 if (check_col(fd, COL_PROTOCOL))
1145 col_add_str(fd, COL_PROTOCOL, "RPC");
1148 rpc_item = proto_tree_add_item(tree, proto_rpc, NullTVB, offset, END_OF_FRAME, FALSE);
1150 rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
1154 if (use_rm && rpc_tree) {
1155 proto_tree_add_boolean(rpc_tree,hf_rpc_lastfrag, NullTVB,
1156 offset-4, 4, (rpc_rm >> 31) & 0x1);
1157 proto_tree_add_uint(rpc_tree,hf_rpc_fraglen, NullTVB,
1158 offset-4, 4, rpc_rm & RPC_RM_FRAGLEN);
1161 xid = EXTRACT_UINT(pd,offset+0);
1163 proto_tree_add_uint_format(rpc_tree,hf_rpc_xid, NullTVB,
1164 offset+0, 4, xid, "XID: 0x%x (%u)", xid, xid);
1167 msg_type_name = val_to_str(msg_type,rpc_msg_type,"%u");
1169 proto_tree_add_uint(rpc_tree, hf_rpc_msgtype, NullTVB,
1170 offset+4, 4, msg_type);
1175 if (msg_type==RPC_CALL) {
1176 /* we know already the proto-entry, the ETT-const,
1178 proto = rpc_prog->proto;
1179 ett = rpc_prog->ett;
1180 progname = rpc_prog->progname;
1182 rpcvers = EXTRACT_UINT(pd,offset+0);
1184 proto_tree_add_uint(rpc_tree,
1185 hf_rpc_version, NullTVB, offset+0, 4, rpcvers);
1188 prog = EXTRACT_UINT(pd,offset+4);
1191 proto_tree_add_uint_format(rpc_tree,
1192 hf_rpc_program, NullTVB, offset+4, 4, prog,
1193 "Program: %s (%u)", progname, prog);
1196 if (check_col(fd, COL_PROTOCOL)) {
1197 /* Set the protocol name to the underlying
1199 col_add_fstr(fd, COL_PROTOCOL, "%s", progname);
1202 if (!BYTES_ARE_IN_FRAME(offset+8,4))
1204 vers = EXTRACT_UINT(pd,offset+8);
1206 proto_tree_add_uint(rpc_tree,
1207 hf_rpc_programversion, NullTVB, offset+8, 4, vers);
1210 if (!BYTES_ARE_IN_FRAME(offset+12,4))
1212 proc = EXTRACT_UINT(pd,offset+12);
1214 /* Check for RPCSEC_GSS */
1215 if (proc == 0 && BYTES_ARE_IN_FRAME(offset+16,28)) {
1216 flavor = EXTRACT_UINT(pd, offset+16);
1217 if (flavor == RPCSEC_GSS) {
1218 gss_proc = EXTRACT_UINT(pd, offset+28);
1219 gss_svc = EXTRACT_UINT(pd, offset+34);
1226 if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
1227 dissect_function = value->dissect_call;
1228 procname = value->name;
1231 /* happens only with strange program versions or
1232 non-existing dissectors */
1233 dissect_function = NULL;
1234 sprintf(procname_static, "proc-%u", proc);
1235 procname = procname_static;
1239 proto_tree_add_uint_format(rpc_tree,
1240 hf_rpc_procedure, NullTVB, offset+12, 4, proc,
1241 "Procedure: %s (%u)", procname, proc);
1244 if (check_col(fd, COL_INFO)) {
1245 col_add_fstr(fd, COL_INFO,"V%u %s %s XID 0x%x",
1252 /* Keep track of the address and port whence the call came,
1253 and the port to which the call is being sent, so that
1254 we can match up calls wityh replies. (We don't worry
1255 about the address to which the call was sent and from
1256 which the reply was sent, because there's no
1257 guarantee that the reply will come from the address
1258 to which the call was sent.) */
1259 conversation = find_conversation(&pi.src, &null_address,
1260 pi.ptype, pi.srcport, pi.destport);
1261 if (conversation == NULL) {
1262 /* It's not part of any conversation - create a new one. */
1263 conversation = conversation_new(&pi.src, &null_address,
1264 pi.ptype, pi.srcport, pi.destport, NULL);
1267 /* prepare the key data */
1268 rpc_call_msg.xid = xid;
1269 rpc_call_msg.conversation = conversation;
1271 /* look up the request */
1272 if ((rpc_call = rpc_call_lookup(&rpc_call_msg)) != NULL) {
1273 /* We've seen a request with this XID, with the same
1274 source and destination, before - but was it
1276 if (fd->num != rpc_call->req_num) {
1277 /* No, so it's a duplicate request.
1279 if (check_col(fd, COL_INFO)) {
1280 col_append_fstr(fd, COL_INFO, " dup XID 0x%x", xid);
1282 proto_tree_add_uint_hidden(rpc_tree,
1283 hf_rpc_dup, NullTVB, 0,0, xid);
1284 proto_tree_add_uint_hidden(rpc_tree,
1285 hf_rpc_call_dup, NullTVB, 0,0, xid);
1291 /* Prepare the value data.
1292 "req_num" and "rep_num" are frame numbers;
1293 frame numbers are 1-origin, so we use 0
1294 to mean "we don't yet know in which frame
1295 the reply for this call appears". */
1296 rpc_call_msg.req_num = fd->num;
1297 rpc_call_msg.rep_num = 0;
1298 rpc_call_msg.prog = prog;
1299 rpc_call_msg.vers = vers;
1300 rpc_call_msg.proc = proc;
1301 rpc_call_msg.flavor = flavor;
1302 rpc_call_msg.gss_proc = gss_proc;
1303 rpc_call_msg.gss_svc = gss_svc;
1304 rpc_call_msg.proc_info = value;
1306 rpc_call_insert(&rpc_call_msg);
1311 offset = dissect_rpc_cred(pd, offset, fd, rpc_tree);
1312 offset = dissect_rpc_verf(pd, offset, fd, rpc_tree);
1314 /* go to the next dissector */
1316 } /* end of RPC call */
1317 else if (msg_type == RPC_REPLY)
1319 /* we know already the type from the calling routine,
1320 and we already have "rpc_call" set above. */
1321 prog = rpc_call->prog;
1322 vers = rpc_call->vers;
1323 proc = rpc_call->proc;
1324 flavor = rpc_call->flavor;
1325 gss_proc = rpc_call->gss_proc;
1326 gss_svc = rpc_call->gss_svc;
1328 /* Indicate the frame to which this is a reply. */
1329 proto_tree_add_text(rpc_tree, NullTVB, 0, 0,
1330 "This is a reply to a request starting in frame %u",
1333 if (rpc_call->proc_info != NULL) {
1334 dissect_function = rpc_call->proc_info->dissect_reply;
1335 if (rpc_call->proc_info->name != NULL) {
1336 procname = rpc_call->proc_info->name;
1339 sprintf(procname_static, "proc-%u", proc);
1340 procname = procname_static;
1344 dissect_function = NULL;
1345 sprintf(procname_static, "proc-%u", proc);
1346 procname = procname_static;
1349 rpc_prog_key.prog = prog;
1350 if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
1353 progname = "Unknown";
1356 proto = rpc_prog->proto;
1357 ett = rpc_prog->ett;
1358 progname = rpc_prog->progname;
1360 if (check_col(fd, COL_PROTOCOL)) {
1361 /* Set the protocol name to the underlying
1363 col_add_fstr(fd, COL_PROTOCOL, "%s",
1368 if (check_col(fd, COL_INFO)) {
1369 col_add_fstr(fd, COL_INFO,"V%u %s %s XID 0x%x",
1377 proto_tree_add_uint_format(rpc_tree,
1378 hf_rpc_program, NullTVB, 0, 0, prog,
1379 "Program: %s (%u)", progname, prog);
1380 proto_tree_add_uint(rpc_tree,
1381 hf_rpc_programversion, NullTVB, 0, 0, vers);
1382 proto_tree_add_uint_format(rpc_tree,
1383 hf_rpc_procedure, NullTVB, 0, 0, proc,
1384 "Procedure: %s (%u)", procname, proc);
1387 if (rpc_call->rep_num == 0) {
1388 /* We have not yet seen a reply to that call, so
1389 this must be the first reply; remember its
1391 rpc_call->rep_num = fd->num;
1393 /* We have seen a reply to this call - but was it
1395 if (rpc_call->rep_num != fd->num) {
1396 /* No, so it's a duplicate reply.
1398 if (check_col(fd, COL_INFO)) {
1399 col_append_fstr(fd, COL_INFO, " dup XID 0x%x", xid);
1401 proto_tree_add_uint_hidden(rpc_tree,
1402 hf_rpc_dup, NullTVB, 0,0, xid);
1403 proto_tree_add_uint_hidden(rpc_tree,
1404 hf_rpc_reply_dup, NullTVB, 0,0, xid);
1410 if (!BYTES_ARE_IN_FRAME(offset,4))
1412 reply_state = EXTRACT_UINT(pd,offset+0);
1414 proto_tree_add_uint(rpc_tree, hf_rpc_state_reply, NullTVB,
1415 offset+0, 4, reply_state);
1419 if (reply_state == MSG_ACCEPTED) {
1420 offset = dissect_rpc_verf(pd, offset, fd, rpc_tree);
1421 if (!BYTES_ARE_IN_FRAME(offset,4))
1423 accept_state = EXTRACT_UINT(pd,offset+0);
1425 proto_tree_add_uint(rpc_tree, hf_rpc_state_accept, NullTVB,
1426 offset+0, 4, accept_state);
1429 switch (accept_state) {
1431 /* go to the next dissector */
1434 if (!BYTES_ARE_IN_FRAME(offset,8))
1436 vers_low = EXTRACT_UINT(pd,offset+0);
1437 vers_high = EXTRACT_UINT(pd,offset+4);
1439 proto_tree_add_uint(rpc_tree,
1440 hf_rpc_programversion_min,
1441 NullTVB, offset+0, 4, vers_low);
1442 proto_tree_add_uint(rpc_tree,
1443 hf_rpc_programversion_max,
1444 NullTVB, offset+4, 4, vers_high);
1452 } else if (reply_state == MSG_DENIED) {
1453 if (!BYTES_ARE_IN_FRAME(offset,4))
1455 reject_state = EXTRACT_UINT(pd,offset+0);
1457 proto_tree_add_uint(rpc_tree,
1458 hf_rpc_state_reject, NullTVB, offset+0, 4,
1463 if (reject_state==RPC_MISMATCH) {
1464 if (!BYTES_ARE_IN_FRAME(offset,8))
1466 vers_low = EXTRACT_UINT(pd,offset+0);
1467 vers_high = EXTRACT_UINT(pd,offset+4);
1469 proto_tree_add_uint(rpc_tree,
1471 NullTVB, offset+0, 4, vers_low);
1472 proto_tree_add_uint(rpc_tree,
1474 NullTVB, offset+4, 4, vers_high);
1477 } else if (reject_state==AUTH_ERROR) {
1478 if (!BYTES_ARE_IN_FRAME(offset,4))
1480 auth_state = EXTRACT_UINT(pd,offset+0);
1482 proto_tree_add_uint(rpc_tree,
1483 hf_rpc_state_auth, NullTVB, offset+0, 4,
1489 } /* end of RPC reply */
1491 /* now we know, that RPC was shorter */
1493 proto_item_set_len(rpc_item, offset - offset_old);
1496 /* create here the program specific sub-tree */
1498 pitem = proto_tree_add_item(tree, proto, NullTVB, offset, END_OF_FRAME, FALSE);
1500 ptree = proto_item_add_subtree(pitem, ett);
1504 proto_tree_add_uint(ptree,
1505 hf_rpc_programversion, NullTVB, 0, 0, vers);
1506 proto_tree_add_uint_format(ptree,
1507 hf_rpc_procedure, NullTVB, 0, 0, proc,
1508 "Procedure: %s (%u)", procname, proc);
1512 /* RPCSEC_GSS processing. */
1513 if (flavor == RPCSEC_GSS) {
1515 case RPCSEC_GSS_INIT:
1516 case RPCSEC_GSS_CONTINUE_INIT:
1517 if (msg_type == RPC_CALL) {
1518 offset = dissect_rpc_authgss_initarg(pd, offset, fd, ptree);
1521 offset = dissect_rpc_authgss_initres(pd, offset, fd, ptree);
1524 case RPCSEC_GSS_DATA:
1525 if (gss_svc == RPCSEC_GSS_SVC_NONE) {
1526 if (dissect_function != NULL &&
1527 proto_is_protocol_enabled(proto))
1528 offset = dissect_function(pd, offset, fd, ptree);
1530 else if (gss_svc == RPCSEC_GSS_SVC_INTEGRITY) {
1531 offset = dissect_rpc_authgss_integ_data(pd, offset, fd, ptree,
1532 (proto_is_protocol_enabled(proto) ?
1533 dissect_function : NULL));
1535 else if (gss_svc == RPCSEC_GSS_SVC_PRIVACY) {
1536 offset = dissect_rpc_authgss_priv_data(pd, offset, fd, ptree);
1540 dissect_function = NULL;
1544 else if (dissect_function != NULL &&
1545 proto_is_protocol_enabled(proto)) {
1546 offset = dissect_function(pd, offset, fd, ptree);
1549 /* dissect any remaining bytes (incomplete dissection) as pure data in
1551 old_dissect_data(pd, offset, fd, ptree);
1557 /* Discard any state we've saved. */
1559 rpc_init_protocol(void)
1561 memset(rpc_call_table, '\0', sizeof rpc_call_table);
1563 rpc_call_firstfree = 0;
1567 /* will be called once from register.c at startup time */
1569 proto_register_rpc(void)
1571 static hf_register_info hf[] = {
1572 { &hf_rpc_lastfrag, {
1573 "Last Fragment", "rpc.lastfrag", FT_BOOLEAN, BASE_NONE,
1574 &yesno, 0, "Last Fragment" }},
1575 { &hf_rpc_fraglen, {
1576 "Fragment Length", "rpc.fraglen", FT_UINT32, BASE_DEC,
1577 NULL, 0, "Fragment Length" }},
1579 "XID", "rpc.xid", FT_UINT32, BASE_HEX,
1581 { &hf_rpc_msgtype, {
1582 "Message Type", "rpc.msgtyp", FT_UINT32, BASE_DEC,
1583 VALS(rpc_msg_type), 0, "Message Type" }},
1584 { &hf_rpc_state_reply, {
1585 "Reply State", "rpc.replystat", FT_UINT32, BASE_DEC,
1586 VALS(rpc_reply_state), 0, "Reply State" }},
1587 { &hf_rpc_state_accept, {
1588 "Accept State", "rpc.state_accept", FT_UINT32, BASE_DEC,
1589 VALS(rpc_accept_state), 0, "Accept State" }},
1590 { &hf_rpc_state_reject, {
1591 "Reject State", "rpc.state_reject", FT_UINT32, BASE_DEC,
1592 VALS(rpc_reject_state), 0, "Reject State" }},
1593 { &hf_rpc_state_auth, {
1594 "Auth State", "rpc.state_auth", FT_UINT32, BASE_DEC,
1595 VALS(rpc_auth_state), 0, "Auth State" }},
1596 { &hf_rpc_version, {
1597 "RPC Version", "rpc.version", FT_UINT32, BASE_DEC,
1598 NULL, 0, "RPC Version" }},
1599 { &hf_rpc_version_min, {
1600 "RPC Version (Minimum)", "rpc.version.min", FT_UINT32,
1601 BASE_DEC, NULL, 0, "Program Version (Minimum)" }},
1602 { &hf_rpc_version_max, {
1603 "RPC Version (Maximum)", "rpc.version.max", FT_UINT32,
1604 BASE_DEC, NULL, 0, "RPC Version (Maximum)" }},
1605 { &hf_rpc_program, {
1606 "Program", "rpc.program", FT_UINT32, BASE_DEC,
1607 NULL, 0, "Program" }},
1608 { &hf_rpc_programversion, {
1609 "Program Version", "rpc.programversion", FT_UINT32,
1610 BASE_DEC, NULL, 0, "Program Version" }},
1611 { &hf_rpc_programversion_min, {
1612 "Program Version (Minimum)", "rpc.programversion.min", FT_UINT32,
1613 BASE_DEC, NULL, 0, "Program Version (Minimum)" }},
1614 { &hf_rpc_programversion_max, {
1615 "Program Version (Maximum)", "rpc.programversion.max", FT_UINT32,
1616 BASE_DEC, NULL, 0, "Program Version (Maximum)" }},
1617 { &hf_rpc_procedure, {
1618 "Procedure", "rpc.procedure", FT_UINT32, BASE_DEC,
1619 NULL, 0, "Procedure" }},
1620 { &hf_rpc_auth_flavor, {
1621 "Flavor", "rpc.auth.flavor", FT_UINT32, BASE_DEC,
1622 VALS(rpc_auth_flavor), 0, "Flavor" }},
1623 { &hf_rpc_auth_length, {
1624 "Length", "rpc.auth.length", FT_UINT32, BASE_DEC,
1625 NULL, 0, "Length" }},
1626 { &hf_rpc_auth_stamp, {
1627 "Stamp", "rpc.auth.stamp", FT_UINT32, BASE_HEX,
1628 NULL, 0, "Stamp" }},
1629 { &hf_rpc_auth_uid, {
1630 "UID", "rpc.auth.uid", FT_UINT32, BASE_DEC,
1632 { &hf_rpc_auth_gid, {
1633 "GID", "rpc.auth.gid", FT_UINT32, BASE_DEC,
1635 { &hf_rpc_authgss_v, {
1636 "GSS Version", "rpc.authgss.version", FT_UINT32,
1637 BASE_DEC, NULL, 0, "GSS Version" }},
1638 { &hf_rpc_authgss_proc, {
1639 "GSS Procedure", "rpc.authgss.procedure", FT_UINT32,
1640 BASE_DEC, VALS(rpc_authgss_proc), 0, "GSS Procedure" }},
1641 { &hf_rpc_authgss_seq, {
1642 "GSS Sequence Number", "rpc.authgss.seqnum", FT_UINT32,
1643 BASE_DEC, NULL, 0, "GSS Sequence Number" }},
1644 { &hf_rpc_authgss_svc, {
1645 "GSS Service", "rpc.authgss.service", FT_UINT32,
1646 BASE_DEC, VALS(rpc_authgss_svc), 0, "GSS Service" }},
1647 { &hf_rpc_authgss_ctx, {
1648 "GSS Context", "rpc.authgss.context", FT_BYTES,
1649 BASE_HEX, NULL, 0, "GSS Context" }},
1650 { &hf_rpc_authgss_major, {
1651 "GSS Major Status", "rpc.authgss.major", FT_UINT32,
1652 BASE_DEC, NULL, 0, "GSS Major Status" }},
1653 { &hf_rpc_authgss_minor, {
1654 "GSS Minor Status", "rpc.authgss.minor", FT_UINT32,
1655 BASE_DEC, NULL, 0, "GSS Minor Status" }},
1656 { &hf_rpc_authgss_window, {
1657 "GSS Sequence Window", "rpc.authgss.window", FT_UINT32,
1658 BASE_DEC, NULL, 0, "GSS Sequence Window" }},
1659 { &hf_rpc_authgss_token, {
1660 "GSS Token", "rpc.authgss.token", FT_BYTES,
1661 BASE_HEX, NULL, 0, "GSS Token" }},
1662 { &hf_rpc_authgss_data_length, {
1663 "Length", "rpc.authgss.data.length", FT_UINT32,
1664 BASE_DEC, NULL, 0, "Length" }},
1665 { &hf_rpc_authgss_data, {
1666 "GSS Data", "rpc.authgss.data", FT_BYTES,
1667 BASE_HEX, NULL, 0, "GSS Data" }},
1668 { &hf_rpc_authgss_checksum, {
1669 "GSS Checksum", "rpc.authgss.checksum", FT_BYTES,
1670 BASE_HEX, NULL, 0, "GSS Checksum" }},
1671 { &hf_rpc_auth_machinename, {
1672 "Machine Name", "rpc.auth.machinename", FT_STRING,
1673 BASE_DEC, NULL, 0, "Machine Name" }},
1675 "Duplicate Transaction", "rpc.dup", FT_UINT32, BASE_DEC,
1676 NULL, 0, "Duplicate Transaction" }},
1677 { &hf_rpc_call_dup, {
1678 "Duplicate Call", "rpc.call.dup", FT_UINT32, BASE_DEC,
1679 NULL, 0, "Duplicate Call" }},
1680 { &hf_rpc_reply_dup, {
1681 "Duplicate Reply", "rpc.reply.dup", FT_UINT32, BASE_DEC,
1682 NULL, 0, "Duplicate Reply" }},
1683 { &hf_rpc_value_follows, {
1684 "Value Follows", "rpc.value_follows", FT_BOOLEAN, BASE_NONE,
1685 &yesno, 0, "Value Follows" }}
1687 static gint *ett[] = {
1695 proto_rpc = proto_register_protocol("Remote Procedure Call", "rpc");
1696 proto_register_field_array(proto_rpc, hf, array_length(hf));
1697 proto_register_subtree_array(ett, array_length(ett));
1698 register_init_routine(&rpc_init_protocol);
1701 * Init the hash tables. Dissectors for RPC protocols must
1702 * have a "handoff registration" routine that registers the
1703 * protocol with RPC; they must not do it in their protocol
1704 * registration routine, as their protocol registration
1705 * routine might be called before this routine is called and
1706 * thus might be called before the hash tables are initialized,
1707 * but it's guaranteed that all protocol registration routines
1708 * will be called before any handoff registration routines
1711 rpc_progs = g_hash_table_new(rpc_prog_hash, rpc_prog_equal);
1712 rpc_procs = g_hash_table_new(rpc_proc_hash, rpc_proc_equal);
1717 proto_reg_handoff_rpc(void)
1719 old_heur_dissector_add("tcp", dissect_rpc);
1720 old_heur_dissector_add("udp", dissect_rpc);