Ethereal-dev: [ethereal-dev] Re: Adding NetInfo (ONC RPC proto) support to ethereal

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Nicolas Williams <Nicolas.Williams@xxxxxxx>
Date: Mon, 3 Jan 2000 12:09:55 -0500
Replying to myself, again. This time I include patches.

The included patch implements correct dissection of indirect ONC RPC
calls via the portmapper and calls the appropriate dissection functions
of indirectly called procedures to dissect the encapsulated RPC
arguments/results.

Some simple changes to packet-rpc.[ch] were needed to support the new
functions in packet-portmap.c.

These changes are necessary to effectively follow NetInfo traffic once I
finish the NetInfo protocol dissectors. But these changes are also
usefule when looking at NIS clients' broadcast binding (ypbind -broadcast
broadcasts DOMAIN_NONACK calls to YPSERV indirectly via
PORTMAPper's CALLIT call), as well as other RPC protocols such as
bootparams.

What is the protocol to follow to get patches incorporated into
Ethereal?

BTW, I'd never used, much less hacked, Ethereal before this past Friday.
That I was able to add this feature in less than 8 hours of work having
had no previous experience with Ethereal is testament to how well
Ethereal is designed and implemented.

Thank you!

Nico
-DISCLAIMER: an automatically appended disclaimer may follow. By posting-
-to a public e-mail mailing list I hereby grant permission to distribute-
-and copy this message.-
*** packet-rpc.h	Mon Jan  3 11:52:47 2000
--- packet-rpc.h-	Sat Jan  1 18:13:00 2000
***************
*** 108,121 ****
  extern int dissect_rpc_uint64(const u_char *pd, int offset, frame_data *fd,
  	proto_tree *tree, char* name, char* type);
  
- /* Hash table with info on RPC program numbers */
- /* packet-portmap.c requires access to this hash table */
- extern GHashTable *rpc_progs;
- 
- /* Hash table with info on RPC procedure numbers */
- /* packet-portmap.c requires access to this hash table */
- extern GHashTable *rpc_procs;
- 
  
  #endif /* packet-rpc.h */
  
--- 108,113 ----
*** packet-rpc.c	Mon Jan  3 11:52:03 2000
--- packet-rpc.c-	Sat Jan  1 18:12:51 2000
***************
*** 127,136 ****
  static gint ett_rpc_gids = -1;
  
  /* Hash table with info on RPC program numbers */
! GHashTable *rpc_progs;
  
  /* Hash table with info on RPC procedure numbers */
! GHashTable *rpc_procs;
  
  
  /***********************************/
--- 127,136 ----
  static gint ett_rpc_gids = -1;
  
  /* Hash table with info on RPC program numbers */
! static GHashTable *rpc_progs;
  
  /* Hash table with info on RPC procedure numbers */
! static GHashTable *rpc_procs;
  
  
  /***********************************/
***************
*** 836,848 ****
  		conversation = find_conversation(&null_address, &pi.dst,
  		    pi.ptype, pi.srcport, pi.destport);
  		if (conversation == NULL) {
- 			conversation = find_conversation(&null_address,
- 				&pi.dst, pi.ptype, 111, pi.destport);
  			/* We haven't seen an RPC call for that conversation,
  			   so we can't check for a reply to that call. */
! 			if (conversation == NULL) {
! 				return FALSE;
! 			}
  		}
  
  		/* The XIDs of the call and reply must match. */
--- 836,844 ----
  		conversation = find_conversation(&null_address, &pi.dst,
  		    pi.ptype, pi.srcport, pi.destport);
  		if (conversation == NULL) {
  			/* We haven't seen an RPC call for that conversation,
  			   so we can't check for a reply to that call. */
! 			return FALSE;
  		}
  
  		/* The XIDs of the call and reply must match. */
***************
*** 973,982 ****
  		    pi.ptype, pi.srcport, pi.destport);
  		if (conversation == NULL) {
  			/* It's not part of any conversation - create a new one. */
- 			/* And alloc an rpc_call_msg as the conversation data */
  			conversation = conversation_new(&pi.src, &null_address,
! 			    pi.ptype, pi.srcport, pi.destport,
! 			    g_malloc(sizeof(rpc_call_msg)));
  		}
  
  		/* prepare the key data */
