diff options
author | Roland McGrath <roland@gnu.org> | 1999-07-16 01:19:06 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1999-07-16 01:19:06 +0000 |
commit | b75dafc8199111a4f88f28382ae2f0563a7a0fec (patch) | |
tree | b770374ab9a9c445363b5c4e3803f1a7570ea813 /utils | |
parent | e1344cb5eb3fda906522978e506679721dac5624 (diff) |
1999-07-15 Roland McGrath <roland@baalperazim.frob.com>
* rpctrace.c: New file, from josem and gord. Not yet functional.
* Makefile (rpctrace): New target.
(targets): Add rpctrace.
(SRCS): Add rpctrace.c.
Diffstat (limited to 'utils')
-rw-r--r-- | utils/Makefile | 17 | ||||
-rw-r--r-- | utils/rpctrace.c | 271 |
2 files changed, 281 insertions, 7 deletions
diff --git a/utils/Makefile b/utils/Makefile index a2a1a3b1..3f443050 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation +# Copyright (C) 1994,95,96,97,98,99 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -20,14 +20,15 @@ makemode := utilities targets = shd ps settrans showtrans syncfs su mount fsysopts \ storeinfo login w uptime ids loginpr sush vmstat portinfo \ - devprobe vminfo addauth rmauth unsu setauth ftpcp ftpdir storecat \ - storeread ping msgport + devprobe vminfo addauth freeauth rmauth unsu setauth ftpcp ftpdir storecat \ + storeread ping msgport rpctrace special-targets = mount loginpr sush uptime SRCS = shd.c ps.c su.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ mount.sh fsysopts.c storeinfo.c login.c loginpr.sh sush.sh w.c \ uptime.sh psout.c ids.c vmstat.c portinfo.c devprobe.c vminfo.c \ parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \ - unsu.c ftpcp.c ftpdir.c storeread.c storecat.c ping.c msgport.c + unsu.c ftpcp.c ftpdir.c storeread.c storecat.c ping.c msgport.c \ + rpctrace.c LCLHDRS = psout.h parse.h pids.h frobauth.h OBJS = $(filter-out %.sh,$(SRCS:.c=.o)) @@ -49,9 +50,9 @@ INSTALL-ping-ops = -o root -m 4755 include ../Makeconf -ps addauth rmauth setauth su unsu msgport: parse.o pids.o +freeauth ps addauth rmauth setauth su unsu msgport: parse.o pids.o login addauth setauth su: nonsugid.o -addauth rmauth setauth su unsu: frobauth.o +freeauth addauth rmauth setauth su unsu: frobauth.o rmauth setauth su unsu: frobauth-mod.o ps w: psout.o ../libps/libps.a ../libihash/libihash.a @@ -64,8 +65,10 @@ ping: ../libthreads/libthreads.a # work: all libraries that *any* routine in libfshelp uses must be defined. settrans: ../libfshelp/libfshelp.a ../libports/libports.a ../libthreads/libthreads.a ps w ids settrans syncfs showtrans fsysopts storeinfo login vmstat portinfo \ - devprobe vminfo addauth rmauth setauth su unsu ftpcp ftpdir storeread \ + devprobe vminfo addauth freeauth rmauth setauth su unsu ftpcp ftpdir storeread \ storecat msgport: \ ../libshouldbeinlibc/libshouldbeinlibc.a $(filter-out $(special-targets), $(targets)): %: %.o + +rpctrace: ../libports/libports.a ../libihash/libihash.a ../libthreads/libthreads.a diff --git a/utils/rpctrace.c b/utils/rpctrace.c new file mode 100644 index 00000000..bf6e71d5 --- /dev/null +++ b/utils/rpctrace.c @@ -0,0 +1,271 @@ +/* Trace RPCs sent to selected ports + + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + + Written by Jose M. Moya <josem@gnu.org> + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. */ +#include <hurd.h> +#include <hurd/ports.h> +#include <hurd/ihash.h> +#include <mach/message.h> +#include <assert.h> +#include <fcntl.h> +#include <unistd.h> +#include <argp.h> +#include <error.h> +#include <version.h> + +const char *argp_program_version = STANDARD_HURD_VERSION (rpctrace); + +static const struct argp_option options[] = { + {"output", 'o', "FILE", 0, "Send trace output to FILE instead of stderr."}, + {0} +}; + +static const char *args_doc = "COMMAND [ARG...]"; +static const char *doc = +"Trace Mach Remote Procedure Calls." +"\v."; + + +struct traced_info +{ + struct port_info pi; + mach_port_t forward; +}; + +task_t traced_task; +ihash_t traced_names; +struct port_class *traced_class; +struct port_bucket *traced_bucket; +FILE *ostream; +cthread_t traced_thread; +char *cmd; +char **cmd_argv; +char **cmd_envp; + +int print_message (FILE *stream, mach_msg_header_t *msg); + +#if 1 +int +print_message (FILE *stream, mach_msg_header_t *msg) +{ + fprintf (stream, "[%d] %d -> %d\n", msg->msgh_id, + msg->msgh_local_port, msg->msgh_remote_port); + return 0; +} +#endif + +mach_port_t +trace_wrapper (mach_port_t orig) +{ + struct traced_info *info; + mach_port_t port = MACH_PORT_NULL; + + /* Never wrap the null port. */ + if (orig == MACH_PORT_NULL) + return orig; + + info = ihash_find (traced_names, orig); + if (! info) + { + error_t err; + mach_port_type_t type; + mach_msg_type_name_t typename; + + ports_create_port (traced_class, traced_bucket, + sizeof (struct traced_info), &info); + port = ports_get_right (info); + info->forward = MACH_PORT_NULL; + + mach_port_type (traced_task, orig, &type); + /* FIXME: type == 0x11bdf68: how do I get the type of right? */ + + if (type & MACH_PORT_TYPE_SEND) + { + err = mach_port_extract_right (traced_task, orig, + MACH_MSG_TYPE_MOVE_SEND, + &info->forward, &typename); + assert_perror (err); + err = mach_port_insert_right (traced_task, orig, port, + MACH_MSG_TYPE_MAKE_SEND); + assert_perror (err); + } + if (type & MACH_PORT_TYPE_SEND_ONCE) + { + err = mach_port_extract_right (traced_task, orig, + MACH_MSG_TYPE_MOVE_SEND_ONCE, + &info->forward, &typename); + assert_perror (err); + err = mach_port_insert_right (traced_task, orig, port, + MACH_MSG_TYPE_MAKE_SEND_ONCE); + assert_perror (err); + } + if (info->forward == MACH_PORT_NULL) + { + err = mach_port_extract_right (traced_task, orig, + MACH_MSG_TYPE_MAKE_SEND, + &info->forward, &typename); + assert_perror (err); + } + + ihash_add (traced_names, orig, info, NULL); + + } + else + port = ports_get_right (info); + mach_port_insert_right (mach_task_self (), port, port, + MACH_MSG_TYPE_MAKE_SEND); + return port; +} + +int +trace_and_forward (mach_msg_header_t *inp, mach_msg_header_t *outp) +{ + struct traced_info *info; + void *msg_buf_ptr = (void *) inp + sizeof (*inp); + + /* Print the message trace. */ + print_message (ostream, inp); fflush (ostream); + + /* Wrap ports. */ + while (msg_buf_ptr < (void *) inp + inp->msgh_size) + { + mach_msg_type_t type = *(mach_msg_type_t *) msg_buf_ptr; + msg_buf_ptr += sizeof (mach_msg_type_t); + if (type.msgt_name == MACH_MSG_TYPE_PORT_NAME) + { + mach_port_t *port = msg_buf_ptr; + *port = trace_wrapper (*port); + } + msg_buf_ptr += type.msgt_size / 8; + } + + info = ports_lookup_port (traced_bucket, inp->msgh_local_port, + traced_class); + if (! info) + return 0; + + /* Swap the header data like a crossover cable. */ + inp->msgh_bits + = MACH_MSGH_BITS (MACH_MSGH_BITS_LOCAL (inp->msgh_bits), + MACH_MSGH_BITS_REMOTE (inp->msgh_bits)); + inp->msgh_local_port = trace_wrapper (inp->msgh_remote_port); + inp->msgh_remote_port = info->forward; + + /* Resend the message to the tracee. */ + mach_msg (inp, MACH_SEND_MSG, inp->msgh_size, 0, + MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + + return 1; +} + +static any_t +trace_thread_function (struct port_bucket *bucket) +{ + ports_manage_port_operations_one_thread (bucket, trace_and_forward, 0); + return 0; +} + +static any_t +traced_thread_function (struct port_bucket *bucket) +{ + mach_port_t wrapper; + struct traced_info *info; + file_t file = file_name_path_lookup (cmd, getenv ("PATH"), O_EXEC, 0, 0); + + if (file == MACH_PORT_NULL) + error (1, errno, "cannot lookup `%s' in PATH", cmd); + task_create (mach_task_self (), 0, &traced_task); + + /* Create a trace wrapper for the task port. */ + ports_create_port (traced_class, traced_bucket, sizeof (*info), &info); + info->forward = traced_task; + ihash_add (traced_names, wrapper, info, NULL); + + /* Make sure the traced task uses this wrapper. */ + wrapper = ports_get_right (info); + mach_port_insert_right (mach_task_self (), wrapper, + wrapper, MACH_MSG_TYPE_MAKE_SEND); + task_set_special_port (traced_task, TASK_KERNEL_PORT, wrapper); + + /* Now actually run the command they told us to trace. */ + proc_child (getproc (), traced_task); + _hurd_exec (traced_task, file, cmd_argv, cmd_envp); + + /* FIXME: falls through immediately if we don't spin */ + for (;;) ; + return 0; +} + +int +main (int argc, char **argv, char **envp) +{ + + /* Parse our options... */ + error_t parse_opt (int key, char *arg, struct argp_state *state) + { + switch (key) + { + case 'o': + ostream = fopen (arg, "w"); + break; + + case ARGP_KEY_NO_ARGS: + argp_usage (state); + return EINVAL; + + case ARGP_KEY_ARG: + cmd = arg; + cmd_argv = &state->argv[state->next-1]; + cmd_envp = envp; + state->next = state->argc; + traced_thread = cthread_fork ((cthread_fn_t) + traced_thread_function, 0); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; + } + const struct argp argp = { options, parse_opt, args_doc, doc }; + + traced_class = ports_create_class (0, 0); + traced_bucket = ports_create_bucket(); + + ihash_create (&traced_names); + ostream = stderr; + + cthread_detach (cthread_fork ((cthread_fn_t)trace_thread_function, + traced_bucket)); + /* Parse our arguments. */ + argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0); + + cthread_join (traced_thread); + + fprintf (stderr, "***************hola***************\n"); + exit (0); +} + +/* + Local Variables: + compile-command: "gcc -Wall -g -D_GNU_SOURCE=1 -o rpctrace rpctrace.c -lthreads -lports -lihash" + End: +*/ |