--- 969,976 ----
  		    pi.ptype, pi.srcport, pi.destport);
  		if (conversation == NULL) {
  			/* It's not part of any conversation - create a new one. */
  			conversation = conversation_new(&pi.src, &null_address,
! 			    pi.ptype, pi.srcport, pi.destport, NULL);
  		}
  
  		/* prepare the key data */
***************
*** 1005,1020 ****
  			rpc_call_msg.proc_info = value;
  			/* store it */
  			rpc_call_insert(&rpc_call_msg);
- 
- 			/* Now copy rpc_call_msg into the conversation
- 			   data that was g_malloc()ed above. */
- 
- 			/* This is needed by packet-portmap.c in the
- 			   dissect_rmtcall*() functions for processing
- 			   of indirect RPC calls via the portmapper.
- 
- 			   See comments therein.	*/
- 			memcpy(conversation->data,&rpc_call_msg,sizeof(rpc_call_msg));
  		}
  
  		offset += 16;
--- 999,1004 ----
*** packet-portmap.c	Mon Jan  3 11:53:24 2000
--- packet-portmap.c-	Sat Jan  1 18:13:38 2000
***************
*** 33,40 ****
  #include <sys/types.h>
  #endif
  
- #include <stdio.h>
- 
  
  #include "packet-rpc.h"
  #include "packet-portmap.h"
--- 33,38 ----
***************
*** 55,63 ****
  static int hf_portmap_rpcb_owner = -1;
  static int hf_portmap_uaddr = -1;
  static int hf_portmap_value_follows = -1;
- static int hf_portmap_rmtcall_prog = -1;
- static int hf_portmap_rmtcall_vers = -1;
- static int hf_portmap_rmtcall_proc = -1;
  
  
  static gint ett_portmap = -1;
--- 53,58 ----
***************
*** 67,322 ****
  
  static struct true_false_string yesno = { "Yes", "No" };
  
- /* Stolen from packet-rpc.c:dissect_rpc_uint32() */
- int
- dissect_rpc_guint32_val(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, char* name, char* type, guint32 * val)
- {
-         guint32 value;
- 
-         if (!BYTES_ARE_IN_FRAME(offset,4)) return offset;
-         value = EXTRACT_UINT(pd, offset+0);
- 
-         if (tree && name) {
-                 proto_tree_add_text(tree, offset, 4,
-                 "%s: %u", name, value);
-         }
- 
-         offset += 4;
-         *val = value;
-         return offset;
- }
- 
- int dissect_rmtcall(const u_char *pd, int offset, frame_data *fd,
- 	proto_tree *tree)
- {
- 	int offset_old = offset;
-         proto_item *pitem=NULL;
-         proto_tree *ptree = NULL;
- 	dissect_function_t *dissect_function = NULL;
- 	rpc_proc_info_key       key;
- 	rpc_proc_info_value     *value = NULL;
-         rpc_prog_info_value *rpc_prog = NULL;
-         rpc_prog_info_key rpc_prog_key;
-         char *progname = "Unknown";
-         char *procname = "Unknown";
-         static char procname_static[20];
- 	int     proto = 0;
- 	int     ett = 0;
- 	unsigned int prog = 0;
- 	unsigned int vers = 0;
- 	unsigned int proc = 0;
- 	conversation_t *conversation = NULL;
- 	rpc_call_info *conversation_data = NULL;
- 	static address null_address = { AT_NONE, 0, NULL };
- 
- 
- 	dissect_rpc_guint32_val(pd, offset, fd, NULL, "prog", "unit32", &prog);
- 	dissect_rpc_guint32_val(pd, offset+4, fd, NULL, "vers", "unit32", &vers);
- 	dissect_rpc_guint32_val(pd, offset+8, fd, NULL, "proc", "unit32", &proc);
- 
- 	conversation = find_conversation(&pi.src, &null_address,
- 		pi.ptype, pi.srcport, pi.destport);
- 
- 	key.prog = prog;
- 	key.vers = vers;
- 	key.proc = proc;
- 	conversation_data = conversation->data;
- 
- 	/* conversation->data was set by dissect_rpc() but this is an
- 	   indirect call so we'll want to update the original
- 	   rpc_call_info stored therein to reflect the indirect call,
- 	   not the portmap CALLIT call that dissect_rpc() thought this
- 	   is!
- 	   
- 	   See dissect_portmap_rmtcall_reply().
- 	   Also see dissect_rpc().		*/
- 	if (conversation_data)
- 	{
- 		conversation_data->prog = prog;
- 		conversation_data->vers = vers;
- 		conversation_data->proc = proc;
- 	}
- 
- 	rpc_prog_key.prog=key.prog;
- 	if ((rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key)))
- 	{
- 		proto = rpc_prog->proto;
- 		ett = rpc_prog->ett;
- 		progname = rpc_prog->progname;
- 	}
- 
- 	value = g_hash_table_lookup(rpc_procs,&key);
- 	if (value != NULL) {
- 		dissect_function = value->dissect_call;
- 		procname = value->name;
- 
- 		/* Again, we have to update conversation->data so it
- 		   reflects the indirect call, not the portmap call.
- 
- 		   See above.	*/
- 		if (conversation_data)
- 		{
- 			conversation_data->proc_info = value;
- 		}
- 	}
- 	else {
- 		dissect_function = NULL;
- 		sprintf(procname_static, "proc-%u", proc);
- 		procname = procname_static;
- 	}
- 
- 	if (procname && check_col(fd, COL_INFO)) {
- 		col_add_fstr(fd, COL_INFO,"V%u %s %s",
- 			key.vers,
- 			procname,
- 			"Call");
- 	}
- 
- 	if (tree) {
- 		if (!progname)
- 			progname = "Unknown";
- 		if (!procname)
- 			procname = "Unknown";
- 		proto_tree_add_item_format(tree,
- 			hf_portmap_rmtcall_prog, offset, 4, proc,
- 			"Indirect Program: %s (%u)", progname,
- 			prog);
- 		proto_tree_add_item_format(tree,
- 			hf_portmap_rmtcall_vers, offset+4, 4, vers,
- 			"Indirect Program Version: %u", vers);
- 		proto_tree_add_item_format(tree,
- 			hf_portmap_rmtcall_proc, offset+8, 4, proc,
- 			"Indirect Procedure: %s (%u)", procname,
- 			proc);
- 	}
- 
- 	offset += 12;
- 
- 	if (dissect_function != NULL) {
- 		ptree=tree;
- 		if (tree)
- 		{
- 			pitem = proto_tree_add_item(tree, proto, offset, END_OF_FRAME);
- 			if (pitem) {
- 				ptree = proto_item_add_subtree(pitem, ett);
- 			}
- 		}
- 		offset = dissect_function(pd, offset, fd, ptree);
- 	}
- 
- 	/* dissect any remaining bytes (incomplete dissection) as pure data in
- 	   the ptree */
- 	dissect_data(pd, offset, fd, ptree);
- 
- 	if (pitem) {
- 		proto_item_set_len(pitem, offset - offset_old);
- 	}
- 
- 	return fd->cap_len;
- }
- 
- int dissect_rmtcall_reply(const u_char *pd, int offset, frame_data *fd,
- 	proto_tree *tree)
- {
-         proto_item *pitem=NULL;
-         proto_tree *ptree = NULL;
- 	dissect_function_t *dissect_function = NULL;
- 	rpc_proc_info_key       key;
-         rpc_prog_info_value *rpc_prog = NULL;
-         rpc_prog_info_key rpc_prog_key;
-         char *progname = NULL;
-         char *procname = NULL;
-         static char procname_static[20];
- 	int     proto = 0;
- 	int     ett = 0;
- 	unsigned int port = 0;
- 	unsigned int prog = 0;
- 	unsigned int vers = 0;
- 	unsigned int proc = 0;
- 	conversation_t *conversation = NULL;
- 	rpc_call_info *conversation_data = NULL;
- 	static address null_address = { AT_NONE, 0, NULL };
- 
- 	dissect_rpc_guint32_val(pd, offset, fd, tree, "Port of Indirect Program", "unit32", &port);
- 
- 	conversation = find_conversation(&null_address, &pi.dst,
- 		pi.ptype, 111, pi.destport);
- 
- 	if (conversation == NULL)
- 	{
- 		conversation = find_conversation(&null_address, &pi.dst,
- 			pi.ptype, pi.srcport, pi.destport);
- 	}
- 
- 	if (conversation == NULL || conversation->data == NULL)
- 	{
- 		dissect_data(pd, offset+4, fd, ptree);
- 		return fd->cap_len;
- 	}
- 
- 	conversation_data = (rpc_call_info *) (conversation->data);
- 
- 	prog = conversation_data->prog;
- 	vers = conversation_data->vers;
- 	proc = conversation_data->proc;
- 
- 	key.prog = prog;
- 	key.vers = vers;
- 	key.proc = proc;
- 
- 	rpc_prog_key.prog=key.prog;
- 
- 	if ((rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key)))
- 	{
- 		proto = rpc_prog->proto;
- 		ett = rpc_prog->ett;
- 		progname = rpc_prog->progname;
- 	}
- 
- 	dissect_function = NULL;
- 	sprintf(procname_static, "proc-%u", proc);
- 	procname = procname_static;
- 	if (conversation_data->proc_info == NULL)
- 	{
- 		dissect_data(pd, offset+4, fd, ptree);
- 		return fd->cap_len;
- 	}
- 	procname = conversation_data->proc_info->name;
- 	dissect_function = conversation_data->proc_info->dissect_reply;
- 
- 	if (tree) {
- 		if (!progname)
- 			progname = "Unknown";
- 		if (!procname)
- 			procname = "Unknown";
- 		proto_tree_add_item_format(tree,
- 			hf_portmap_rmtcall_prog, offset, 0, proc,
- 			"Indirect Program: %s (%u)", progname,
- 			prog);
- 		proto_tree_add_item_format(tree,
- 			hf_portmap_rmtcall_vers, offset, 0, vers,
- 			"Indirect Program Version: %u", vers);
- 		proto_tree_add_item_format(tree,
- 			hf_portmap_rmtcall_proc, offset, 0, proc,
- 			"Indirect Procedure: %s (%u)", procname,
- 			proc);
- 	}
- 
- 	if (dissect_function != NULL) {
- 		ptree=tree;
- 		if (tree)
- 		{
- 			pitem = proto_tree_add_item(tree, proto, offset+4, END_OF_FRAME);
- 			if (pitem) {
- 				ptree = proto_item_add_subtree(pitem, ett);
- 			}
- 		}
- 		offset = dissect_function(pd, offset, fd, ptree);
- 	}
- 
- 	return fd->cap_len;
- 
- }
  
  /* Dissect a getport call */
  int dissect_getport_call(const u_char *pd, int offset, frame_data *fd,
--- 62,67 ----
***************
*** 503,509 ****
  	{ PORTMAPPROC_DUMP, "DUMP",
  		NULL, dissect_dump_reply },
  	{ PORTMAPPROC_CALLIT, "CALLIT",
! 		dissect_rmtcall, dissect_rmtcall_reply },
      { 0, NULL, NULL, NULL }
  };
  /* end of Portmap version 2 */
--- 248,254 ----
  	{ PORTMAPPROC_DUMP, "DUMP",
  		NULL, dissect_dump_reply },
  	{ PORTMAPPROC_CALLIT, "CALLIT",
! 		NULL, NULL },
      { 0, NULL, NULL, NULL }
  };
  /* end of Portmap version 2 */
***************
*** 611,617 ****
  	{ RPCBPROC_DUMP,	"DUMP",
  		NULL, dissect_rpcb3_dump_reply },
  	{ RPCBPROC_CALLIT,	"CALLIT",
! 		dissect_rmtcall, dissect_rmtcall_reply },
  	{ RPCBPROC_GETTIME,	"GETTIME",
  		NULL, NULL },
  	{ RPCBPROC_UADDR2TADDR,	"UADDR2TADDR",
--- 356,362 ----
  	{ RPCBPROC_DUMP,	"DUMP",
  		NULL, dissect_rpcb3_dump_reply },
  	{ RPCBPROC_CALLIT,	"CALLIT",
! 		NULL, NULL },
  	{ RPCBPROC_GETTIME,	"GETTIME",
  		NULL, NULL },
  	{ RPCBPROC_UADDR2TADDR,	"UADDR2TADDR",
***************
*** 636,642 ****
  	{ RPCBPROC_DUMP,	"DUMP",
  		NULL, dissect_rpcb3_dump_reply },
  	{ RPCBPROC_BCAST,	"BCAST",
! 		dissect_rmtcall, dissect_rmtcall_reply },
  	{ RPCBPROC_GETTIME,	"GETTIME",
  		NULL, NULL },
  	{ RPCBPROC_UADDR2TADDR,	"UADDR2TADDR",
--- 381,387 ----
  	{ RPCBPROC_DUMP,	"DUMP",
  		NULL, dissect_rpcb3_dump_reply },
  	{ RPCBPROC_BCAST,	"BCAST",
! 		NULL, NULL },
  	{ RPCBPROC_GETTIME,	"GETTIME",
  		NULL, NULL },
  	{ RPCBPROC_UADDR2TADDR,	"UADDR2TADDR",
***************
*** 646,652 ****
  	{ RPCBPROC_GETVERSADDR,	"GETVERSADDR",
  		NULL, NULL },
  	{ RPCBPROC_INDIRECT,	"INDIRECT",
! 		dissect_rmtcall_reply, dissect_rmtcall_reply },
  	{ RPCBPROC_GETADDRLIST,	"GETADDRLIST",
  		NULL, NULL },
  	{ RPCBPROC_GETSTAT,	"GETSTAT",
--- 391,397 ----
  	{ RPCBPROC_GETVERSADDR,	"GETVERSADDR",
  		NULL, NULL },
  	{ RPCBPROC_INDIRECT,	"INDIRECT",
! 		NULL, NULL },
  	{ RPCBPROC_GETADDRLIST,	"GETADDRLIST",
  		NULL, NULL },
  	{ RPCBPROC_GETSTAT,	"GETSTAT",
***************
*** 659,673 ****
  proto_register_portmap(void)
  {
  	static hf_register_info hf[] = {
- 		{ &hf_portmap_rmtcall_prog, {
- 			"Indirect Program", "portmap.rmtcall.prog", FT_UINT32, BASE_DEC,
- 			NULL, 0, "Indirect Program" }},
- 		{ &hf_portmap_rmtcall_vers, {
- 			"Indirect Version", "portmap.rmtcall.vers", FT_UINT32, BASE_DEC,
- 			NULL, 0, "Indirect Version" }},
- 		{ &hf_portmap_rmtcall_proc, {
- 			"Indirect Procedure", "portmap.rmtcall.proc", FT_UINT32, BASE_DEC,
- 			NULL, 0, "Indirect Procedure" }},
  		{ &hf_portmap_prog, {
  			"Program", "portmap.prog", FT_UINT32, BASE_DEC,
  			NULL, 0, "Program" }},
--- 404,409 ----
This message contains confidential information and is intended only 
for the individual named.  If you are not the named addressee you 
should not disseminate, distribute or copy this e-mail.  Please 
notify the sender immediately by e-mail if you have received this 
e-mail by mistake and delete this e-mail from your system.

E-mail transmission cannot be guaranteed to be secure or error-free 
as information could be intercepted, corrupted, lost, destroyed, 
arrive late or incomplete, or contain viruses.  The sender therefore 
does not accept liability for any errors or omissions in the contents 
of this message which arise as a result of e-mail transmission.  If 
verification is required please request a hard-copy version.  This 
message is provided for informational purposes and should not be 
construed as a solicitation or offer to buy or sell any securities or 
related financial instruments.