From 4721cf1ecb949b37c98b6fce79163541711de2e5 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 3 Dec 1998 23:54:14 +0000 Subject: Patch from Emmanuel Raguet to add remote debug server and RPC support to RTEMS. Thanks. :) Email follows: Hello, For Xmas, here is the Remote Debugger on RTEMS ! Here are 2 patches for the Remote Debugger on RTEMS for pc386 from Linux host : - one for RTEMS it self, - one for GDB-4.17. 1/ RTEMS patch -------------- This patch adds 2 libraries : - a simplified SUN RPC library - the Remote Debugger library The configuration command is the following : ../rtems4/configure --target=i386-rtemself --enable-rtemsbsp=pc386 --enable-rdbg The SUN RPC library is built only if networking is set. The RDBG library is built if networking and enable-rdbg are set. The function used to initialize the debugger is : rtems_rdbg_initialize (); A special function has been created to force a task to be in a "debug" state : enterRdbg(). The use of this function is not mandatory. 2/ GDB-4.17 patch ----------------- This patch create a new RTEMS target for GDB-4.17. The configuration command is the following : ./configure --enable-shared --target=i386RTEMS To connect to a target, use : target rtems [your_site_address] Then, attach the target using : attach 1 And... Debug ;) You can obtain the original GDB-4.17 on ftp://ftp.debian.org/debian/dists/stable/main/source/devel/gdb_4.17.orig.tar.gz This has been tested from a Debian 2.0.1 linux host. --- c/Makefile.in | 10 + c/src/exec/librpc/include/rpc/auth.h | 167 +++++++ c/src/exec/librpc/include/rpc/clnt.h | 336 +++++++++++++++ c/src/exec/librpc/include/rpc/rpc.h | 86 ++++ c/src/exec/librpc/include/rpc/rpc_msg.h | 192 +++++++++ c/src/exec/librpc/include/rpc/svc.h | 291 +++++++++++++ c/src/exec/librpc/include/rpc/svc_auth.h | 47 ++ c/src/exec/librpc/include/rpc/types.h | 75 ++++ c/src/exec/librpc/include/rpc/xdr.h | 275 ++++++++++++ c/src/exec/score/cpu/i386/cpu.h | 40 +- c/src/exec/score/cpu/i386/cpu_asm.s | 1 + c/src/lib/Makefile.in | 11 +- c/src/lib/include/Makefile.in | 15 +- c/src/lib/include/rdbg/i386/rdbg_f.h | 53 +++ c/src/lib/include/rdbg/i386/reg.h | 32 ++ c/src/lib/include/rdbg/rdbg.h | 53 +++ c/src/lib/include/rdbg/servrpc.h | 268 ++++++++++++ c/src/lib/include/rpc/auth.h | 167 +++++++ c/src/lib/include/rpc/clnt.h | 336 +++++++++++++++ c/src/lib/include/rpc/rpc.h | 86 ++++ c/src/lib/include/rpc/rpc_msg.h | 192 +++++++++ c/src/lib/include/rpc/svc.h | 291 +++++++++++++ c/src/lib/include/rpc/svc_auth.h | 47 ++ c/src/lib/include/rpc/types.h | 75 ++++ c/src/lib/include/rpc/xdr.h | 275 ++++++++++++ c/src/lib/librdbg/Makefile.in | 96 +++++ c/src/lib/librdbg/_servtgt.c | 360 ++++++++++++++++ c/src/lib/librdbg/awk.svc | 65 +++ c/src/lib/librdbg/i386/excep.c | 233 ++++++++++ c/src/lib/librdbg/i386/pc386/remdeb_f.x | 58 +++ c/src/lib/librdbg/i386/rdbg_cpu_asm.s | 70 +++ c/src/lib/librdbg/i386/rdbg_f.c | 130 ++++++ c/src/lib/librdbg/ptrace.c | 335 ++++++++++++++ c/src/lib/librdbg/rdbg.c | 139 ++++++ c/src/lib/librdbg/remdeb.x | 544 +++++++++++++++++++++++ c/src/lib/librdbg/servbkpt.c | 587 +++++++++++++++++++++++++ c/src/lib/librdbg/servcon.c | 136 ++++++ c/src/lib/librdbg/servrpc.c | 720 +++++++++++++++++++++++++++++++ c/src/lib/librdbg/servtgt.c | 550 +++++++++++++++++++++++ c/src/lib/librdbg/servtsp.c | 329 ++++++++++++++ c/src/lib/librdbg/servutil.c | 130 ++++++ c/src/lib/librpc/Makefile.in | 49 +++ c/src/lib/librpc/rpc_callmsg.c | 191 ++++++++ c/src/lib/librpc/rpc_prot.c | 271 ++++++++++++ c/src/lib/librpc/svc.c | 259 +++++++++++ c/src/lib/librpc/svc_auth.c | 122 ++++++ c/src/lib/librpc/svc_udp.c | 476 ++++++++++++++++++++ c/src/lib/librpc/xdr.c | 578 +++++++++++++++++++++++++ c/src/lib/librpc/xdr_array.c | 157 +++++++ c/src/lib/librpc/xdr_mem.c | 185 ++++++++ c/src/lib/wrapup/Makefile.in | 2 + c/src/librdbg/include/rdbg/i386/rdbg_f.h | 53 +++ c/src/librdbg/include/rdbg/i386/reg.h | 32 ++ c/src/librdbg/include/rdbg/rdbg.h | 53 +++ c/src/librdbg/include/rdbg/servrpc.h | 268 ++++++++++++ c/src/librdbg/src/Makefile.in | 96 +++++ c/src/librdbg/src/_servtgt.c | 360 ++++++++++++++++ c/src/librdbg/src/awk.svc | 65 +++ c/src/librdbg/src/i386/any/remdeb_f.x | 58 +++ c/src/librdbg/src/i386/excep.c | 233 ++++++++++ c/src/librdbg/src/i386/pc386/remdeb_f.x | 58 +++ c/src/librdbg/src/i386/rdbg_cpu_asm.s | 70 +++ c/src/librdbg/src/i386/rdbg_f.c | 130 ++++++ c/src/librdbg/src/ptrace.c | 335 ++++++++++++++ c/src/librdbg/src/rdbg.c | 139 ++++++ c/src/librdbg/src/remdeb.x | 544 +++++++++++++++++++++++ c/src/librdbg/src/servbkpt.c | 587 +++++++++++++++++++++++++ c/src/librdbg/src/servcon.c | 136 ++++++ c/src/librdbg/src/servrpc.c | 720 +++++++++++++++++++++++++++++++ c/src/librdbg/src/servtgt.c | 550 +++++++++++++++++++++++ c/src/librdbg/src/servtsp.c | 329 ++++++++++++++ c/src/librdbg/src/servutil.c | 130 ++++++ c/src/librpc/include/rpc/auth.h | 167 +++++++ c/src/librpc/include/rpc/clnt.h | 336 +++++++++++++++ c/src/librpc/include/rpc/rpc.h | 86 ++++ c/src/librpc/include/rpc/rpc_msg.h | 192 +++++++++ c/src/librpc/include/rpc/svc.h | 291 +++++++++++++ c/src/librpc/include/rpc/svc_auth.h | 47 ++ c/src/librpc/include/rpc/types.h | 75 ++++ c/src/librpc/include/rpc/xdr.h | 275 ++++++++++++ c/src/librpc/src/Makefile.in | 49 +++ c/src/librpc/src/rpc_callmsg.c | 191 ++++++++ c/src/librpc/src/rpc_prot.c | 271 ++++++++++++ c/src/librpc/src/svc.c | 259 +++++++++++ c/src/librpc/src/svc_auth.c | 122 ++++++ c/src/librpc/src/svc_udp.c | 476 ++++++++++++++++++++ c/src/librpc/src/xdr.c | 578 +++++++++++++++++++++++++ c/src/librpc/src/xdr_array.c | 157 +++++++ c/src/librpc/src/xdr_mem.c | 185 ++++++++ c/src/wrapup/Makefile.in | 2 + configure | 305 +++++++------ configure.in | 13 + cpukit/librpc/include/rpc/auth.h | 167 +++++++ cpukit/librpc/include/rpc/clnt.h | 336 +++++++++++++++ cpukit/librpc/include/rpc/rpc.h | 86 ++++ cpukit/librpc/include/rpc/rpc_msg.h | 192 +++++++++ cpukit/librpc/include/rpc/svc.h | 291 +++++++++++++ cpukit/librpc/include/rpc/svc_auth.h | 47 ++ cpukit/librpc/include/rpc/types.h | 75 ++++ cpukit/librpc/include/rpc/xdr.h | 275 ++++++++++++ make/custom/default.cfg | 7 + make/target.cfg.in | 1 + 102 files changed, 20545 insertions(+), 148 deletions(-) create mode 100644 c/src/exec/librpc/include/rpc/auth.h create mode 100644 c/src/exec/librpc/include/rpc/clnt.h create mode 100644 c/src/exec/librpc/include/rpc/rpc.h create mode 100644 c/src/exec/librpc/include/rpc/rpc_msg.h create mode 100644 c/src/exec/librpc/include/rpc/svc.h create mode 100644 c/src/exec/librpc/include/rpc/svc_auth.h create mode 100644 c/src/exec/librpc/include/rpc/types.h create mode 100644 c/src/exec/librpc/include/rpc/xdr.h create mode 100644 c/src/lib/include/rdbg/i386/rdbg_f.h create mode 100644 c/src/lib/include/rdbg/i386/reg.h create mode 100644 c/src/lib/include/rdbg/rdbg.h create mode 100644 c/src/lib/include/rdbg/servrpc.h create mode 100644 c/src/lib/include/rpc/auth.h create mode 100644 c/src/lib/include/rpc/clnt.h create mode 100644 c/src/lib/include/rpc/rpc.h create mode 100644 c/src/lib/include/rpc/rpc_msg.h create mode 100644 c/src/lib/include/rpc/svc.h create mode 100644 c/src/lib/include/rpc/svc_auth.h create mode 100644 c/src/lib/include/rpc/types.h create mode 100644 c/src/lib/include/rpc/xdr.h create mode 100644 c/src/lib/librdbg/Makefile.in create mode 100644 c/src/lib/librdbg/_servtgt.c create mode 100644 c/src/lib/librdbg/awk.svc create mode 100644 c/src/lib/librdbg/i386/excep.c create mode 100644 c/src/lib/librdbg/i386/pc386/remdeb_f.x create mode 100644 c/src/lib/librdbg/i386/rdbg_cpu_asm.s create mode 100644 c/src/lib/librdbg/i386/rdbg_f.c create mode 100644 c/src/lib/librdbg/ptrace.c create mode 100644 c/src/lib/librdbg/rdbg.c create mode 100644 c/src/lib/librdbg/remdeb.x create mode 100644 c/src/lib/librdbg/servbkpt.c create mode 100644 c/src/lib/librdbg/servcon.c create mode 100644 c/src/lib/librdbg/servrpc.c create mode 100644 c/src/lib/librdbg/servtgt.c create mode 100644 c/src/lib/librdbg/servtsp.c create mode 100644 c/src/lib/librdbg/servutil.c create mode 100644 c/src/lib/librpc/Makefile.in create mode 100644 c/src/lib/librpc/rpc_callmsg.c create mode 100644 c/src/lib/librpc/rpc_prot.c create mode 100644 c/src/lib/librpc/svc.c create mode 100644 c/src/lib/librpc/svc_auth.c create mode 100644 c/src/lib/librpc/svc_udp.c create mode 100644 c/src/lib/librpc/xdr.c create mode 100644 c/src/lib/librpc/xdr_array.c create mode 100644 c/src/lib/librpc/xdr_mem.c create mode 100644 c/src/librdbg/include/rdbg/i386/rdbg_f.h create mode 100644 c/src/librdbg/include/rdbg/i386/reg.h create mode 100644 c/src/librdbg/include/rdbg/rdbg.h create mode 100644 c/src/librdbg/include/rdbg/servrpc.h create mode 100644 c/src/librdbg/src/Makefile.in create mode 100644 c/src/librdbg/src/_servtgt.c create mode 100644 c/src/librdbg/src/awk.svc create mode 100644 c/src/librdbg/src/i386/any/remdeb_f.x create mode 100644 c/src/librdbg/src/i386/excep.c create mode 100644 c/src/librdbg/src/i386/pc386/remdeb_f.x create mode 100644 c/src/librdbg/src/i386/rdbg_cpu_asm.s create mode 100644 c/src/librdbg/src/i386/rdbg_f.c create mode 100644 c/src/librdbg/src/ptrace.c create mode 100644 c/src/librdbg/src/rdbg.c create mode 100644 c/src/librdbg/src/remdeb.x create mode 100644 c/src/librdbg/src/servbkpt.c create mode 100644 c/src/librdbg/src/servcon.c create mode 100644 c/src/librdbg/src/servrpc.c create mode 100644 c/src/librdbg/src/servtgt.c create mode 100644 c/src/librdbg/src/servtsp.c create mode 100644 c/src/librdbg/src/servutil.c create mode 100644 c/src/librpc/include/rpc/auth.h create mode 100644 c/src/librpc/include/rpc/clnt.h create mode 100644 c/src/librpc/include/rpc/rpc.h create mode 100644 c/src/librpc/include/rpc/rpc_msg.h create mode 100644 c/src/librpc/include/rpc/svc.h create mode 100644 c/src/librpc/include/rpc/svc_auth.h create mode 100644 c/src/librpc/include/rpc/types.h create mode 100644 c/src/librpc/include/rpc/xdr.h create mode 100644 c/src/librpc/src/Makefile.in create mode 100644 c/src/librpc/src/rpc_callmsg.c create mode 100644 c/src/librpc/src/rpc_prot.c create mode 100644 c/src/librpc/src/svc.c create mode 100644 c/src/librpc/src/svc_auth.c create mode 100644 c/src/librpc/src/svc_udp.c create mode 100644 c/src/librpc/src/xdr.c create mode 100644 c/src/librpc/src/xdr_array.c create mode 100644 c/src/librpc/src/xdr_mem.c create mode 100644 cpukit/librpc/include/rpc/auth.h create mode 100644 cpukit/librpc/include/rpc/clnt.h create mode 100644 cpukit/librpc/include/rpc/rpc.h create mode 100644 cpukit/librpc/include/rpc/rpc_msg.h create mode 100644 cpukit/librpc/include/rpc/svc.h create mode 100644 cpukit/librpc/include/rpc/svc_auth.h create mode 100644 cpukit/librpc/include/rpc/types.h create mode 100644 cpukit/librpc/include/rpc/xdr.h diff --git a/c/Makefile.in b/c/Makefile.in index b1de42ce0f..2f3eaaedc0 100644 --- a/c/Makefile.in +++ b/c/Makefile.in @@ -33,6 +33,14 @@ LIBNETWORKING_yes_V = lib/include/networking lib/include/networking/sys \ lib/include/networking/nfs LIBNETWORKING = $(LIBNETWORKING_$(HAS_NETWORKING)_V) +# We only make the rpc install point if networking is enabled. +LIBRPC_yes_V = lib/include/rpc +LIBRPC = $(LIBRPC_$(HAS_NETWORKING)_V) + +# We only make the rdbg install point if networking and rdbg is enabled. +LIBRDBG_yes_yes_V = lib/include/rdbg +LIBRDBG = $(LIBRDBG_$(HAS_NETWORKING)_$(HAS_RDBG)_V) + # We only make the rtems++ install point if it is enabled. LIBRTEMSCPLUSPLUS_yes_V = lib/include/rtems++ LIBRTEMSCPLUSPLUS = $(LIBRTEMSCPLUSPLUS_$(HAS_CPLUSPLUS)_V) @@ -45,6 +53,8 @@ CREATE_DIRS = \ lib/include/motorola lib/include/zilog \ lib/include/libchip \ $(LIBNETWORKING) \ + $(LIBRPC) \ + $(LIBRDBG) \ $(LIBRTEMSCPLUSPLUS) \ bin samples \ tests tests/screens tests/screens/sptests \ diff --git a/c/src/exec/librpc/include/rpc/auth.h b/c/src/exec/librpc/include/rpc/auth.h new file mode 100644 index 0000000000..8f14d144f6 --- /dev/null +++ b/c/src/exec/librpc/include/rpc/auth.h @@ -0,0 +1,167 @@ +#ifndef RPC_AUTH_H +#define RPC_AUTH_H + +/* @(#)auth.h 2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * auth.h, Authentication interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * The data structures are completely opaque to the client. The client + * is required to pass a AUTH * to routines that create rpc + * "sessions". + */ + + +#define MAX_AUTH_BYTES 400 +#define MAXNETNAMELEN 255 /* maximum length of network user's name */ + +/* + * Status returned from authentication check + */ +enum auth_stat { + AUTH_OK=0, + /* + * failed at remote end + */ + AUTH_BADCRED=1, /* bogus credentials (seal broken) */ + AUTH_REJECTEDCRED=2, /* client should begin new session */ + AUTH_BADVERF=3, /* bogus verifier (seal broken) */ + AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ + AUTH_TOOWEAK=5, /* rejected due to security reasons */ + /* + * failed locally + */ + AUTH_INVALIDRESP=6, /* bogus response verifier */ + AUTH_FAILED=7 /* some unknown reason */ +}; + +union des_block { + struct { + u_int32 high; + u_int32 low; + } key; + char c[8]; +}; +typedef union des_block des_block; +extern bool_t xdr_des_block(); + +/* + * Authentication info. Opaque to client. + */ +struct opaque_auth { + enum_t oa_flavor; /* flavor of auth */ + caddr_t oa_base; /* address of more auth stuff */ + u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ +}; + + +/* + * Auth handle, interface to client side authenticators. + */ +typedef struct { + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + struct auth_ops { + void (*ah_nextverf)(); + int (*ah_marshal)(); /* nextverf & serialize */ + int (*ah_validate)(); /* validate varifier */ + int (*ah_refresh)(); /* refresh credentials */ + void (*ah_destroy)(); /* destroy this structure */ + } *ah_ops; + caddr_t ah_private; +} AUTH; + + +/* + * Authentication ops. + * The ops and the auth handle provide the interface to the authenticators. + * + * AUTH *auth; + * XDR *xdrs; + * struct opaque_auth verf; + */ +#define AUTH_NEXTVERF(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) +#define auth_nextverf(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) + +#define AUTH_MARSHALL(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) +#define auth_marshall(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) + +#define AUTH_VALIDATE(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) +#define auth_validate(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) + +#define AUTH_REFRESH(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) +#define auth_refresh(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) + +#define AUTH_DESTROY(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) +#define auth_destroy(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) + + +extern struct opaque_auth _null_auth; + + +/* + * These are the various implementations of client side authenticators. + */ + +/* + * Unix style authentication + * AUTH *authunix_create(machname, uid, gid, len, aup_gids) + * char *machname; + * int uid; + * int gid; + * int len; + * int *aup_gids; + */ +extern AUTH *authunix_create(); +extern AUTH *authunix_create_default(); /* takes no parameters */ +extern AUTH *authnone_create(); /* takes no parameters */ +extern AUTH *authdes_create(); + +#define AUTH_NONE 0 /* no authentication */ +#define AUTH_NULL 0 /* backward compatibility */ +#define AUTH_UNIX 1 /* unix style (uid, gids) */ +#define AUTH_SHORT 2 /* short hand unix style */ +#define AUTH_DES 3 /* des style (encrypted timestamps) */ + +#endif /* RPC_AUTH_H */ diff --git a/c/src/exec/librpc/include/rpc/clnt.h b/c/src/exec/librpc/include/rpc/clnt.h new file mode 100644 index 0000000000..faefdb5d50 --- /dev/null +++ b/c/src/exec/librpc/include/rpc/clnt.h @@ -0,0 +1,336 @@ +#ifndef RPC_CLNT_H +#define RPC_CLNT_H + +/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * clnt.h - Client side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _CLNT_ +#define _CLNT_ + +/* + * Rpc calls return an enum clnt_stat. This should be looked at more, + * since each implementation is required to live with this (implementation + * independent) list of errors. + */ +enum clnt_stat { + RPC_SUCCESS=0, /* call succeeded */ + /* + * local errors + */ + RPC_CANTENCODEARGS=1, /* can't encode arguments */ + RPC_CANTDECODERES=2, /* can't decode results */ + RPC_CANTSEND=3, /* failure in sending call */ + RPC_CANTRECV=4, /* failure in receiving result */ + RPC_TIMEDOUT=5, /* call timed out */ + /* + * remote errors + */ + RPC_VERSMISMATCH=6, /* rpc versions not compatible */ + RPC_AUTHERROR=7, /* authentication error */ + RPC_PROGUNAVAIL=8, /* program not available */ + RPC_PROGVERSMISMATCH=9, /* program version mismatched */ + RPC_PROCUNAVAIL=10, /* procedure unavailable */ + RPC_CANTDECODEARGS=11, /* decode arguments error */ + RPC_SYSTEMERROR=12, /* generic "other problem" */ + + /* + * callrpc & clnt_create errors + */ + RPC_UNKNOWNHOST=13, /* unknown host name */ + RPC_UNKNOWNPROTO=17, /* unkown protocol */ + + /* + * _ create errors + */ + RPC_PMAPFAILURE=14, /* the pmapper failed in its call */ + RPC_PROGNOTREGISTERED=15, /* remote program is not registered */ + /* + * unspecified error + */ + RPC_FAILED=16 +}; + + +/* + * Error info. + */ +struct rpc_err { + enum clnt_stat re_status; + union { + int RE_errno; /* realated system error */ + enum auth_stat RE_why; /* why the auth error occurred */ + struct { + u_long low; /* lowest verion supported */ + u_long high; /* highest verion supported */ + } RE_vers; + struct { /* maybe meaningful if RPC_FAILED */ + long s1; + long s2; + } RE_lb; /* life boot & debugging only */ + } ru; +#define re_errno ru.RE_errno +#define re_why ru.RE_why +#define re_vers ru.RE_vers +#define re_lb ru.RE_lb +}; + + +/* + * Client rpc handle. + * Created by individual implementations, see e.g. rpc_udp.c. + * Client is responsible for initializing auth, see e.g. auth_none.c. + */ +typedef struct { + AUTH *cl_auth; /* authenticator */ + struct clnt_ops { + enum clnt_stat (*cl_call)(); /* call remote procedure */ + void (*cl_abort)(); /* abort a call */ + void (*cl_geterr)(); /* get specific error code */ + bool_t (*cl_freeres)(); /* frees results */ + void (*cl_destroy)();/* destroy this structure */ + bool_t (*cl_control)();/* the ioctl() of rpc */ + } *cl_ops; + caddr_t cl_private; /* private stuff */ +} CLIENT; + + +/* + * client side rpc interface ops + * + * Parameter types are: + * + */ + +/* + * enum clnt_stat + * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) + * CLIENT *rh; + * u_long proc; + * xdrproc_t xargs; + * caddr_t argsp; + * xdrproc_t xres; + * caddr_t resp; + * struct timeval timeout; + */ +#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) +#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) + +/* + * void + * CLNT_ABORT(rh); + * CLIENT *rh; + */ +#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) +#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) + +/* + * struct rpc_err + * CLNT_GETERR(rh); + * CLIENT *rh; + */ +#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) +#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) + + +/* + * bool_t + * CLNT_FREERES(rh, xres, resp); + * CLIENT *rh; + * xdrproc_t xres; + * caddr_t resp; + */ +#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) +#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) + +/* + * bool_t + * CLNT_CONTROL(cl, request, info) + * CLIENT *cl; + * u_int request; + * char *info; + */ +#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) +#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) + +/* + * control operations that apply to both udp and tcp transports + */ +#define CLSET_TIMEOUT 1 /* set timeout (timeval) */ +#define CLGET_TIMEOUT 2 /* get timeout (timeval) */ +#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */ +/* + * udp only control operations + */ +#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ +#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ + +/* + * void + * CLNT_DESTROY(rh); + * CLIENT *rh; + */ +#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) +#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) + + +/* + * RPCTEST is a test program which is accessable on every rpc + * transport/port. It is used for testing, performance evaluation, + * and network administration. + */ + +#define RPCTEST_PROGRAM ((u_long)1) +#define RPCTEST_VERSION ((u_long)1) +#define RPCTEST_NULL_PROC ((u_long)2) +#define RPCTEST_NULL_BATCH_PROC ((u_long)3) + +/* + * By convention, procedure 0 takes null arguments and returns them + */ + +#define NULLPROC ((u_long)0) + +/* + * Below are the client handle creation routines for the various + * implementations of client side rpc. They can return NULL if a + * creation failure occurs. + */ + +/* + * Memory based rpc (for speed check and testing) + * CLIENT * + * clntraw_create(prog, vers) + * u_long prog; + * u_long vers; + */ +extern CLIENT *clntraw_create(); + + +/* + * Generic client creation routine. Supported protocols are "udp" and "tcp" + */ +extern CLIENT * +clnt_create(/*host, prog, vers, prot*/); /* + char *host; -- hostname + u_long prog; -- program number + u_long vers; -- version number + char *prot; -- protocol +*/ + + + + +/* + * TCP based rpc + * CLIENT * + * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clnttcp_create(); + +/* + * UDP based rpc. + * CLIENT * + * clntudp_create(raddr, program, version, wait, sockp) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait; + * int *sockp; + * + * Same as above, but you specify max packet sizes. + * CLIENT * + * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait; + * int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clntudp_create(); +extern CLIENT *clntudp_bufcreate(); + +/* + * Print why creation failed + */ +void clnt_pcreateerror(/* char *msg */); /* stderr */ +char *clnt_spcreateerror(/* char *msg */); /* string */ + +/* + * Like clnt_perror(), but is more verbose in its output + */ +void clnt_perrno(/* enum clnt_stat num */); /* stderr */ + +/* + * Print an English error message, given the client error code + */ +void clnt_perror(/* CLIENT *clnt, char *msg */); /* stderr */ +char *clnt_sperror(/* CLIENT *clnt, char *msg */); /* string */ + +/* + * If a creation fails, the following allows the user to figure out why. + */ +struct rpc_createerr { + enum clnt_stat cf_stat; + struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ +}; + +extern struct rpc_createerr rpc_createerr; + + + +/* + * Copy error message to buffer. + */ +char *clnt_sperrno(/* enum clnt_stat num */); /* string */ + + + +#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ +#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ + +#endif /*!_CLNT_*/ + +#endif /* RPC_CLNT_H */ diff --git a/c/src/exec/librpc/include/rpc/rpc.h b/c/src/exec/librpc/include/rpc/rpc.h new file mode 100644 index 0000000000..0a0affd82a --- /dev/null +++ b/c/src/exec/librpc/include/rpc/rpc.h @@ -0,0 +1,86 @@ +#ifndef RPC_H +#define RPC_H + +/* @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC; from 1.9 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * rpc.h, Just includes the billions of rpc header files necessary to + * do remote procedure calling. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +#ifndef __RPC_HEADER__ +#define __RPC_HEADER__ + +#include /* some typedefs */ +#include +#include + +/* external data representation interfaces */ +#include /* generic (de)serializer */ + +/* Client side only authentication */ +#include /* generic authenticator (client side) */ + +/* Client side (mostly) remote procedure call */ +#include /* generic rpc stuff */ + +/* semi-private protocol headers */ +#include /* protocol for rpc messages */ +/*#include "auth_unix.h" * protocol for unix style cred */ +/* + * Uncomment-out the next line if you are building the rpc library with + * DES Authentication (see the README file in the secure_rpc/ directory). + */ +/*#include "auth_des.h" * protocol for des style cred */ + +/* Server side only remote procedure callee */ +#include /* service manager and multiplexer */ +#include /* service side authenticator */ + +/* + * COMMENT OUT THE NEXT INCLUDE (or add to the #ifndef) IF RUNNING ON + * A VERSION OF UNIX THAT USES SUN'S NFS SOURCE. These systems will + * already have the structures defined by included in . + */ +/* routines for parsing /etc/rpc */ + +struct rpcent { + char *r_name; /* name of server for this rpc program */ + char **r_aliases; /* alias list */ + int r_number; /* rpc program number */ +}; + +struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent(); + +#endif /* ndef __RPC_HEADER__ */ + +#endif /* RPC_H */ diff --git a/c/src/exec/librpc/include/rpc/rpc_msg.h b/c/src/exec/librpc/include/rpc/rpc_msg.h new file mode 100644 index 0000000000..2f34fb614c --- /dev/null +++ b/c/src/exec/librpc/include/rpc/rpc_msg.h @@ -0,0 +1,192 @@ +#ifndef RPC_MSG_H +#define RPC_MSG_H + +/* @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)rpc_msg.h 1.7 86/07/16 SMI */ + +/* + * rpc_msg.h + * rpc message definition + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define RPC_MSG_VERSION ((u_long) 2) +#define RPC_SERVICE_PORT ((u_short) 2048) + +/* + * Bottom up definition of an rpc message. + * NOTE: call and reply use the same overall stuct but + * different parts of unions within it. + */ + +enum msg_type { + CALL=0, + REPLY=1 +}; + +enum reply_stat { + MSG_ACCEPTED=0, + MSG_DENIED=1 +}; + +enum accept_stat { + SUCCESS=0, + PROG_UNAVAIL=1, + PROG_MISMATCH=2, + PROC_UNAVAIL=3, + GARBAGE_ARGS=4, + SYSTEM_ERR=5 +}; + +enum reject_stat { + RPC_MISMATCH=0, + AUTH_ERROR=1 +}; + +/* + * Reply part of an rpc exchange + */ + +/* + * Reply to an rpc request that was accepted by the server. + * Note: there could be an error even though the request was + * accepted. + */ +struct accepted_reply { + struct opaque_auth ar_verf; + enum accept_stat ar_stat; + union { + struct { + u_long low; + u_long high; + } AR_versions; + struct { + caddr_t where; + xdrproc_t proc; + } AR_results; + /* and many other null cases */ + } ru; +#define ar_results ru.AR_results +#define ar_vers ru.AR_versions +}; + +/* + * Reply to an rpc request that was rejected by the server. + */ +struct rejected_reply { + enum reject_stat rj_stat; + union { + struct { + u_long low; + u_long high; + } RJ_versions; + enum auth_stat RJ_why; /* why authentication did not work */ + } ru; +#define rj_vers ru.RJ_versions +#define rj_why ru.RJ_why +}; + +/* + * Body of a reply to an rpc request. + */ +struct reply_body { + enum reply_stat rp_stat; + union { + struct accepted_reply RP_ar; + struct rejected_reply RP_dr; + } ru; +#define rp_acpt ru.RP_ar +#define rp_rjct ru.RP_dr +}; + +/* + * Body of an rpc request call. + */ +struct call_body { + u_long cb_rpcvers; /* must be equal to two */ + u_long cb_prog; + u_long cb_vers; + u_long cb_proc; + struct opaque_auth cb_cred; + struct opaque_auth cb_verf; /* protocol specific - provided by client */ +}; + +/* + * The rpc message + */ +struct rpc_msg { + u_long rm_xid; + enum msg_type rm_direction; + union { + struct call_body RM_cmb; + struct reply_body RM_rmb; + } ru; +#define rm_call ru.RM_cmb +#define rm_reply ru.RM_rmb +}; +#define acpted_rply ru.RM_rmb.ru.RP_ar +#define rjcted_rply ru.RM_rmb.ru.RP_dr + + +/* + * XDR routine to handle a rpc message. + * xdr_callmsg(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callmsg(); + +/* + * XDR routine to pre-serialize the static part of a rpc message. + * xdr_callhdr(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callhdr(); + +/* + * XDR routine to handle a rpc reply. + * xdr_replymsg(xdrs, rmsg) + * XDR *xdrs; + * struct rpc_msg *rmsg; + */ +extern bool_t xdr_replymsg(); + +/* + * Fills in the error part of a reply message. + * _seterr_reply(msg, error) + * struct rpc_msg *msg; + * struct rpc_err *error; + */ +extern void _seterr_reply(); + +#endif /* RPC_MSG_H */ diff --git a/c/src/exec/librpc/include/rpc/svc.h b/c/src/exec/librpc/include/rpc/svc.h new file mode 100644 index 0000000000..c576b5538b --- /dev/null +++ b/c/src/exec/librpc/include/rpc/svc.h @@ -0,0 +1,291 @@ + +#ifndef RPC_SVC_H +#define RPC_SVC_H + +/* @(#)svc.h 2.2 88/07/29 4.0 RPCSRC; from 1.20 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc.h, Server-side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef __SVC_HEADER__ +#define __SVC_HEADER__ + +/* + * This interface must manage two items concerning remote procedure calling: + * + * 1) An arbitrary number of transport connections upon which rpc requests + * are received. The two most notable transports are TCP and UDP; they are + * created and registered by routines in svc_tcp.c and svc_udp.c, respectively; + * they in turn call xprt_register and xprt_unregister. + * + * 2) An arbitrary number of locally registered services. Services are + * described by the following four data: program number, version number, + * "service dispatch" function, a transport handle, and a boolean that + * indicates whether or not the exported program should be registered with a + * local binder service; if true the program's number and version and the + * port number from the transport handle are registered with the binder. + * These data are registered with the rpc svc system via svc_register. + * + * A service's dispatch function is called whenever an rpc request comes in + * on a transport. The request's program and version numbers must match + * those of the registered service. The dispatch function is passed two + * parameters, struct svc_req * and SVCXPRT *, defined below. + */ + +enum xprt_stat { + XPRT_DIED, + XPRT_MOREREQS, + XPRT_IDLE +}; + +/* + * Server side transport handle + */ +typedef struct { + int xp_sock; + u_short xp_port; /* associated port number */ + struct xp_ops { + bool_t (*xp_recv)(); /* receive incomming requests */ + enum xprt_stat (*xp_stat)(); /* get transport status */ + bool_t (*xp_getargs)(); /* get arguments */ + bool_t (*xp_reply)(); /* send reply */ + bool_t (*xp_freeargs)();/* free mem allocated for args */ + void (*xp_destroy)(); /* destroy this struct */ + } *xp_ops; + int xp_addrlen; /* length of remote address */ + struct sockaddr_in xp_raddr; /* remote address */ + struct opaque_auth xp_verf; /* raw response verifier */ + caddr_t xp_p1; /* private */ + caddr_t xp_p2; /* private */ +} SVCXPRT; + +/* + * Approved way of getting address of caller + */ +#define svc_getcaller(x) (&(x)->xp_raddr) + +/* + * Operations defined on an SVCXPRT handle + * + * SVCXPRT *xprt; + * struct rpc_msg *msg; + * xdrproc_t xargs; + * caddr_t argsp; + */ +#define SVC_RECV(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) +#define svc_recv(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) + +#define SVC_STAT(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) +#define svc_stat(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) + +#define SVC_GETARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) +#define svc_getargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) + +#define SVC_REPLY(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) +#define svc_reply(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) + +#define SVC_FREEARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) +#define svc_freeargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) + +#define SVC_DESTROY(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) +#define svc_destroy(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) + + +/* + * Service request + */ +struct svc_req { + u_long rq_prog; /* service program number */ + u_long rq_vers; /* service protocol version */ + u_long rq_proc; /* the desired procedure */ + struct opaque_auth rq_cred; /* raw creds from the wire */ + caddr_t rq_clntcred; /* read only cooked cred */ + SVCXPRT *rq_xprt; /* associated transport */ +}; + + +/* + * Service registration + * + * svc_register(xprt, prog, vers, dispatch, protocol) + * SVCXPRT *xprt; + * u_long prog; + * u_long vers; + * void (*dispatch)(); + * int protocol; (like TCP or UDP, zero means do not register) + */ +extern bool_t svc_register(); + +/* + * Service un-registration + * + * svc_unregister(prog, vers) + * u_long prog; + * u_long vers; + */ +extern void svc_unregister(); + +/* + * Transport registration. + * + * xprt_register(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_register(); + +/* + * Transport un-register + * + * xprt_unregister(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_unregister(); + + + + +/* + * When the service routine is called, it must first check to see if it + * knows about the procedure; if not, it should call svcerr_noproc + * and return. If so, it should deserialize its arguments via + * SVC_GETARGS (defined above). If the deserialization does not work, + * svcerr_decode should be called followed by a return. Successful + * decoding of the arguments should be followed the execution of the + * procedure's code and a call to svc_sendreply. + * + * Also, if the service refuses to execute the procedure due to too- + * weak authentication parameters, svcerr_weakauth should be called. + * Note: do not confuse access-control failure with weak authentication! + * + * NB: In pure implementations of rpc, the caller always waits for a reply + * msg. This message is sent when svc_sendreply is called. + * Therefore pure service implementations should always call + * svc_sendreply even if the function logically returns void; use + * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows + * for the abuse of pure rpc via batched calling or pipelining. In the + * case of a batched call, svc_sendreply should NOT be called since + * this would send a return message, which is what batching tries to avoid. + * It is the service/protocol writer's responsibility to know which calls are + * batched and which are not. Warning: responding to batch calls may + * deadlock the caller and server processes! + */ + +extern bool_t svc_sendreply(); +extern void svcerr_decode(); +extern void svcerr_weakauth(); +extern void svcerr_noproc(); +extern void svcerr_progvers(); +extern void svcerr_auth(); +extern void svcerr_noprog(); +extern void svcerr_systemerr(); + +/* + * Lowest level dispatching -OR- who owns this process anyway. + * Somebody has to wait for incoming requests and then call the correct + * service routine. The routine svc_run does infinite waiting; i.e., + * svc_run never returns. + * Since another (co-existant) package may wish to selectively wait for + * incoming calls or other events outside of the rpc architecture, the + * routine svc_getreq is provided. It must be passed readfds, the + * "in-place" results of a select system call (see select, section 2). + */ + +/* + * Global keeper of rpc service descriptors in use + * dynamic; must be inspected before each call to select + */ +#ifdef FD_SETSIZE +extern fd_set svc_fdset; +#define svc_fds svc_fdset.fds_bits[0] /* compatibility */ +#else +extern int svc_fds; +#endif /* def FD_SETSIZE */ + +/* + * a small program implemented by the svc_rpc implementation itself; + * also see clnt.h for protocol numbers. + */ +extern void rpctest_service(); + +extern void svc_getreq(); +extern void svc_getreqset(); /* takes fdset instead of int */ +extern void svc_run(); /* never returns */ + +/* + * Socket to use on svcxxx_create call to get default socket + */ +#define RPC_ANYSOCK -1 + +/* + * These are the existing service side transport implementations + */ + +/* + * Memory based rpc for testing and timing. + */ +extern SVCXPRT *svcraw_create(); + +/* + * Udp based rpc. + */ +extern SVCXPRT *svcudp_create(); +extern SVCXPRT *svcudp_bufcreate(); +extern int svcudp_enablecache(SVCXPRT *transp, u_long size); + +/* + * Tcp based rpc. + */ +extern SVCXPRT *svctcp_create(); + + + +#endif /* !__SVC_HEADER__ */ + +extern int _rpcsvccount; +extern int _rpcsvcstate; +extern int _SERVED; + +#endif /* RPC_SVC_H */ diff --git a/c/src/exec/librpc/include/rpc/svc_auth.h b/c/src/exec/librpc/include/rpc/svc_auth.h new file mode 100644 index 0000000000..5c233a6a47 --- /dev/null +++ b/c/src/exec/librpc/include/rpc/svc_auth.h @@ -0,0 +1,47 @@ +#ifndef RPC_SVC_AUTH_H +#define RPC_SVC_AUTH_H + +/* @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)svc_auth.h 1.6 86/07/16 SMI */ + +/* + * svc_auth.h, Service side of rpc authentication. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + + +/* + * Server side authenticator + */ +extern enum auth_stat _authenticate(); + +#endif /* SVC_AUTH_H */ diff --git a/c/src/exec/librpc/include/rpc/types.h b/c/src/exec/librpc/include/rpc/types.h new file mode 100644 index 0000000000..b6d7eb3ccc --- /dev/null +++ b/c/src/exec/librpc/include/rpc/types.h @@ -0,0 +1,75 @@ +#ifndef RPC_TYPES_H +#define RPC_TYPES_H + +/* @(#)types.h 2.3 88/08/15 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)types.h 1.18 87/07/24 SMI */ + +/* + * Rpc additions to + */ +#ifndef __TYPES_RPC_HEADER__ +#define __TYPES_RPC_HEADER__ + +/*#include */ +typedef unsigned long u_int32; /* 32-bit unsigned integers */ + +#define bool_t int +#define enum_t int +#ifndef FALSE +# define FALSE (0) +#endif +#ifndef TRUE +# define TRUE (1) +#endif +#define __dontcare__ -1 +#ifndef NULL +# define NULL 0 +#endif + +void *malloc(); +#define mem_alloc(bsize) malloc(bsize) +#define mem_free(ptr, bsize) free(ptr) + +#ifndef makedev /* ie, we haven't already included it */ +#include +#endif +#include + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK (u_long)0x7F000001 +#endif +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#endif /* ndef __TYPES_RPC_HEADER__ */ + +#endif /* RPC_TYPES_H */ diff --git a/c/src/exec/librpc/include/rpc/xdr.h b/c/src/exec/librpc/include/rpc/xdr.h new file mode 100644 index 0000000000..ef2df51d93 --- /dev/null +++ b/c/src/exec/librpc/include/rpc/xdr.h @@ -0,0 +1,275 @@ +#ifndef RPC_XDR_H +#define RPC_XDR_H + +/* @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)xdr.h 1.19 87/04/22 SMI */ + +/* + * xdr.h, External Data Representation Serialization Routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef __XDR_HEADER__ +#define __XDR_HEADER__ + +/* + * XDR provides a conventional way for converting between C data + * types and an external bit-string representation. Library supplied + * routines provide for the conversion on built-in C data types. These + * routines and utility routines defined here are used to help implement + * a type encode/decode routine for each user-defined type. + * + * Each data type provides a single procedure which takes two arguments: + * + * bool_t + * xdrproc(xdrs, argresp) + * XDR *xdrs; + * *argresp; + * + * xdrs is an instance of a XDR handle, to which or from which the data + * type is to be converted. argresp is a pointer to the structure to be + * converted. The XDR handle contains an operation field which indicates + * which of the operations (ENCODE, DECODE * or FREE) is to be performed. + * + * XDR_DECODE may allocate space if the pointer argresp is null. This + * data can be freed with the XDR_FREE operation. + * + * We write only one procedure per data type to make it easy + * to keep the encode and decode procedures for a data type consistent. + * In many cases the same code performs all operations on a user defined type, + * because all the hard work is done in the component type routines. + * decode as a series of calls on the nested data types. + */ + +/* + * Xdr operations. XDR_ENCODE causes the type to be encoded into the + * stream. XDR_DECODE causes the type to be extracted from the stream. + * XDR_FREE can be used to release the space allocated by an XDR_DECODE + * request. + */ +enum xdr_op { + XDR_ENCODE=0, + XDR_DECODE=1, + XDR_FREE=2 +}; + +/* + * This is the number of bytes per unit of external data. + */ +#define BYTES_PER_XDR_UNIT (4) +#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ + * BYTES_PER_XDR_UNIT) + +/* + * A xdrproc_t exists for each data type which is to be encoded or decoded. + * + * The second argument to the xdrproc_t is a pointer to an opaque pointer. + * The opaque pointer generally points to a structure of the data type + * to be decoded. If this pointer is 0, then the type routines should + * allocate dynamic storage of the appropriate size and return it. + * bool_t (*xdrproc_t)(XDR *, caddr_t *); + */ +typedef bool_t (*xdrproc_t)(); + +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the paticular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular impelementation. + */ +typedef struct { + enum xdr_op x_op; /* operation; fast additional param */ + struct xdr_ops { + bool_t (*x_getlong)(); /* get a long from underlying stream */ + bool_t (*x_putlong)(); /* put a long to " */ + bool_t (*x_getbytes)();/* get some bytes from " */ + bool_t (*x_putbytes)();/* put some bytes to " */ + u_int (*x_getpostn)();/* returns bytes off from beginning */ + bool_t (*x_setpostn)();/* lets you reposition the stream */ + long * (*x_inline)(); /* buf quick ptr to buffered data */ + void (*x_destroy)(); /* free privates of this xdr_stream */ + } *x_ops; + caddr_t x_public; /* users' data */ + caddr_t x_private; /* pointer to private data */ + caddr_t x_base; /* private used for position info */ + int x_handy; /* extra private word */ +} XDR; + +/* + * Operations defined on a XDR handle + * + * XDR *xdrs; + * long *longp; + * caddr_t addr; + * u_int len; + * u_int pos; + */ +#define XDR_GETLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) +#define xdr_getlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) + +#define XDR_PUTLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) +#define xdr_putlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) + +#define XDR_GETBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) +#define xdr_getbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) + +#define XDR_PUTBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) +#define xdr_putbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) + +#define XDR_GETPOS(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) +#define xdr_getpos(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) + +#define XDR_SETPOS(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) +#define xdr_setpos(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) + +#define XDR_INLINE(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) +#define xdr_inline(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) + +#define XDR_DESTROY(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) +#define xdr_destroy(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) + +/* + * Support struct for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * a entry with a null procedure pointer. The xdr_union routine gets + * the discriminant value and then searches the array of structures + * for a matching value. If a match is found the associated xdr routine + * is called to handle that part of the union. If there is + * no match, then a default routine may be called. + * If there is no match and no default routine it is an error. + */ +#define NULL_xdrproc_t ((xdrproc_t)0) +struct xdr_discrim { + int value; + xdrproc_t proc; +}; + +/* + * In-line routines for fast encode/decode of primitve data types. + * Caveat emptor: these use single memory cycles to get the + * data from the underlying buffer, and will fail to operate + * properly if the data is not aligned. The standard way to use these + * is to say: + * if ((buf = XDR_INLINE(xdrs, count)) == NULL) + * return (FALSE); + * <<< macro calls >>> + * where ``count'' is the number of bytes of data occupied + * by the primitive data types. + * + * N.B. and frozen for all time: each data type here uses 4 bytes + * of external representation. + */ +#define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*(buf)++)) +#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((u_long)v)) + +#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) +#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) +#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) + +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) + +/* + * These are the "generic" xdr routines. + */ +extern bool_t xdr_void(); +extern bool_t xdr_int(); +extern bool_t xdr_u_int(); +extern bool_t xdr_long(); +extern bool_t xdr_u_long(); +extern bool_t xdr_short(); +extern bool_t xdr_u_short(); +extern bool_t xdr_bool(); +extern bool_t xdr_enum(); +extern bool_t xdr_array(); +extern bool_t xdr_bytes(); +extern bool_t xdr_opaque(); +extern bool_t xdr_string(); +extern bool_t xdr_union(); +extern bool_t xdr_char(); +extern bool_t xdr_u_char(); +extern bool_t xdr_vector(); +extern bool_t xdr_float(); +extern bool_t xdr_double(); +extern bool_t xdr_reference(); +extern bool_t xdr_pointer(); +extern bool_t xdr_wrapstring(); + +/* + * Common opaque bytes objects used by many rpc protocols; + * declared here due to commonality. + */ +#define MAX_NETOBJ_SZ 1024 +struct netobj { + u_int n_len; + char *n_bytes; +}; +typedef struct netobj netobj; +extern bool_t xdr_netobj(); + +/* + * These are the public routines for the various implementations of + * xdr streams. + */ +extern void xdrmem_create(); /* XDR using memory buffers */ +extern void xdrstdio_create(); /* XDR using stdio library */ +extern void xdrrec_create(); /* XDR pseudo records for tcp */ +extern bool_t xdrrec_endofrecord(); /* make end of xdr record */ +extern bool_t xdrrec_skiprecord(); /* move to beginning of next record */ +extern bool_t xdrrec_eof(); /* true if no more input */ + +#endif /* !__XDR_HEADER__ */ + +#endif /* RPC_XDR_H */ diff --git a/c/src/exec/score/cpu/i386/cpu.h b/c/src/exec/score/cpu/i386/cpu.h index 4d22e53a93..29f7d1161b 100644 --- a/c/src/exec/score/cpu/i386/cpu.h +++ b/c/src/exec/score/cpu/i386/cpu.h @@ -151,25 +151,27 @@ extern void rtems_exception_init_mngt(); typedef CPU_Exception_frame CPU_Interrupt_frame; typedef enum { - I386_EXCEPTION_DIVIDE_BY_ZERO = 0, - I386_EXCEPTION_DEBUG = 1, - I386_EXCEPTION_NMI = 2, - I386_EXCEPTION_BREAKPOINT = 3, - I386_EXCEPTION_OVERFLOW = 4, - I386_EXCEPTION_BOUND = 5, - I386_EXCEPTION_ILLEGAL_INSTR = 6, - I386_EXCEPTION_MATH_COPROC_UNAVAIL = 7, - I386_EXCEPTION_DOUBLE_FAULT = 8, - I386_EXCEPTION_I386_COPROC_SEG_ERR = 9, - I386_EXCEPTION_INVALID_TSS = 10, - I386_EXCEPTION_SEGMENT_NOT_PRESENT = 11, - I386_EXCEPTION_STACK_SEGMENT_FAULT = 12, - I386_EXCEPTION_GENERAL_PROT_ERR = 13, - I386_EXCEPTION_PAGE_FAULT = 14, - I386_EXCEPTION_INTEL_RES15 = 15, - I386_EXCEPTION_FLOAT_ERROR = 16, - I386_EXCEPTION_ALIGN_CHECK = 17, - I386_EXCEPTION_MACHINE_CHECK = 18 + I386_EXCEPTION_DIVIDE_BY_ZERO = 0, + I386_EXCEPTION_DEBUG = 1, + I386_EXCEPTION_NMI = 2, + I386_EXCEPTION_BREAKPOINT = 3, + I386_EXCEPTION_OVERFLOW = 4, + I386_EXCEPTION_BOUND = 5, + I386_EXCEPTION_ILLEGAL_INSTR = 6, + I386_EXCEPTION_MATH_COPROC_UNAVAIL = 7, + I386_EXCEPTION_DOUBLE_FAULT = 8, + I386_EXCEPTION_I386_COPROC_SEG_ERR = 9, + I386_EXCEPTION_INVALID_TSS = 10, + I386_EXCEPTION_SEGMENT_NOT_PRESENT = 11, + I386_EXCEPTION_STACK_SEGMENT_FAULT = 12, + I386_EXCEPTION_GENERAL_PROT_ERR = 13, + I386_EXCEPTION_PAGE_FAULT = 14, + I386_EXCEPTION_INTEL_RES15 = 15, + I386_EXCEPTION_FLOAT_ERROR = 16, + I386_EXCEPTION_ALIGN_CHECK = 17, + I386_EXCEPTION_MACHINE_CHECK = 18, + I386_EXCEPTION_ENTER_RDBG = 50 /* to enter manually RDBG */ + } Intel_symbolic_exception_name; diff --git a/c/src/exec/score/cpu/i386/cpu_asm.s b/c/src/exec/score/cpu/i386/cpu_asm.s index 16d0a7c205..4ac4dab626 100644 --- a/c/src/exec/score/cpu/i386/cpu_asm.s +++ b/c/src/exec/score/cpu/i386/cpu_asm.s @@ -109,6 +109,7 @@ SYM (_CPU_Context_restore_fp): frstor (eax) # restore FP context ret + PUBLIC (_Exception_Handler) SYM (_Exception_Handler): pusha # Push general purpose registers pushl esp # Push exception frame address diff --git a/c/src/lib/Makefile.in b/c/src/lib/Makefile.in index fe900e8b05..23bbc6ab0a 100644 --- a/c/src/lib/Makefile.in +++ b/c/src/lib/Makefile.in @@ -17,6 +17,14 @@ LIBNETWORKING = $(LIBNETWORKING_$(HAS_NETWORKING)_V) NETWORKING_INCLUDE_yes_V = libnetworking/include NETWORKING_INCLUDE = $(NETWORKING_INCLUDE_$(HAS_NETWORKING)_V) +# We only build the rpc library if HAS_NETWORKING was defined +LIBRPC_yes_V = librpc +LIBRPC = $(LIBRPC_$(HAS_NETWORKING)_V) + +# We only build the rdbg library if HAS_NETWORKING and HAS_RDBG was defined +LIBRDBG_yes_yes_V = librdbg +LIBRDBG = $(LIBRDBG_$(HAS_NETWORKING)_$(HAS_RDBG)_V) + # We only build the rtems++ library if HAS_CPLUSPLUS was defined LIBRTEMSCPLUSPLUS_yes_V = librtems++ LIBRTEMSCPLUSPLUS = $(LIBRTEMSCPLUSPLUS_$(HAS_CPLUSPLUS)_V) @@ -25,7 +33,8 @@ LIBRTEMSCPLUSPLUS = $(LIBRTEMSCPLUSPLUS_$(HAS_CPLUSPLUS)_V) LIBHWAPI=$(wildcard libhwapi) -ifneq ($(RTEMS_CPU),unix) + $(LIBNETWORKING) $(LIBRPC) $(LIBRDBG) \ + $(LIBHWAPI) $(LIBRTEMSCPLUSPLUS) wrapup LIBCHIP=libchip endif diff --git a/c/src/lib/include/Makefile.in b/c/src/lib/include/Makefile.in index 4d5aef8a89..01f24139ea 100644 --- a/c/src/lib/include/Makefile.in +++ b/c/src/lib/include/Makefile.in @@ -25,8 +25,15 @@ RTEMSCPLUSPLUS_H_PIECES= rtemsEvent rtemsInterrupt rtemsMessageQueue \ rtemsSemaphore rtemsStatusCode rtemsTask rtemsTaskMode rtemsTimer RTEMSCPLUSPLUS_H_FILES=$(RTEMSCPLUSPLUS_H_PIECES:%=$(srcdir)/rtems++/%.h) +RPC_H_PIECES= auth clnt rpc rpc_msg svc svc_auth types xdr +RPC_H_FILES=$(RPC_H_PIECES:%=$(srcdir)/rpc/%.h) + +RDBG_H_PIECES= servrpc rdbg $(RTEMS_CPU)/rdbg_f $(RTEMS_CPU)/reg +RDBG_H_FILES=$(RDBG_H_PIECES:%=$(srcdir)/rdbg/%.h) + SRCS=$(H_FILES) $(SYS_H_FILES) \ - $(MOTOROLA_H_FILES) $(RTEMSCPLUSPLUS_H_FILES) + $(MOTOROLA_H_FILES) $(RTEMSCPLUSPLUS_H_FILES) \ + $(RPC_H_FILES) $(RDBG_H_FILES) include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg include $(RTEMS_ROOT)/make/leaf.cfg @@ -42,3 +49,9 @@ all: $(SRCS) ifeq ($(HAS_CPLUSPLUS),yes) $(INSTALL) -m 444 $(RTEMSCPLUSPLUS_H_FILES) $(PROJECT_INCLUDE)/rtems++ endif +ifeq ($(HAS_NETWORKING),yes) + $(INSTALL) -m 444 $(RPC_H_FILES) $(PROJECT_INCLUDE)/rpc +ifeq ($(HAS_RDBG),yes) + $(INSTALL) -m 444 $(RDBG_H_FILES) $(PROJECT_INCLUDE)/rdbg +endif +endif diff --git a/c/src/lib/include/rdbg/i386/rdbg_f.h b/c/src/lib/include/rdbg/i386/rdbg_f.h new file mode 100644 index 0000000000..3fd087f50a --- /dev/null +++ b/c/src/lib/include/rdbg/i386/rdbg_f.h @@ -0,0 +1,53 @@ +/* + ************************************************************************** + * + * Component = RDBG + * Module = rdbg_f.h + * + * Synopsis = Machine-dependent header file + * + ************************************************************************** + */ + +#ifndef RDBG_F_H +#define RDBG_F_H + +#include +#include + +#define EFLAGS_TF 0x00100 + +typedef struct Exception_context_struct { + struct Exception_context_struct *next; + struct Exception_context_struct *previous; + Objects_Id id; + Objects_Id semaphoreId; + CPU_Exception_frame *ctx; +} Exception_context; + +extern int PushExceptCtx (Objects_Id Id, + Objects_Id semId, + CPU_Exception_frame *ctx); +extern int PopExceptCtx (Objects_Id Id); +extern Exception_context *GetExceptCtx (Objects_Id Id); +extern int Single_Step (CPU_Exception_frame* ctx); +extern int CheckForSingleStep (CPU_Exception_frame* ctx); +extern void BreakPointExcHdl (CPU_Exception_frame *ctx); +extern void CtxToRegs (const CPU_Exception_frame*,xdr_regs*); +extern void RegsToCtx (const xdr_regs*,CPU_Exception_frame*); + +extern void enterRdbg (); +extern void get_ctx_thread (Thread_Control *thread, + CPU_Exception_frame* ctx); +extern void set_ctx_thread (Thread_Control *thread, + CPU_Exception_frame* ctx); + +void copyback_data_cache_and_invalidate_instr_cache(); + +extern int ExitForSingleStep; + + +#endif + + + diff --git a/c/src/lib/include/rdbg/i386/reg.h b/c/src/lib/include/rdbg/i386/reg.h new file mode 100644 index 0000000000..d6b34f3c28 --- /dev/null +++ b/c/src/lib/include/rdbg/i386/reg.h @@ -0,0 +1,32 @@ + + +#define NBREGS 19 + +#define SS 18 +#define UESP 17 +#define EFL 16 +#define CS 15 +#define EIP 14 +#define ERR 13 +#define TRAPNO 12 +#define EAX 11 +#define ECX 10 +#define EDX 9 +#define EBX 8 +#define ESP 7 +#define EBP 6 +#define ESI 5 +#define EDI 4 +#define DS 3 +#define ES 2 +#define FS 1 +#define GS 0 + +typedef unsigned int regs[NBREGS]; + +/* To be used in common code */ +typedef regs REGS; + + + + diff --git a/c/src/lib/include/rdbg/rdbg.h b/c/src/lib/include/rdbg/rdbg.h new file mode 100644 index 0000000000..737edd5575 --- /dev/null +++ b/c/src/lib/include/rdbg/rdbg.h @@ -0,0 +1,53 @@ +/* + ************************************************************************** + * + * Component = RDBG + * + * Synopsis = rdbg.h + * + ************************************************************************** + */ + +#ifndef RDBG_H +#define RDBG_H + +#include +#include +#include +#include +#include /* For malloc() and free() prototypes */ +#include + +#define Malloc(size) malloc (size) +#define Free(block) free (block) +#define Realloc(block,size) realloc (block, size) +#define StrDup(str) strdup(str) + +#define LIST_PID 16 /* dynamic list of processes/tasks */ +#define LIST_PID_DEB 17 /* list of processes under debug now */ +#define LIST_PID_THREAD 18 /* list of threads for specific process */ +#define LIST_CONN 19 /* dynamic list of connections */ + + /* RTEMS internals */ +extern void remotedeb_2 (struct svc_req* rqstp, SVCXPRT* transp); +extern void setErrno (int error); +extern int getErrno (); +extern int ptrace (int request, int pid, char* addr, + int data, char* addr2); + +extern int TSP_RETRIES; +extern volatile int ExitForSingleStep; +extern volatile int justSaveContext; +extern volatile Objects_Id currentTargetThread; +extern volatile int CannotRestart; +extern volatile int TotalReboot; + + /* Missing RPC prototypes */ +SVCXPRT* svcudp_create (int fd); +void svc_processrequest (SVCXPRT* xprt, + u_long prog, u_long vers, + void (*dispatch)()); +int svcudp_enablecache (SVCXPRT *transp, u_long size); + +#endif /* !RDBG_H */ + diff --git a/c/src/lib/include/rdbg/servrpc.h b/c/src/lib/include/rdbg/servrpc.h new file mode 100644 index 0000000000..71198d4d1f --- /dev/null +++ b/c/src/lib/include/rdbg/servrpc.h @@ -0,0 +1,268 @@ + +#ifndef SERVRPC_H +#define SERVRPC_H + + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +extern int CONN_LIST_INC; +extern int PID_LIST_INC; +extern int TSP_RETRIES; +extern int BackPort; +extern char ActName[]; +extern int getId(); + + +#ifdef DDEBUG +int rdb_debug; /* True if env var RDB_DEBUG defined */ +extern const char* PtraceNames[]; /* list of ptrace requests for debug out */ +extern const char* BmsgNames[]; /* list of BMSG_xxx names */ +extern const char* PtraceName(int req); + +# define DPRINTF(a) (rdb_debug ? printk ("%d >>> ", getId()), printk a : 0) +#else +# define DPRINTF(a) /* suppress */ +#endif + + /* Macros for analyzing/creating process status values. Presently do + not need to be separated per target. Could even use WIF... */ + +#define STS_SIGNALLED(status) (((status) & 0xFF) == 0x7F) +#define STS_TERMONSIG(status) (((status) & 0xFF) && !STS_SIGNALLED(status)) +#define STS_TERMGETSIG(status) ((status) & 0x7F) +#define STS_MAKESIG(sig) (((sig) << 8) | 0x7f) +#define STS_GETSIG(status) ((status) >> 8) +#define STS_GETCODE(status) ((status) >> 8) + + +/* now define base types */ +#ifndef UCHAR_DEFINED +#define UCHAR_DEFINED /* to handle duplicate typedes */ +typedef unsigned char UCHAR; +typedef unsigned char UINT8; +typedef char INT8; +typedef unsigned short UINT16; +typedef short INT16; +typedef unsigned long UINT32; +typedef long INT32; +#endif /* UCHAR_DEFINED */ + +typedef long PID; /* generalized process id */ + +#ifndef True +# define True 1 +# define False 0 +typedef char Boolean; +#endif + +#define MAX_FILENAME 1024 /* largest filename with path */ +#define MAX_SEND 5 /* up to 5 pended outbound messages */ + +#define SERVER_VERS 1 + +typedef enum +{ /* message types */ + BMSG_WARM=1, /* warm test for network connection */ + BMSG_WAIT, /* wait change (stopped/started) */ + BMSG_BREAK, /* breakpoint changed */ + BMSG_EXEC_FAIL, /* exec failed from spawn */ + BMSG_DETACH, /* process detached from server */ + BMSG_KILLED, /* killed by server */ + BMSG_NOT_PRIM, /* no longer the primary owner */ + BMSG_NEW_PID /* the process was restart with new pid (in + context). Same ownership rules. */ +} BACK_MSG; + +typedef struct +{ /* this is the break_list[0] entry of pid */ + UCHAR clr_step; /* true if step off break in last_break */ + UCHAR pad1; /* Set if STEPEMUL breakpoints exist */ + UINT16 last_break; /* last breakpoint we stopped on (if break) */ + UINT32 range_start; /* start address of range */ + UINT32 range_end; /* end address inclusive */ +} BASE_BREAK; + +enum +{ /* last start values */ + LAST_NONE, /* stopped already */ + LAST_STEP, /* did a step last - do not send to prim */ + LAST_CONT, /* did a continue last */ + LAST_RANGE, /* in the middle of step-in-range */ + LAST_STEPOFF, /* stepped off break, now need to cont */ + LAST_KILLED, /* was killed by ptrace */ + LAST_DETACHED /* was detached by ptrace */ +}; +#define LAST_START 0x80 /* first execed. This is to handle MiX + bug where we need to start again */ + +typedef struct +{ /* one per open process */ + PID pid; /* process id (or 0 if free) */ + int state; /* status from last wait if stopped */ + UCHAR running; /* True if running, else stopped/term */ + /* now connection control over process */ + UCHAR owners; /* count of owners for notify and term release */ + UCHAR primary_conn; /* primary owner connection or 255=none */ + + UCHAR filler; /* Preserve alignment */ + + /* now break control and support */ + UINT8 last_start; /* LAST_xx start info for wait() */ + UINT8 flags; /* PIDFLG_xxx flags */ + UINT16 break_alloc; /* number of entries in break_list */ + xdr_break *break_list; /* list of breakpoints ([0] is BASE_BREAK) */ + /* now registers and other save information */ + xdr_regs regs; /* saved registers when stopped */ + int is_step; /* Was break or step (regs ambiguous often) */ + int stop_wanted; /* Don't ignore next stop */ + UINT32 thread; /* current stopped thread or -1 if none */ + char *name; /* full pathname or NULL if not known */ + INT32 child; /* child pid that manages the pid */ + UINT32 textStart; /* for relocating breakpoints at restart */ +} PID_LIST; +PID_LIST *pid_list; /* array of processes being managed */ +int pid_list_cnt; /* number of entries allocated */ +UINT16 last_break; /* unique handle generator for breaks */ +#define NO_PRIMARY ((UCHAR)-1) + +typedef union +{ /* an opaque net address */ + unsigned long l[4]; + unsigned char c[16]; /* corresponds to IP, enough for ChIPC */ +} NET_OPAQUE; + +typedef struct +{ /* one per connection */ + UCHAR in_use; /* True if in use */ + UCHAR debug_type; /* type of connection */ + UINT16 flags; /* flags for connection (CFLG_xxx) */ + NET_OPAQUE sender; /* opaque address for transport compare */ + NET_OPAQUE back_port; /* opaque address for transport event msgs */ + NET_OPAQUE route; /* optional route address */ + UINT32 pid_map[10]; /* map of pids owned relative to pid list */ + /* this allows up to 320 pids to be managed */ + UCHAR last_msg_num; /* msg number used last to handle multi-send */ + /* next field associated with UDP send messages */ + UCHAR retry; /* count of retries. If 0, ok. If not 0, we + are in active wait for reply to an event */ + UCHAR send_idx; /* current number of send's pended */ + struct SEND_LIST + { /* holds pending msgs */ + UCHAR send_type; /* BMSG_xxx type of message */ + UCHAR retry; /* number of times to retry */ + UINT16 spec; /* spec field */ + PID pid; /* pid if applies */ + UINT32 context; /* additional context if needed */ + } send_list[MAX_SEND]; /* pended list of messages being sent */ + char user_name[NAMEMAX]; /* name of user connecting in */ + /* next fields are managed at runtime to handle lists, command upload, and + command download. */ + enum {LST_NONE, LST_SPAWN, LST_INFO, LST_CMD_DOWN} list_type; + char *list; /* curr list we are sending/getting (malloced) */ + UINT16 list_sz; /* size of current list (string len) */ + UINT16 list_num; /* number of current list or position */ + UINT16 list_alloc; /* amount allocated so far */ + UINT16 list_save; /* used internally */ +} CONN_LIST; +CONN_LIST *conn_list; /* an array of connections */ +int conn_list_cnt; /* number allocated */ + + /* Operations over the PID map. Each indexes into long and then bit */ + /* 5 is log2 of 32, the number of bits in an int */ +#define PIDMAP_TEST(conn,idx) \ + (conn_list [conn].pid_map [(idx) >> 5] & (1 << ((idx) & 31))) + +#define PIDMAP_SET(conn,idx) \ + (conn_list [conn].pid_map [(idx) >> 5] |= 1 << ((idx) & 31)) + +#define PIDMAP_CLEAR(conn,idx) \ + (conn_list [conn].pid_map [(idx) >> 5] &= ~(1 << ((idx) &31))) + +#define PROC_TERMINATED(plst) \ + (!(plst)->running && !STS_SIGNALLED ((plst)->state)) + + +/* first define the Connection routines exported from servcon.c */ + +int ConnCreate (struct svc_req *rqstp, open_in *in); +void ConnDelete (int conn_idx, struct svc_req *rqstp, close_control control); + +void TspInit (int rpc_io_channel); +Boolean TspTranslateRpcAddr (struct svc_req *rqstp, NET_OPAQUE *opaque); +Boolean TspValidateAddr (NET_OPAQUE *opaque, NET_OPAQUE *sender); +int TspConnGetIndex (struct svc_req *rqstp); + +void TspSendWaitChange (int conn_idx, BACK_MSG msg, UINT16 spec, PID pid, + UINT32 context, Boolean force); +void TspSendMessage (int conn_idx, Boolean resend); +void TspMessageReceive (int conn_idx, PID pid); +char* TspGetHostName (int conn_idx); +void TgtCreateNew (PID pid, int conn_idx, INT32 child, + char *name, Boolean spawn); +Boolean TgtAttach (int conn_idx, PID pid); +void TgtNotifyWaitChange(PID pid, int status, Boolean exclude); +void TgtNotifyAll (int pid_idx, BACK_MSG msg, UINT16 spec, + UINT32 context, int exclude_conn, Boolean force); +void TgtDelete (PID_LIST*, int conn_idx, BACK_MSG notify); +int TgtKillAndDelete (PID_LIST *plst, struct svc_req *rqstp, Boolean term); +void TgtDetachCon (int conn_idx, int pid_idx, Boolean delete); +int TgtThreadList (PID_LIST*, unsigned* buf, unsigned int size); +int TgtGetThreadName (PID_LIST*, unsigned thLi, char* name); +int TgtPtrace (int req, PID pid, char *addr, int data, void *addr2); +int TgtRealPtrace (int req, PID pid, char *addr, int data, void *addr2); +Boolean TgtHandleChildChange(PID pid, int* status, int* unexp, + CPU_Exception_frame *ctx); +#ifdef DDEBUG + /* TgtDbgPtrace is a wrapper for RealPtrace() doing traces */ +int TgtDbgPtrace (int req, PID pid, char *addr, int data, void *addr2); +#endif + + +/* Information stored in "handle" */ +#define BKPT_INACTIVE 1 /* bkpt inactive for this execution */ +#define BKPT_ACTIVE 0 /* bkpt active for this execution */ + +int BreakOverwrite (const PID_LIST* plst,const char* addr, + unsigned int size); +int BreakSet (PID_LIST*, int conn_idx, xdr_break*); +int BreakSetAt (PID_LIST*, int conn_idx, unsigned long addr,break_type); +int BreakClear (PID_LIST*, int conn_idx, int handle); +int BreakGetIndex (PID_LIST*, void* addr); +int BreakGet (const PID_LIST*, int data, xdr_break*); +void BreakHide (const PID_LIST*, void*, int, void*); +int BreakStepOff (const PID_LIST*, void** paddr2); +void BreakSteppedOff (PID_LIST*); +int BreakRespawn (PID_LIST*); +int BreakIdentify (PID_LIST*, int adjust, int thread); +void BreakPcChanged (PID_LIST*); +int BreakStepRange (PID_LIST*, void* addr, int len); +void BreaksDisable (int pid); +void BreaksEnable (int pid); + +int TgtBreakRestoreOrig (int pid, void* addr, void* addr2); +void TgtBreakCancelStep (PID_LIST* plst); + +Boolean ListAlloc (char *buff, CONN_LIST *clst); +int FindPidEntry (int pid); + +open_out* RPCGENSRVNAME(open_connex_2_svc) (open_in *in, + struct svc_req *rqstp); +signal_out* RPCGENSRVNAME(send_signal_2_svc) (signal_in *in, + struct svc_req *rqstp); +ptrace_out* RPCGENSRVNAME(ptrace_2_svc) (ptrace_in *in, + struct svc_req *rqstp); +wait_out* RPCGENSRVNAME(wait_info_2_svc) (wait_in *in, + struct svc_req *rqstp); +#endif /* !SERVRPC_H */ + diff --git a/c/src/lib/include/rpc/auth.h b/c/src/lib/include/rpc/auth.h new file mode 100644 index 0000000000..8f14d144f6 --- /dev/null +++ b/c/src/lib/include/rpc/auth.h @@ -0,0 +1,167 @@ +#ifndef RPC_AUTH_H +#define RPC_AUTH_H + +/* @(#)auth.h 2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * auth.h, Authentication interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * The data structures are completely opaque to the client. The client + * is required to pass a AUTH * to routines that create rpc + * "sessions". + */ + + +#define MAX_AUTH_BYTES 400 +#define MAXNETNAMELEN 255 /* maximum length of network user's name */ + +/* + * Status returned from authentication check + */ +enum auth_stat { + AUTH_OK=0, + /* + * failed at remote end + */ + AUTH_BADCRED=1, /* bogus credentials (seal broken) */ + AUTH_REJECTEDCRED=2, /* client should begin new session */ + AUTH_BADVERF=3, /* bogus verifier (seal broken) */ + AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ + AUTH_TOOWEAK=5, /* rejected due to security reasons */ + /* + * failed locally + */ + AUTH_INVALIDRESP=6, /* bogus response verifier */ + AUTH_FAILED=7 /* some unknown reason */ +}; + +union des_block { + struct { + u_int32 high; + u_int32 low; + } key; + char c[8]; +}; +typedef union des_block des_block; +extern bool_t xdr_des_block(); + +/* + * Authentication info. Opaque to client. + */ +struct opaque_auth { + enum_t oa_flavor; /* flavor of auth */ + caddr_t oa_base; /* address of more auth stuff */ + u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ +}; + + +/* + * Auth handle, interface to client side authenticators. + */ +typedef struct { + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + struct auth_ops { + void (*ah_nextverf)(); + int (*ah_marshal)(); /* nextverf & serialize */ + int (*ah_validate)(); /* validate varifier */ + int (*ah_refresh)(); /* refresh credentials */ + void (*ah_destroy)(); /* destroy this structure */ + } *ah_ops; + caddr_t ah_private; +} AUTH; + + +/* + * Authentication ops. + * The ops and the auth handle provide the interface to the authenticators. + * + * AUTH *auth; + * XDR *xdrs; + * struct opaque_auth verf; + */ +#define AUTH_NEXTVERF(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) +#define auth_nextverf(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) + +#define AUTH_MARSHALL(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) +#define auth_marshall(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) + +#define AUTH_VALIDATE(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) +#define auth_validate(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) + +#define AUTH_REFRESH(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) +#define auth_refresh(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) + +#define AUTH_DESTROY(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) +#define auth_destroy(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) + + +extern struct opaque_auth _null_auth; + + +/* + * These are the various implementations of client side authenticators. + */ + +/* + * Unix style authentication + * AUTH *authunix_create(machname, uid, gid, len, aup_gids) + * char *machname; + * int uid; + * int gid; + * int len; + * int *aup_gids; + */ +extern AUTH *authunix_create(); +extern AUTH *authunix_create_default(); /* takes no parameters */ +extern AUTH *authnone_create(); /* takes no parameters */ +extern AUTH *authdes_create(); + +#define AUTH_NONE 0 /* no authentication */ +#define AUTH_NULL 0 /* backward compatibility */ +#define AUTH_UNIX 1 /* unix style (uid, gids) */ +#define AUTH_SHORT 2 /* short hand unix style */ +#define AUTH_DES 3 /* des style (encrypted timestamps) */ + +#endif /* RPC_AUTH_H */ diff --git a/c/src/lib/include/rpc/clnt.h b/c/src/lib/include/rpc/clnt.h new file mode 100644 index 0000000000..faefdb5d50 --- /dev/null +++ b/c/src/lib/include/rpc/clnt.h @@ -0,0 +1,336 @@ +#ifndef RPC_CLNT_H +#define RPC_CLNT_H + +/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * clnt.h - Client side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _CLNT_ +#define _CLNT_ + +/* + * Rpc calls return an enum clnt_stat. This should be looked at more, + * since each implementation is required to live with this (implementation + * independent) list of errors. + */ +enum clnt_stat { + RPC_SUCCESS=0, /* call succeeded */ + /* + * local errors + */ + RPC_CANTENCODEARGS=1, /* can't encode arguments */ + RPC_CANTDECODERES=2, /* can't decode results */ + RPC_CANTSEND=3, /* failure in sending call */ + RPC_CANTRECV=4, /* failure in receiving result */ + RPC_TIMEDOUT=5, /* call timed out */ + /* + * remote errors + */ + RPC_VERSMISMATCH=6, /* rpc versions not compatible */ + RPC_AUTHERROR=7, /* authentication error */ + RPC_PROGUNAVAIL=8, /* program not available */ + RPC_PROGVERSMISMATCH=9, /* program version mismatched */ + RPC_PROCUNAVAIL=10, /* procedure unavailable */ + RPC_CANTDECODEARGS=11, /* decode arguments error */ + RPC_SYSTEMERROR=12, /* generic "other problem" */ + + /* + * callrpc & clnt_create errors + */ + RPC_UNKNOWNHOST=13, /* unknown host name */ + RPC_UNKNOWNPROTO=17, /* unkown protocol */ + + /* + * _ create errors + */ + RPC_PMAPFAILURE=14, /* the pmapper failed in its call */ + RPC_PROGNOTREGISTERED=15, /* remote program is not registered */ + /* + * unspecified error + */ + RPC_FAILED=16 +}; + + +/* + * Error info. + */ +struct rpc_err { + enum clnt_stat re_status; + union { + int RE_errno; /* realated system error */ + enum auth_stat RE_why; /* why the auth error occurred */ + struct { + u_long low; /* lowest verion supported */ + u_long high; /* highest verion supported */ + } RE_vers; + struct { /* maybe meaningful if RPC_FAILED */ + long s1; + long s2; + } RE_lb; /* life boot & debugging only */ + } ru; +#define re_errno ru.RE_errno +#define re_why ru.RE_why +#define re_vers ru.RE_vers +#define re_lb ru.RE_lb +}; + + +/* + * Client rpc handle. + * Created by individual implementations, see e.g. rpc_udp.c. + * Client is responsible for initializing auth, see e.g. auth_none.c. + */ +typedef struct { + AUTH *cl_auth; /* authenticator */ + struct clnt_ops { + enum clnt_stat (*cl_call)(); /* call remote procedure */ + void (*cl_abort)(); /* abort a call */ + void (*cl_geterr)(); /* get specific error code */ + bool_t (*cl_freeres)(); /* frees results */ + void (*cl_destroy)();/* destroy this structure */ + bool_t (*cl_control)();/* the ioctl() of rpc */ + } *cl_ops; + caddr_t cl_private; /* private stuff */ +} CLIENT; + + +/* + * client side rpc interface ops + * + * Parameter types are: + * + */ + +/* + * enum clnt_stat + * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) + * CLIENT *rh; + * u_long proc; + * xdrproc_t xargs; + * caddr_t argsp; + * xdrproc_t xres; + * caddr_t resp; + * struct timeval timeout; + */ +#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) +#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) + +/* + * void + * CLNT_ABORT(rh); + * CLIENT *rh; + */ +#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) +#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) + +/* + * struct rpc_err + * CLNT_GETERR(rh); + * CLIENT *rh; + */ +#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) +#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) + + +/* + * bool_t + * CLNT_FREERES(rh, xres, resp); + * CLIENT *rh; + * xdrproc_t xres; + * caddr_t resp; + */ +#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) +#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) + +/* + * bool_t + * CLNT_CONTROL(cl, request, info) + * CLIENT *cl; + * u_int request; + * char *info; + */ +#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) +#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) + +/* + * control operations that apply to both udp and tcp transports + */ +#define CLSET_TIMEOUT 1 /* set timeout (timeval) */ +#define CLGET_TIMEOUT 2 /* get timeout (timeval) */ +#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */ +/* + * udp only control operations + */ +#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ +#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ + +/* + * void + * CLNT_DESTROY(rh); + * CLIENT *rh; + */ +#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) +#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) + + +/* + * RPCTEST is a test program which is accessable on every rpc + * transport/port. It is used for testing, performance evaluation, + * and network administration. + */ + +#define RPCTEST_PROGRAM ((u_long)1) +#define RPCTEST_VERSION ((u_long)1) +#define RPCTEST_NULL_PROC ((u_long)2) +#define RPCTEST_NULL_BATCH_PROC ((u_long)3) + +/* + * By convention, procedure 0 takes null arguments and returns them + */ + +#define NULLPROC ((u_long)0) + +/* + * Below are the client handle creation routines for the various + * implementations of client side rpc. They can return NULL if a + * creation failure occurs. + */ + +/* + * Memory based rpc (for speed check and testing) + * CLIENT * + * clntraw_create(prog, vers) + * u_long prog; + * u_long vers; + */ +extern CLIENT *clntraw_create(); + + +/* + * Generic client creation routine. Supported protocols are "udp" and "tcp" + */ +extern CLIENT * +clnt_create(/*host, prog, vers, prot*/); /* + char *host; -- hostname + u_long prog; -- program number + u_long vers; -- version number + char *prot; -- protocol +*/ + + + + +/* + * TCP based rpc + * CLIENT * + * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clnttcp_create(); + +/* + * UDP based rpc. + * CLIENT * + * clntudp_create(raddr, program, version, wait, sockp) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait; + * int *sockp; + * + * Same as above, but you specify max packet sizes. + * CLIENT * + * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait; + * int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clntudp_create(); +extern CLIENT *clntudp_bufcreate(); + +/* + * Print why creation failed + */ +void clnt_pcreateerror(/* char *msg */); /* stderr */ +char *clnt_spcreateerror(/* char *msg */); /* string */ + +/* + * Like clnt_perror(), but is more verbose in its output + */ +void clnt_perrno(/* enum clnt_stat num */); /* stderr */ + +/* + * Print an English error message, given the client error code + */ +void clnt_perror(/* CLIENT *clnt, char *msg */); /* stderr */ +char *clnt_sperror(/* CLIENT *clnt, char *msg */); /* string */ + +/* + * If a creation fails, the following allows the user to figure out why. + */ +struct rpc_createerr { + enum clnt_stat cf_stat; + struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ +}; + +extern struct rpc_createerr rpc_createerr; + + + +/* + * Copy error message to buffer. + */ +char *clnt_sperrno(/* enum clnt_stat num */); /* string */ + + + +#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ +#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ + +#endif /*!_CLNT_*/ + +#endif /* RPC_CLNT_H */ diff --git a/c/src/lib/include/rpc/rpc.h b/c/src/lib/include/rpc/rpc.h new file mode 100644 index 0000000000..0a0affd82a --- /dev/null +++ b/c/src/lib/include/rpc/rpc.h @@ -0,0 +1,86 @@ +#ifndef RPC_H +#define RPC_H + +/* @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC; from 1.9 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * rpc.h, Just includes the billions of rpc header files necessary to + * do remote procedure calling. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +#ifndef __RPC_HEADER__ +#define __RPC_HEADER__ + +#include /* some typedefs */ +#include +#include + +/* external data representation interfaces */ +#include /* generic (de)serializer */ + +/* Client side only authentication */ +#include /* generic authenticator (client side) */ + +/* Client side (mostly) remote procedure call */ +#include /* generic rpc stuff */ + +/* semi-private protocol headers */ +#include /* protocol for rpc messages */ +/*#include "auth_unix.h" * protocol for unix style cred */ +/* + * Uncomment-out the next line if you are building the rpc library with + * DES Authentication (see the README file in the secure_rpc/ directory). + */ +/*#include "auth_des.h" * protocol for des style cred */ + +/* Server side only remote procedure callee */ +#include /* service manager and multiplexer */ +#include /* service side authenticator */ + +/* + * COMMENT OUT THE NEXT INCLUDE (or add to the #ifndef) IF RUNNING ON + * A VERSION OF UNIX THAT USES SUN'S NFS SOURCE. These systems will + * already have the structures defined by included in . + */ +/* routines for parsing /etc/rpc */ + +struct rpcent { + char *r_name; /* name of server for this rpc program */ + char **r_aliases; /* alias list */ + int r_number; /* rpc program number */ +}; + +struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent(); + +#endif /* ndef __RPC_HEADER__ */ + +#endif /* RPC_H */ diff --git a/c/src/lib/include/rpc/rpc_msg.h b/c/src/lib/include/rpc/rpc_msg.h new file mode 100644 index 0000000000..2f34fb614c --- /dev/null +++ b/c/src/lib/include/rpc/rpc_msg.h @@ -0,0 +1,192 @@ +#ifndef RPC_MSG_H +#define RPC_MSG_H + +/* @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)rpc_msg.h 1.7 86/07/16 SMI */ + +/* + * rpc_msg.h + * rpc message definition + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define RPC_MSG_VERSION ((u_long) 2) +#define RPC_SERVICE_PORT ((u_short) 2048) + +/* + * Bottom up definition of an rpc message. + * NOTE: call and reply use the same overall stuct but + * different parts of unions within it. + */ + +enum msg_type { + CALL=0, + REPLY=1 +}; + +enum reply_stat { + MSG_ACCEPTED=0, + MSG_DENIED=1 +}; + +enum accept_stat { + SUCCESS=0, + PROG_UNAVAIL=1, + PROG_MISMATCH=2, + PROC_UNAVAIL=3, + GARBAGE_ARGS=4, + SYSTEM_ERR=5 +}; + +enum reject_stat { + RPC_MISMATCH=0, + AUTH_ERROR=1 +}; + +/* + * Reply part of an rpc exchange + */ + +/* + * Reply to an rpc request that was accepted by the server. + * Note: there could be an error even though the request was + * accepted. + */ +struct accepted_reply { + struct opaque_auth ar_verf; + enum accept_stat ar_stat; + union { + struct { + u_long low; + u_long high; + } AR_versions; + struct { + caddr_t where; + xdrproc_t proc; + } AR_results; + /* and many other null cases */ + } ru; +#define ar_results ru.AR_results +#define ar_vers ru.AR_versions +}; + +/* + * Reply to an rpc request that was rejected by the server. + */ +struct rejected_reply { + enum reject_stat rj_stat; + union { + struct { + u_long low; + u_long high; + } RJ_versions; + enum auth_stat RJ_why; /* why authentication did not work */ + } ru; +#define rj_vers ru.RJ_versions +#define rj_why ru.RJ_why +}; + +/* + * Body of a reply to an rpc request. + */ +struct reply_body { + enum reply_stat rp_stat; + union { + struct accepted_reply RP_ar; + struct rejected_reply RP_dr; + } ru; +#define rp_acpt ru.RP_ar +#define rp_rjct ru.RP_dr +}; + +/* + * Body of an rpc request call. + */ +struct call_body { + u_long cb_rpcvers; /* must be equal to two */ + u_long cb_prog; + u_long cb_vers; + u_long cb_proc; + struct opaque_auth cb_cred; + struct opaque_auth cb_verf; /* protocol specific - provided by client */ +}; + +/* + * The rpc message + */ +struct rpc_msg { + u_long rm_xid; + enum msg_type rm_direction; + union { + struct call_body RM_cmb; + struct reply_body RM_rmb; + } ru; +#define rm_call ru.RM_cmb +#define rm_reply ru.RM_rmb +}; +#define acpted_rply ru.RM_rmb.ru.RP_ar +#define rjcted_rply ru.RM_rmb.ru.RP_dr + + +/* + * XDR routine to handle a rpc message. + * xdr_callmsg(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callmsg(); + +/* + * XDR routine to pre-serialize the static part of a rpc message. + * xdr_callhdr(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callhdr(); + +/* + * XDR routine to handle a rpc reply. + * xdr_replymsg(xdrs, rmsg) + * XDR *xdrs; + * struct rpc_msg *rmsg; + */ +extern bool_t xdr_replymsg(); + +/* + * Fills in the error part of a reply message. + * _seterr_reply(msg, error) + * struct rpc_msg *msg; + * struct rpc_err *error; + */ +extern void _seterr_reply(); + +#endif /* RPC_MSG_H */ diff --git a/c/src/lib/include/rpc/svc.h b/c/src/lib/include/rpc/svc.h new file mode 100644 index 0000000000..c576b5538b --- /dev/null +++ b/c/src/lib/include/rpc/svc.h @@ -0,0 +1,291 @@ + +#ifndef RPC_SVC_H +#define RPC_SVC_H + +/* @(#)svc.h 2.2 88/07/29 4.0 RPCSRC; from 1.20 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc.h, Server-side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef __SVC_HEADER__ +#define __SVC_HEADER__ + +/* + * This interface must manage two items concerning remote procedure calling: + * + * 1) An arbitrary number of transport connections upon which rpc requests + * are received. The two most notable transports are TCP and UDP; they are + * created and registered by routines in svc_tcp.c and svc_udp.c, respectively; + * they in turn call xprt_register and xprt_unregister. + * + * 2) An arbitrary number of locally registered services. Services are + * described by the following four data: program number, version number, + * "service dispatch" function, a transport handle, and a boolean that + * indicates whether or not the exported program should be registered with a + * local binder service; if true the program's number and version and the + * port number from the transport handle are registered with the binder. + * These data are registered with the rpc svc system via svc_register. + * + * A service's dispatch function is called whenever an rpc request comes in + * on a transport. The request's program and version numbers must match + * those of the registered service. The dispatch function is passed two + * parameters, struct svc_req * and SVCXPRT *, defined below. + */ + +enum xprt_stat { + XPRT_DIED, + XPRT_MOREREQS, + XPRT_IDLE +}; + +/* + * Server side transport handle + */ +typedef struct { + int xp_sock; + u_short xp_port; /* associated port number */ + struct xp_ops { + bool_t (*xp_recv)(); /* receive incomming requests */ + enum xprt_stat (*xp_stat)(); /* get transport status */ + bool_t (*xp_getargs)(); /* get arguments */ + bool_t (*xp_reply)(); /* send reply */ + bool_t (*xp_freeargs)();/* free mem allocated for args */ + void (*xp_destroy)(); /* destroy this struct */ + } *xp_ops; + int xp_addrlen; /* length of remote address */ + struct sockaddr_in xp_raddr; /* remote address */ + struct opaque_auth xp_verf; /* raw response verifier */ + caddr_t xp_p1; /* private */ + caddr_t xp_p2; /* private */ +} SVCXPRT; + +/* + * Approved way of getting address of caller + */ +#define svc_getcaller(x) (&(x)->xp_raddr) + +/* + * Operations defined on an SVCXPRT handle + * + * SVCXPRT *xprt; + * struct rpc_msg *msg; + * xdrproc_t xargs; + * caddr_t argsp; + */ +#define SVC_RECV(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) +#define svc_recv(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) + +#define SVC_STAT(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) +#define svc_stat(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) + +#define SVC_GETARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) +#define svc_getargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) + +#define SVC_REPLY(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) +#define svc_reply(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) + +#define SVC_FREEARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) +#define svc_freeargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) + +#define SVC_DESTROY(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) +#define svc_destroy(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) + + +/* + * Service request + */ +struct svc_req { + u_long rq_prog; /* service program number */ + u_long rq_vers; /* service protocol version */ + u_long rq_proc; /* the desired procedure */ + struct opaque_auth rq_cred; /* raw creds from the wire */ + caddr_t rq_clntcred; /* read only cooked cred */ + SVCXPRT *rq_xprt; /* associated transport */ +}; + + +/* + * Service registration + * + * svc_register(xprt, prog, vers, dispatch, protocol) + * SVCXPRT *xprt; + * u_long prog; + * u_long vers; + * void (*dispatch)(); + * int protocol; (like TCP or UDP, zero means do not register) + */ +extern bool_t svc_register(); + +/* + * Service un-registration + * + * svc_unregister(prog, vers) + * u_long prog; + * u_long vers; + */ +extern void svc_unregister(); + +/* + * Transport registration. + * + * xprt_register(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_register(); + +/* + * Transport un-register + * + * xprt_unregister(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_unregister(); + + + + +/* + * When the service routine is called, it must first check to see if it + * knows about the procedure; if not, it should call svcerr_noproc + * and return. If so, it should deserialize its arguments via + * SVC_GETARGS (defined above). If the deserialization does not work, + * svcerr_decode should be called followed by a return. Successful + * decoding of the arguments should be followed the execution of the + * procedure's code and a call to svc_sendreply. + * + * Also, if the service refuses to execute the procedure due to too- + * weak authentication parameters, svcerr_weakauth should be called. + * Note: do not confuse access-control failure with weak authentication! + * + * NB: In pure implementations of rpc, the caller always waits for a reply + * msg. This message is sent when svc_sendreply is called. + * Therefore pure service implementations should always call + * svc_sendreply even if the function logically returns void; use + * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows + * for the abuse of pure rpc via batched calling or pipelining. In the + * case of a batched call, svc_sendreply should NOT be called since + * this would send a return message, which is what batching tries to avoid. + * It is the service/protocol writer's responsibility to know which calls are + * batched and which are not. Warning: responding to batch calls may + * deadlock the caller and server processes! + */ + +extern bool_t svc_sendreply(); +extern void svcerr_decode(); +extern void svcerr_weakauth(); +extern void svcerr_noproc(); +extern void svcerr_progvers(); +extern void svcerr_auth(); +extern void svcerr_noprog(); +extern void svcerr_systemerr(); + +/* + * Lowest level dispatching -OR- who owns this process anyway. + * Somebody has to wait for incoming requests and then call the correct + * service routine. The routine svc_run does infinite waiting; i.e., + * svc_run never returns. + * Since another (co-existant) package may wish to selectively wait for + * incoming calls or other events outside of the rpc architecture, the + * routine svc_getreq is provided. It must be passed readfds, the + * "in-place" results of a select system call (see select, section 2). + */ + +/* + * Global keeper of rpc service descriptors in use + * dynamic; must be inspected before each call to select + */ +#ifdef FD_SETSIZE +extern fd_set svc_fdset; +#define svc_fds svc_fdset.fds_bits[0] /* compatibility */ +#else +extern int svc_fds; +#endif /* def FD_SETSIZE */ + +/* + * a small program implemented by the svc_rpc implementation itself; + * also see clnt.h for protocol numbers. + */ +extern void rpctest_service(); + +extern void svc_getreq(); +extern void svc_getreqset(); /* takes fdset instead of int */ +extern void svc_run(); /* never returns */ + +/* + * Socket to use on svcxxx_create call to get default socket + */ +#define RPC_ANYSOCK -1 + +/* + * These are the existing service side transport implementations + */ + +/* + * Memory based rpc for testing and timing. + */ +extern SVCXPRT *svcraw_create(); + +/* + * Udp based rpc. + */ +extern SVCXPRT *svcudp_create(); +extern SVCXPRT *svcudp_bufcreate(); +extern int svcudp_enablecache(SVCXPRT *transp, u_long size); + +/* + * Tcp based rpc. + */ +extern SVCXPRT *svctcp_create(); + + + +#endif /* !__SVC_HEADER__ */ + +extern int _rpcsvccount; +extern int _rpcsvcstate; +extern int _SERVED; + +#endif /* RPC_SVC_H */ diff --git a/c/src/lib/include/rpc/svc_auth.h b/c/src/lib/include/rpc/svc_auth.h new file mode 100644 index 0000000000..5c233a6a47 --- /dev/null +++ b/c/src/lib/include/rpc/svc_auth.h @@ -0,0 +1,47 @@ +#ifndef RPC_SVC_AUTH_H +#define RPC_SVC_AUTH_H + +/* @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)svc_auth.h 1.6 86/07/16 SMI */ + +/* + * svc_auth.h, Service side of rpc authentication. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + + +/* + * Server side authenticator + */ +extern enum auth_stat _authenticate(); + +#endif /* SVC_AUTH_H */ diff --git a/c/src/lib/include/rpc/types.h b/c/src/lib/include/rpc/types.h new file mode 100644 index 0000000000..b6d7eb3ccc --- /dev/null +++ b/c/src/lib/include/rpc/types.h @@ -0,0 +1,75 @@ +#ifndef RPC_TYPES_H +#define RPC_TYPES_H + +/* @(#)types.h 2.3 88/08/15 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)types.h 1.18 87/07/24 SMI */ + +/* + * Rpc additions to + */ +#ifndef __TYPES_RPC_HEADER__ +#define __TYPES_RPC_HEADER__ + +/*#include */ +typedef unsigned long u_int32; /* 32-bit unsigned integers */ + +#define bool_t int +#define enum_t int +#ifndef FALSE +# define FALSE (0) +#endif +#ifndef TRUE +# define TRUE (1) +#endif +#define __dontcare__ -1 +#ifndef NULL +# define NULL 0 +#endif + +void *malloc(); +#define mem_alloc(bsize) malloc(bsize) +#define mem_free(ptr, bsize) free(ptr) + +#ifndef makedev /* ie, we haven't already included it */ +#include +#endif +#include + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK (u_long)0x7F000001 +#endif +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#endif /* ndef __TYPES_RPC_HEADER__ */ + +#endif /* RPC_TYPES_H */ diff --git a/c/src/lib/include/rpc/xdr.h b/c/src/lib/include/rpc/xdr.h new file mode 100644 index 0000000000..ef2df51d93 --- /dev/null +++ b/c/src/lib/include/rpc/xdr.h @@ -0,0 +1,275 @@ +#ifndef RPC_XDR_H +#define RPC_XDR_H + +/* @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)xdr.h 1.19 87/04/22 SMI */ + +/* + * xdr.h, External Data Representation Serialization Routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef __XDR_HEADER__ +#define __XDR_HEADER__ + +/* + * XDR provides a conventional way for converting between C data + * types and an external bit-string representation. Library supplied + * routines provide for the conversion on built-in C data types. These + * routines and utility routines defined here are used to help implement + * a type encode/decode routine for each user-defined type. + * + * Each data type provides a single procedure which takes two arguments: + * + * bool_t + * xdrproc(xdrs, argresp) + * XDR *xdrs; + * *argresp; + * + * xdrs is an instance of a XDR handle, to which or from which the data + * type is to be converted. argresp is a pointer to the structure to be + * converted. The XDR handle contains an operation field which indicates + * which of the operations (ENCODE, DECODE * or FREE) is to be performed. + * + * XDR_DECODE may allocate space if the pointer argresp is null. This + * data can be freed with the XDR_FREE operation. + * + * We write only one procedure per data type to make it easy + * to keep the encode and decode procedures for a data type consistent. + * In many cases the same code performs all operations on a user defined type, + * because all the hard work is done in the component type routines. + * decode as a series of calls on the nested data types. + */ + +/* + * Xdr operations. XDR_ENCODE causes the type to be encoded into the + * stream. XDR_DECODE causes the type to be extracted from the stream. + * XDR_FREE can be used to release the space allocated by an XDR_DECODE + * request. + */ +enum xdr_op { + XDR_ENCODE=0, + XDR_DECODE=1, + XDR_FREE=2 +}; + +/* + * This is the number of bytes per unit of external data. + */ +#define BYTES_PER_XDR_UNIT (4) +#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ + * BYTES_PER_XDR_UNIT) + +/* + * A xdrproc_t exists for each data type which is to be encoded or decoded. + * + * The second argument to the xdrproc_t is a pointer to an opaque pointer. + * The opaque pointer generally points to a structure of the data type + * to be decoded. If this pointer is 0, then the type routines should + * allocate dynamic storage of the appropriate size and return it. + * bool_t (*xdrproc_t)(XDR *, caddr_t *); + */ +typedef bool_t (*xdrproc_t)(); + +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the paticular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular impelementation. + */ +typedef struct { + enum xdr_op x_op; /* operation; fast additional param */ + struct xdr_ops { + bool_t (*x_getlong)(); /* get a long from underlying stream */ + bool_t (*x_putlong)(); /* put a long to " */ + bool_t (*x_getbytes)();/* get some bytes from " */ + bool_t (*x_putbytes)();/* put some bytes to " */ + u_int (*x_getpostn)();/* returns bytes off from beginning */ + bool_t (*x_setpostn)();/* lets you reposition the stream */ + long * (*x_inline)(); /* buf quick ptr to buffered data */ + void (*x_destroy)(); /* free privates of this xdr_stream */ + } *x_ops; + caddr_t x_public; /* users' data */ + caddr_t x_private; /* pointer to private data */ + caddr_t x_base; /* private used for position info */ + int x_handy; /* extra private word */ +} XDR; + +/* + * Operations defined on a XDR handle + * + * XDR *xdrs; + * long *longp; + * caddr_t addr; + * u_int len; + * u_int pos; + */ +#define XDR_GETLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) +#define xdr_getlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) + +#define XDR_PUTLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) +#define xdr_putlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) + +#define XDR_GETBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) +#define xdr_getbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) + +#define XDR_PUTBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) +#define xdr_putbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) + +#define XDR_GETPOS(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) +#define xdr_getpos(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) + +#define XDR_SETPOS(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) +#define xdr_setpos(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) + +#define XDR_INLINE(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) +#define xdr_inline(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) + +#define XDR_DESTROY(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) +#define xdr_destroy(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) + +/* + * Support struct for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * a entry with a null procedure pointer. The xdr_union routine gets + * the discriminant value and then searches the array of structures + * for a matching value. If a match is found the associated xdr routine + * is called to handle that part of the union. If there is + * no match, then a default routine may be called. + * If there is no match and no default routine it is an error. + */ +#define NULL_xdrproc_t ((xdrproc_t)0) +struct xdr_discrim { + int value; + xdrproc_t proc; +}; + +/* + * In-line routines for fast encode/decode of primitve data types. + * Caveat emptor: these use single memory cycles to get the + * data from the underlying buffer, and will fail to operate + * properly if the data is not aligned. The standard way to use these + * is to say: + * if ((buf = XDR_INLINE(xdrs, count)) == NULL) + * return (FALSE); + * <<< macro calls >>> + * where ``count'' is the number of bytes of data occupied + * by the primitive data types. + * + * N.B. and frozen for all time: each data type here uses 4 bytes + * of external representation. + */ +#define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*(buf)++)) +#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((u_long)v)) + +#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) +#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) +#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) + +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) + +/* + * These are the "generic" xdr routines. + */ +extern bool_t xdr_void(); +extern bool_t xdr_int(); +extern bool_t xdr_u_int(); +extern bool_t xdr_long(); +extern bool_t xdr_u_long(); +extern bool_t xdr_short(); +extern bool_t xdr_u_short(); +extern bool_t xdr_bool(); +extern bool_t xdr_enum(); +extern bool_t xdr_array(); +extern bool_t xdr_bytes(); +extern bool_t xdr_opaque(); +extern bool_t xdr_string(); +extern bool_t xdr_union(); +extern bool_t xdr_char(); +extern bool_t xdr_u_char(); +extern bool_t xdr_vector(); +extern bool_t xdr_float(); +extern bool_t xdr_double(); +extern bool_t xdr_reference(); +extern bool_t xdr_pointer(); +extern bool_t xdr_wrapstring(); + +/* + * Common opaque bytes objects used by many rpc protocols; + * declared here due to commonality. + */ +#define MAX_NETOBJ_SZ 1024 +struct netobj { + u_int n_len; + char *n_bytes; +}; +typedef struct netobj netobj; +extern bool_t xdr_netobj(); + +/* + * These are the public routines for the various implementations of + * xdr streams. + */ +extern void xdrmem_create(); /* XDR using memory buffers */ +extern void xdrstdio_create(); /* XDR using stdio library */ +extern void xdrrec_create(); /* XDR pseudo records for tcp */ +extern bool_t xdrrec_endofrecord(); /* make end of xdr record */ +extern bool_t xdrrec_skiprecord(); /* move to beginning of next record */ +extern bool_t xdrrec_eof(); /* true if no more input */ + +#endif /* !__XDR_HEADER__ */ + +#endif /* RPC_XDR_H */ diff --git a/c/src/lib/librdbg/Makefile.in b/c/src/lib/librdbg/Makefile.in new file mode 100644 index 0000000000..8d4a72ca96 --- /dev/null +++ b/c/src/lib/librdbg/Makefile.in @@ -0,0 +1,96 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +VPATH = @srcdir@:@srcdir@/$(RTEMS_CPU) +RTEMS_ROOT = @top_srcdir@ +PROJECT_ROOT = @PROJECT_ROOT@ + +LIBNAME=librdbg.a +LIB=${ARCH}/${LIBNAME} + +# C and C++ source names, if any, go here -- minus the .c or .cc +C_PIECES= rdbg servcon servbkpt servrpc excep \ + servtgt servtsp servutil _servtgt rdbg_f \ + ptrace +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +# Asm source names, if any, go here -- minus the .s +ASM_PIECES= rdbg_cpu_asm +ASM_FILES=$(ASM_PIECES:%=%.s) +ASM_O_FILES=$(ASM_PIECES:%=${ARCH}/%.o) + +# Generated C source names, if any, go here -- minus the .c +C_GEN_PIECES= remdeb_xdr remdeb_svc +C_GEN_FILES=$(C_GEN_PIECES:%=%.c) +C_GEN_O_FILES=$(C_GEN_PIECES:%=${ARCH}/%.o) + +# H source names, if any, go here -- minus the .h +H_PIECES=remdeb +H_FILES=$(H_PIECES:%=%.h) + +# X source names, if any, go here -- minus the .x +X_FILE1=remdeb.x +X_FILE2=remdeb_f.x +X_FILES=$(X_FILE1) $(X_FILE2) + +SRCS=$(C_FILES) $(ASM_FILES) +OBJS=$(X_FILES) $(H_FILES) $(C_GEN_FILES) $(C_GEN_O_FILES) $(C_O_FILES) $(ASM_O_FILES) + +RPCGEN=rpcgen +AWK=awk + +include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg +include $(RTEMS_ROOT)/make/lib.cfg + +# +# Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += $(LIB) $(H_FILES) $(X_FILES) $(C_GEN_FILES) +CLOBBER_ADDITIONS += + +all: ${ARCH} $(LIB) + $(INSTALL_VARIANT) -m 644 $(LIB) ${PROJECT_RELEASE}/lib + +$(LIB): $(SRCS) ${OBJS} + $(make-library) + +remdeb.h: $(X_FILES) + @rm -f $@ + $(RPCGEN) -h remdeb.x -o $@ + @rm -f $(PROJECT_INCLUDE)/rdbg/$@ + $(INSTALL) -m 444 $@ $(PROJECT_INCLUDE)/rdbg + +remdeb_xdr.c: $(X_FILES) + @rm -f $@ + $(RPCGEN) -c remdeb.x -o $@ + +remdeb_svc.c: $(X_FILES) + @rm -f $@ tmpSvc.c + $(RPCGEN) -s udp remdeb.x -o tmpSvc.c + $(AWK) -f @srcdir@/awk.svc THEPROG="remdeb.h" tmpSvc.c >$@ + @rm -f tmpSvc.c + +preinstall: + @rm -f $(X_FILES) + @cp @srcdir@/$(X_FILE1) . + @cp @srcdir@/$(RTEMS_CPU)/$(RTEMS_BSP)/$(X_FILE2) . + + + + diff --git a/c/src/lib/librdbg/_servtgt.c b/c/src/lib/librdbg/_servtgt.c new file mode 100644 index 0000000000..184415a1e2 --- /dev/null +++ b/c/src/lib/librdbg/_servtgt.c @@ -0,0 +1,360 @@ +/* + ============================================================================ + _SERVTGT + ============================================================================ +*/ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +extern void rtems_exception_prologue_50(); + + +#ifdef DDEBUG +#define Ptrace TgtDbgPtrace +#else +#define Ptrace TgtRealPtrace +#endif + +extern int errno; + +rtems_id eventTaskId; +rtems_id serializeSemId; +rtems_id wakeupEventSemId; + +CPU_Exception_frame Idle_frame; + +cpuExcHandlerType old_currentExcHandler; + +/* ----------------------------------------------------------------- + TgtRealPtrace - lowest level ptrace() wrapper + ----------------------------------------------------------------- */ + + int +TgtRealPtrace(int req, PID aid, char* addr, int d, void* addr2) +{ + return ptrace(req, aid, addr, d, addr2); +} + + +/* ----------------------------------------------------------------- + Maping of hardware exceptions into Unix-like signal numbers. + It is identical to the one used by the PM and the AM. + ----------------------------------------------------------------- */ + + int +ExcepToSig (int excep) +{ + switch (excep) { + + case I386_EXCEPTION_MATH_COPROC_UNAVAIL: + case I386_EXCEPTION_I386_COPROC_SEG_ERR: + case I386_EXCEPTION_FLOAT_ERROR: + case I386_EXCEPTION_BOUND: + return SIGFPE; + + case I386_EXCEPTION_DEBUG: + case I386_EXCEPTION_BREAKPOINT: + case I386_EXCEPTION_ENTER_RDBG: + return SIGTRAP; + + case I386_EXCEPTION_OVERFLOW: + case I386_EXCEPTION_DIVIDE_BY_ZERO: + case I386_EXCEPTION_ILLEGAL_INSTR: + return SIGILL; + + case I386_EXCEPTION_SEGMENT_NOT_PRESENT: + case I386_EXCEPTION_STACK_SEGMENT_FAULT: + case I386_EXCEPTION_GENERAL_PROT_ERR: + case I386_EXCEPTION_PAGE_FAULT: + return SIGSEGV; + + default: + break; + } + return SIGKILL; +} + +/* ----------------------------------------------------------------------- + TgtChange() is called when the system stops. + It informs the generic layers must be informed of + that fact. + ----------------------------------------------------------------------- */ + + static int +TgtChange (PID pid, CPU_Exception_frame* ctx, int status) +{ + + if (TgtHandleChildChange (pid, &status, NULL, ctx)) { + TgtNotifyWaitChange (pid, status, -1); + } + + return 0; +} + +/* ----------------------------------------------------------------------- + eventTask + ----------------------------------------------------------------------- */ + +rtems_task eventTask( rtems_task_argument pid) +{ + Exception_context *ctx; + + DPRINTF (("event task: pid %d\n", pid)); + + + /* + * we spend all our time waiting for a semaphore. + * If wait change, we send info + */ + + for (;;){ + DPRINTF (("Event Task: wait event\n")); + rtems_semaphore_obtain(wakeupEventSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + DPRINTF (("Event Task: wake up !!!!!!!!!!!!!\n")); + + errno = 0; + ctx = GetExceptCtx(currentTargetThread); + + CheckForSingleStep(ctx->ctx); + + TgtChange(pid, ctx->ctx,STS_MAKESIG(ExcepToSig(ctx->ctx->idtIndex))); + + } +} + +/* ------------------------------------------------------------------- + MyThreadIdle - + + This task is used to initiate the exception mechanism: + It calls the enterDebug function with justSaveContext=1 + only to push a first valid context in the list + ---------------------------------------------------------------------*/ + +rtems_task MyThreadIdle(rtems_task_argument argument) +{ + enterRdbg(); + rtems_task_delete( RTEMS_SELF ); +} + +/* ----------------------------------------------------------------------- + TgtAttach - attach to a process that is running without control. + + Notes: + - this function performs a ptrace ATTACH equivalent (attaching to a + process that we do not control now). + ----------------------------------------------------------------------- */ + +Boolean TgtAttach( + int conn_idx, /* client that is requesting */ + PID pid) /* process to attach to */ +{ + rtems_name task_name; + rtems_status_code status; + rtems_id debugId; + interrupt_gate_descriptor *currentIdtEntry; + unsigned limit; + unsigned level; + + errno = 0; + + DPRINTF (("TgtAttach pid=%d\n",pid)); + + Ptrace(RPT_ATTACH, pid, NULL, 0, NULL); + if (errno) + return(False); /* failed */ + + TgtCreateNew(pid, conn_idx, 0, NULL, False); + + + /* + * Connect the Exception used to debug + */ + i386_get_info_from_IDTR (¤tIdtEntry, &limit); + + _CPU_ISR_Disable(level); + create_interrupt_gate_descriptor (¤tIdtEntry[50], rtems_exception_prologue_50); + _CPU_ISR_Enable(level); + + old_currentExcHandler = _currentExcHandler; + _currentExcHandler = BreakPointExcHdl ; + + + /* + * Create the attach debuger task + */ + task_name = rtems_build_name( 'E', 'v', 'n', 't' ); + if ((status = rtems_task_create( task_name, 10, 24576, + RTEMS_INTERRUPT_LEVEL(0), + RTEMS_DEFAULT_ATTRIBUTES | RTEMS_SYSTEM_TASK, + &eventTaskId )) + != RTEMS_SUCCESSFUL){ + printf("status = %d\n",status); + rtems_panic ("Can't create task.\n"); + } + + status = rtems_task_start(eventTaskId, eventTask, pid); + + status = rtems_semaphore_create (rtems_build_name('D', 'B', 'G', 's'), + 1, + RTEMS_FIFO | + RTEMS_COUNTING_SEMAPHORE | + RTEMS_NO_INHERIT_PRIORITY | + RTEMS_NO_PRIORITY_CEILING | + RTEMS_LOCAL, + 0, + &serializeSemId); + if (status != RTEMS_SUCCESSFUL) + rtems_panic ("Can't create serialize semaphore: `%s'\n",rtems_status_text(status)); + + status = rtems_semaphore_create (rtems_build_name('D', 'B', 'G', 'w'), + 0, + RTEMS_FIFO | + RTEMS_COUNTING_SEMAPHORE | + RTEMS_NO_INHERIT_PRIORITY | + RTEMS_NO_PRIORITY_CEILING | + RTEMS_LOCAL, + 0, + &wakeupEventSemId); + if (status != RTEMS_SUCCESSFUL) + rtems_panic ("Can't create wakeup semaphore: `%s'\n",rtems_status_text(status)); + + /* + * Create the MyThreadIdle task to init Exception mechanism + */ + task_name = rtems_build_name( 'R', 'i', 'n', 'i' ); + if ((status = rtems_task_create( task_name, 10, 24576, + RTEMS_INTERRUPT_LEVEL(0), + RTEMS_DEFAULT_ATTRIBUTES, + &debugId )) + != RTEMS_SUCCESSFUL){ + printf("status = %d\n",status); + rtems_panic ("Can't create task.\n"); + } + + status = rtems_task_start(debugId, MyThreadIdle, pid); + + return(True); +} + +/* ----------------------------------------------------------------------- + TgtPtrace - handle ptrace requests for server. + ----------------------------------------------------------------------- */ + +int TgtPtrace( + int req, + PID pid, + char *addr, + int data, + void *addr2) +{ + if ((req == RPT_SINGLESTEP || req == RPT_CONT) + && addr2) /* clear then step */ + { /* addr2 is the old value */ + int ret; + + errno = 0; + TgtBreakRestoreOrig (pid, addr, addr2); + ret = Ptrace(RPT_SINGLESTEP, pid, addr, data, NULL); /* step over */ + if (ret) /* error, cannot single-step */ + { + int pid_idx = FindPidEntry (pid); + TgtBreakCancelStep (&pid_list [pid_idx]); + } + return(ret); /* failed or done */ + } + else + return(Ptrace(req, pid, addr, data, addr2)); /* normal call */ +} + +/* ----------------------------------------------------------------- + TgtGetThreadName - get thread name + --------------------------------------------------------------- */ + +int TgtGetThreadName ( + PID_LIST *plst, /* Process entry */ + unsigned Id, /* Thread ID */ + char *ThrName) /* Thread name */ +{ + int index; + unsigned name; + + if ( Id <_Objects_Information_table[OBJECTS_RTEMS_TASKS]->maximum_id && + Id >_Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id) { + + index = Id - _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; + name = *(unsigned*)(_Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index]->name); + ThrName[0] = (char)((name >> 24) & 0xFF ); + ThrName[1] = (char)((name >> 16) & 0xFF ); + ThrName[2] = (char)((name >> 8) & 0xFF ); + ThrName[3] = (char)( name & 0xFF ); + ThrName[4] = 0x0; + return 0; + } + + if ( Id <_Objects_Information_table[OBJECTS_POSIX_THREADS]->maximum_id && + Id >_Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id) { + + index = Id - _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; + name = *(unsigned*)(_Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index]->name); + ThrName[0] = (char)((name >> 24) & 0xFF ); + ThrName[1] = (char)((name >> 16) & 0xFF ); + ThrName[2] = (char)((name >> 8) & 0xFF ); + ThrName[3] = (char)( name & 0xFF ); + ThrName[4] = 0x0; + return 0; + } + + + return -1; + +} + +/* ----------------------------------------------------------------- + TgtThreadList - return all the threads in the system + ----------------------------------------------------------------- */ + + int +TgtThreadList ( + PID_LIST* plst, /* Process entry */ + unsigned* threads, /* Output buffer */ + unsigned size) /* Output buffer size */ +{ + int curr = 0; + Objects_Id id; + unsigned index; + + id = _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; + + while (id < _Objects_Information_table[OBJECTS_RTEMS_TASKS]->maximum_id){ + index = id - _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; + if ( _Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index] != NULL){ + threads[curr] = (unsigned) id; + curr++; + } + id ++; + } + + id = _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; + + while (id < _Objects_Information_table[OBJECTS_POSIX_THREADS]->maximum_id){ + index = id - _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; + if ( _Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index] != NULL){ + threads[curr] = (unsigned) id; + curr++; + } + id ++; + } + + return curr; +} diff --git a/c/src/lib/librdbg/awk.svc b/c/src/lib/librdbg/awk.svc new file mode 100644 index 0000000000..79e24a9d90 --- /dev/null +++ b/c/src/lib/librdbg/awk.svc @@ -0,0 +1,65 @@ +######################################################################### +# +# Component: RDBG +# Module: awk.svc +# +# Synopsis: AWK script which transforms the server skeleton produced +# by rpcgen(1) into something suitable for RDB servers. +# +######################################################################### + +BEGIN { + headerstarted = 0 + withinproc = 0 + brack = 0 +} + +$1 ~ /^\/\*HEADER_START\*\/$/ { + headerstarted = 1 + printf("#include \n"); + printf("#include \n"); + printf("#include \n"); + printf("#include \n"); + printf("#include \n"); + printf("#include \n"); + printf("#include \n"); + printf("#include \n", THEPROG); + printf("#define fprintf(a,b) printf(b)\n"); + printf("#define msgout(a) printf(a)\n") + printf("#define _msgout(a) fprintf(stderr,a)\n"); +} + +$1 ~ /^\/\*HEADER_END\*\/$/ { + headerstarted = 0 +} + +{ + if (headerstarted == 1) { + print $0 + } else if ($1 ~ /.*_2.*/) { + withinproc = 1 + printf("void\n"); + print $0 + } else if (withinproc == 1) { + if ($1 == "switch") { + print "\tDPRINTF ((\"remotedeb_2: %s (%d)\\n\", " + print "\t\t(unsigned) rqstp->rq_proc < " + print "\t\t(unsigned) (sizeof names / sizeof names[0]) ?" + print "\t\tnames [rqstp->rq_proc] : \"???\", " + print "\t\t(int) rqstp->rq_proc));\n" + } + for (i = 1; i <= NF; i++) { + if ($i == "{") { + brack++; + } else if ($i == "}") { + brack--; + if (brack == 0) { + withinproc = 0; + } + } + } + if ($1 != "_rpcsvcdirty" ) { + print $0 + } + } +} diff --git a/c/src/lib/librdbg/i386/excep.c b/c/src/lib/librdbg/i386/excep.c new file mode 100644 index 0000000000..5ca1fd8df6 --- /dev/null +++ b/c/src/lib/librdbg/i386/excep.c @@ -0,0 +1,233 @@ +/* + ************************************************************************** + * + * Component = + * + * Synopsis = rdbg/i386/excep.c + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include + + +extern rtems_id serializeSemId; +extern rtems_id wakeupEventSemId; + + +unsigned int NbExceptCtx; +volatile unsigned int NbSerializedCtx; +Exception_context *FirstCtx = NULL; +Exception_context *LastCtx = NULL; + +CPU_Exception_frame SavedContext; + + +/********* Save an exception context at the end of a list *****/ + +int PushExceptCtx ( Objects_Id Id, Objects_Id semId, CPU_Exception_frame *ctx ) { + + Exception_context *SaveCtx; + + SaveCtx = (Exception_context *)malloc(sizeof(Exception_context)); + if (SaveCtx == NULL) + rtems_panic("Can't allocate memory to save Exception context"); + + SaveCtx->id = Id; + SaveCtx->ctx = ctx; + SaveCtx->semaphoreId = semId; + SaveCtx->previous = NULL; + SaveCtx->next = NULL; + + if (FirstCtx == NULL){ /* initialization */ + FirstCtx = SaveCtx; + LastCtx = SaveCtx; + NbExceptCtx = 1; + } + else { + NbExceptCtx ++; + LastCtx->next = SaveCtx; + SaveCtx->previous = LastCtx; + LastCtx = SaveCtx; + } + return 0; +} + +/********* Save an temporary exception context in a ******/ +/********* global variable ******/ + +int PushSavedExceptCtx ( Objects_Id Id, CPU_Exception_frame *ctx ) { + + memcpy (&(SavedContext), ctx, sizeof(CPU_Exception_frame)); + return 0; +} + + +/****** Remove the context of the specified Id thread *********/ +/****** If Id = -1, then return the first context *********/ + + +int PopExceptCtx ( Objects_Id Id ) { + + Exception_context *ExtractCtx; + + if (FirstCtx == NULL) return -1; + + if (Id == -1) { + ExtractCtx = LastCtx; + LastCtx = LastCtx->previous; + free(ExtractCtx); + NbExceptCtx --; + return 0; + } + + ExtractCtx = LastCtx; + + while (ExtractCtx->id != Id && ExtractCtx != NULL) { + ExtractCtx = ExtractCtx->previous; + } + + if (ExtractCtx == NULL) + return -1; + + if ( ExtractCtx->previous != NULL) + (ExtractCtx->previous)->next = ExtractCtx->next; + + if ( ExtractCtx->next != NULL) + (ExtractCtx->next)->previous = ExtractCtx->previous; + + if (ExtractCtx == FirstCtx) + FirstCtx = FirstCtx->next; + else + if (ExtractCtx == LastCtx) + LastCtx = LastCtx->previous; + + free(ExtractCtx); + NbExceptCtx --; + return 0; +} + +/****** Return the context of the specified Id thread *********/ +/****** If Id = -1, then return the first context *********/ + + +Exception_context *GetExceptCtx ( Objects_Id Id ) { + + Exception_context *ExtractCtx; + + if (FirstCtx == NULL) return NULL; + + if (Id == -1) { + return LastCtx; + } + + ExtractCtx = LastCtx; + + while (ExtractCtx->id != Id && ExtractCtx != NULL) { + ExtractCtx = ExtractCtx->previous; + } + + if (ExtractCtx == NULL) + return NULL; + + return ExtractCtx; +} + +/*----- Breakpoint Exception management -----*/ + + /* + * Handler for Breakpoint Exceptions : + * software breakpoints. + */ + +void +BreakPointExcHdl(CPU_Exception_frame *ctx) +{ + rtems_status_code status; + rtems_id continueSemId; + + if ( (justSaveContext) && (ctx->idtIndex == I386_EXCEPTION_ENTER_RDBG) ) { + PushSavedExceptCtx (_Thread_Executing->Object.id, ctx); + justSaveContext = 0; + } + else { + if (ctx->idtIndex != DEBUG){ + NbSerializedCtx++; + rtems_semaphore_obtain(serializeSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + NbSerializedCtx--; + } + + currentTargetThread = _Thread_Executing->Object.id; + +#ifdef DDEBUG + printk("----------------------------------------------------------\n"); + printk("Exception %d caught at PC %x by thread %d\n", + ctx->idtIndex, + ctx->eip, + _Thread_Executing->Object.id); + printk("----------------------------------------------------------\n"); + printk("Processor execution context at time of the fault was :\n"); + printk("----------------------------------------------------------\n"); + printk(" EAX = %x EBX = %x ECX = %x EDX = %x\n", + ctx->eax, ctx->ebx, ctx->ecx, ctx->edx); + printk(" ESI = %x EDI = %x EBP = %x ESP = %x\n", + ctx->esi, ctx->edi, ctx->ebp, ctx->esp0); + printk("----------------------------------------------------------\n"); + printk("Error code pushed by processor itself (if not 0) = %x\n", + ctx->faultCode); + printk("----------------------------------------------------------\n\n"); +#endif + + status = rtems_semaphore_create (rtems_build_name('D', 'B', 'G', 'c'), + 0, + RTEMS_FIFO | + RTEMS_COUNTING_SEMAPHORE | + RTEMS_NO_INHERIT_PRIORITY | + RTEMS_NO_PRIORITY_CEILING | + RTEMS_LOCAL, + 0, + &continueSemId); + if (status != RTEMS_SUCCESSFUL) + rtems_panic ("Can't create continue semaphore: `%s'\n",rtems_status_text(status)); + + PushExceptCtx (_Thread_Executing->Object.id, continueSemId, ctx); + + switch (ctx->idtIndex){ + case I386_EXCEPTION_DEBUG: + DPRINTF((" DEBUG EXCEPTION !!!\n")); + ctx->eflags &= ~EFLAGS_TF; + ExitForSingleStep-- ; + rtems_semaphore_release( wakeupEventSemId ); + break; + + case I386_EXCEPTION_BREAKPOINT: + DPRINTF((" BREAKPOINT EXCEPTION !!!\n")); + rtems_semaphore_release( wakeupEventSemId ); + break; + + case I386_EXCEPTION_ENTER_RDBG: + DPRINTF((" ENTER RDBG !!!\n")); + rtems_semaphore_release( wakeupEventSemId ); + break; + + default: + DPRINTF((" OTHER EXCEPTION !!!\n")); + rtems_semaphore_release( wakeupEventSemId ); + break; + } + + rtems_semaphore_obtain(continueSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + + PopExceptCtx (_Thread_Executing->Object.id); + rtems_semaphore_delete(continueSemId); + } +} + + + diff --git a/c/src/lib/librdbg/i386/pc386/remdeb_f.x b/c/src/lib/librdbg/i386/pc386/remdeb_f.x new file mode 100644 index 0000000000..0ff52d1307 --- /dev/null +++ b/c/src/lib/librdbg/i386/pc386/remdeb_f.x @@ -0,0 +1,58 @@ +/* + ************************************************************************** + * + * Component = rdblib + * + * Synopsis = remdeb_f.x + * + * + ************************************************************************** + */ + +struct xdr_regs +{ + unsigned int tabreg[19]; +}; + +#ifdef RPC_HDR + +%/* now define register macros to apply to xdr_reg struct */ +% +%#define GS 0 +%#define FS 1 +%#define ES 2 +%#define DS 3 +%#define EDI 4 +%#define ESI 5 +%#define EBP 6 +%#define ESP 7 +%#define EBX 8 +%#define EDX 9 +%#define ECX 10 +%#define EAX 11 +%#define TRAPNO 12 +%#define ERR 13 +%#define EIP 14 +%#define CS 15 +%#define EFL 16 +%#define UESP 17 +%#define SS 18 +% +%#define REG_PC tabreg[EIP] /* PC (eip) register offset */ +%#define REG_SP tabreg[UESP] /* SP (uesp) register offset */ +%#define REG_FP tabreg[EBP] /* FP (ebp) register offset */ + +%/* now define the BREAKPOINT mask technique to a long word */ +%#define SET_BREAK(l) ((l&0xFFFFFF00) | 0xCC) +%#define IS_BREAK(l) (((l) & 0xFF) == 0xCC) +%#define ORG_BREAK(c,p) (((c) & 0xFFFFFF00) | ((p) & 0xFF)) +%#define IS_STEP(regs) (regs.tabreg[TRAPNO] == 1) /* was step and not break */ +%#define BREAK_ADJ 1 /* must subtract one from address after bp */ +%#define BREAK_SIZE 1 /* Breakpoint occupies one byte */ + +%#define TARGET_PROC_TYPE 0 + +#endif + + + diff --git a/c/src/lib/librdbg/i386/rdbg_cpu_asm.s b/c/src/lib/librdbg/i386/rdbg_cpu_asm.s new file mode 100644 index 0000000000..f0942310ce --- /dev/null +++ b/c/src/lib/librdbg/i386/rdbg_cpu_asm.s @@ -0,0 +1,70 @@ +/* cpu_asm.s + * + * This file contains all assembly code for the Intel i386 implementation + * of RDBG. + * + */ + +#include + + BEGIN_CODE + +/* + * void copyback_data_cache_and_invalidate_instr_cache() + * + * This routine performs a copy of the data cache + * and invalidate the instruction cache + */ + + .p2align 1 + PUBLIC (copyback_data_cache_and_invalidate_instr_cache) + +SYM (copyback_data_cache_and_invalidate_instr_cache): + wbinvd + ret + + + +/* + * void enterRdbg(void) + * + * This function perform a call to the exception 19 + * It is used : + * 1 - in the user code, to simulate a Breakpoint. + * (with justSaveContext = 0) + * 2 - in the RDBG code, to push a ctx in the list. + * (with justSaveContext = 1) + * + * In most of case, it will be use as described in 1. + * The 2nd possibility will be used by RDBG to obtain + * its own ctx + */ + + PUBLIC (enterRdbg) + +SYM (enterRdbg): + int $50 + ret + + +/* + * void rtems_exception_prologue_50(void) + * + * Exception 50 is used to enter Rdbg + * + */ + + .p2align 4 + + PUBLIC (rtems_exception_prologue_50) + PUBLIC (_Exception_Handler) + +SYM (rtems_exception_prologue_50): + pushl $ 0 + pushl $ 50 + jmp SYM(_Exception_Handler) ; + + +END_CODE + +END diff --git a/c/src/lib/librdbg/i386/rdbg_f.c b/c/src/lib/librdbg/i386/rdbg_f.c new file mode 100644 index 0000000000..aeb07fcbe8 --- /dev/null +++ b/c/src/lib/librdbg/i386/rdbg_f.c @@ -0,0 +1,130 @@ +/* + ************************************************************************** + * + * Component = + * + * Synopsis = rdbg/i386/rdbg_f.c + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include + + +void +CtxToRegs (const CPU_Exception_frame* ctx, xdr_regs* regs) +{ + regs->tabreg [GS] = 0; + regs->tabreg [FS] = 0; + regs->tabreg [ES] = 0; + regs->tabreg [DS] = 0; + regs->tabreg [EDI] = ctx->edi; + regs->tabreg [ESI] = ctx->esi; + regs->tabreg [EBP] = ctx->ebp; + regs->tabreg [ESP] = ctx->esp0; + regs->tabreg [EBX] = ctx->ebx; + regs->tabreg [EDX] = ctx->edx; + regs->tabreg [ECX] = ctx->ecx; + regs->tabreg [EAX] = ctx->eax; + regs->tabreg [TRAPNO] = ctx->idtIndex; + regs->tabreg [ERR] = ctx->faultCode; + regs->tabreg [EIP] = ctx->eip; + regs->tabreg [CS] = ctx->cs & 0xFFFF; + regs->tabreg [EFL] = ctx->eflags; +} + + + void +RegsToCtx (const xdr_regs* regs, CPU_Exception_frame* ctx) +{ + ctx->edi = regs->tabreg [EDI]; + ctx->esi = regs->tabreg [ESI]; + ctx->ebp = regs->tabreg [EBP]; + ctx->esp0 = regs->tabreg [ESP]; + ctx->ebx = regs->tabreg [EBX]; + ctx->edx = regs->tabreg [EDX]; + ctx->ecx = regs->tabreg [ECX]; + ctx->eax = regs->tabreg [EAX]; + ctx->idtIndex = regs->tabreg [TRAPNO]; + ctx->faultCode = regs->tabreg [ERR]; + ctx->eip = regs->tabreg [EIP]; + ctx->cs = regs->tabreg [CS]; + ctx->eflags = regs->tabreg [EFL]; +} + +void +get_ctx_thread( Thread_Control *thread, CPU_Exception_frame* ctx) +{ + ctx->edi = thread->Registers.edi; + ctx->esi = thread->Registers.esi; + ctx->ebp = (unsigned32)(thread->Registers.ebp); + ctx->esp0 = (unsigned32)(thread->Registers.esp); + ctx->ebx = thread->Registers.ebx; + ctx->edx = 0; + ctx->ecx = 0; + ctx->eax = 0; + ctx->idtIndex = 0; + ctx->faultCode = 0; + ctx->eip = *(unsigned int*)(thread->Registers.esp); + ctx->cs = 0; + ctx->eflags = thread->Registers.eflags; +} + +void +set_ctx_thread( Thread_Control *thread, CPU_Exception_frame* ctx) +{ + thread->Registers.edi = ctx->edi; + thread->Registers.esi = ctx->esi; + thread->Registers.ebp = (void*)(ctx->ebp); + thread->Registers.esp = (void*)(ctx->esp0); + thread->Registers.ebx = ctx->ebx; + thread->Registers.eflags = ctx->eflags; +} + + + +int +Single_Step(CPU_Exception_frame* ctx) +{ + /* Check if not already set */ + if ((ctx->eflags & EFLAGS_TF) != 0 || ExitForSingleStep != 0) { + /* Check coherency */ + assert ((ctx->eflags & EFLAGS_TF) != 0); + assert (ExitForSingleStep != 0); + return 0; + } + ctx->eflags |= EFLAGS_TF; /* eflags */ + ++ExitForSingleStep; + + return 0; +} + + int +CheckForSingleStep (CPU_Exception_frame* ctx) +{ + if (ExitForSingleStep) { + /* + * This functions can be called both from + * INT1 and INT3 handlers. In case it is + * called from INT3, need to clear TF. + */ + ctx->eflags &= ~EFLAGS_TF; + ExitForSingleStep = 0; + return 1; + } + return 0; +} + +void +CancelSingleStep (CPU_Exception_frame* ctx) +{ + /* Cancel scheduled SS */ + ctx->eflags &= ~EFLAGS_TF; + ExitForSingleStep-- ; +} diff --git a/c/src/lib/librdbg/ptrace.c b/c/src/lib/librdbg/ptrace.c new file mode 100644 index 0000000000..158bd57cbb --- /dev/null +++ b/c/src/lib/librdbg/ptrace.c @@ -0,0 +1,335 @@ +/* + ************************************************************************** + * + * Component = + * + * Synopsis = rkdb/rkdb.c + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include + +extern rtems_id serializeSemId; +extern rtems_id wakeupEventSemId; +extern rtems_id eventTaskId; +extern Exception_context *FirstCtx; +extern Exception_context *LastCtx; +extern CPU_Exception_frame SavedContext; +extern unsigned int NbExceptCtx; +extern unsigned int NbSerializedCtx; + + + +/* -------------------------------------------------------------------- + return a pointeur to the Tread Control structure of the specified + Id + -------------------------------------------------------------------- */ + +Thread_Control *Thread_Get_RDBG ( + Objects_Id Id +) +{ + unsigned index; + + if ( Id <_Objects_Information_table[OBJECTS_RTEMS_TASKS]->maximum_id && + Id >_Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id) { + + index = Id - _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; + if ( _Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index] != NULL) { + return (Thread_Control *)(_Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index]); + } + } + + if ( Id <_Objects_Information_table[OBJECTS_POSIX_THREADS]->maximum_id && + Id >_Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id) { + + index = Id - _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; + if ( _Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index] != NULL) + return (Thread_Control *)(_Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index]); + } + + return 0; + +} + + +/* -------------------------------------------------------------------- + Memory read + -------------------------------------------------------------------- */ + +int +safeMemRead(void *src, void *dest, int nbBytes){ + + /* + * safe because if it generates an exception, + * it must return normally + * TBD + */ + + memcpy(dest, src, nbBytes); + return 0; +} + +/* -------------------------------------------------------------------- + Memory write + -------------------------------------------------------------------- */ +int +safeMemWrite(void *src, void * dest, int nbBytes){ + + /* + * safe because if it generates an exception, + * it must return normally + * TBD + */ + + memcpy(dest, src, nbBytes); + return 0; +} + +/* -------------------------------------------------------------------- + Ptrace + -------------------------------------------------------------------- */ + +int +ptrace (int request, int pid, char* addr, int data, char* addr2) + { + int diag; + errno = 0 ; + if (pid != 1) { + errno = ESRCH; + return -1; + } + switch (request) { + + case RPT_SINGLESTEP:{ + Exception_context *ctx; + + if (CannotRestart == 1){ + setErrno(EIO); + return -1; + } + + if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { + Single_Step(ctx->ctx); + rtems_semaphore_release( ctx->semaphoreId ); + return 0; + } + break; + } + + case RPT_PEEKTEXT: + case RPT_PEEKDATA: { + diag = safeMemRead(addr, &data, sizeof data); + if (diag == 0) return data; + mem_error: + return -1; + } + + case RPT_POKETEXT: { + diag = safeMemWrite(&data, addr, sizeof data); + + /* + * We must flush the INSTR and DATA cache to be sure the + * opcode modification is taken into account, because + * the breakpoint opcode is written via the data cache + * while execution code is fetched via the instruction + * cache + */ + + if (diag == 0) { + copyback_data_cache_and_invalidate_instr_cache(); + return 0; + } + goto mem_error; + } + case RPT_POKEDATA: { + diag = safeMemWrite(&data, addr, sizeof data); + if (diag == 0) return 0; + goto mem_error; + } + case RPT_CONT: { + Exception_context *ctx; + + if (CannotRestart == 1){ + setErrno (EIO); + return -1; + } + + ctx = GetExceptCtx (currentTargetThread); + + if ( + ctx->ctx->idtIndex != I386_EXCEPTION_DEBUG && + ctx->ctx->idtIndex != I386_EXCEPTION_BREAKPOINT && + ctx->ctx->idtIndex != I386_EXCEPTION_ENTER_RDBG + ) { + CannotRestart = 1; + setErrno (EIO); + return -1; + } + + assert (data == 0); + assert (ExitForSingleStep == 0); + + rtems_semaphore_release( serializeSemId ); + + if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { + rtems_semaphore_release( ctx->semaphoreId ); + } + return 0; + } + + case RPT_ATTACH: + return 0; + + case RPT_DETACH:{ + Exception_context *ctx; + + if (NbExceptCtx || NbSerializedCtx) { + ctx = FirstCtx; + rtems_task_delete(eventTaskId); + rtems_semaphore_delete(serializeSemId); + rtems_semaphore_delete(wakeupEventSemId); + } + return 0; + } + + case RPT_GETREGS:{ + Exception_context *ctx; + + if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { + CtxToRegs (ctx->ctx, (xdr_regs*) addr); + return 0; + } + break; + } + + case RPT_SETREGS:{ + Exception_context *ctx; + + if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { + RegsToCtx ((xdr_regs*) addr, ctx->ctx); + return 0; + } + break; + } + + case RPT_READTEXT: + case RPT_READDATA: { + diag = safeMemRead(addr, addr2, data); + if (diag == 0) return 0; + goto mem_error; + } + case RPT_WRITETEXT: + case RPT_WRITEDATA: { + diag = safeMemWrite(addr2, addr, data); + if (diag == 0) return 0; + goto mem_error; + } + + case RPT_GETTARGETTHREAD: + if (!NbExceptCtx) { + errno = EBUSY; + return -1; + } + return currentTargetThread; + + case RPT_SETTARGETTHREAD: + if (!NbExceptCtx) { + errno = EBUSY; + return -1; + } + currentTargetThread = data; + return 0; + + case RPT_GETTHREADNAME: { + return TgtGetThreadName (NULL, (unsigned)(data), (char *) addr); + } + + case RPT_THREADLIST: { + int count = TgtThreadList (NULL, (unsigned*) addr, UTHREAD_MAX + * sizeof (unsigned)); + if (count < 0) { + errno = EINVAL; + return -1; + } + return count; + } + + case RPT_SETTHREADREGS: { + Exception_context *ctx; + CPU_Exception_frame Ectx; + Thread_Control *thread; + rtems_id id; + + rtems_task_ident(RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &id); + if (data == (unsigned)id) + break; + + if ((ctx = GetExceptCtx (data)) != NULL) { + RegsToCtx ((xdr_regs*) addr, ctx->ctx); + return 0; + } + thread = Thread_Get_RDBG ((Objects_Id)(data)); + if (thread != NULL) { + RegsToCtx ((xdr_regs*) addr, &Ectx); + set_ctx_thread (thread, &Ectx); + return 0; + } + break; + } + + case RPT_GETTHREADREGS: { + Exception_context *ctx; + CPU_Exception_frame Ectx; + Thread_Control *thread; + rtems_id id; + + rtems_task_ident(RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &id); + if (data == (unsigned)id){ + justSaveContext = 1; + enterRdbg(); + CtxToRegs (&(SavedContext), (xdr_regs*) addr); + return 0; + } + + if ((ctx = GetExceptCtx (data)) != NULL) { + CtxToRegs (ctx->ctx, (xdr_regs*) addr); + return 0; + } + thread = Thread_Get_RDBG ((Objects_Id)(data)); + if (thread != NULL) { + get_ctx_thread (thread, &Ectx); + CtxToRegs (&Ectx, (xdr_regs*) addr); + return 0; + } + break; + } + + case RPT_KILL: + TotalReboot = 1; + return 0; + + case RPT_TRACEME: + case RPT_PEEKUSER: + case RPT_POKEUSER: + case RPT_GETFPREGS: + case RPT_SETFPREGS: + case RPT_GETFPAREGS: + case RPT_SETFPAREGS: + case RPT_SYSCALL: + case RPT_DUMPCORE: + case RPT_GETUCODE: + case RPT_THREADSUSPEND: + case RPT_THREADRESUME: + case RPT_SETTHREADNAME: + default: + break; + } + errno = EINVAL; + return -1; +} diff --git a/c/src/lib/librdbg/rdbg.c b/c/src/lib/librdbg/rdbg.c new file mode 100644 index 0000000000..1f04119e8e --- /dev/null +++ b/c/src/lib/librdbg/rdbg.c @@ -0,0 +1,139 @@ +/* + ************************************************************************** + * + * Component = + * + * Synopsis = rkdb/rkdb.c + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include +#include + +u_short rtemsPort = RTEMS_PORT; +int BackPort = RTEMS_BACK_PORT; +int rtemsActive = 0; +SVCXPRT* rtemsXprt; +int rtemsSock; +char ActName[] = "RTEMS"; +volatile int ExitForSingleStep = 0 ; +volatile int Continue; +volatile int justSaveContext; +volatile Objects_Id currentTargetThread; +volatile int CannotRestart = 0; +volatile int TotalReboot = 0; +int CONN_LIST_INC = 3; +int PID_LIST_INC = 1; +int TSP_RETRIES = 10; + + + int +getId() +{ + rtems_id id; + + rtems_task_ident(RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &id); + return (int)(id) ; +} + + static int +rdbgInit (void) +{ + int sock; + struct sockaddr_in addr; + + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock == -1) { + printf("%s: rkdbInit: cannot allocate socket\n", ActName); + return -1; + } + + bzero( (void *)&addr, sizeof(struct sockaddr_in)); + addr.sin_port = htons(rtemsPort); + if ((bind(sock, (struct sockaddr*) &addr, sizeof(addr))) == -1) { + printf("%s: rkdbInit: cannot bind socket\n", ActName); + return -2; + } + rtemsXprt = svcudp_create(sock); + if (svcudp_enablecache(rtemsXprt, 1) == 0) { + printf("%s: rkdbInit: cannot enable rpc cache\n", ActName); + return -3; + } + rtemsSock = sock; + return 0; +} + + rtems_task +rdbgDaemon (rtems_task_argument argument) +{ + for (;;){ + + if (TotalReboot == 1){ + rtemsReboot(); + } + + svc_processrequest( rtemsXprt, REMOTEDEB, REMOTEVERS, remotedeb_2); + } +} + + void +rtems_rdbg_initialize (void) +{ + rtems_name task_name; + rtems_id tid; + rtems_status_code status; + +#ifdef DDEBUG + rdb_debug = 1; /* DPRINTF now will display */ +#endif + + DPRINTF (("%s init starting\n", ActName)); + + /* Print version string */ +#ifdef DDEBUG + printk ("RDBG v.%d built on [%s %s]\n", SERVER_VERS, __DATE__, __TIME__); +#else + printk ("RDBG v.%d\n", SERVER_VERS); +#endif + + /* Create socket and init UDP RPC server */ + if (rdbgInit() != 0) goto error; + + Continue = 1; + justSaveContext = 0; + currentTargetThread = 0; + + task_name = rtems_build_name( 'R', 'D', 'B', 'G' ); + if ((status = rtems_task_create( task_name, 5, 24576, + RTEMS_INTERRUPT_LEVEL(0), + RTEMS_DEFAULT_ATTRIBUTES | RTEMS_SYSTEM_TASK + , &tid )) + != RTEMS_SUCCESSFUL){ + printf("status = %d\n",status); + rtems_panic ("Can't create task.\n"); + } + + status = rtems_task_start(tid, rdbgDaemon, 0); + + return; + +error: + printf ("initialization failed.\n"); +} + + void +setErrno (int error) +{ + errno = error; +} + + int +getErrno() +{ + return errno; +} diff --git a/c/src/lib/librdbg/remdeb.x b/c/src/lib/librdbg/remdeb.x new file mode 100644 index 0000000000..e4cb998ebc --- /dev/null +++ b/c/src/lib/librdbg/remdeb.x @@ -0,0 +1,544 @@ +/* + ********************************************************************** + * + * Component: RDBG servers + * Module: remdeb.x + * + * Synopsis: XDR definitions for remote debug server RPC calls. + * XDR definitions for RPCGEN to build remote debug server. + * + ********************************************************************** + */ + +#ifdef RPC_SVC +%/*HEADER_START*/ +#endif + +%#define RTEMS_PORT 2071 +%#define RTEMS_BACK_PORT 2073 + +#ifdef RPC_HDR +%#ifndef REMDEB_H +%#define RPCGENSRVNAME(a) a +#endif + +enum rpc_type { + SUNRPC = 0, + BADRPCTYPE = 25 +}; + + +const NET_SAFE = 1400; /* this is safe for UDP messages */ + +struct UDP_MSG +{ /* format of UDP messages (should be in .h) */ + unsigned char type; /* type of message (BMSG_xx) */ + unsigned char msg_num; /* ringed number for resend detect */ + unsigned short spec; /* specific information for type */ + long pid; /* process this affects */ + unsigned long context; /* specific information to request */ +}; + + /* First we support the overhead structures and types needed for RPC + requests. Then, we have all RPC routines input/output args. */ + +%/* +% * Sun request values for the remote ptrace system call +% */ +% +enum ptracereq +{ /* these match PTRACE_xxx numbers */ + RPT_TRACEME = 0, /* 0, by tracee to begin tracing */ + RPT_CHILDDONE = 0, /* 0, tracee is done with his half */ + RPT_PEEKTEXT, /* 1, read word from text segment */ + RPT_PEEKDATA, /* 2, read word from data segment */ + RPT_PEEKUSER, /* 3, read word from user struct */ + RPT_POKETEXT, /* 4, write word into text segment */ + RPT_POKEDATA, /* 5, write word into data segment */ + RPT_POKEUSER, /* 6, write word into user struct */ + RPT_CONT, /* 7, continue process */ + RPT_KILL, /* 8, terminate process */ + RPT_SINGLESTEP, /* 9, single step process */ + RPT_ATTACH, /* 10, attach to an existing process (returns 2 if not primary)*/ + RPT_DETACH, /* 11, detach from a process */ + RPT_GETREGS, /* 12, get all registers */ + RPT_SETREGS, /* 13, set all registers */ + RPT_GETFPREGS, /* 14, get all floating point regs */ + RPT_SETFPREGS, /* 15, set all floating point regs */ + RPT_READDATA, /* 16, read data segment */ + RPT_WRITEDATA, /* 17, write data segment */ + RPT_READTEXT, /* 18, read text segment */ + RPT_WRITETEXT, /* 19, write text segment */ + RPT_GETFPAREGS, /* 20, get all fpa regs */ + RPT_SETFPAREGS, /* 21, set all fpa regs */ + RPT_22, /* 22, filler */ + RPT_23, /* 23, filler */ + RPT_SYSCALL, /* 24, trap next sys call */ + RPT_DUMPCORE, /* 25, dump process core */ + RPT_26, /* 26, filler */ + RPT_27, /* 27, filler */ + RPT_28, /* 28, filler */ + RPT_GETUCODE, /* 29, get u.u_code */ + /* Begin specific ptrace options */ + RPT_GETTARGETTHREAD = 50, /* get PM target thread identifier */ + RPT_SETTARGETTHREAD = 51, /* set PM target thread identifier */ + RPT_THREADSUSPEND = 52, /* suspend a thread */ + RPT_THREADRESUME = 53, /* resume a thread */ + RPT_THREADLIST = 54, /* get list of process's threads */ + RPT_GETTHREADNAME = 55, /* get the name of the thread */ + RPT_SETTHREADNAME = 56, /* set the name of the thread */ + RPT_SETTHREADREGS = 57, /* set all registers for a specific thread*/ + RPT_GETTHREADREGS = 58, /* get all registers for a specific thread*/ + /* Begin extended ptrace options for remote debug server */ + RPT_STEPRANGE = 75, /* step while in range (addr=start, data=len) */ + RPT_CONTTO = 76, /* cont from PC to temp break in addr */ + RPT_SETBREAK = 77, /* set a breakpoint (addr=break) */ + RPT_CLRBREAK = 78, /* clear a breakpoint (data=handle or 0 for all) */ + RPT_GETBREAK = 79, /* get breakpoint (data=handle, addr=buffer to + fill). Returns next break. If data=0, + returns number of breaks. */ + RPT_GETNAME = 80, /* get name of process (data 0=name, 1=path + as started, 2=fullpath). Return in addr + as mem) */ + RPT_STOP = 81, /* (C-actors) Stop the C-actor */ + RPT_PGETREGS = 82, /* portable version */ + RPT_PSETREGS = 83, /* portable version */ + RPT_PSETTHREADREGS = 84, /* portable version */ + RPT_PGETTHREADREGS = 85 /* portable version */ +}; + +#include "remdeb_f.x" + +const MAXDEBUGGEE= 150; +const NAMEMAX = 17; + +% /* +% * Memory data for read/write text or data. The size is in data. The target +% * addr is in the addr field. +% * Be careful before modifying because this value goes into internal +% * pipes and is allocated on stack too. Pipes and/or the stack could +% * become too small if this value gets incremented. +% */ + +const MEM_DATA_MAX = 256; + +#ifndef RPC_XDR + +struct xdr_mem { + u_long addr; + u_int dataNb; + unsigned char data[MEM_DATA_MAX]; +}; + +#else +/* manually define best XDR function for this */ +%bool_t xdr_xdr_mem(xdrs, objp) +% XDR *xdrs; +% struct xdr_mem *objp; +%{ +% if (!xdr_u_long(xdrs, &objp->addr)) { +% return (FALSE); +% } +% if (!xdr_u_int(xdrs, &objp->dataNb)) { +% return(FALSE); +% } +% return (xdr_opaque(xdrs, objp->data, objp->dataNb)); +%} + +#endif + +/* Breakpoint structure maps to same structure on host. Do not change one + without changing the other. */ + +enum break_type +{ /* types of breakpoints */ + BRKT_NONE, /* unused entry */ + BRKT_INSTR, /* general instruction break */ + BRKT_READ, /* read break */ + BRKT_WRITE, /* write breakpoint */ + BRKT_ACCESS, /* read-or-write break */ + BRKT_EXEC, /* execution HW breakpoint */ + BRKT_OS_CALL, /* break on OS call, addr is call number */ + BRKT_OS_SWITCH, /* dispatch breakpoint */ + BRKT_STEPEMUL /* emulate hardware single-step */ +}; +const MAX_THRD_BRK = 4; /* enough for 128 threads per process */ +struct xdr_break +{ /* one per process local breakpoint */ + u_char type; /* BRKT_xxx type of break */ + u_char thread_spec; /* 0=all, else count of threads it affects */ + u_short handle; /* handle of breakpoint returned */ + u_long ee_loc; /* address of start */ + u_long ee_type; /* type/method of address */ + u_short length; /* length of break if range, else 0 */ + u_char pass_count; /* pass count to initialize to (0=none) */ + u_char curr_pass; /* pass count current value */ + u_long thread_list[MAX_THRD_BRK]; /* bit map for thread list */ +}; /* 20 bytes+4 per thread_list (4x4=16) = 36 */ + +const UTHREAD_MAX = 64; + +const THREADNAMEMAX = 16; +typedef string thread_name ; + +struct KernThread { + unsigned int threadLi; +}; + +#ifndef RPC_XDR + +#ifdef RPC_HDR +%typedef KernThread *ptThreadList; +#endif + +struct thread_list { + unsigned int nbThread; + ptThreadList threads; +}; + +#else /* RPC_XDR */ + +/* must write this function by hand */ + +%bool_t xdr_thread_list(xdrs, objp) +% XDR *xdrs; +% struct thread_list *objp; +%{ +% return (xdr_array(xdrs, (char**)&objp->threads, &objp->nbThread, +% UTHREAD_MAX, sizeof(KernThread), xdr_KernThread)); +%} + +#endif /* not RPC_XDR */ + + +union ptrace_addr_data_in switch (ptracereq req) { + /* + * due to rpcgen poor features, we cannot put RPC_SETREGS + * AND RPC_SETTHREADREGS in the case list. So we use a hack (FIX rpcgen). + */ +#ifndef RPC_HDR + case RPT_SETTHREADREGS : + xdr_regs regs; +#endif + case RPT_SETREGS: + + xdr_regs regs; + +#ifndef RPC_HDR + case RPT_PSETTHREADREGS: + u_int pregs<>; +#endif + case RPT_PSETREGS: + u_int pregs<>; + +#ifdef LATER + case RPT_SETFPREGS: + xdr_fp_status fpregs; +#endif + case RPT_SETTHREADNAME: + thread_name name; +#ifndef RPC_HDR + case RPT_WRITETEXT: + xdr_mem mem; +#endif + case RPT_WRITEDATA: + xdr_mem mem; + case RPT_SETBREAK: + xdr_break breakp; + default: + u_int address; +}; + +union ptrace_addr_data_out switch (ptracereq req) { + case RPT_GETREGS: + xdr_regs regs; +#ifndef RPC_HDR + case RPT_GETTHREADREGS: + xdr_regs regs; +#endif + + case RPT_PGETREGS: + u_int pregs<>; + +#ifndef RPC_HDR + case RPT_PGETTHREADREGS: + u_int pregs<>; +#endif + +#ifdef LATER + case RPT_GETFPREGS: + xdr_fp_status fpregs; +#endif + case RPT_THREADLIST: + thread_list threads; + case RPT_GETTHREADNAME: + thread_name name; +#ifndef RPC_HDR + case RPT_READTEXT: + xdr_mem mem; + case RPT_GETNAME: + xdr_mem mem; +#endif + case RPT_READDATA: + xdr_mem mem; + case RPT_GETBREAK: + xdr_break breakp; + default: + u_int addr; +}; + +typedef opaque CHAR_DATA ; /* variable sized data */ + +const XRY_MAX_INST_BUFF = 128; +const XRY_MAX_INSTANCES = 16; +%#ifndef XRY_MAX_CMD_STR +const XRY_MAX_CMD_STR = 320; /* XRY_MAX_INST_BUFF+(XRY_MAX_INSTANCES*12) */ +%#endif /* REMDEB_H */ + + +struct xry_inst +{ + unsigned char flags; /* value2 interp, etc. INFL_xxx */ + unsigned char type; /* base type of data (str, val, etc) INST_xxx */ + unsigned char sub_type; /* specific type (task, res, etc). This is + set and defined by the user defined instance + processor and not the auto-processor */ + unsigned char res_type; + u_long value; /* pointer to value or value itself */ + u_long value2; /* second value (optional - based on flags) */ +}; + +struct instance +{ + struct xry_inst instances[XRY_MAX_INSTANCES]; + unsigned char buffer[XRY_MAX_INST_BUFF]; +}; + +union instance_union switch (bool instances) +{ + case TRUE: + instance inst; + case FALSE: + string buffer ; +}; + +typedef string one_arg ; + +const XRY_MAX_OBJ_NAME = 32; /* objname in some commands */ + +% /* now open_connex() routine which establishes a connection to server */ + +enum debug_type +{ /* type of connection requested */ + DEBTYP_PROCESS = 0, /* process connection */ + DEBTYP_C_ACTOR = 1, /* C-Actor connection */ + DEBTYP_KERNEL = 2, /* kernel debug connection */ + DEBTYP_OTHER = 3 /* other subsystem */ +}; + +%#define DEBUGGER_IS_GDB 0x2 /* */ + +struct open_in +{ /* input args to open a connection */ + u_char back_port[16]; /* opaque NET address format */ + u_short debug_type; /* type of process DEBTYP_xxx */ + u_short flags; /* connection information OPNFLG_xxx */ + u_char destination[16];/* opaque address if to router */ + one_arg user_name; /* name of user on host */ +}; + +struct open_out +{ /* return from open_connex */ + u_long port; /* connection number to server or -1 if error */ + u_int pad[4]; /* Planned to be KnIpcDest. Never used */ + u_int fp; /* True if floating point processor. If error, + set to errno for open error. */ + u_char cmd_table_num; /* command table used */ + u_char cmd_table_vers; /* version of command table */ + u_short server_vers; /* version number of server itself */ +}; + +% /* now close_connex() routine which detaches from server */ + +enum close_control +{ /* choice of how to handle owned processes */ + CLOSE_IGNORE = 0, /* ignore all controlled pids on close */ + CLOSE_KILL = 1, /* kill all controlled pids on close */ + CLOSE_DETACH = 2 /* detach free running all controlled pids */ +}; + +struct close_in +{ /* arg to close connection */ + close_control control; /* shutdown of owned processes control */ +}; + +% /* now send_signal() routine which sends signals to processes like kill(2) */ + +struct signal_in +{ /* input to send_signal */ + int pid; /* process/actor to send signal to */ + int sig; /* signal to send (from /usr/include/signal.h) */ +}; + +struct signal_out +{ /* return from send_signal */ + int kill_return; /* return code from kill(2) call */ + int errNo; /* error code if failed */ +}; + + +% /* now wait_info() routine which returns results of polling the wait status +% of a process/actor. It may return 0 if running, else pid or -1 */ + +enum stop_code +{ /* stop code information */ + STOP_ERROR = 0, /* error, errno set */ + STOP_NONE = 1, /* not stopped */ + STOP_UNKNOWN = 2, /* unknown stop reason */ + STOP_BREAK = 3, /* stopped on breakpoint */ + STOP_STEP = 4, /* stopped on step */ + STOP_SIGNAL = 5, /* stopped on signal receieve */ + STOP_TERM_EXIT = 6, /* terminated normally */ + STOP_TERM_SIG = 7, /* terminated by signal */ + STOP_DETACHED = 8, /* detached from server */ + STOP_KILLED = 9, /* killed by ptrace KILL */ + STOP_SPAWN_FAILED = 10 /* spawn failed in exec part, handle=errno */ +}; + +struct wait_in +{ /* input arg to wait is process */ + int pid; /* process/actor id */ +}; + +struct wait_out +{ /* result of wait_info call */ + int wait_return; /* -1=error,0=running,pid=stopped */ + int errNo; /* error code if error */ + int status; /* wait(2) status if stopped */ + stop_code reason; /* reason in more abstracted terms */ + int handle; /* handle of break if stopped on break, + or signal number or exit code */ + u_long PC; /* program counter if stopped */ + u_long SP; /* stack pointer if stopped */ + u_long FP; /* frame pointer if stopped */ + u_long thread; /* thread that stopped if applies (else -1) */ +}; + +% /* now ptrace() routine. This matches the Sun UNIX ptrace as well as +% some additions */ + +const PTRFLG_FORCE = 1; /* when set and process running, forces process + to stop, make the request, then start again. + This is used for breakpoints and the like */ +const PTRFLG_NON_OWNER = 2; /* do request even if not primary owner (will + notify all owners including caller if owns) */ +const PTRFLG_FREE = 4; /* free pid_list after KILL/DETACH */ + +const PTRDET_UNOWN = 0x100; /* data value in RPT_DETACH just disconnects + caller as an owner of process. */ + +struct ptrace_in +{ /* input args matches ptrace but for XDR */ + int pid; /* process to act on */ + ptrace_addr_data_in addr; /* mappings for addr and addr2 */ + u_int data; /* simple data arg of ptrace */ + u_int flags; /* mask of PTRFLG_xxx flags. */ +}; + +struct ptrace_out +{ /* return information from ptrace */ + ptrace_addr_data_out addr; /* return through addr/addr2 */ + int result; /* result of ptrace call (return value) */ + int errNo; /* error code if error */ +}; + + /* Data for GET_GLOBAL_SYMBOLS */ +struct one_symbol { /* Must match common/src/lib/ctx/ctx.h */ + string symbolName<>; + long symbolValue; +}; + +typedef one_symbol all_symbols<>; + +struct get_global_symbols_out { + all_symbols symbols; +}; + + /* Data for GET_TEXT_DATA */ +struct get_text_data_in { + int pid; /* process/actor id if non-zero */ + string actorName<16>; /* actor name for system mode */ +}; + +struct get_text_data_out { + int result; + int errNo; + u_long textStart; + u_long textSize; + u_long dataStart; + u_long dataSize; +}; + + /* Data for GET_SIGNAL_NAMES */ +struct one_signal { + u_int number; + string name<>; +}; + +typedef one_signal all_signals<>; + +struct get_signal_names_out { + all_signals signals; +}; + +% /* now define the actual calls we support */ + +program REMOTEDEB { + version REMOTEVERS { + + /* open a connection to server or router */ + open_out + OPEN_CONNEX(open_in) = 1; + + /* send a signal to a process */ + signal_out + SEND_SIGNAL(signal_in) = 2; + + /* all routines below require a connection first */ + + /* close the connection to the server */ + void + CLOSE_CONNEX(close_in) = 10; + + /* process ptrace request */ + ptrace_out + PTRACE(ptrace_in) = 11; + + /* poll for status of process */ + wait_out + WAIT_INFO(wait_in) = 13; + + get_signal_names_out + GET_SIGNAL_NAMES(void) = 17; + + } = 2; /* now version 2 */ +} = 0x20000fff; + +#ifdef RPC_HDR +%#define REMDEB_H +%#endif +#endif + +#ifdef RPC_SVC + +%const char* names [] = { +% "NULLPROC", "OPEN_CONNEX", "SEND_SIGNAL", "name3", +% "name4", "name5", "name6", "name7", +% "name8", "name9", "CLOSE_CONNEX", "PTRACE", +% "name12", "WAIT_INFO", "name14", "name15", +% "name16", "GET_SIGNAL_NAMES", "name18" +%}; +% + +%/*HEADER_END*/ +#endif diff --git a/c/src/lib/librdbg/servbkpt.c b/c/src/lib/librdbg/servbkpt.c new file mode 100644 index 0000000000..8d986751a2 --- /dev/null +++ b/c/src/lib/librdbg/servbkpt.c @@ -0,0 +1,587 @@ +/* + ********************************************************************** + * + * Component: RDB servers + * Module: servbkpt.c + * + * Synopsis: Management of breakpoints + * + ********************************************************************** + */ + +#include +#include +#include +#include + +/*----- Macros -----*/ + +#define BKPT0(plst) ((BASE_BREAK*)(plst)->break_list) +#define BKPT_INCR 5 /* how many bkpt slots alloc at a time */ + +#define BKPT_OVER(plst,idx,addr,size) \ + ((plst)->break_list[idx].ee_loc + BREAK_SIZE > (UINT32) (addr) \ + && (plst)->break_list[idx].ee_loc < (UINT32) (addr) + (size)) + +#define BKPT_SLOTS \ + (sizeof ((xdr_break*) 0)->thread_list / \ + sizeof ((xdr_break*) 0)->thread_list [0]) + + + /* + * BreakAlloc - alloc a breakpoint entry. + * + * This is a generic routine to insert an entry in the + * breakpoint list. It returns the number of entry just + * created. It returns -1 if failed. + */ + + static int +BreakAlloc (PID_LIST* plst, Boolean normal) +{ + int idx, len; + xdr_break* blst; + + if (!normal) { /* want 0 entry */ + if (plst->break_list) { + return(0); /* already there */ + } + idx = 1; /* force alloc below */ + } else { + for (idx = 1; idx < (int)plst->break_alloc; idx++) { + if (plst->break_list[idx].type == BRKT_NONE) { + /* got a free one */ + memset(&plst->break_list[idx], 0, sizeof(xdr_break)); + return(idx); /* found one */ + } + } + } + /* idx is the requested entry */ + + if (idx >= (int)plst->break_alloc) { /* need more space */ + len = plst->break_alloc + BKPT_INCR; + blst = (xdr_break*)Realloc(plst->break_list, len*sizeof(xdr_break)); + if (!blst) { + return(-1); /* failed, no space */ + } + plst->break_alloc = len; /* got more */ + plst->break_list = blst; + + /* Clear new space */ + memset(blst + len - BKPT_INCR, 0, BKPT_INCR * sizeof(xdr_break)); + idx = len - BKPT_INCR; /* next available */ + if (!idx) { + idx = 1; /* for normal cases */ + } + } + return(normal ? idx : 0); /* return it */ +} + + /* + * BreakSet - set a breakpoint in process + * + * Returns the number or -1/errno. + */ + +#ifdef DDEBUG +static const char* BreakTypes[] = { + "NONE", "INSTR", "READ", "WRITE", + "ACCESS", "EXEC", "OS_CALL", "OS_SWITCH", + "STEPEMUL" +}; + +#define BN_MAX (sizeof BreakTypes / sizeof BreakTypes[0]) +#define BREAK_NAME(t) ((unsigned) (t) < BN_MAX ? BreakTypes[t] : "???") +#endif + + int +BreakSet (PID_LIST* plst, int conn_idx, xdr_break* bkpt) +{ + int pid = plst->pid; + int type = bkpt->type; + void* addr = (void *) bkpt->ee_loc; + int idx; + int data; + + DPRINTF(("BreakSet: type %d (%s) at 0x%x th %d ee_type %d len %d " + "pass %d curr %d list %d %d %d %d\n", type, BREAK_NAME(type), + (int) addr, + bkpt->thread_spec, bkpt->ee_type, bkpt->length, bkpt->pass_count, + bkpt->curr_pass, bkpt->thread_list [0], bkpt->thread_list [1], + bkpt->thread_list [2], bkpt->thread_list [3])); + + idx = BreakAlloc(plst, True); /* get entry */ + if (idx < 0) { /* no memory */ + setErrno(ENOMEM); /* set for safety */ + return -1; /* return the error */ + } + + data = TgtPtrace(RPT_PEEKTEXT, pid, addr, 0, NULL); /* current */ + if (getErrno()) { + return -1; /* failed, return the error */ + } + if (IS_BREAK(data)) { /* There is already a break here */ + DPRINTF(("BreakSet: already have soft bkpt at %x\n", addr)); + if (type == BRKT_STEPEMUL) { + ++BKPT0 (plst)->pad1; + return 1; /* Any non-error value is OK */ + } + setErrno(EBUSY); + return -1; + } + + TgtPtrace(RPT_POKETEXT, pid, addr, SET_BREAK(data), NULL); + + if (getErrno()) { + return -1; + } + + plst->break_list[idx] = *bkpt; + plst->break_list[idx].ee_type = data; /* saved data */ + + /* Inform other owners */ + if (type != BRKT_STEPEMUL) { + TgtNotifyAll (plst - pid_list, BMSG_BREAK, 1 /*added*/, idx, + conn_idx, False); + } else { + ++BKPT0 (plst)->pad1; + } + /* Return the number */ + setErrno(0); /* Just in case */ + return idx; +} + + int +BreakSetAt (PID_LIST* plst, int conn_idx, unsigned long addr, break_type type) +{ + xdr_break xb; + + memset (&xb, 0, sizeof xb); + xb.type = type; + xb.ee_loc = addr; + return BreakSet (plst, conn_idx, &xb); +} + +/*----- Find a breakpoint by address -----*/ + + int +BreakGetIndex(PID_LIST* plst, void* addr) +{ + int idx; + int data = -1; + + if (!plst->break_alloc) { + setErrno(EFAULT); + return -1; + } + for (idx = 1; idx < (int)plst->break_alloc; idx++) { + if ((u_long) addr == plst->break_list [idx].ee_loc) { + data = idx; + break; + } + } + return data; +} + +/*----- Getting information about breakpoint -----*/ + + /* + * If data > 0, fill "bkpt" with information about breakpoint + * and return the number of the next one. + * If data == 0, return the count of breakpoints. + */ + + int +BreakGet (const PID_LIST* plst, int data, xdr_break* bkpt) +{ + int idx; + + if (!data) { /* just count them */ + for (idx = 1; idx < (int)plst->break_alloc; idx++) { + if (plst->break_list[idx].type != BRKT_NONE) { + data++; + } + } + return data; /* count */ + } + if ((unsigned) data >= plst->break_alloc) { + /* out of range */ + setErrno(EFAULT); /* closest match */ + return -1; + } + /* get it and say which is next */ + *bkpt = plst->break_list[data]; + for (idx = (int)data+1; idx < (int)plst->break_alloc; idx++) { + if (plst->break_list[idx].type != BRKT_NONE) { + return idx; + } + } + return 0; /* otherwise returns 0 for no more */ +} + +/*----- Clearing bkpts -----*/ + + /* + * BreakClear - clear one (if data != 0) or all breakpoints + * (if data == 0). Return the number of bkpts cleared. + * If (data == -1), remove step-emulation breakpoints. + */ + + int +BreakClear (PID_LIST* plst, int conn_idx, int data) +{ + int pid_idx = plst - pid_list; + int idx; + int cleared = 0; + int clearStepEmul = 0; + int terminated = PROC_TERMINATED (plst); + int stepEmulCount = 0; + + /* break handle in data */ + if (!plst->break_alloc) { /* there are no breaks */ + DPRINTF (("BreakClear: no bkpts defined.\n")); + setErrno(EFAULT); /* closest match */ + return -1; /* return error */ + } + if (!data) { /* clear all */ + idx = 1; + data = plst->break_alloc-1; + + /* Inform other owners */ + DPRINTF (("BreakClear: clearing all bkpts.\n")); + TgtNotifyAll (pid_idx, BMSG_BREAK, 0 /*clr*/, 0, conn_idx, False); + + } else if (data == -1) { /* clear all step-emul bkpts */ + DPRINTF(("BreakClear: removing %d step-emul bkpts\n", + BKPT0 (plst)->pad1)); + + stepEmulCount = BKPT0 (plst)->pad1; + BKPT0 (plst)->pad1 = 0; + + clearStepEmul = 1; + idx = 1; + data = plst->break_alloc-1; + } else if ((unsigned) data >= plst->break_alloc + || plst->break_list[data].type == BRKT_NONE) { + + /* out of range */ + DPRINTF (("BreakClear: invalid bkpt %d\n", data)); + setErrno(EFAULT); /* closest match */ + return -1; /* return error */ + } else { + idx = data; + /* Inform other owners */ + TgtNotifyAll (pid_idx, BMSG_BREAK, 0 /*clr*/, idx, conn_idx, False); + DPRINTF (("BreakClear: clearing bkpt %d\n", data)); + } + + for (; idx <= data; idx++) { /* clear each one */ + int type = plst->break_list[idx].type; + + if (clearStepEmul && type != BRKT_STEPEMUL) continue; + + if (type == BRKT_INSTR || (clearStepEmul && type == BRKT_STEPEMUL)) { + /* just patch back */ + char* addr = (char *)plst->break_list[idx].ee_loc; + int val; + + if (BKPT0 (plst)->clr_step && BKPT0 (plst)->last_break == idx) { + BKPT0 (plst)->clr_step = 0; /* not needed */ + } + /* Neighboring bytes can have breakpoints too... */ + if (! terminated) { + setErrno (0); + val = TgtPtrace(RPT_PEEKTEXT, plst->pid, addr, 0, NULL); + if (getErrno()) { + DPRINTF (("BreakClear: addr %x not readable!\n", addr)); + setErrno (0); /* Forget bkpt */ + } else { + assert (IS_BREAK (val)); + val = ORG_BREAK (val, (int)plst->break_list[idx].ee_type); + TgtPtrace(RPT_POKETEXT, plst->pid, addr, val, NULL); + if (getErrno()) { + DPRINTF (("BreakClear: addr %x not writable!\n", addr)); + setErrno (0); + } + } + } + ++cleared; /* indicate cleared */ + } + memset(&plst->break_list[idx], 0, sizeof(xdr_break)); + } + assert (!clearStepEmul || cleared <= stepEmulCount); + if (stepEmulCount && cleared == 0) { + DPRINTF (("BreakClear: all STEPEMUL bkpts were shared\n")); + return 1; + } + return cleared; +} + +/*----- Hiding of breakpoints -----*/ + + /* + * PatchBreak - patch original data from break into data buffer. + * + * Notes: + * - this routine patches the original data under a break into the data + * buffer from a ptrace read/peek. + */ + + static void +PatchBreak (char* buff, UINT32 bstart, int bsize, UINT32 dstart, char* dvalue) +{ + int size = BREAK_SIZE; /* default size */ + + /* Must deal with all sorts of unalignments + * (3 full overlaps, 3 unaligns) + */ + if (bsize < BREAK_SIZE) { + /* case where buffer is smaller than data */ + memcpy(buff, dvalue+(bstart-dstart), bsize); /* copy over */ + return; + } + /* buffer larger than data. + * we need to see where break fits in buffer and whether + * we have part of it off the end. We set bstart to be the + * buffer offset, dtart to be the break data offset, and + * size to be the amount to copy + */ + if (dstart < bstart) { + /* break before actual buffer */ + dstart = bstart-dstart; /* offset in data */ + size -= dstart; /* amount to copy */ + bstart = 0; /* offset in buffer */ + + } else if (dstart + size > bstart + bsize) { + /* off end */ + bstart += bsize; /* end of buffer */ + size -= (dstart + size) - bstart; + bstart = bsize - size; /* come back into buffer enough */ + dstart = 0; /* start of data */ + + } else { /* normal case */ + bstart = dstart - bstart; /* offset in buffer */ + dstart = 0; + } + memcpy(buff+bstart, dvalue+dstart, size); +} + + void +BreakHide (const PID_LIST* plst, void* addr, int data, void* addr2) +{ + int idx; + + if (!plst->break_list) /* no breaks exist, so skip this */ + return; + + /* if breakpoints, replace */ + + for (idx = 1; idx < (int)plst->break_alloc; idx++) { + int type = plst->break_list[idx].type; + + if (type != BRKT_INSTR && type != BRKT_STEPEMUL) { + continue; + } + /* break, see if overlaps */ + if (BKPT_OVER (plst, idx, addr, data)) { + + /* overlaps, patch in old value */ + PatchBreak((char *)addr2, (UINT32)addr, data, + plst->break_list[idx].ee_loc, + (char *)&plst->break_list[idx].ee_type); + } + } +} + +/*----- Checking of breakpoint overwrites -----*/ + + /* + * BreakOverwrite - check if memory write does not involve addresses + * having software breakpoints. + */ + + int +BreakOverwrite (const PID_LIST* plst, const char* addr, unsigned int size) +{ + int idx; + + if (!plst->break_list) { /* No breaks exist */ + return 0; + } + + for (idx = 1; idx < (int)plst->break_alloc; idx++) { + int type = plst->break_list[idx].type; + + /* Consider only breakpoints involving modified memory */ + if (type != BRKT_INSTR && type != BRKT_STEPEMUL) { + continue; + } + if (BKPT_OVER (plst, idx, addr, size)) { + return -1; /* overlaps */ + } + } + return 0; +} + +/*----- Execution support -----*/ + + /* + * BreakStepRange - Start stepping in a range. + * + * Range is saved in breakpoint 0. + */ + + int +BreakStepRange (PID_LIST* plst, void* addr, int len) +{ + if (!plst->break_list) { + /* get list */ + if (BreakAlloc (plst, False) == -1) { /* must not be any memory */ + setErrno(ENOMEM); /* to be safe */ + return -1; /* fails */ + } + } + BKPT0 (plst)->range_start = (UINT32)addr; + BKPT0 (plst)->range_end = (UINT32)addr+(len-1); + return 0; +} + + /* + * If the Program Counter is changed, consider that the + * current breakpoint has not been reached yet. + */ + + void +BreakPcChanged (PID_LIST* plst) +{ + if (plst->break_list) { + /* clear break stuff */ + BKPT0 (plst)->clr_step = False; + } +} + + /* + * BreakStepOff - prepare stepping off a breakpoint. + */ + + int +BreakStepOff (const PID_LIST* plst, void** paddr2) +{ + if (plst->break_list && BKPT0 (plst)->clr_step) { + + /* need clear then step off break */ + int last = BKPT0 (plst)->last_break; + + /* clear break, step, then do exec */ + + *paddr2 = (void*) plst->break_list[last].ee_type; + + /* Need to clr_step after TgtPtrace() when wait() returns */ + return 1; + } + return 0; +} + + /* + * BreakSteppedOff - check if just stepped off a breakpoint + * and re-insert it into the code. + */ + + void +BreakSteppedOff (PID_LIST* plst) +{ + if (plst->break_list && BKPT0 (plst)->clr_step) { + int idx = BKPT0 (plst)->last_break; + int data; + + BKPT0 (plst)->clr_step = 0; + + /* + * Re-insert the breakpoint. + */ + data = TgtPtrace (RPT_PEEKTEXT, plst->pid, + (char *)plst->break_list [idx].ee_loc, 0, NULL); + assert (! IS_BREAK (data)); + TgtPtrace (RPT_POKETEXT, plst->pid, + (char *)plst->break_list[idx].ee_loc, + (int) SET_BREAK (data), NULL); + } +} + + + /* + * Returns whether a thread matches a breakpoint. + */ + + static int +BreakThreadMatch (xdr_break* xb, int thread) +{ + int slot; + + if (thread < 0) return 1; /* Break existence check only */ + + if (xb->thread_list [0] == 0) return 1; /* Universal break */ + + for (slot = 0; slot < BKPT_SLOTS; ++slot) { + if (xb->thread_list [slot] == 0) return 0; /* End of list */ + if (xb->thread_list [slot] == thread) return 1; /* Match */ + } + return 0; /* No matches found */ +} + + +int +BreakAdjustPC (PID_LIST* plst) +{ + /* + * BREAK_ADJ is the value by which the Program Counter + * has to be decremented after a software breakpoint + * is hit. It must be defined and can be zero. + */ +#if BREAK_ADJ + /* subtract back if necessary */ + plst->regs.REG_PC -= BREAK_ADJ; /* now write back */ + TgtPtrace(RPT_SETREGS, plst->pid, (char *)&plst->regs, 0, NULL); +#else + (void) plst; +#endif + return 0; +} + + +/* + * Identify the current breakpoint. The process just stopped. + */ + + int +BreakIdentify (PID_LIST* plst, int adjust, int thread) +{ + int foreignBkpt = 0; + int bidx; + + for (bidx = 1; bidx < (int) plst->break_alloc; bidx++) { + int type = plst->break_list[bidx].type; + + if ((type == BRKT_INSTR || type == BRKT_STEPEMUL) + && plst->regs.REG_PC - BREAK_ADJ + == plst->break_list[bidx].ee_loc) { /* found matching */ + if (!BreakThreadMatch (&plst->break_list[bidx], thread)) { + if (foreignBkpt == 0) { + foreignBkpt = bidx; + } + continue; + } + if (adjust) { + BreakAdjustPC (plst); + } + return bidx; + } + } + if (foreignBkpt) { + if (adjust) { + BreakAdjustPC (plst); + } + return -foreignBkpt; + } + return 0; +} diff --git a/c/src/lib/librdbg/servcon.c b/c/src/lib/librdbg/servcon.c new file mode 100644 index 0000000000..a26bfd2c7b --- /dev/null +++ b/c/src/lib/librdbg/servcon.c @@ -0,0 +1,136 @@ +/* + ************************************************************************** + * + * Component: RDBG + * Module: servcon.c + * + * Synopsis: Management of RPC client connections. + * + ************************************************************************** + */ + +#include +#include +#include + + /* + * ConnCreate - create a new connection entry for a client. + * + * This function finds an empty entry in the connection array + * or makes space. It fills in the fields that are passed to it. + * It does not do any validation on net addresses nor does it + * start a validation cycle on other clients. This is done by + * the caller. + */ + + int +ConnCreate (struct svc_req* rqstp, open_in* in) +{ + NET_OPAQUE sender; + int idx; + CONN_LIST* clst; + + setErrno (0); + + /* Convert to valid Net address */ + if (! TspTranslateRpcAddr (rqstp, &sender)) { + DPRINTF (("ConnCreate: TspTranslateRpcAddr failed\n")); + return -1; + } + if (! TspValidateAddr ((NET_OPAQUE*) in->back_port, &sender)) { + DPRINTF (("ConnCreate: TspValidateAddr failed\n")); + return -1; /* errno now setup with error */ + } + + /* look for an empty connection entry */ + for (idx = 0; idx < conn_list_cnt; idx++) { + if (!conn_list[idx].in_use) + break; /* an empty one found */ + } + + if (idx >= conn_list_cnt) { /* no empties, create space */ + CONN_LIST* tmp_conn_list = conn_list; + + conn_list_cnt += CONN_LIST_INC; + if (conn_list) { + conn_list = (CONN_LIST *) Realloc (conn_list, /* extend */ + conn_list_cnt * sizeof (CONN_LIST)); + } else { + conn_list = (CONN_LIST *)Malloc(conn_list_cnt * sizeof(CONN_LIST)); + } + + if (!conn_list) { /* unable to get space */ + if ((conn_list_cnt -= CONN_LIST_INC)) { + /* was realloc, restore space */ + conn_list = tmp_conn_list; + } + return -1; /* errno set by failed alloc */ + } + /* clear newly created memory */ + memset (conn_list + idx, 0, CONN_LIST_INC * sizeof (CONN_LIST)); + } else { /* clear new entry */ + memset (conn_list + idx, 0, sizeof (CONN_LIST)); + } + clst = conn_list + idx; + + clst->in_use = True; /* now in use */ + clst->sender = sender; + memcpy (&clst->back_port, &in->back_port, sizeof (NET_OPAQUE)); + memcpy (&clst->route, &in->destination, sizeof (NET_OPAQUE)); + clst->debug_type = (UCHAR) in->debug_type; + clst->flags = in->flags; + strncpy (clst->user_name, in->user_name, NAMEMAX-1); + clst->user_name [NAMEMAX-1] = 0; + + return idx; +} + + /* + * ConnDelete - remove connection entry when shutdown. + * + */ + + void +ConnDelete (int conn, struct svc_req* rqstp, close_control control) +{ + CONN_LIST* clst = conn_list + conn; + int idx; + Boolean prim; + + if (! clst->in_use) return; /* not active */ + + for (idx = 0; idx < pid_list_cnt; idx++) { + PID_LIST* plst = pid_list + idx; + + if (! PIDMAP_TEST (conn, idx)) continue; + + /* found a controlled pid */ + prim = (plst->primary_conn == conn) ? True : False; + TgtDetachCon (conn, idx, True); + + /* if still running or alive, we use close control on it */ + if (! plst->pid) + continue; /* entry gone */ + + if (prim && control == CLOSE_KILL) { + /* kill off process */ + TgtKillAndDelete (plst, rqstp, True); + } else if (! plst->owners) { + /* no owners left */ + if (control == CLOSE_DETACH) { + TgtKillAndDelete (plst, rqstp, False); + } + if (control == CLOSE_DETACH || PROC_TERMINATED (plst)) { + TgtDelete (plst, conn, (control==CLOSE_DETACH) ? + BMSG_DETACH : 0); + } + } + } + if (clst->list) { + Free (clst->list); /* free allocated memory */ + } + DPRINTF (("ConnDelete: Connection closed for port %u\n", + HL_W(*((UINT16*) &clst->back_port.c[2])))); + + clst->in_use = False; /* free it back */ +} diff --git a/c/src/lib/librdbg/servrpc.c b/c/src/lib/librdbg/servrpc.c new file mode 100644 index 0000000000..f62a2ecbb8 --- /dev/null +++ b/c/src/lib/librdbg/servrpc.c @@ -0,0 +1,720 @@ +/* + ********************************************************************** + * + * Component: RDBG + * Module: servrpc.c + * + * Synopsis: support routines for RPC dispatch for remote debug server. + * Main server dispatch routines from RPC to support remote debug. + * + ********************************************************************** + */ + +#include +#include +#include +#include +#include + +/************************************************************************/ + +/* ----------------------------------------------------------------------- + open_connex_2_svc - setup a new connection from a client. + + Notes: + - this function creates a new connection to a client. It allocates + an entry in the connection structure and fills in the information + sent and implied by the message. + - a client connection entry is needed for all further messages to work + properly. + ----------------------------------------------------------------------- */ + +open_out* RPCGENSRVNAME(open_connex_2_svc) (open_in *in, struct svc_req *rqstp) +{ + static open_out out; /* output response. This could be heap local */ + int idx; + static int one_time = 0; /* we do one-time setup on back port */ + + /* need to support in->debug_type, in->flags, and in->destination!!! */ + + if (!one_time) + { /* only setup one backport socket */ + /* now setup signals and the like for handling process changes */ + setErrno(0); + TspInit(rqstp->rq_xprt->xp_sock); /* init transport system */ + if (getErrno()) + { /* failed in setup */ + out.port = (u_long)-1; + out.fp = getErrno(); /* error causing to fail */ + return(&out); /* fail */ + } + one_time = True; /* disable doing this again */ + } + + DPRINTF(("open_connex_2_svc: Opening connection from '%s'\n", + in->user_name)); + + /* now setup a validation of all other connections */ + for (idx = 0; idx < conn_list_cnt; idx++) + if (conn_list[idx].in_use) + { /* setup retry timer */ + DPRINTF(("open_connex_2_svc: Still have connection %d with port %d\n", + idx, HL_W(*((UINT16*)&conn_list[idx].back_port.c[2])))); + } + + idx = ConnCreate(rqstp, in); /* setup the connection */ + out.port = idx; /* connection number */ + if (idx == -1) + out.fp = getErrno(); /* error causing to fail */ + else + out.fp = TARGET_PROC_TYPE; + + out.server_vers = SERVER_VERS; + return(&out); +} + +/* ----------------------------------------------------------------------- + send_signal_2_svc - send a kill/signal to the specified process. + + Notes: + - this function sends a signal to the process specified. This process + does not have to be under debug nor attached by this server. The kill + may be refused on other grounds though. + - kill(pid, 0) can be used to validate the process still exists if + needed. + ----------------------------------------------------------------------- */ + +signal_out *RPCGENSRVNAME(send_signal_2_svc) (signal_in *in, struct svc_req *rqstp) +{ + static signal_out out; /* return code from kill */ + + /* we do not care if connected */ + setErrno(0); + out.kill_return = 0; + out.errNo = 0; + TotalReboot = 1; + return(&out); +} + +/* ----------------------------------------------------------------------- + close_connex_2_svc - close a connection from a client. + ----------------------------------------------------------------------- */ + +void *RPCGENSRVNAME(close_connex_2_svc) (close_in *in, struct svc_req *rqstp) +{ + int conn_idx = TspConnGetIndex(rqstp); + + if (conn_idx != -1) /* found it, clear out */ + ConnDelete(conn_idx, rqstp, in->control); + + return (void*) ""; /* need to return something */ +} + +/* ----------------------------------------------------------------------- + ptrace_2_svc - control process under debug. + ----------------------------------------------------------------------- */ + +#define REG_COUNT \ + (sizeof (xdr_regs) / sizeof (int)) + +ptrace_out *RPCGENSRVNAME(ptrace_2_svc) (ptrace_in *in, struct svc_req *rqstp) +{ + int conn_idx = rqstp ? TspConnGetIndex(rqstp) : -1; + static ptrace_out out; /* outut response (error or data) */ + void *addr, *addr2; /* used for actual ptrace call */ + unsigned int data; + int req, pid, ret, pid_idx, idx; + static union + { /* local buffer for returned data */ + Objects_Id t_list[UTHREAD_MAX]; /* thread_list return */ + char t_name[THREADNAMEMAX]; /* thread name return */ + } local_buff; /* for return handling of strings and the like */ + PID_LIST *plst = NULL; /* current pid_list entry */ + + DPRINTF (("ptrace_2_svc: entered (%s (%d), %d, XXXX, %d, XXXX)\n", + PtraceName (in->addr.req), in->addr.req, in->pid, + in->data)); + + out.addr.ptrace_addr_data_out_u.addr = 0; + + /* validate the connection */ + if (conn_idx == -1 && rqstp != NULL) + { /* no connection, error */ + DPRINTF(("ptrace_2_svc: msg from unknown debugger!\n")); + out.result = -1; + out.errNo = ECHILD; /* closest error */ + out.addr.req = 0; /* to avoid copies that should not occur */ + return(&out); + } + /* Consider that the last back-message is acknowledged */ + if (conn_idx >= 0 && conn_list[conn_idx].retry) { + TspMessageReceive(conn_idx, in->pid); + } + + req = in->addr.req; + out.addr.req = req; /* needed for RPC */ + pid = in->pid; + addr = addr2 = NULL; + data = in->data; + setErrno(0); /* assume works */ + out.result = 0; /* assume worked ok */ + out.errNo = 0; + + /* lookup process to make sure we have under control */ + pid_idx = FindPidEntry (in->pid); + if (pid_idx >= 0) /* found it */ + { + plst = &pid_list[pid_idx]; + if (conn_idx < 0) + conn_idx = plst->primary_conn; + } + + /* now we handle the special case of ATTACH to a pid we already control */ + if (req == RPT_ATTACH) + { /* look it up first */ + if (plst) + { /* we have controlled , so return ok+show conn */ + ret = 2; /* normally secondary connection */ + if (! PIDMAP_TEST (conn_idx, pid_idx)) + { /* mark as an owner if not already */ + plst->owners++; + PIDMAP_SET (conn_idx, pid_idx); /* mask in */ + } + else if (plst->primary_conn != NO_PRIMARY) + { /* regrab makes primary */ + /* Only if not primary already */ + if (plst->primary_conn != conn_idx) { + TspSendWaitChange(plst->primary_conn, BMSG_NOT_PRIM, + conn_idx, plst->pid, 0, False); /* tell old owner */ + } + plst->primary_conn = NO_PRIMARY; + } + + if (plst->primary_conn == NO_PRIMARY) + { /* none now, so take over */ + plst->primary_conn = conn_idx; /* new primary */ + ret = 1; /* primary */ + } + out.result = ret; /* primary or secondary owner */ + return(&out); + } + /* else attach process using target code */ + setErrno(ESRCH); /* assume the worst */ + if (!TgtAttach(conn_idx, pid)) + { /* failed */ + out.errNo = getErrno(); + out.result = 0; + } + return(&out); + } + else if (req == RPT_DETACH) + { /* see which kind of detach */ + if (data == PTRDET_UNOWN) + { /* only want to disconnect from */ + TgtDetachCon(conn_idx, pid_idx, True); /* remove from control */ + return(&out); /* done */ + } + } + else if (plst && (req == RPT_GETNAME || req == RPT_GETBREAK)) + { + /* do nothing */ + } + + else if (plst && req == RPT_CLRBREAK) { + /* To be able to remove breakpoints from a "running" system */ + DPRINTF (("ptrace_2_svc: allowing RPT_CLRBREAK %d\n", data)); + /* do nothing */ + } + + else if (plst && plst->running) + { /* error, process is running and not detach */ + out.result = -1; + out.errNo = ETXTBSY; /* closest error */ + DPRINTF (("ptrace_2_svc: failed, still running.\n")); + return(&out); + } + if (plst == NULL) { + out.result = -1; + out.errNo = ESRCH; + DPRINTF (("ptrace_2_svc: No such process.\n")); + return (&out); + } + + /* now make sure secondary owner is not trying to modify */ + if (!(in->flags & PTRFLG_NON_OWNER)) /* if not overriden */ + if (conn_idx != plst->primary_conn + && ( (req >= RPT_POKETEXT && req <= RPT_SINGLESTEP) + || (req >= RPT_SETREGS && req <= RPT_SETFPAREGS && (req & 1)) + || (req >= RPT_SYSCALL && req <= RPT_DUMPCORE) + || (req >= RPT_SETTARGETTHREAD && req <= RPT_THREADRESUME) + || (req >= RPT_SETTHREADNAME && req <= RPT_SETTHREADREGS) + || (req >= RPT_STEPRANGE && req <= RPT_CLRBREAK) + || (req == RPT_STOP) + || (req >= RPT_PSETREGS && req <= RPT_PSETTHREADREGS))) + { /* not owner */ + out.result = -1; + out.errNo = EPERM; /* cannot alter as not primary */ + DPRINTF (("ptrace_2_svc: refused, not owner, flags %d conn_idx %d primary_conn %d\n", in->flags, conn_idx, + plst->primary_conn)); + return(&out); + } + + addr = (void *)in->addr.ptrace_addr_data_in_u.address; /* default */ + /* now setup normal ptrace request by unpacking. May execute here. */ + switch (req) + { /* handle unpacking or setup for real call */ + /* first the ones where addr points to input data */ + case RPT_SETREGS: + case RPT_SETTHREADREGS: + addr = (void *)&in->addr.ptrace_addr_data_in_u.regs; /* reg list */ + break; + + case RPT_PSETREGS: + case RPT_PSETTHREADREGS: + if (in->addr.ptrace_addr_data_in_u.pregs.pregs_len != REG_COUNT) { + DPRINTF(("ptrace_2_svc: pid %d got %d expected %d\n", pid, + in->addr.ptrace_addr_data_in_u.pregs.pregs_len, REG_COUNT)); + setErrno(EINVAL); + break; + } + req = req == RPT_PSETREGS ? RPT_SETREGS : RPT_SETTHREADREGS; + addr = (void *) in->addr.ptrace_addr_data_in_u.pregs.pregs_val; + break; + + case RPT_SETTHREADNAME: + addr = (void *)in->addr.ptrace_addr_data_in_u.name; + break; + case RPT_WRITETEXT: + case RPT_WRITEDATA: + if ((int) data < 0) { + setErrno(EINVAL); + break; + } + addr = (void *)in->addr.ptrace_addr_data_in_u.mem.addr; /* targ addr */ + addr2 = (void *)in->addr.ptrace_addr_data_in_u.mem.data; /* buff */ + + /* Forbid writing over breakpoints */ + if (BreakOverwrite (plst, addr, data)) { + setErrno(EBUSY); + } + break; + + case RPT_POKETEXT: + case RPT_POKEDATA: + /* Forbid writing over breakpoints */ + if (BreakOverwrite (plst, addr, sizeof (int))) { + setErrno(EBUSY); + } + break; + + /* now ones where we handle locally */ + case RPT_GETTARGETTHREAD: + out.result = plst->thread; + req = 0; /* force exit */ + break; + + case RPT_PGETREGS: /* return from our buffer */ + out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT; + out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (u_int*) &plst->regs; + req = 0; /* force exit */ + break; + + case RPT_GETREGS: + /* return directly from our buffer */ + /* this buffer is refreshed when changing target thread */ + out.addr.ptrace_addr_data_out_u.regs = plst->regs; + req = 0; /* force exit */ + break; + + case RPT_SETBREAK: + idx = BreakSet (plst, conn_idx, &in->addr.ptrace_addr_data_in_u.breakp); + if (idx < 0) break; + req = 0; /* force exit */ + out.result = idx; /* return break index (>0) */ + break; + + case RPT_CLRBREAK: + if (conn_list[conn_idx].flags & DEBUGGER_IS_GDB) { + data = BreakGetIndex (plst, addr); + } + out.result = BreakClear (plst, conn_idx, data); + /* if errored, errno will still be set */ + req = 0; + break; + + case RPT_GETBREAK: + /* data=handle, addr=in_buffer, returns next break. Data=0, returns cnt */ + out.result = BreakGet (plst, data, &out.addr. + ptrace_addr_data_out_u.breakp); + req = 0; /* handle locally */ + break; + + case RPT_GETNAME: /* get the name of the process */ + if (!plst->name) + out.addr.ptrace_addr_data_out_u.mem.dataNb = 0; + else + { + int maxLen = sizeof out.addr.ptrace_addr_data_out_u.mem.data - 1; + data = strlen(plst->name); + if (data > maxLen) + data = maxLen; + out.addr.ptrace_addr_data_out_u.mem.dataNb = data+1; + memcpy(out.addr.ptrace_addr_data_out_u.mem.data, plst->name, data+1); + out.addr.ptrace_addr_data_out_u.mem.data [maxLen] = '\0'; + } + req = 0; + break; + + case RPT_CONTTO: + if (BreakSetAt (plst, conn_idx, (u_long) addr, BRKT_STEPEMUL) < 0) + { + DPRINTF(("ptrace_2_svc: BreakSet failed at %x", addr)); + break; + } + req = RPT_CONT; + /* data can contain a signal number, addr2 is unused */ + goto case_RPT_CONT; + + case RPT_STEPRANGE: + /* convert to step */ + if (!data) + data = 1; /* should we give an error?? */ + BreakStepRange (plst, addr, data); + if (getErrno()) break; + + req = RPT_SINGLESTEP; /* do by stepping */ + addr = (void*) 1; /* start from current PC */ + data = -2; /* want non-atomic stepping */ + /* fall through to other exec cases */ + + case RPT_CONT: + case_RPT_CONT: + case RPT_SINGLESTEP: + + if (BreakStepOff (plst, &addr2)) + { /* need clear then step off break */ + /* clear break, step, then do exec */ + if (addr == (void*) 1) + addr = (void*) plst->regs.REG_PC;/* need for patch */ + + /* data is always 0, so atomic single-step */ + } else if (req == RPT_SINGLESTEP) { + data = -2; /* want non-atomic stepping */ + } + break; + + /* now ones where addr points to an output area */ + case RPT_PGETTHREADREGS: + addr = (void*) out.addr.ptrace_addr_data_out_u.mem.data; + if (sizeof out.addr.ptrace_addr_data_out_u.mem.data < + REG_COUNT * sizeof(int)) { + setErrno(EINVAL); + break; + } + if (data == plst->thread) { + out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT; + out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (u_int*) &plst->regs; + req = 0; /* force exit */ + break; + } + req = RPT_GETTHREADREGS; + break; + + case RPT_GETTHREADREGS: + addr = (void*) &out.addr.ptrace_addr_data_out_u.regs; + break; + case RPT_GETTHREADNAME: + out.addr.ptrace_addr_data_out_u.name = local_buff.t_name; + addr = (void*) out.addr.ptrace_addr_data_out_u.name; + break; + case RPT_THREADLIST: + out.addr.ptrace_addr_data_out_u.threads.threads =(ptThreadList) local_buff.t_list; + addr = (void*) out.addr.ptrace_addr_data_out_u.threads.threads; + break; + case RPT_READTEXT: + case RPT_READDATA: + if ((int) data < 0) { + setErrno(EINVAL); + break; + } + addr = (void *)in->addr.ptrace_addr_data_in_u.address; + addr2 = (void *)out.addr.ptrace_addr_data_out_u.mem.data; + out.addr.ptrace_addr_data_out_u.mem.dataNb = data; + break; + case RPT_DETACH: + /* Do not allow detaching if breakpoints still there */ + if (BreakGet (plst, 0, NULL)) + { /* some bkpts still set */ + setErrno(EINVAL); /* cannot detach safely */ + break; + } + /* fall through */ + case RPT_KILL: + /* in the event they are trying to detach or kill a terminated process, + we just delete the entry. */ + if (PROC_TERMINATED (plst)) + { + TgtDelete(plst, -1, BMSG_KILLED); /* just blow off */ + req = 0; /* now exit */ + } + break; + } + + if (getErrno()) + { /* failed in code above */ + out.result = -1; + out.errNo = getErrno(); + DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); + return(&out); + } + else if (!req) + { /* bail out now */ + DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); + return(&out); + } + + /* OK, make the call */ + out.result = TgtPtrace(req, pid, addr, data, addr2); + out.errNo = getErrno(); + + /* if no error, cleanup afterwards */ + if (getErrno()) + { + /* Remove step-emul breakpoints if any */ + if (req == RPT_SINGLESTEP || req == RPT_CONT) { + BreakClear (plst, -1, -1); + } + DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); + return(&out); /* return error */ + } + + switch (in->addr.req) + { /* handle some special calls that affect state */ + case RPT_CONT: + case RPT_STEPRANGE: + /* change to running */ + if (in->addr.req == RPT_STEPRANGE) + plst->last_start = LAST_RANGE; /* so range steps */ + else if (addr2) + plst->last_start = LAST_STEPOFF; /* now continue after wait */ + else + plst->last_start = LAST_CONT; + plst->running = 1; /* mark as running */ + if (!rqstp) /* Called internally to restart bkpt, no msg to anybody */ + break; + TgtNotifyAll(pid_idx, BMSG_WAIT, 0, 0, (in->flags & PTRFLG_NON_OWNER) + ? -1 : conn_idx, True); + break; + case RPT_SINGLESTEP: + /* mark as step */ + plst->last_start = LAST_STEP; /* so we know how started */ + plst->running = 1; /* mark as running (wait should catch fast) */ + break; + case RPT_DETACH: /* mark as disconnected */ + case RPT_KILL: /* mark as killed */ + if (in->flags & PTRFLG_FREE) /* notify and delete entry */ + TgtDelete(plst, -1, (in->addr.req==RPT_KILL) ? BMSG_KILLED : BMSG_DETACH); + else + { /* notify and mark */ + plst->last_start = (in->addr.req==RPT_KILL) ? + LAST_KILLED : LAST_DETACHED; + plst->state = -1; + plst->running = False; + TgtNotifyAll(pid_idx, (in->addr.req==RPT_KILL) ? + BMSG_KILLED : BMSG_DETACH, 0, 0, -1, True); + } + break; + case RPT_SETTHREADREGS: + case RPT_PSETTHREADREGS: + if (data != plst->thread) + break; + DPRINTF(("ptrace_2_svc: pid %d target thread regs changed!\n", pid)); + + case RPT_SETREGS: + case RPT_PSETREGS: + /* change our buffer as well */ + if (plst->regs.REG_PC != ((xdr_regs*)addr)->REG_PC) + BreakPcChanged (plst); + plst->regs = *(xdr_regs*) addr; /* copy in */ + break; + + /* case RPT_PGETREGS has been handled locally above */ + case RPT_PGETTHREADREGS: + /* We need to update pointer so that XDR works on return */ + out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT; + out.addr.ptrace_addr_data_out_u.pregs.pregs_val = + (void*) out.addr.ptrace_addr_data_out_u.mem.data; + break; + + case RPT_PEEKTEXT: + case RPT_PEEKDATA: + case RPT_READDATA: + case RPT_READTEXT: + if (req < RPT_READDATA) + { /* peek */ + /* addr is start */ + data = sizeof(int); + addr2 = &out.result; /* data buffer */ + /* Like read: addr is start, data is length, addr2 is buffer */ + } + BreakHide (plst, addr, data, addr2); + break; + + case RPT_SETTARGETTHREAD: + DPRINTF(("ptrace_2_svc: pid %d new target thread %d\n", pid, data)); + TgtPtrace (RPT_GETREGS, pid, (char*) &plst->regs, 0, NULL); + plst->thread = data; + if (plst->break_list) { /* Forget we had to step off breakpoint */ + BASE_BREAK* base = (BASE_BREAK*) plst->break_list; + DPRINTF(("ptrace_2_svc: clr_step %d last_break %d\n", base->clr_step, + base->last_break)); + base->clr_step = 0; /* Not stopped on break */ + base->last_break = 0; + } + break; + + case RPT_THREADLIST: + out.addr.ptrace_addr_data_out_u.threads.nbThread = out.result; + break; + + default: + break; + } /* end switch */ + DPRINTF(("ptrace_2_svc 2: result %d errNo %d\n", out.result, out.errNo)); + return(&out); +} + +/* ----------------------------------------------------------------------- + wait_info_2_svc - non-blocking wait request to check status. + ----------------------------------------------------------------------- */ + +wait_out *RPCGENSRVNAME(wait_info_2_svc) (in, rqstp) + wait_in *in; + struct svc_req *rqstp; /* server info */ +{ + int conn_idx = TspConnGetIndex(rqstp); + static wait_out out; /* output of pid and status */ + int idx; + PID_LIST *plst; + + memset(&out, 0, sizeof(out)); /* zero for safety */ + out.reason = STOP_ERROR; /* assume the worst */ + + if (conn_idx == -1) + { /* no connection, error */ + DPRINTF(("wait_info_2_svc: msg from unknown debugger!\n")); + out.wait_return = -1; + out.errNo = ECHILD; /* closest error */ + return(&out); + } + else + { /* see if confirming message received */ + if (conn_list[conn_idx].retry) + TspMessageReceive(conn_idx, in->pid); + } + + if (!in->pid) + { /* warm test verify only */ + /* this call (pid==0) is made to confirm that that connection is still + active. */ + /* we let it fall through as an error since any use other than connection + reset would be an error (there is no pid0). */ + } + else + { /* normal request */ + idx = FindPidEntry (in->pid); + if (idx >= 0) + { /* found process they requested on */ + plst = &pid_list[idx]; + out.wait_return = plst->running ? 0 : in->pid; + /* return: 0 is running, pid is stopped/term */ + out.errNo = 0; + out.status = plst->state; /* last stopped reason if stopped */ + out.thread = plst->thread;/* current thread (or -1 if none) from stop */ + if (!out.wait_return) + out.reason = STOP_NONE; /* running, no action */ + else if (STS_SIGNALLED (out.status)) + { /* stopped on signal */ + out.handle = STS_GETSIG (out.status); /* signal number */ + if (out.handle == SIGTRAP) + if (plst->is_step) + { /* single step with hitting a break */ + out.reason = STOP_STEP; + out.handle = 0; /* no information */ + } + else + { /* stopped on break */ + out.reason = STOP_BREAK; + if (plst->break_list) + out.handle = ((BASE_BREAK*)plst->break_list)->last_break; + else + out.handle = 0; /* no break */ + } + else + out.reason = STOP_SIGNAL; + out.PC = plst->regs.REG_PC; /* copy standard regs */ + out.SP = plst->regs.REG_SP; + out.FP = plst->regs.REG_FP; + } + else + { /* terminated, so lower use count */ + if (plst->last_start == LAST_KILLED) + out.reason = STOP_KILLED; + else if (plst->last_start == LAST_DETACHED) + out.reason = STOP_DETACHED; + else if (plst->last_start == LAST_START) + { /* failed in exec */ + out.reason = STOP_SPAWN_FAILED; + out.handle = STS_GETCODE (out.status); /* errno reason */ + } + else if (STS_TERMONSIG (out.status)) + { /* terminated on signal */ + out.reason = STOP_TERM_SIG; + /* mask off the core-dumped bit 7 */ + out.handle = (int)(unsigned)(u_char) STS_TERMGETSIG (out.status); + } + else + { /* exit(2)ed */ + out.reason = STOP_TERM_EXIT; + out.handle = STS_GETCODE (out.status); /* code */ + } + } + DPRINTF(("wait_info_2_svc: pid %d return %d status %x errNo %d" + " reason %d handle %d pc %x sp %x fp %x thread %d\n", + in->pid, out.wait_return, out.status, out.errNo, out.reason, + out.handle, out.PC, out.SP, out.FP, out.thread)); + return(&out); + } + } + /* if not found in list, we return error: no such process */ + out.wait_return = -1; + out.errNo = ESRCH; /* no process */ + out.status = 0; + return(&out); +} + +/* ----------------------------------------------------------------------- + get_signal_names_2_svc - return names for signals + ----------------------------------------------------------------------- */ + +static one_signal SignalNames[] = { + {SIGILL, "SIGILL/EVT_ILL"}, + {SIGTRAP, "SIGTRAP/EVT_BKPT"}, + {SIGFPE, "SIGFPE/EVT_FPE"}, + {SIGKILL, "SIGKILL/EVT_AKILL"}, + {SIGSEGV, "SIGSEGV/EVT_SEGV"}, + {17, "SIGSTOP"}, + {23, "SIGSTOP"} +}; + +get_signal_names_out* RPCGENSRVNAME(get_signal_names_2_svc) (in, rqstp) + void* in; + struct svc_req *rqstp; /* server info */ +{ + static get_signal_names_out out; + + out.signals.all_signals_len = sizeof SignalNames / sizeof SignalNames[0]; + out.signals.all_signals_val = SignalNames; + + return(&out); +} diff --git a/c/src/lib/librdbg/servtgt.c b/c/src/lib/librdbg/servtgt.c new file mode 100644 index 0000000000..7a8471e3e2 --- /dev/null +++ b/c/src/lib/librdbg/servtgt.c @@ -0,0 +1,550 @@ +/* + ************************************************************************** + * + * Component: RDB servers + * Module: servtgt.c + * + ************************************************************************** + */ + + +#include +#include +#include +#include +#include +#include + +#ifdef DDEBUG +#define Ptrace TgtDbgPtrace +#else +#define Ptrace TgtRealPtrace +#endif + +/* ---------------------------------------------------------------- + TgtBreakRestoreOrig - Restore original instruction at "addr" + just before single-stepping it. + ---------------------------------------------------------------- */ + +int TgtBreakRestoreOrig (int pid, void *addr, void *addr2) + /* Process identifier */ + /* Breakpoint address */ + /* Original instruction or bkpt number */ +{ + int ret; + int l; + + l = (long)Ptrace(RPT_PEEKTEXT, pid, addr, 0, NULL); /* assume ok */ + ret = ORG_BREAK (l, (UINT32) addr2); /* reconstruct old instr */ + ret = Ptrace(RPT_POKETEXT, pid, addr, ret, NULL); /* poke back old */ + return ret; +} + +/* ----------------------------------------------------------------------- + TgtBreakCancelStep - Restore the breakpoint at "addr" if the single-step + has failed at the ptrace level. + ----------------------------------------------------------------------- */ + +#define BKPT0(plst) ((BASE_BREAK*)(plst)->break_list) + +void TgtBreakCancelStep (PID_LIST* plst) +{ + assert (plst->break_list); + assert (BKPT0 (plst)->clr_step); + + if (plst->break_list && BKPT0 (plst)->clr_step) { + int idx = BKPT0 (plst)->last_break; + int data; + + data = Ptrace (RPT_PEEKTEXT, plst->pid, + (char *)plst->break_list [idx].ee_loc, 0, NULL); + assert (! IS_BREAK (data)); + Ptrace (RPT_POKETEXT, plst->pid, + (char *)plst->break_list[idx].ee_loc, + (int) SET_BREAK (data), NULL); + } +} + +/* ----------------------------------------------------------------------- + TgtCreateNew - add a new process into the process management lists. + ----------------------------------------------------------------------- */ + + void +TgtCreateNew(PID pid, int conn, INT32 child, char *name, Boolean spawn) +{ + int idx; + + for (idx = 0; idx < pid_list_cnt; idx++) + if (!pid_list[idx].pid) + break; /* find empty */ + + if (idx >= pid_list_cnt) + { /* no empties, add more */ + PID_LIST *tmp_pid_list = pid_list; + + pid_list_cnt += PID_LIST_INC; + pid_list = (PID_LIST*) Realloc(pid_list, /* get new or extend */ + pid_list_cnt * sizeof(PID_LIST)); + if (!pid_list) + { /* out of memory */ + pid_list_cnt -= PID_LIST_INC; + if (pid_list_cnt) + { /* realloc failed - malloc again */ + pid_list = tmp_pid_list; + /* above relies on old pointer being valid after failed realloc */ + } + return; /* failed */ + } + /* now clear newly added space */ + memset(pid_list+pid_list_cnt-PID_LIST_INC, 0, + PID_LIST_INC * sizeof(PID_LIST)); + idx = pid_list_cnt - PID_LIST_INC; + } + else /* clear entry we found */ + memset(&pid_list[idx], 0, sizeof(PID_LIST)); + + /* now fill in empty entry */ + pid_list[idx].pid = pid; + pid_list[idx].running = 1; /* we have not called wait yet */ + pid_list[idx].primary_conn = (UCHAR)conn; /* primary owner */ + if (conn != -1) + { /* found caller */ + pid_list[idx].owners = 1; + PIDMAP_SET (conn, idx); /* mask in */ + } + pid_list[idx].thread = (UINT32)-1; /* no thread for now */ + pid_list[idx].last_start = LAST_START; /* handle MiX bug */ + + pid_list[idx].name = name ? (char *)StrDup(name) : (char *)NULL; + +} + +/* ----------------------------------------------------------------------- + TgtNotifyWaitChange - send event to clients indicating child changed state. + ----------------------------------------------------------------------- */ + + void +TgtNotifyWaitChange( PID pid, int status, Boolean exclude) +{ + int conn, idx; + + idx = FindPidEntry (pid); /* locate the pid that changed */ + if (idx < 0) + { + DPRINTF(("TgtNotifyWaitChange: pid %d not in our list\n", + (int) pid)); + return; /* not in our list */ + } + pid_list[idx].running = 0; /* not running */ + pid_list[idx].state = status; /* save status of stop/term */ + if (!pid_list[idx].owners && !STS_SIGNALLED(status)) + TgtDelete(&pid_list[idx], -1, 0); /* terminated and no owners */ + else + { /* normal cases */ + for (conn = 0; conn < conn_list_cnt; conn++) + { /* now find all interested clients */ + if (!conn_list[conn].in_use /* free entry */ + || ! PIDMAP_TEST (conn, idx)) + continue; /* not using this pid */ + if (conn == exclude) + continue; /* do not do this one */ + TspSendWaitChange(conn, BMSG_WAIT, 1, pid, 0, False);/* notify of change */ + } + } +} + +/* ----------------------------------------------------------------------- + TgtNotifyAll - send a message to all clients interested in process. + ----------------------------------------------------------------------- */ + + void + TgtNotifyAll( int pid_idx, BACK_MSG msg, UINT16 spec, + UINT32 context, int exclude, Boolean force) +{ + int conn; + + DPRINTF(("TgtNotifyAll: msg %d (%s) for pid_idx=%d (%d,%d)\n", + msg, BmsgNames [msg], pid_idx, exclude, force)); + for (conn = 0; conn < conn_list_cnt; conn++) + if (conn_list[conn].in_use /* not free */ + && PIDMAP_TEST (conn, pid_idx)) + { + if (conn != exclude) + TspSendWaitChange(conn, msg, spec, pid_list[pid_idx].pid, context, + force); + } +} + +/* ----------------------------------------------------------------------- + TgtDelete - mark process as now uncontrolled. + + Notes: + - this function removes a process from the process list. + - the notify argument indicates a message to send if needed. + ----------------------------------------------------------------------- */ + +void TgtDelete(PID_LIST *plst, int conn_idx, BACK_MSG notify) +{ + int idx = plst - pid_list, cnt, conn; + + /* found */ + cnt = pid_list[idx].owners; + if (cnt) + { /* some connections to break */ + for (conn = 0; cnt && conn < conn_list_cnt; conn++) + if (conn_list[conn].in_use /* not free */ + && PIDMAP_TEST (conn, idx)) + { /* found one that uses it */ + PIDMAP_CLEAR (conn, idx); + if (notify && conn != conn_idx) + TspSendWaitChange(conn, notify, 0, plst->pid, 0, True); + if (!--cnt) + break; + } + } + if (pid_list[idx].name) + Free(pid_list[idx].name); /* free string name back */ + /* Free breakpoint list */ + if (pid_list [idx].break_list != NULL) { + Free (pid_list [idx].break_list); + } + pid_list[idx].pid = 0; /* gone */ +} + + +/* ----------------------------------------------------------------------- + TgtKillAndDelete - kill or detach process and remove entry. + ----------------------------------------------------------------------- */ + + int +TgtKillAndDelete( PID_LIST *plst, struct svc_req *rqstp, Boolean term) +{ + ptrace_in pin; /* used for ptrace call */ + ptrace_out *pout; + + /* Remove breakpoints */ + if (plst->break_alloc > 0) { + pin.pid = plst->pid; + pin.addr.req = RPT_CLRBREAK; + pin.data = 0; /* clear all */ + pin.flags = PTRFLG_NON_OWNER; + pout = RPCGENSRVNAME(ptrace_2_svc) (&pin, rqstp); + if (pout->result < 0) { + DPRINTF (("TgtKillAndDelete: RPT_CLRBREAK failed %d\n", + getErrno())); + return -1; + } + } + + if (term) + { /* kill */ + pin.addr.ptrace_addr_data_in_u.address = 0; + pin.data = -1; /* Don't want notification from slave */ + pin.addr.req = RPT_KILL; + } + else + { /* detach */ + pin.addr.ptrace_addr_data_in_u.address = 1; + pin.data = 0; + pin.addr.req = RPT_DETACH; + } + pin.pid = plst->pid; + pin.flags = PTRFLG_FREE | PTRFLG_NON_OWNER; + + DPRINTF (("TgtKillAndDelete: ptrace_2_svc (%s (%d), %d)\n", + PtraceName (pin.addr.req), pin.addr.req, pin.pid)); + + pout = RPCGENSRVNAME(ptrace_2_svc) (&pin, rqstp);/* start it */ + if (pout->errNo == ESRCH && plst->pid) + TgtDelete(plst, -1, BMSG_KILLED); /* only entry remains */ + return 0; +} + +/* ----------------------------------------------------------------------- + TgtDetachCon - detach a connection's ownership of a process. + ----------------------------------------------------------------------- */ + + void +TgtDetachCon( int conn_idx, int pid_idx, Boolean delete) +{ + if ((unsigned) pid_idx >= pid_list_cnt + || !pid_list[pid_idx].pid) + return; /* not valid */ + if (PIDMAP_TEST (conn_idx, pid_idx)) + { /* if an owner, release control */ + PIDMAP_CLEAR (conn_idx, pid_idx); + + if (pid_list[pid_idx].owners) + pid_list[pid_idx].owners--; + if (pid_list[pid_idx].primary_conn == conn_idx) + pid_list[pid_idx].primary_conn = NO_PRIMARY; + if (delete + && !pid_list[pid_idx].owners + && PROC_TERMINATED (pid_list + pid_idx)) + TgtDelete(&pid_list[pid_idx], -1, 0); /* remove entry */ + } +} + +/* ----------------------------------------------------------------------- + TgtHandleChildChange - decide what action to take after wait() returns. + Used in the master only. + ----------------------------------------------------------------------- */ + +#ifdef DDEBUG +static char* LastStartNames[] = { + "NONE", "STEP", "CONT", "RANGE", + "STEPOFF", "KILLED", "DETACHED" +}; + +char* GetLastStartName (int last_start) +{ + static char buf [32]; + + strcpy (buf, LastStartNames [last_start & ~LAST_START]); + if (last_start & LAST_START) { + strcat (buf, "+START"); + } + return buf; +} +#endif + +Boolean TgtHandleChildChange(PID pid, int* status, int *unexp, + CPU_Exception_frame* ctx) +{ /* return False if continue, else stop */ + int idx, sig; + int bidx = 0; + PID_LIST *plst; + unsigned long PC; + BASE_BREAK *base = NULL; /* break_list[0] is really BASE_BREAK */ + int hadStepEmul; + int origHadStepEmul; + int stopWanted; + + DPRINTF (("TgtHandleChildChange: pid %d status %x cap\n", + (int) pid, *status)); + if (unexp) + *unexp = 0; /* initialize to ok */ + + /* first, find pid in question */ + idx = FindPidEntry (pid); + if (idx < 0) + { /* cannot locate this process */ + DPRINTF (("TgtHandleChildChange: unknown process (%s pid)\n", + FindPidEntry (pid) >= 0 ? "stale" : "unknown")); + if (unexp) + *unexp = 1; /* Unexpected change */ + return(False); /* unknown: ignore (used to stop and notify) */ + } + + /* found */ + plst = &pid_list[idx]; /* pointer to entry */ + /* first we see if just stopped */ + + /* copy ctxt */ + CtxToRegs(ctx, &(plst->regs)); + + stopWanted = plst->stop_wanted; + plst->stop_wanted = 0; /* For the next time */ + + hadStepEmul = BreakClear (plst, -1, -1) > 0; + origHadStepEmul = hadStepEmul; /* hadStepEmul is cleared if real bkpt met */ + + if (STS_SIGNALLED (*status)) + { /* stopped, not terminated */ + sig = STS_GETSIG (*status); /* signal that stopped us */ + + /* now, we read the registers and see what to do next */ + if (TgtPtrace(RPT_GETREGS, pid, (void *)&plst->regs, 0, NULL) < 0) { + memset (&plst->regs, 0, sizeof plst->regs); + } + + /* Get current thread */ + plst->thread = TgtPtrace(RPT_GETTARGETTHREAD, pid, NULL, 0, NULL); + + if (sig == SIGTRAP) + { /* stopped from break/step */ + PC = plst->regs.REG_PC; + /* Must check PC to see whether in situations where we had + step emulation we are on a breakpoint or just + have returned from an emulated single-step */ + if (BreakIdentify (plst, 0 /*no adjust*/, -1 /*no thread*/) > 0) { + hadStepEmul = 0; + } + plst->is_step = hadStepEmul || IS_STEP(plst->regs) + || plst->last_start == LAST_START; + DPRINTF (("TgtHandleChildChange: %s last_start %s\n", plst->is_step + ? "step": "break", GetLastStartName (plst->last_start))); + + if ((plst->is_step || origHadStepEmul || stopWanted) + && (plst->last_start == LAST_STEP + || plst->last_start == LAST_STEPOFF + || plst->last_start == LAST_RANGE)) + { + DPRINTF (("TgtHandleChildChange: restoring stepped-off bkpt\n")); + BreakSteppedOff (plst); + } + + if (plst->last_start == LAST_STEPOFF && (plst->is_step||origHadStepEmul)) + { /* stepped off break and now need cont */ + DPRINTF (("TgtHandleChildChange: auto-resuming after step-off\n")); + plst->last_start = LAST_CONT; /* convert to normal cont */ + if (!stopWanted) { + if (TgtPtrace(RPT_CONT, pid, (char *)1, 0, NULL)) + return True; /* tell people */ + return(False); /* wait for change */ + } + DPRINTF (("TgtHandleChildChange: stop_wanted %d in step-off\n", + stopWanted)); + *status = STS_MAKESIG (stopWanted); + return True; /* Stop and notify */ + } + + base = plst->break_list ? ((BASE_BREAK*)plst->break_list) : + ((BASE_BREAK*)NULL); + /* now see if step in range */ + + if (plst->last_start == LAST_RANGE /* step in range */ + && (plst->is_step || origHadStepEmul) /* not a breakpoint */ + && PC >= base->range_start + && PC <= base->range_end) + { /* still in range, keep going */ + if (stopWanted) { + DPRINTF (("TgtHandleChildChange: stop_wanted %d in step-range\n", + stopWanted)); + } else { + DPRINTF (("TgtHandleChildChange: Reservation at %x\n", + plst->regs.REG_PC)); + } + } + if (!plst->is_step) /* was break */ + { + bidx = BreakIdentify (plst, 1 /*adjust*/, plst->thread); + if (bidx == 0) { + DPRINTF (("TgtHandleChildChange: forwarding bkpt to kernel\n")); + if (unexp) { + *unexp = 1; + } + return False; + } + if (bidx < 0) { /* Unwanted breakpoint, must step it off */ + ptrace_in pin; + ptrace_out* out; + if (origHadStepEmul) + { + DPRINTF (("TgtHandleChildChange: bkpt %x becomes step\n", + plst->regs.REG_PC)); + bidx = -bidx; + plst->is_step = 1; + base->clr_step = plst->break_list [bidx].type == BRKT_INSTR; + base->last_break = bidx; + return True; + } + if (stopWanted) { + DPRINTF (("TgtHandleChildChange: stop_wanted %d at bkpt %x\n", + stopWanted, plst->regs.REG_PC)); + /* The PC has already been adjusted by BreakIdentify */ + *status = STS_MAKESIG (stopWanted); + return True; + } + /* All the handling is done in ptrace_2_svc() so call it */ + bidx = -bidx; + DPRINTF (("TgtHandleChildChange: last %d (%s) restarting bkpt %d\n", + plst->last_start, GetLastStartName (plst->last_start), bidx)); + base->clr_step = 1; + base->last_break = bidx; /* remember which one */ + plst->running = 0; /* So that ptrace is accepted */ + pin.pid = plst->pid; + + if (plst->last_start == LAST_STEP) { + pin.addr.req = RPT_SINGLESTEP; + } else { + pin.addr.req = RPT_CONT; + } + pin.addr.ptrace_addr_data_in_u.address = 1; + pin.data = 0; + pin.flags = PTRFLG_NON_OWNER; + out = RPCGENSRVNAME(ptrace_2_svc) (&pin, NULL); + if (out->result == 0) return False; /* Continue waiting */ + DPRINTF(("TgtHandleChildChange: failed to restart bkpt!\n")); + /* If something went wrong, just stop on breakpoint */ + } + } + } /* else sig != SIGTRAP */ + + /* finally, fill in stop info in break point array base */ + if (bidx > 0) + { /* store break info */ + /* will need to get off the break for SW breakpoints only */ + base->clr_step = plst->break_list [bidx].type == BRKT_INSTR; + base->last_break = bidx; /* remember which one */ + } + else if (base) + { /* clear break info */ + base->clr_step = False; /* not stopped on break */ + base->last_break = 0; + } + /* decision to notify owner based on last_start */ + } /* stopped */ + else /* terminated */ + { + if (plst->last_start == LAST_START) + { /* spawn failed */ + TgtNotifyAll(idx, BMSG_EXEC_FAIL, 0, 0, -1, True); + plst->running = False; /* not running - dead */ + plst->state = *status; /* contains errno in high word */ + return(False); + } + + else if ((UCHAR)(plst->last_start & ~LAST_START) < (UCHAR)LAST_KILLED) + plst->last_start = LAST_NONE; /* doesn't matter anymore */ + else + return(False); /* killed and detach already notified */ + } + return(True); /* stop and notify */ +} + +#ifdef DDEBUG + +/* ----------------------------------------------------------------------- + TgtDbgPtrace - debug version of ptrace. + ----------------------------------------------------------------------- */ + +int TgtDbgPtrace(int request, PID pid, char *addr, int data, void *addr2) +{ + int diag; + + DPRINTF (("TgtDbgPtrace: entered (%s (%d), %d, %x, %d, %x)\n", + PtraceName (request), request, pid, (int) addr, data, + (int) addr2)); + + if (request == RPT_WRITETEXT || request == RPT_WRITEDATA) { + int i; + + DPRINTF (("TgtDbgPtrace:")); + if (rdb_debug) { + for (i = 0; i < data && i < 16; ++i) { + printf (" %02x", ((char*) addr2) [i] & 0xFF); + } + printf ("\n"); + } + } + + diag = TgtRealPtrace (request, pid, addr, data, addr2); + + DPRINTF (("TgtDbgPtrace: returned %d (%x) errno %d\n", + diag, diag, getErrno())); + + if (request == RPT_GETREGS || request == RPT_GETTHREADREGS + || request == RPT_SETREGS || request == RPT_SETTHREADREGS) + { + /* Use DPRINTF() so as to have the id prefix */ + DPRINTF (("TgtDbgPtrace: (%s) PC = %x, SP = %x, FP = %x\n", + PtraceName (request), + ((xdr_regs*)addr)->REG_PC, + ((xdr_regs*)addr)->REG_SP, + ((xdr_regs*)addr)->REG_FP)); + } + + return(diag); +} +#endif /* DDEBUG */ diff --git a/c/src/lib/librdbg/servtsp.c b/c/src/lib/librdbg/servtsp.c new file mode 100644 index 0000000000..6a83c6caf5 --- /dev/null +++ b/c/src/lib/librdbg/servtsp.c @@ -0,0 +1,329 @@ +/* + ************************************************************************** + * + * Component: RDBG + * Module: servtsp.c + * + * Synopsis: Transport management for remote debug server. + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int out_sock; +static int warm_test; + +static void TimeTestHandler(); + + /* + * TspInit - Initialize the transport system. + * + */ + + void +TspInit (int id) +{ + struct sigaction sa; + + /* setup a socket to send event messages back through */ + out_sock = socket (PF_INET, SOCK_DGRAM, 0); + if (out_sock < 0) { + DPRINTF (("TspInit: socket() failed %d errno %d\n", + out_sock, getErrno())); + return; /* failed to open socket, let caller deal with */ + } + { + struct sockaddr_in addr; + + bzero ((void *)(&addr), sizeof addr); + addr.sin_family = AF_INET; + addr.sin_port = htons (BackPort); + if (bind (out_sock, (struct sockaddr*) &addr, sizeof addr) < 0) { + DPRINTF (("TspInit: bind() failed\n")); + } + } + /* setup alarm timer for warm testing */ + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = TimeTestHandler; + sigaction (SIGALRM, &sa, 0); +} + + /* + * TspTranslateRpcAddr - translate from an RPC handle to an + * opaque address. + * + * Converts the sender's address into the opaque data structure + * used for network addresses. This is used to look up the sender + * on each call. + */ + + Boolean +TspTranslateRpcAddr (struct svc_req* rqstp, NET_OPAQUE* opaque) +{ + struct sockaddr_in* addr; /* used as template to extract net info */ + unsigned char* up; + + memset (opaque, 0, sizeof (NET_OPAQUE)); + /* + * We interpret the remote address as a standard netbuf name. + * The format is 2 bytes of address family (normally AF_INET) + * and then a length (5) and then the IP address. + */ + if (rqstp->rq_xprt->xp_addrlen != 16) + { + DPRINTF (("TspTranslateRpcAddr: Unknown remote address!!!\n")); + setErrno (EPROTONOSUPPORT); + return False; /* invalid, so fails */ + } + /* addr = &rqstp->rq_xprt->xp_raddr; */ + addr = svc_getcaller (rqstp->rq_xprt); + /* verify it is AF_INET */ + if (addr->sin_family != AF_INET) { /* no, error */ + DPRINTF (("TspTranslateRpcAddr: Not an internet address!!\n")); + setErrno (EAFNOSUPPORT);/* invalid addr family */ + return False; + } + /* good address type */ + up = (unsigned char *) &addr->sin_addr.s_addr; + DPRINTF (("TspTranslateRpcAddr: Sent by %u.%u.%u.%u port #%u\n", + up[0], up[1], up[2], up[3], htons (addr->sin_port))); + memcpy (opaque, addr, sizeof (struct sockaddr_in)); + return True; +} + + /* + * TspValidateAddr - validate a passed in opaque address. + * + * Checks that the passed in address is in the format + * expected. + */ + + Boolean +TspValidateAddr (NET_OPAQUE* opaque, NET_OPAQUE* sender) +{ + struct sockaddr_in* addr; /* used as template to extract net info */ + + addr = (struct sockaddr_in*) opaque; + /* Verify it is AF_INET. Should check against sender IP address too */ + if (addr->sin_family != AF_INET) { + DPRINTF (("TspValidateAddr: Back port invalid: %d\n", + htons (addr->sin_port))); + return False; /* not valid */ + } + /* otherwise, we copy in the IP address, since client may not know it */ + addr->sin_addr.s_addr = ((struct sockaddr_in*) sender)->sin_addr.s_addr; + DPRINTF (("TspValidateAddr: Back port is %d\n", htons (addr->sin_port))); + return True; +} + + /* + * TspConnGetIndex - lookup an rpc caller's address as a connection entry. + * + * Looks up an ip address of a caller to locate the + * connection index in our connection array. + */ + + int +TspConnGetIndex (struct svc_req* rqstp) +{ + int conn; + /* &rqstp->rq_xprt->xp_raddr; */ + struct sockaddr_in *addr = svc_getcaller (rqstp->rq_xprt); + + for (conn = 0; conn < conn_list_cnt; conn++) { + if (!conn_list[conn].in_use) + continue; /* not used */ + + if (addr->sin_addr.s_addr == ((struct sockaddr_in *) + &conn_list [conn].sender)->sin_addr.s_addr + && addr->sin_port == ((struct sockaddr_in *) + &conn_list[conn].sender)->sin_port) { + return conn; + } + } + return -1; +} + + + /* + * TspSendWaitChange - send wait-change message to clients to + * notify change. + */ + + void +TspSendWaitChange( + int conn, /* connection to send to */ + BACK_MSG msg, /* BMSG type */ + UINT16 spec, /* special information */ + PID pid, /* pid it refers to */ + UINT32 context, /* additional context for message */ + Boolean force) /* force into being only message */ +{ + int idx; + struct SEND_LIST* snd_ptr; + + if (force) { + /* force to top, which means others gone */ + idx = 0; + conn_list [conn].send_idx = 1; + conn_list[conn].retry = 0; + } else { + for (idx = 0; idx < (int) conn_list[conn].send_idx; idx++) { + if (conn_list[conn].send_list[idx].send_type == msg + && conn_list[conn].send_list[idx].pid == pid) + return; /* already pended for this pid */ + } + idx = conn_list[conn].send_idx; + if (idx+1 > MAX_SEND) + return; /* we lose it, what should we do??? */ + conn_list[conn].send_idx++; + } + snd_ptr = &conn_list[conn].send_list[idx]; + snd_ptr->send_type = msg; /* message to send */ + snd_ptr->retry = TSP_RETRIES; /* about 1 minute of retries */ + snd_ptr->spec = htons ((u_short) spec); + snd_ptr->pid = htonl (pid); + snd_ptr->context = htonl (context); + TspSendMessage (conn, False); /* now do the send */ +} + + /* + * TspSendMessage - send message at top of send list for connection. + */ + + void +TspSendMessage( int conn, Boolean resend) +{ + struct sockaddr_in addr; + struct UDP_MSG msg; + int cnt; + + if (!resend && conn_list[conn].retry) + return; /* already waiting for reply */ + + /* + * Note on above: if no back port we can't remove unless + * someone blows off. + */ + if (!resend) { + /* first time, setup. Set retry count: */ + conn_list[conn].retry = conn_list[conn].send_list[0].retry; + conn_list[conn].last_msg_num++; /* new sequence number */ + if (!warm_test++) { /* starting, so enable timer */ + alarm (2); /* resend every 2 seconds as needed */ + } + } + + msg.type = conn_list[conn].send_list[0].send_type; + msg.msg_num = conn_list[conn].last_msg_num; + msg.spec = conn_list[conn].send_list[0].spec; + msg.pid = conn_list[conn].send_list[0].pid; + msg.context = conn_list[conn].send_list[0].context; + + memset (&addr, 0, sizeof addr); + addr.sin_family = AF_INET; + addr.sin_port = ((struct sockaddr_in*)&conn_list[conn].back_port)->sin_port; + addr.sin_addr.s_addr = + ((struct sockaddr_in*)&conn_list[conn].back_port)->sin_addr.s_addr; + + DPRINTF (("TspSendMessage: Sending msg %d (%s) to port %d\n", + msg.type, BmsgNames [msg.type], HL_W (addr.sin_port))); + + cnt = sendto (out_sock, &msg, sizeof msg, 0, (struct sockaddr*) &addr, + sizeof addr); + if (cnt != sizeof msg) { /* failed on send */ + printf ("%s: Failed to send msg %d to conn %d (%d vs. %d)\n", + ActName, msg.type, conn, cnt, sizeof msg); + } +} + + /* + * TspMessageReceive - confirmation received, now send next if any. + * + * - since UDP is connectionless, we batch up the sends and use + * one at a time until we get a message indicating ready for + * next (from ack). + */ + + void +TspMessageReceive (int conn, PID pid) +{ + /* We remove the send list entry and use next if any */ + conn_list[conn].retry = 0; /* reset */ + if (!warm_test || !--warm_test) { + alarm (0); /* reset timer if not used */ + } +#ifdef DDEBUG + if (conn_list[conn].send_list[0].send_type == BMSG_WARM) { + DPRINTF (("TspMessageReceive: Connection reset for conn %d\n", conn)); + } +#endif + /* Move up by one if needed */ + if (!--conn_list[conn].send_idx) + return; /* no more to do */ + + memcpy (conn_list[conn].send_list, conn_list[conn].send_list+1, + conn_list[conn].send_idx * sizeof(struct SEND_LIST)); /* copy down */ + TspSendMessage (conn, 0); +} + + /* + * TspGetHostName - return client's host name. + * + * - this routine returns the name of the client's host or the net + * number of unknown. + */ + + char* +TspGetHostName (conn_idx) + int conn_idx; /* client connection number */ +{ + static char buff [30]; /* largest net num */ + unsigned char* cp; + + cp = conn_list[conn_idx].sender.c+4; + sprintf (buff, "%u.%u.%u.%u", cp[0], cp[1], cp[2], cp[3]); + return buff; +} + + /* + * TimeTestHandler - alarm timer handler to resend warm/wait test. + */ + + static void +TimeTestHandler() +{ + int conn; + + if (!warm_test) + return; /* no longer enabled */ + + for (conn = 0; conn < conn_list_cnt; conn++) { + /* locate all that are using this */ + if (!conn_list[conn].in_use) + continue; /* not used */ + + if (!conn_list[conn].retry) continue; + /* found one that we are testing */ + if (!--conn_list[conn].retry) { + /* + * Counted down the retries: blow off. + * Need to have connection flag to indicate not blowing + * off for cases where client is stopped due to being + * debugged. + */ + ConnDelete (conn, NULL, CLOSE_IGNORE); + continue; + } + TspSendMessage (conn, True); /* send another message */ + } + alarm (2); /* setup for 2 seconds from now */ +} diff --git a/c/src/lib/librdbg/servutil.c b/c/src/lib/librdbg/servutil.c new file mode 100644 index 0000000000..40187faead --- /dev/null +++ b/c/src/lib/librdbg/servutil.c @@ -0,0 +1,130 @@ +/* + ********************************************************************** + * + * Component: RDB + * Module: servutil.c + * + * Synopsis: Various utility routines + * + ********************************************************************** + */ + +#include +#include +#include + +/*----- Management of per-process list ----*/ + + /* + * ListAlloc - build up list entry. + * + * Notes: + * - this is a generic routine to build up entries in the per-connection + * list. The fields list, list_sz and list_alloc are affected. + */ + + Boolean +ListAlloc(buff, clst) + char *buff; + CONN_LIST *clst; /* place to copy it */ +{ + int tmp; + char* name; + int new_len; + int len; + + tmp = strlen(buff); + new_len = (int)clst->list_sz + 1 + tmp; + if (clst->list_alloc < (unsigned)new_len) { + /* need more space */ + name = (char *)Realloc(clst->list, len = new_len + MAX_FILENAME); + if (name == NULL) { + return(False); /* failed, no space */ + } + clst->list_alloc = len; + clst->list = name; + } + strcpy(clst->list + clst->list_sz, buff); + clst->list_sz += tmp; + return(True); +} + +/*----- Management of processes -----*/ + + /* + * FindPidEntry - locate pid_list entry from pid + */ + + int +FindPidEntry (pid) + int pid; /* process identifier */ +{ + int idx; + + /* pid 0 is invalid, and signals a free slot */ + if (pid_list == NULL || pid == 0) { + return -1; + } + for (idx = 0; idx < pid_list_cnt; idx++) { + if (pid_list [idx].pid == pid ) + return idx; + } + return -1; +} + +/*----- Debug suport -----*/ + +#ifdef DDEBUG + + /* + * Names of debug primitives + */ + +const char* PtraceNames [] = { + +"RPT_TRACEME", "RPT_PEEKTEXT", "RPT_PEEKDATA", "RPT_PEEKUSER", +"RPT_POKETEXT", "RPT_POKEDATA", "RPT_POKEUSER", "RPT_CONT", +"RPT_KILL", "RPT_SINGLESTEP", "RPT_ATTACH", "RPT_DETACH", +"RPT_GETREGS", "RPT_SETREGS", "RPT_GETFPREGS", "RPT_SETFPREGS", +"RPT_READDATA", "RPT_WRITEDATA", "RPT_READTEXT", "RPT_WRITETEXT", +"RPT_GETFPAREGS", "RPT_SETFPAREGS", "RPT_22", "RPT_23", +"RPT_SYSCALL", "RPT_DUMPCORE", "RPT_26", "RPT_27", +"RPT_28", "RPT_GETUCODE", "RPT_30", "RPT_31", +"RPT_32", "RPT_33", "RPT_34", "RPT_35", +"RPT_36", "RPT_37", "RPT_38", "RPT_39", +"RPT_40", "RPT_41", "RPT_42", "RPT_43", +"RPT_44", "RPT_45", "RPT_46", "RPT_47", +"RPT_48", "RPT_49", "RPT_GETTARGETTHREAD", "RPT_SETTARGETTHREAD", +"RPT_THREADSUSPEND", "RPT_THREADRESUME", "RPT_THREADLIST", "RPT_GETTHREADNAME", +"RPT_SETTHREADNAME", "RPT_SETTHREADREGS", "RPT_GETTHREADREGS", + "RPT_59", +"RPT_60", "RPT_61", "RPT_62", "RPT_63", +"RPT_64", "RPT_65", "RPT_66", "RPT_67", +"RPT_68", "RPT_69", "RPT_70", "RPT_71", +"RPT_72", "RPT_73", "RPT_74", "RPT_STEPRANGE", +"RPT_CONTTO", "RPT_SETBREAK", "RPT_CLRBREAK", "RPT_GETBREAK", +"RPT_GETNAME", "RPT_STOP", +"RPT_PGETREGS", "RPT_PSETREGS", +"RPT_PSETTHREADREGS", "RPT_PGETTHREADREGS" +}; + +const char* +PtraceName(req) + int req; +{ + static char bufret[40]; + + if ((req < 0) || (req >= sizeof(PtraceNames)/sizeof(char*))) { + sprintf(bufret, "BAD_REQ_%d", req); + return bufret; + } + return PtraceNames[req]; +} + +const char* BmsgNames [] = { + "?", "WARM", "WAIT", "BREAK", + "EXEC_FAIL", "DETACH", "KILLED", "NOT_PRIM", + "NEW_PID" +}; + +#endif /* DDEBUG */ diff --git a/c/src/lib/librpc/Makefile.in b/c/src/lib/librpc/Makefile.in new file mode 100644 index 0000000000..9c3f0986f0 --- /dev/null +++ b/c/src/lib/librpc/Makefile.in @@ -0,0 +1,49 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @top_srcdir@ +PROJECT_ROOT = @PROJECT_ROOT@ + +LIBNAME=librpc.a +LIB=${ARCH}/${LIBNAME} + +# C and C++ source names, if any, go here -- minus the .c or .cc +C_PIECES= rpc_callmsg rpc_prot svc svc_auth svc_udp xdr xdr_array xdr_mem +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +SRCS=$(C_FILES) +OBJS=$(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg +include $(RTEMS_ROOT)/make/lib.cfg + +# +# Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += $(LIBC_DEFINES) + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += $(LIB) +CLOBBER_ADDITIONS += + +all: ${ARCH} $(LIB) + $(INSTALL_VARIANT) -m 644 ${LIB} ${PROJECT_RELEASE}/lib + +$(LIB): $(SRCS) ${OBJS} + $(make-library) + + diff --git a/c/src/lib/librpc/rpc_callmsg.c b/c/src/lib/librpc/rpc_callmsg.c new file mode 100644 index 0000000000..4f95254e82 --- /dev/null +++ b/c/src/lib/librpc/rpc_callmsg.c @@ -0,0 +1,191 @@ +/* @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * rpc_callmsg.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + */ + +#include /* bcopy */ +#include + +bool_t xdr_opaque_auth (register XDR *xdrs, register struct + opaque_auth *ap); +/* + * XDR a call message + */ +bool_t +xdr_callmsg(xdrs, cmsg) + register XDR *xdrs; + register struct rpc_msg *cmsg; +{ + register long *buf; + register struct opaque_auth *oa; + + if (xdrs->x_op == XDR_ENCODE) { + if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) { + return (FALSE); + } + if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) { + return (FALSE); + } + buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + + RNDUP(cmsg->rm_call.cb_cred.oa_length) + + 2 * BYTES_PER_XDR_UNIT + + RNDUP(cmsg->rm_call.cb_verf.oa_length)); + if (buf != NULL) { + IXDR_PUT_LONG(buf, cmsg->rm_xid); + IXDR_PUT_ENUM(buf, cmsg->rm_direction); + if (cmsg->rm_direction != CALL) { + return (FALSE); + } + IXDR_PUT_LONG(buf, cmsg->rm_call.cb_rpcvers); + if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { + return (FALSE); + } + IXDR_PUT_LONG(buf, cmsg->rm_call.cb_prog); + IXDR_PUT_LONG(buf, cmsg->rm_call.cb_vers); + IXDR_PUT_LONG(buf, cmsg->rm_call.cb_proc); + oa = &cmsg->rm_call.cb_cred; + IXDR_PUT_ENUM(buf, oa->oa_flavor); + IXDR_PUT_LONG(buf, oa->oa_length); + if (oa->oa_length) { + bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); + buf += RNDUP(oa->oa_length) / sizeof (long); + } + oa = &cmsg->rm_call.cb_verf; + IXDR_PUT_ENUM(buf, oa->oa_flavor); + IXDR_PUT_LONG(buf, oa->oa_length); + if (oa->oa_length) { + bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); + /* no real need.... + buf += RNDUP(oa->oa_length) / sizeof (long); + */ + } + return (TRUE); + } + } + if (xdrs->x_op == XDR_DECODE) { + buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT); + if (buf != NULL) { + cmsg->rm_xid = IXDR_GET_LONG(buf); + cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type); + if (cmsg->rm_direction != CALL) { + return (FALSE); + } + cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG(buf); + if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { + return (FALSE); + } + cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf); + cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf); + cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf); + oa = &cmsg->rm_call.cb_cred; + oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); + oa->oa_length = IXDR_GET_LONG(buf); + if (oa->oa_length) { + if (oa->oa_length > MAX_AUTH_BYTES) { + return (FALSE); + } + if (oa->oa_base == NULL) { + oa->oa_base = (caddr_t) + mem_alloc(oa->oa_length); + } + buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); + if (buf == NULL) { + if (xdr_opaque(xdrs, oa->oa_base, + oa->oa_length) == FALSE) { + return (FALSE); + } + } else { + bcopy((caddr_t)buf, oa->oa_base, + oa->oa_length); + /* no real need.... + buf += RNDUP(oa->oa_length) / + sizeof (long); + */ + } + } + oa = &cmsg->rm_call.cb_verf; + buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE || + xdr_u_int(xdrs, &oa->oa_length) == FALSE) { + return (FALSE); + } + } else { + oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); + oa->oa_length = IXDR_GET_LONG(buf); + } + if (oa->oa_length) { + if (oa->oa_length > MAX_AUTH_BYTES) { + return (FALSE); + } + if (oa->oa_base == NULL) { + oa->oa_base = (caddr_t) + mem_alloc(oa->oa_length); + } + buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); + if (buf == NULL) { + if (xdr_opaque(xdrs, oa->oa_base, + oa->oa_length) == FALSE) { + return (FALSE); + } + } else { + bcopy((caddr_t)buf, oa->oa_base, + oa->oa_length); + /* no real need... + buf += RNDUP(oa->oa_length) / + sizeof (long); + */ + } + } + return (TRUE); + } + } + if ( + xdr_u_long(xdrs, &(cmsg->rm_xid)) && + xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && + (cmsg->rm_direction == CALL) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) && + (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers)) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_proc)) && + xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) ) + return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf))); + return (FALSE); +} + diff --git a/c/src/lib/librpc/rpc_prot.c b/c/src/lib/librpc/rpc_prot.c new file mode 100644 index 0000000000..8d2fde7116 --- /dev/null +++ b/c/src/lib/librpc/rpc_prot.c @@ -0,0 +1,271 @@ +/* @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + */ + +/* + * rpc_prot.c + */ + +#include + +/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ + +struct opaque_auth _null_auth; + +/* + * XDR an opaque authentication struct + * (see auth.h) + */ +bool_t +xdr_opaque_auth(xdrs, ap) + register XDR *xdrs; + register struct opaque_auth *ap; +{ + + if (xdr_enum(xdrs, &(ap->oa_flavor))) + return (xdr_bytes(xdrs, &ap->oa_base, + &ap->oa_length, MAX_AUTH_BYTES)); + return (FALSE); +} + +/* + * XDR a DES block + */ +bool_t +xdr_des_block(xdrs, blkp) + register XDR *xdrs; + register des_block *blkp; +{ + return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block))); +} + +/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ + +/* + * XDR the MSG_ACCEPTED part of a reply message union + */ +bool_t +xdr_accepted_reply(xdrs, ar) + register XDR *xdrs; + register struct accepted_reply *ar; +{ + + /* personalized union, rather than calling xdr_union */ + if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) + return (FALSE); + if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat))) + return (FALSE); + switch (ar->ar_stat) { + + case SUCCESS: + return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); + + case PROG_MISMATCH: + if (! xdr_u_long(xdrs, &(ar->ar_vers.low))) + return (FALSE); + return (xdr_u_long(xdrs, &(ar->ar_vers.high))); + default: + break; + } + return (TRUE); /* TRUE => open ended set of problems */ +} + +/* + * XDR the MSG_DENIED part of a reply message union + */ +bool_t +xdr_rejected_reply(xdrs, rr) + register XDR *xdrs; + register struct rejected_reply *rr; +{ + + /* personalized union, rather than calling xdr_union */ + if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat))) + return (FALSE); + switch (rr->rj_stat) { + + case RPC_MISMATCH: + if (! xdr_u_long(xdrs, &(rr->rj_vers.low))) + return (FALSE); + return (xdr_u_long(xdrs, &(rr->rj_vers.high))); + + case AUTH_ERROR: + return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why))); + } + return (FALSE); +} + +static struct xdr_discrim reply_dscrm[3] = { + { (int)MSG_ACCEPTED, xdr_accepted_reply }, + { (int)MSG_DENIED, xdr_rejected_reply }, + { __dontcare__, NULL_xdrproc_t } }; + +/* + * XDR a reply message + */ +bool_t +xdr_replymsg(xdrs, rmsg) + register XDR *xdrs; + register struct rpc_msg *rmsg; +{ + if ( + xdr_u_long(xdrs, &(rmsg->rm_xid)) && + xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) && + (rmsg->rm_direction == REPLY) ) + return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat), + (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t)); + return (FALSE); +} + + +/* + * Serializes the "static part" of a call message header. + * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. + * The rm_xid is not really static, but the user can easily munge on the fly. + */ +bool_t +xdr_callhdr(xdrs, cmsg) + register XDR *xdrs; + register struct rpc_msg *cmsg; +{ + + cmsg->rm_direction = CALL; + cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; + if ( + (xdrs->x_op == XDR_ENCODE) && + xdr_u_long(xdrs, &(cmsg->rm_xid)) && + xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) ) + return (xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers))); + return (FALSE); +} + +/* ************************** Client utility routine ************* */ + +static void +accepted(acpt_stat, error) + register enum accept_stat acpt_stat; + register struct rpc_err *error; +{ + + switch (acpt_stat) { + + case PROG_UNAVAIL: + error->re_status = RPC_PROGUNAVAIL; + return; + + case PROG_MISMATCH: + error->re_status = RPC_PROGVERSMISMATCH; + return; + + case PROC_UNAVAIL: + error->re_status = RPC_PROCUNAVAIL; + return; + + case GARBAGE_ARGS: + error->re_status = RPC_CANTDECODEARGS; + return; + + case SYSTEM_ERR: + error->re_status = RPC_SYSTEMERROR; + return; + + case SUCCESS: + error->re_status = RPC_SUCCESS; + return; + } + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long)MSG_ACCEPTED; + error->re_lb.s2 = (long)acpt_stat; +} + +static void +rejected(rjct_stat, error) + register enum reject_stat rjct_stat; + register struct rpc_err *error; +{ + + switch (rjct_stat) { + + case RPC_VERSMISMATCH: + error->re_status = RPC_VERSMISMATCH; + return; + + case AUTH_ERROR: + error->re_status = RPC_AUTHERROR; + return; + + default: + break; + } + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long)MSG_DENIED; + error->re_lb.s2 = (long)rjct_stat; +} + +/* + * given a reply message, fills in the error + */ +void +_seterr_reply(msg, error) + register struct rpc_msg *msg; + register struct rpc_err *error; +{ + + /* optimized for normal, SUCCESSful case */ + switch (msg->rm_reply.rp_stat) { + + case MSG_ACCEPTED: + if (msg->acpted_rply.ar_stat == SUCCESS) { + error->re_status = RPC_SUCCESS; + return; + }; + accepted(msg->acpted_rply.ar_stat, error); + break; + + case MSG_DENIED: + rejected(msg->rjcted_rply.rj_stat, error); + break; + + default: + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long)(msg->rm_reply.rp_stat); + break; + } + switch (error->re_status) { + + case RPC_VERSMISMATCH: + error->re_vers.low = msg->rjcted_rply.rj_vers.low; + error->re_vers.high = msg->rjcted_rply.rj_vers.high; + break; + + case RPC_AUTHERROR: + error->re_why = msg->rjcted_rply.rj_why; + break; + + case RPC_PROGVERSMISMATCH: + error->re_vers.low = msg->acpted_rply.ar_vers.low; + error->re_vers.high = msg->acpted_rply.ar_vers.high; + break; + + default: + break; + } +} diff --git a/c/src/lib/librpc/svc.c b/c/src/lib/librpc/svc.c new file mode 100644 index 0000000000..c4ccb46aa5 --- /dev/null +++ b/c/src/lib/librpc/svc.c @@ -0,0 +1,259 @@ +/* @(#)svc.c 2.4 88/08/11 4.0 RPCSRC; from 1.44 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)svc.c 1.41 87/10/13 Copyr 1984 Sun Micro"; +#endif + +/* + * svc.c, Server-side remote procedure call interface. + * + * There are two sets of procedures here. The xprt routines are + * for handling transport handles. The svc routines handle the + * list of service routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include + +#define RQCRED_SIZE 400 /* this size is excessive */ + +/* ******************* REPLY GENERATION ROUTINES ************ */ + +/* + * Send a reply to an rpc request + */ +bool_t +svc_sendreply(xprt, xdr_results, xdr_location) + register SVCXPRT *xprt; + xdrproc_t xdr_results; + caddr_t xdr_location; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = SUCCESS; + rply.acpted_rply.ar_results.where = xdr_location; + rply.acpted_rply.ar_results.proc = xdr_results; + return (SVC_REPLY(xprt, &rply)); +} + +/* + * No procedure error reply + */ +void +svcerr_noproc(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROC_UNAVAIL; + SVC_REPLY(xprt, &rply); +} + +/* + * Can't decode args error reply + */ +void +svcerr_decode(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = GARBAGE_ARGS; + SVC_REPLY(xprt, &rply); +} + +/* + * Some system error + */ +void +svcerr_systemerr(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = SYSTEM_ERR; + SVC_REPLY(xprt, &rply); +} + +/* + * Authentication error reply + */ +void +svcerr_auth(xprt, why) + SVCXPRT *xprt; + enum auth_stat why; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_DENIED; + rply.rjcted_rply.rj_stat = AUTH_ERROR; + rply.rjcted_rply.rj_why = why; + SVC_REPLY(xprt, &rply); +} + +/* + * Auth too weak error reply + */ +void +svcerr_weakauth(xprt) + SVCXPRT *xprt; +{ + + svcerr_auth(xprt, AUTH_TOOWEAK); +} + +/* + * Program unavailable error reply + */ +void +svcerr_noprog(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROG_UNAVAIL; + SVC_REPLY(xprt, &rply); +} + +/* + * Program version mismatch error reply + */ +void +svcerr_progvers(xprt, low_vers, high_vers) + register SVCXPRT *xprt; + u_long low_vers; + u_long high_vers; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROG_MISMATCH; + rply.acpted_rply.ar_vers.low = low_vers; + rply.acpted_rply.ar_vers.high = high_vers; + SVC_REPLY(xprt, &rply); +} + + void +svc_processrequest(xprt, prog, vers, dispatch) + SVCXPRT *xprt; + u_long prog; + u_long vers; + void (*dispatch)(); +{ + struct rpc_msg msg; + int prog_found = FALSE; + u_long low_vers = 0; /* dummy init */ + u_long high_vers = 0; /* dummy init */ + struct svc_req r; + /*static char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];*/ + char *cred_area; + + cred_area = (char *)malloc(2*MAX_AUTH_BYTES + RQCRED_SIZE); + msg.rm_call.cb_cred.oa_base = cred_area; + msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); + r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); + + if (SVC_RECV(xprt, &msg)) { + + /* now find the exported program and call it */ + /* register struct svc_callout *s; */ + enum auth_stat why; + + r.rq_xprt = xprt; + r.rq_prog = msg.rm_call.cb_prog; + r.rq_vers = msg.rm_call.cb_vers; + r.rq_proc = msg.rm_call.cb_proc; + r.rq_cred = msg.rm_call.cb_cred; + + /* first authenticate the message */ + if ((why= _authenticate(&r, &msg)) != AUTH_OK) { + svcerr_auth(xprt, why); + free(cred_area); + return; + } + + /* now match message with a registered service*/ + prog_found = FALSE; + low_vers = 0 - 1; + high_vers = 0; + if (prog == r.rq_prog) { + if (vers == r.rq_vers) { + (*dispatch)(&r, xprt); + free(cred_area); + return; + } /* found correct version */ + prog_found = TRUE; + if (vers < low_vers) + low_vers = vers; + if (vers > high_vers) + high_vers = vers; + } /* found correct program */ + } + /* + * if we got here, the program or version + * is not served ... + */ + if (prog_found) { + svcerr_progvers(xprt, + low_vers, high_vers); + } else { + svcerr_noprog(xprt); + } + + free(cred_area); + +} + +/* stubs for solaris rpcgen */ +/*int _rpcsvccount; +int _rpcsvcstate; +int _SERVED; +*/ diff --git a/c/src/lib/librpc/svc_auth.c b/c/src/lib/librpc/svc_auth.c new file mode 100644 index 0000000000..f5634d8c37 --- /dev/null +++ b/c/src/lib/librpc/svc_auth.c @@ -0,0 +1,122 @@ + +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)svc_auth.c 2.1 88/08/07 4.0 RPCSRC; from 1.19 87/08/11 Copyr 1984 Sun Micro"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc_auth_nodes.c, Server-side rpc authenticator interface, + * *WITHOUT* DES authentication. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include + +/* + * svcauthsw is the bdevsw of server side authentication. + * + * Server side authenticators are called from authenticate by + * using the client auth struct flavor field to index into svcauthsw. + * The server auth flavors must implement a routine that looks + * like: + * + * enum auth_stat + * flavorx_auth(rqst, msg) + * register struct svc_req *rqst; + * register struct rpc_msg *msg; + * + */ + +enum auth_stat _svcauth_null(); /* no authentication */ +enum auth_stat _svcauth_unix(); /* unix style (uid, gids) */ +enum auth_stat _svcauth_short(); /* short hand unix style */ + +static struct { + enum auth_stat (*authenticator)(); +} svcauthsw[] = { + _svcauth_null, /* AUTH_NULL */ +#ifdef MR + _svcauth_unix, /* AUTH_UNIX */ + _svcauth_short /* AUTH_SHORT */ +#endif +}; + +#ifdef MR +#define AUTH_MAX 2 /* HIGHEST AUTH NUMBER */ +#else +#define AUTH_MAX 0 /* HIGHEST AUTH NUMBER */ +#endif + + +/* + * The call rpc message, msg has been obtained from the wire. The msg contains + * the raw form of credentials and verifiers. authenticate returns AUTH_OK + * if the msg is successfully authenticated. If AUTH_OK then the routine also + * does the following things: + * set rqst->rq_xprt->verf to the appropriate response verifier; + * sets rqst->rq_client_cred to the "cooked" form of the credentials. + * + * NB: rqst->rq_cxprt->verf must be pre-alloctaed; + * its length is set appropriately. + * + * The caller still owns and is responsible for msg->u.cmb.cred and + * msg->u.cmb.verf. The authentication system retains ownership of + * rqst->rq_client_cred, the cooked credentials. + * + * There is an assumption that any flavour less than AUTH_NULL is + * invalid. + */ +enum auth_stat +_authenticate(rqst, msg) + register struct svc_req *rqst; + struct rpc_msg *msg; +{ + register int cred_flavor; + + rqst->rq_cred = msg->rm_call.cb_cred; + rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; + rqst->rq_xprt->xp_verf.oa_length = 0; + cred_flavor = rqst->rq_cred.oa_flavor; + if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) { + return ((*(svcauthsw[cred_flavor].authenticator))(rqst, msg)); + } + + return (AUTH_REJECTEDCRED); +} + +enum auth_stat +_svcauth_null(/*rqst, msg*/) + /*struct svc_req *rqst; + struct rpc_msg *msg;*/ +{ + + return (AUTH_OK); +} diff --git a/c/src/lib/librpc/svc_udp.c b/c/src/lib/librpc/svc_udp.c new file mode 100644 index 0000000000..70e874335b --- /dev/null +++ b/c/src/lib/librpc/svc_udp.c @@ -0,0 +1,476 @@ +/* @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_udp.c, + * Server side for UDP/IP based RPC. (Does some caching in the hopes of + * achieving execute-at-most-once semantics.) + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +/* + * Adapted for rgdb specifi purposes. + * Modifications are under #ifndef NO_RGDB. + */ + +#include /* printf */ +#include /* free */ +#include /* bzero, bcmp */ +#include +#include + +#define rpc_buffer(xprt) ((xprt)->xp_p1) +#define MAX(a, b) ((a > b) ? a : b) + +static bool_t svcudp_recv(); +static bool_t svcudp_reply(); +static enum xprt_stat svcudp_stat(); +static bool_t svcudp_getargs(); +static bool_t svcudp_freeargs(); +static void svcudp_destroy(); +static int cache_get(); +static void cache_set(); + +static struct xp_ops svcudp_op = { + svcudp_recv, + svcudp_stat, + svcudp_getargs, + svcudp_reply, + svcudp_freeargs, + svcudp_destroy +}; + +extern int errno; + +/* + * kept in xprt->xp_p2 + */ +struct svcudp_data { + u_int su_iosz; /* byte size of send.recv buffer */ + u_long su_xid; /* transaction id */ + XDR su_xdrs; /* XDR handle */ + char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */ + char * su_cache; /* cached data, NULL if no cache */ +}; +#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2)) + +/* + * Usage: + * xprt = svcudp_create(sock); + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svcudp_create + * binds it to an arbitrary port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * Once *xprt is initialized, it is registered as a transporter; + * see (svc.h, xprt_register). + * The routines returns NULL if a problem occurred. + */ +SVCXPRT * +svcudp_bufcreate(sock, sendsz, recvsz) + register int sock; + u_int sendsz, recvsz; +{ + register SVCXPRT *xprt; + register struct svcudp_data *su; + struct sockaddr_in addr; + int len = sizeof(struct sockaddr_in); + + if (sock == RPC_ANYSOCK) { + (void)printf + ("svcudp_create: socket should be created and bound\n"); + return ((SVCXPRT *) NULL); + } + + if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) { + (void)printf("svcudp_create - cannot getsockname"); + return ((SVCXPRT *)NULL); + } + + xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); + + if (xprt == NULL) { + (void)printf("svcudp_create: out of memory\n"); + return (NULL); + } + su = (struct svcudp_data *)mem_alloc(sizeof(*su)); + if (su == NULL) { + (void)printf("svcudp_create: out of memory\n"); + return (NULL); + } + su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4; + if ((rpc_buffer(xprt) = (caddr_t) mem_alloc(su->su_iosz)) == NULL) { + (void)printf("svcudp_create: out of memory\n"); + return (NULL); + } + xdrmem_create( + &(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE); + su->su_cache = NULL; + xprt->xp_p2 = (caddr_t)su; + xprt->xp_verf.oa_base = su->su_verfbody; + xprt->xp_ops = &svcudp_op; + xprt->xp_port = ntohs(addr.sin_port); + xprt->xp_sock = sock; + return (xprt); +} + +SVCXPRT * +svcudp_create(sock) + int sock; +{ + +/* return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE));*/ + return(svcudp_bufcreate(sock, 1500, 1500)); +} + +static enum xprt_stat +svcudp_stat(xprt) + SVCXPRT *xprt; +{ + + return (XPRT_IDLE); +} + +static bool_t +svcudp_recv(xprt, msg) + register SVCXPRT *xprt; + struct rpc_msg *msg; +{ + register struct svcudp_data *su = su_data(xprt); + register XDR *xdrs = &(su->su_xdrs); + register int rlen; + char *reply; + u_long replylen; + + again: + xprt->xp_addrlen = sizeof(struct sockaddr_in); + rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz, + 0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen)); + if (rlen == -1 /* && errno == EINTR */) + goto again; + if (rlen < 4*sizeof(u_long)) + return (FALSE); + xdrs->x_op = XDR_DECODE; + XDR_SETPOS(xdrs, 0); + if (! xdr_callmsg(xdrs, msg)) + return (FALSE); + su->su_xid = msg->rm_xid; + if (su->su_cache != NULL) { + if (cache_get(xprt, msg, &reply, &replylen)) { + (void) sendto(xprt->xp_sock, reply, (int) replylen, 0, + (struct sockaddr *) &xprt->xp_raddr, xprt->xp_addrlen); + return (FALSE); + } + } + return (TRUE); +} + +static bool_t +svcudp_reply(xprt, msg) + register SVCXPRT *xprt; + struct rpc_msg *msg; +{ + register struct svcudp_data *su = su_data(xprt); + register XDR *xdrs = &(su->su_xdrs); + register int slen; + register bool_t stat = FALSE; + + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS(xdrs, 0); + msg->rm_xid = su->su_xid; + if (xdr_replymsg(xdrs, msg)) { + slen = (int)XDR_GETPOS(xdrs); + if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0, + (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen) + == slen) { + stat = TRUE; + if (su->su_cache && slen >= 0) { + cache_set(xprt, (u_long) slen); + } + } + } + return (stat); +} + +static bool_t +svcudp_getargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + + return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr)); +} + +static bool_t +svcudp_freeargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + register XDR *xdrs = &(su_data(xprt)->su_xdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_args)(xdrs, args_ptr)); +} + +static void +svcudp_destroy(xprt) + register SVCXPRT *xprt; +{ + register struct svcudp_data *su = su_data(xprt); +/* + xprt_unregister(xprt); + (void)close(xprt->xp_sock); +*/ + XDR_DESTROY(&(su->su_xdrs)); + mem_free(rpc_buffer(xprt), su->su_iosz); + mem_free((caddr_t)su, sizeof(struct svcudp_data)); + mem_free((caddr_t)xprt, sizeof(SVCXPRT)); +} + + +/***********this could be a separate file*********************/ + +/* + * Fifo cache for udp server + * Copies pointers to reply buffers into fifo cache + * Buffers are sent again if retransmissions are detected. + */ + +#define SPARSENESS 4 /* 75% sparse */ + +#define CACHE_PERROR(msg) \ + (void) printf("%s\n", msg) + +#define ALLOC(type, size) \ + (type *) mem_alloc((unsigned) (sizeof(type) * (size))) + +#define BZERO(addr, type, size) \ + bzero((char *) addr, sizeof(type) * (int) (size)) + +/* + * An entry in the cache + */ +typedef struct cache_node *cache_ptr; +struct cache_node { + /* + * Index into cache is xid, proc, vers, prog and address + */ + u_long cache_xid; + u_long cache_proc; + u_long cache_vers; + u_long cache_prog; + struct sockaddr_in cache_addr; + /* + * The cached reply and length + */ + char * cache_reply; + u_long cache_replylen; + /* + * Next node on the list, if there is a collision + */ + cache_ptr cache_next; +}; + + + +/* + * The entire cache + */ +struct udp_cache { + u_long uc_size; /* size of cache */ + cache_ptr *uc_entries; /* hash table of entries in cache */ + cache_ptr *uc_fifo; /* fifo list of entries in cache */ + u_long uc_nextvictim; /* points to next victim in fifo list */ + u_long uc_prog; /* saved program number */ + u_long uc_vers; /* saved version number */ + u_long uc_proc; /* saved procedure number */ + struct sockaddr_in uc_addr; /* saved caller's address */ +}; + + +/* + * the hashing function + */ +#define CACHE_LOC(transp, xid) \ + (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size)) + + +/* + * Enable use of the cache. + * Note: there is no disable. + */ + int +svcudp_enablecache(transp, size) + SVCXPRT *transp; + u_long size; +{ + struct svcudp_data *su = su_data(transp); + struct udp_cache *uc; + + if (su->su_cache != NULL) { + CACHE_PERROR("enablecache: cache already enabled"); + return(0); + } + uc = ALLOC(struct udp_cache, 1); + if (uc == NULL) { + CACHE_PERROR("enablecache: could not allocate cache"); + return(0); + } + uc->uc_size = size; + uc->uc_nextvictim = 0; + uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS); + if (uc->uc_entries == NULL) { + CACHE_PERROR("enablecache: could not allocate cache data"); + return(0); + } + BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS); + uc->uc_fifo = ALLOC(cache_ptr, size); + if (uc->uc_fifo == NULL) { + CACHE_PERROR("enablecache: could not allocate cache fifo"); + return(0); + } + BZERO(uc->uc_fifo, cache_ptr, size); + su->su_cache = (char *) uc; + return(1); +} + + +/* + * Set an entry in the cache + */ +static void +cache_set(xprt, replylen) + SVCXPRT *xprt; + u_long replylen; +{ + register cache_ptr victim; + register cache_ptr *vicp; + register struct svcudp_data *su = su_data(xprt); + struct udp_cache *uc = (struct udp_cache *) su->su_cache; + u_int loc; + char *newbuf; + + /* + * Find space for the new entry, either by + * reusing an old entry, or by mallocing a new one + */ + victim = uc->uc_fifo[uc->uc_nextvictim]; + if (victim != NULL) { + loc = CACHE_LOC(xprt, victim->cache_xid); + for (vicp = &uc->uc_entries[loc]; + *vicp != NULL && *vicp != victim; + vicp = &(*vicp)->cache_next) + ; + if (*vicp == NULL) { + CACHE_PERROR("cache_set: victim not found"); + return; + } + *vicp = victim->cache_next; /* remote from cache */ + newbuf = victim->cache_reply; + } else { + victim = ALLOC(struct cache_node, 1); + if (victim == NULL) { + CACHE_PERROR("cache_set: victim alloc failed"); + return; + } + newbuf = (char*) mem_alloc(su->su_iosz); + if (newbuf == NULL) { + CACHE_PERROR("cache_set: could not allocate new rpc_buffer"); + return; + } + } + + /* + * Store it away + */ + victim->cache_replylen = replylen; + victim->cache_reply = rpc_buffer(xprt); + rpc_buffer(xprt) = newbuf; + xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_ENCODE); + victim->cache_xid = su->su_xid; + victim->cache_proc = uc->uc_proc; + victim->cache_vers = uc->uc_vers; + victim->cache_prog = uc->uc_prog; + victim->cache_addr = uc->uc_addr; + loc = CACHE_LOC(xprt, victim->cache_xid); + victim->cache_next = uc->uc_entries[loc]; + uc->uc_entries[loc] = victim; + uc->uc_fifo[uc->uc_nextvictim++] = victim; + uc->uc_nextvictim %= uc->uc_size; +} + +/* + * Try to get an entry from the cache + * return 1 if found, 0 if not found + */ +static int +cache_get(xprt, msg, replyp, replylenp) + SVCXPRT *xprt; + struct rpc_msg *msg; + char **replyp; + u_long *replylenp; +{ + u_int loc; + register cache_ptr ent; + register struct svcudp_data *su = su_data(xprt); + register struct udp_cache *uc = (struct udp_cache *) su->su_cache; + +# define EQADDR(a1, a2) (bcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0) + + loc = CACHE_LOC(xprt, su->su_xid); + for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) { + if (ent->cache_xid == su->su_xid && + ent->cache_proc == uc->uc_proc && + ent->cache_vers == uc->uc_vers && + ent->cache_prog == uc->uc_prog && + EQADDR(ent->cache_addr, uc->uc_addr)) { + *replyp = ent->cache_reply; + *replylenp = ent->cache_replylen; + return(1); + } + } + /* + * Failed to find entry + * Remember a few things so we can do a set later + */ + uc->uc_proc = msg->rm_call.cb_proc; + uc->uc_vers = msg->rm_call.cb_vers; + uc->uc_prog = msg->rm_call.cb_prog; + uc->uc_addr = xprt->xp_raddr; + return(0); +} + diff --git a/c/src/lib/librpc/xdr.c b/c/src/lib/librpc/xdr.c new file mode 100644 index 0000000000..cc8caf7785 --- /dev/null +++ b/c/src/lib/librpc/xdr.c @@ -0,0 +1,578 @@ +/* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr.c 1.35 87/08/12"; +#endif + +/* + * xdr.c, Generic XDR routines implementation. + * + * Copyright (C) 1986, Sun Microsystems, Inc. + * + * These are the "generic" xdr routines used to serialize and de-serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#include +#include +#include +#include + +/* + * constants specific to the xdr "protocol" + */ +#define XDR_FALSE ((long) 0) +#define XDR_TRUE ((long) 1) +#define LASTUNSIGNED ((u_int) 0-1) + +/* + * for unit alignment + */ +static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; + +/* + * Free a data structure using XDR + * Not a filter, but a convenient utility nonetheless + */ +void +xdr_free(proc, objp) + xdrproc_t proc; + char *objp; +{ + XDR x; + + x.x_op = XDR_FREE; + (*proc)(&x, objp); +} + +/* + * XDR nothing + */ +bool_t +xdr_void(/* xdrs, addr */) + /* XDR *xdrs; */ + /* caddr_t addr; */ +{ + + return (TRUE); +} + +/* + * XDR integers + */ +bool_t +xdr_int(xdrs, ip) + XDR *xdrs; + int *ip; +{ + +#ifdef lint + (void) (xdr_short(xdrs, (short *)ip)); + return (xdr_long(xdrs, (long *)ip)); +#else + if (sizeof (int) == sizeof (long)) { + return (xdr_long(xdrs, (long *)ip)); + } else { + return (xdr_short(xdrs, (short *)ip)); + } +#endif +} + +/* + * XDR unsigned integers + */ +bool_t +xdr_u_int(xdrs, up) + XDR *xdrs; + u_int *up; +{ + +#ifdef lint + (void) (xdr_short(xdrs, (short *)up)); + return (xdr_u_long(xdrs, (u_long *)up)); +#else + if (sizeof (u_int) == sizeof (u_long)) { + return (xdr_u_long(xdrs, (u_long *)up)); + } else { + return (xdr_short(xdrs, (short *)up)); + } +#endif +} + +/* + * XDR long integers + * same as xdr_u_long - open coded to save a proc call! + */ +bool_t +xdr_long(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + + if (xdrs->x_op == XDR_ENCODE) + return (XDR_PUTLONG(xdrs, lp)); + + if (xdrs->x_op == XDR_DECODE) + return (XDR_GETLONG(xdrs, lp)); + + if (xdrs->x_op == XDR_FREE) + return (TRUE); + + return (FALSE); +} + +/* + * XDR unsigned long integers + * same as xdr_long - open coded to save a proc call! + */ +bool_t +xdr_u_long(xdrs, ulp) + register XDR *xdrs; + u_long *ulp; +{ + + if (xdrs->x_op == XDR_DECODE) + return (XDR_GETLONG(xdrs, (long *)ulp)); + if (xdrs->x_op == XDR_ENCODE) + return (XDR_PUTLONG(xdrs, (long *)ulp)); + if (xdrs->x_op == XDR_FREE) + return (TRUE); + return (FALSE); +} + +/* + * XDR short integers + */ +bool_t +xdr_short(xdrs, sp) + register XDR *xdrs; + short *sp; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *sp; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *sp = (short) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR unsigned short integers + */ +bool_t +xdr_u_short(xdrs, usp) + register XDR *xdrs; + u_short *usp; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *usp; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *usp = (u_short) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + + +/* + * XDR a char + */ +bool_t +xdr_char(xdrs, cp) + XDR *xdrs; + char *cp; +{ + int i; + + i = (*cp); + if (!xdr_int(xdrs, &i)) { + return (FALSE); + } + *cp = i; + return (TRUE); +} + +/* + * XDR an unsigned char + */ +bool_t +xdr_u_char(xdrs, cp) + XDR *xdrs; + char *cp; +{ + u_int u; + + u = (*cp); + if (!xdr_u_int(xdrs, &u)) { + return (FALSE); + } + *cp = u; + return (TRUE); +} + +/* + * XDR booleans + */ +bool_t +xdr_bool(xdrs, bp) + register XDR *xdrs; + bool_t *bp; +{ + long lb; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + lb = *bp ? XDR_TRUE : XDR_FALSE; + return (XDR_PUTLONG(xdrs, &lb)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &lb)) { + return (FALSE); + } + *bp = (lb == XDR_FALSE) ? FALSE : TRUE; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR enumerations + */ +bool_t +xdr_enum(xdrs, ep) + XDR *xdrs; + enum_t *ep; +{ +#ifndef lint + enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ + + /* + * enums are treated as ints + */ + if (sizeof (enum sizecheck) == sizeof (long)) { + return (xdr_long(xdrs, (long *)ep)); + } else if (sizeof (enum sizecheck) == sizeof (short)) { + return (xdr_short(xdrs, (short *)ep)); + } else { + return (FALSE); + } +#else + (void) (xdr_short(xdrs, (short *)ep)); + return (xdr_long(xdrs, (long *)ep)); +#endif +} + +/* + * XDR opaque data + * Allows the specification of a fixed size sequence of opaque bytes. + * cp points to the opaque object and cnt gives the byte length. + */ +bool_t +xdr_opaque(xdrs, cp, cnt) + register XDR *xdrs; + caddr_t cp; + register u_int cnt; +{ + register u_int rndup; + static int crud[BYTES_PER_XDR_UNIT]; + + /* + * if no data we are done + */ + if (cnt == 0) + return (TRUE); + + /* + * round byte count to full xdr units + */ + rndup = cnt % BYTES_PER_XDR_UNIT; + if (rndup > 0) + rndup = BYTES_PER_XDR_UNIT - rndup; + + if (xdrs->x_op == XDR_DECODE) { + if (!XDR_GETBYTES(xdrs, cp, cnt)) { + return (FALSE); + } + if (rndup == 0) + return (TRUE); + return (XDR_GETBYTES(xdrs, crud, rndup)); + } + + if (xdrs->x_op == XDR_ENCODE) { + if (!XDR_PUTBYTES(xdrs, cp, cnt)) { + return (FALSE); + } + if (rndup == 0) + return (TRUE); + return (XDR_PUTBYTES(xdrs, xdr_zero, rndup)); + } + + if (xdrs->x_op == XDR_FREE) { + return (TRUE); + } + + return (FALSE); +} + +/* + * XDR counted bytes + * *cpp is a pointer to the bytes, *sizep is the count. + * If *cpp is NULL maxsize bytes are allocated + */ +bool_t +xdr_bytes(xdrs, cpp, sizep, maxsize) + register XDR *xdrs; + char **cpp; + register u_int *sizep; + u_int maxsize; +{ + register char *sp = *cpp; /* sp is the actual string pointer */ + register u_int nodesize; + + /* + * first deal with the length since xdr bytes are counted + */ + if (! xdr_u_int(xdrs, sizep)) { + return (FALSE); + } + nodesize = *sizep; + if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) { + return (FALSE); + } + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) { + + case XDR_DECODE: + if (nodesize == 0) { + return (TRUE); + } + if (sp == NULL) { + *cpp = sp = (char *)mem_alloc(nodesize); + } + if (sp == NULL) { + (void) printf("xdr_bytes: out of memory\n"); + return (FALSE); + } + /* fall into ... */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, nodesize)); + + case XDR_FREE: + if (sp != NULL) { + mem_free(sp, nodesize); + *cpp = NULL; + } + return (TRUE); + } + return (FALSE); +} + +/* + * Implemented here due to commonality of the object. + */ +bool_t +xdr_netobj(xdrs, np) + XDR *xdrs; + struct netobj *np; +{ + + return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); +} + +/* + * XDR a descriminated union + * Support routine for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * an entry with a null procedure pointer. The routine gets + * the discriminant value and then searches the array of xdrdiscrims + * looking for that value. It calls the procedure given in the xdrdiscrim + * to handle the discriminant. If there is no specific routine a default + * routine may be called. + * If there is no specific or default routine an error is returned. + */ +bool_t +xdr_union(xdrs, dscmp, unp, choices, dfault) + register XDR *xdrs; + enum_t *dscmp; /* enum to decide which arm to work on */ + char *unp; /* the union itself */ + struct xdr_discrim *choices; /* [value, xdr proc] for each arm */ + xdrproc_t dfault; /* default xdr routine */ +{ + register enum_t dscm; + + /* + * we deal with the discriminator; it's an enum + */ + if (! xdr_enum(xdrs, dscmp)) { + return (FALSE); + } + dscm = *dscmp; + + /* + * search choices for a value that matches the discriminator. + * if we find one, execute the xdr routine for that value. + */ + for (; choices->proc != NULL_xdrproc_t; choices++) { + if (choices->value == dscm) + return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED)); + } + + /* + * no match - execute the default xdr routine if there is one + */ + return ((dfault == NULL_xdrproc_t) ? FALSE : + (*dfault)(xdrs, unp, LASTUNSIGNED)); +} + + +/* + * Non-portable xdr primitives. + * Care should be taken when moving these routines to new architectures. + */ + + +/* + * XDR null terminated ASCII strings + * xdr_string deals with "C strings" - arrays of bytes that are + * terminated by a NULL character. The parameter cpp references a + * pointer to storage; If the pointer is null, then the necessary + * storage is allocated. The last parameter is the max allowed length + * of the string as specified by a protocol. + */ +bool_t +xdr_string(xdrs, cpp, maxsize) + register XDR *xdrs; + char **cpp; + u_int maxsize; +{ + register char *sp = *cpp; /* sp is the actual string pointer */ + u_int size; + u_int nodesize; + + /* + * first deal with the length since xdr strings are counted-strings + */ + switch (xdrs->x_op) { + case XDR_FREE: + if (sp == NULL) { + return(TRUE); /* already free */ + } + /* fall through... */ + case XDR_ENCODE: + size = strlen(sp); + break; + default: + break; + } + if (! xdr_u_int(xdrs, &size)) { + return (FALSE); + } + if (size > maxsize) { + return (FALSE); + } + nodesize = size + 1; + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) { + + case XDR_DECODE: + if (nodesize == 0) { + return (TRUE); + } + if (sp == NULL) + *cpp = sp = (char *)mem_alloc(nodesize); + if (sp == NULL) { + (void) printf("xdr_string: out of memory\n"); + return (FALSE); + } + sp[size] = 0; + /* fall into ... */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, size)); + + case XDR_FREE: + mem_free(sp, nodesize); + *cpp = NULL; + return (TRUE); + } + return (FALSE); +} + +/* + * Wrapper for xdr_string that can be called directly from + * routines like clnt_call + */ +bool_t +xdr_wrapstring(xdrs, cpp) + XDR *xdrs; + char **cpp; +{ + if (xdr_string(xdrs, cpp, LASTUNSIGNED)) { + return (TRUE); + } + return (FALSE); +} diff --git a/c/src/lib/librpc/xdr_array.c b/c/src/lib/librpc/xdr_array.c new file mode 100644 index 0000000000..b3cd21f2f4 --- /dev/null +++ b/c/src/lib/librpc/xdr_array.c @@ -0,0 +1,157 @@ +/* @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_array.c, Generic XDR routines impelmentation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * arrays. See xdr.h for more info on the interface to xdr. + */ + + +#include /* printf */ +#include /* bcmp */ +#include /* free */ +#include +#include + +#define LASTUNSIGNED ((u_int)0-1) + + +/* + * XDR an array of arbitrary elements + * *addrp is a pointer to the array, *sizep is the number of elements. + * If addrp is NULL (*sizep * elsize) bytes are allocated. + * elsize is the size (in bytes) of each element, and elproc is the + * xdr procedure to call to handle each element of the array. + */ +bool_t +xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc) + register XDR *xdrs; + caddr_t *addrp; /* array pointer */ + u_int *sizep; /* number of elements */ + u_int maxsize; /* max numberof elements */ + u_int elsize; /* size in bytes of each element */ + xdrproc_t elproc; /* xdr routine to handle each element */ +{ + register u_int i; + register caddr_t target = *addrp; + register u_int c; /* the actual element count */ + register bool_t stat = TRUE; + register u_int nodesize; + + /* like strings, arrays are really counted arrays */ + if (! xdr_u_int(xdrs, sizep)) { + return (FALSE); + } + c = *sizep; + if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) { + return (FALSE); + } + nodesize = c * elsize; + + /* + * if we are deserializing, we may need to allocate an array. + * We also save time by checking for a null array if we are freeing. + */ + if (target == NULL) + switch (xdrs->x_op) { + case XDR_DECODE: + if (c == 0) + return (TRUE); + *addrp = target = mem_alloc(nodesize); + if (target == NULL) { + (void) printf( + "xdr_array: out of memory\n"); + return (FALSE); + } + bzero(target, nodesize); + break; + + case XDR_FREE: + return (TRUE); + default: + break; + } + + /* + * now we xdr each element of array + */ + for (i = 0; (i < c) && stat; i++) { + stat = (*elproc)(xdrs, target, LASTUNSIGNED); + target += elsize; + } + + /* + * the array may need freeing + */ + if (xdrs->x_op == XDR_FREE) { + mem_free(*addrp, nodesize); + *addrp = NULL; + } + return (stat); +} + +/* + * xdr_vector(): + * + * XDR a fixed length array. Unlike variable-length arrays, + * the storage of fixed length arrays is static and unfreeable. + * > basep: base of the array + * > size: size of the array + * > elemsize: size of each element + * > xdr_elem: routine to XDR each element + */ +bool_t +xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem) + register XDR *xdrs; + register char *basep; + register u_int nelem; + register u_int elemsize; + register xdrproc_t xdr_elem; +{ + register u_int i; + register char *elptr; + + elptr = basep; + for (i = 0; i < nelem; i++) { + if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) { + return(FALSE); + } + elptr += elemsize; + } + return(TRUE); +} + diff --git a/c/src/lib/librpc/xdr_mem.c b/c/src/lib/librpc/xdr_mem.c new file mode 100644 index 0000000000..280451a349 --- /dev/null +++ b/c/src/lib/librpc/xdr_mem.c @@ -0,0 +1,185 @@ +/* @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_mem.h, XDR implementation using memory buffers. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * If you have some data to be interpreted as external data representation + * or to be converted to external data representation in a memory buffer, + * then this is the package for you. + * + */ + + +#include /* bcopy */ +#include +#include +#include + +static bool_t xdrmem_getlong(); +static bool_t xdrmem_putlong(); +static bool_t xdrmem_getbytes(); +static bool_t xdrmem_putbytes(); +static u_int xdrmem_getpos(); +static bool_t xdrmem_setpos(); +static long * xdrmem_inline(); +static void xdrmem_destroy(); + +static struct xdr_ops xdrmem_ops = { + xdrmem_getlong, + xdrmem_putlong, + xdrmem_getbytes, + xdrmem_putbytes, + xdrmem_getpos, + xdrmem_setpos, + xdrmem_inline, + xdrmem_destroy +}; + +/* + * The procedure xdrmem_create initializes a stream descriptor for a + * memory buffer. + */ +void +xdrmem_create(xdrs, addr, size, op) + register XDR *xdrs; + caddr_t addr; + u_int size; + enum xdr_op op; +{ + + xdrs->x_op = op; + xdrs->x_ops = &xdrmem_ops; + xdrs->x_private = xdrs->x_base = addr; + xdrs->x_handy = size; +} + +static void +xdrmem_destroy(/*xdrs*/) + /*XDR *xdrs;*/ +{ +} + +static bool_t +xdrmem_getlong(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + + if ((xdrs->x_handy -= sizeof(long)) < 0) + return (FALSE); + *lp = (long)ntohl((u_long)(*((long *)(xdrs->x_private)))); + xdrs->x_private += sizeof(long); + return (TRUE); +} + +static bool_t +xdrmem_putlong(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + + if ((xdrs->x_handy -= sizeof(long)) < 0) + return (FALSE); + *(long *)xdrs->x_private = (long)htonl((u_long)(*lp)); + xdrs->x_private += sizeof(long); + return (TRUE); +} + +static bool_t +xdrmem_getbytes(xdrs, addr, len) + register XDR *xdrs; + caddr_t addr; + register u_int len; +{ + + if ((xdrs->x_handy -= len) < 0) + return (FALSE); + bcopy(xdrs->x_private, addr, len); + xdrs->x_private += len; + return (TRUE); +} + +static bool_t +xdrmem_putbytes(xdrs, addr, len) + register XDR *xdrs; + caddr_t addr; + register u_int len; +{ + + if ((xdrs->x_handy -= len) < 0) + return (FALSE); + bcopy(addr, xdrs->x_private, len); + xdrs->x_private += len; + return (TRUE); +} + +static u_int +xdrmem_getpos(xdrs) + register XDR *xdrs; +{ + + return ((u_int)xdrs->x_private - (u_int)xdrs->x_base); +} + +static bool_t +xdrmem_setpos(xdrs, pos) + register XDR *xdrs; + u_int pos; +{ + register caddr_t newaddr = xdrs->x_base + pos; + register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; + + if ((long)newaddr > (long)lastaddr) + return (FALSE); + xdrs->x_private = newaddr; + xdrs->x_handy = (int)lastaddr - (int)newaddr; + return (TRUE); +} + +static long * +xdrmem_inline(xdrs, len) + register XDR *xdrs; + int len; +{ + long *buf = 0; + + if (xdrs->x_handy >= len) { + xdrs->x_handy -= len; + buf = (long *) xdrs->x_private; + xdrs->x_private += len; + } + return (buf); +} diff --git a/c/src/lib/wrapup/Makefile.in b/c/src/lib/wrapup/Makefile.in index d7c6fcdaf9..5e73848490 100644 --- a/c/src/lib/wrapup/Makefile.in +++ b/c/src/lib/wrapup/Makefile.in @@ -19,6 +19,8 @@ SRCS=$(wildcard $(PROJECT_RELEASE)/lib/libbsp$(LIB_VARIANT).a) \ $(PROJECT_RELEASE)/lib/librtems$(LIB_VARIANT).a \ $(wildcard $(PROJECT_RELEASE)/lib/libposix$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/libnetworking$(LIB_VARIANT).a) \ + $(wildcard $(PROJECT_RELEASE)/lib/librpc$(LIB_VARIANT).a) \ + $(wildcard $(PROJECT_RELEASE)/lib/librdbg$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/libcpu$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/librtcio$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/libserialio$(LIB_VARIANT).a) \ diff --git a/c/src/librdbg/include/rdbg/i386/rdbg_f.h b/c/src/librdbg/include/rdbg/i386/rdbg_f.h new file mode 100644 index 0000000000..3fd087f50a --- /dev/null +++ b/c/src/librdbg/include/rdbg/i386/rdbg_f.h @@ -0,0 +1,53 @@ +/* + ************************************************************************** + * + * Component = RDBG + * Module = rdbg_f.h + * + * Synopsis = Machine-dependent header file + * + ************************************************************************** + */ + +#ifndef RDBG_F_H +#define RDBG_F_H + +#include +#include + +#define EFLAGS_TF 0x00100 + +typedef struct Exception_context_struct { + struct Exception_context_struct *next; + struct Exception_context_struct *previous; + Objects_Id id; + Objects_Id semaphoreId; + CPU_Exception_frame *ctx; +} Exception_context; + +extern int PushExceptCtx (Objects_Id Id, + Objects_Id semId, + CPU_Exception_frame *ctx); +extern int PopExceptCtx (Objects_Id Id); +extern Exception_context *GetExceptCtx (Objects_Id Id); +extern int Single_Step (CPU_Exception_frame* ctx); +extern int CheckForSingleStep (CPU_Exception_frame* ctx); +extern void BreakPointExcHdl (CPU_Exception_frame *ctx); +extern void CtxToRegs (const CPU_Exception_frame*,xdr_regs*); +extern void RegsToCtx (const xdr_regs*,CPU_Exception_frame*); + +extern void enterRdbg (); +extern void get_ctx_thread (Thread_Control *thread, + CPU_Exception_frame* ctx); +extern void set_ctx_thread (Thread_Control *thread, + CPU_Exception_frame* ctx); + +void copyback_data_cache_and_invalidate_instr_cache(); + +extern int ExitForSingleStep; + + +#endif + + + diff --git a/c/src/librdbg/include/rdbg/i386/reg.h b/c/src/librdbg/include/rdbg/i386/reg.h new file mode 100644 index 0000000000..d6b34f3c28 --- /dev/null +++ b/c/src/librdbg/include/rdbg/i386/reg.h @@ -0,0 +1,32 @@ + + +#define NBREGS 19 + +#define SS 18 +#define UESP 17 +#define EFL 16 +#define CS 15 +#define EIP 14 +#define ERR 13 +#define TRAPNO 12 +#define EAX 11 +#define ECX 10 +#define EDX 9 +#define EBX 8 +#define ESP 7 +#define EBP 6 +#define ESI 5 +#define EDI 4 +#define DS 3 +#define ES 2 +#define FS 1 +#define GS 0 + +typedef unsigned int regs[NBREGS]; + +/* To be used in common code */ +typedef regs REGS; + + + + diff --git a/c/src/librdbg/include/rdbg/rdbg.h b/c/src/librdbg/include/rdbg/rdbg.h new file mode 100644 index 0000000000..737edd5575 --- /dev/null +++ b/c/src/librdbg/include/rdbg/rdbg.h @@ -0,0 +1,53 @@ +/* + ************************************************************************** + * + * Component = RDBG + * + * Synopsis = rdbg.h + * + ************************************************************************** + */ + +#ifndef RDBG_H +#define RDBG_H + +#include +#include +#include +#include +#include /* For malloc() and free() prototypes */ +#include + +#define Malloc(size) malloc (size) +#define Free(block) free (block) +#define Realloc(block,size) realloc (block, size) +#define StrDup(str) strdup(str) + +#define LIST_PID 16 /* dynamic list of processes/tasks */ +#define LIST_PID_DEB 17 /* list of processes under debug now */ +#define LIST_PID_THREAD 18 /* list of threads for specific process */ +#define LIST_CONN 19 /* dynamic list of connections */ + + /* RTEMS internals */ +extern void remotedeb_2 (struct svc_req* rqstp, SVCXPRT* transp); +extern void setErrno (int error); +extern int getErrno (); +extern int ptrace (int request, int pid, char* addr, + int data, char* addr2); + +extern int TSP_RETRIES; +extern volatile int ExitForSingleStep; +extern volatile int justSaveContext; +extern volatile Objects_Id currentTargetThread; +extern volatile int CannotRestart; +extern volatile int TotalReboot; + + /* Missing RPC prototypes */ +SVCXPRT* svcudp_create (int fd); +void svc_processrequest (SVCXPRT* xprt, + u_long prog, u_long vers, + void (*dispatch)()); +int svcudp_enablecache (SVCXPRT *transp, u_long size); + +#endif /* !RDBG_H */ + diff --git a/c/src/librdbg/include/rdbg/servrpc.h b/c/src/librdbg/include/rdbg/servrpc.h new file mode 100644 index 0000000000..71198d4d1f --- /dev/null +++ b/c/src/librdbg/include/rdbg/servrpc.h @@ -0,0 +1,268 @@ + +#ifndef SERVRPC_H +#define SERVRPC_H + + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +extern int CONN_LIST_INC; +extern int PID_LIST_INC; +extern int TSP_RETRIES; +extern int BackPort; +extern char ActName[]; +extern int getId(); + + +#ifdef DDEBUG +int rdb_debug; /* True if env var RDB_DEBUG defined */ +extern const char* PtraceNames[]; /* list of ptrace requests for debug out */ +extern const char* BmsgNames[]; /* list of BMSG_xxx names */ +extern const char* PtraceName(int req); + +# define DPRINTF(a) (rdb_debug ? printk ("%d >>> ", getId()), printk a : 0) +#else +# define DPRINTF(a) /* suppress */ +#endif + + /* Macros for analyzing/creating process status values. Presently do + not need to be separated per target. Could even use WIF... */ + +#define STS_SIGNALLED(status) (((status) & 0xFF) == 0x7F) +#define STS_TERMONSIG(status) (((status) & 0xFF) && !STS_SIGNALLED(status)) +#define STS_TERMGETSIG(status) ((status) & 0x7F) +#define STS_MAKESIG(sig) (((sig) << 8) | 0x7f) +#define STS_GETSIG(status) ((status) >> 8) +#define STS_GETCODE(status) ((status) >> 8) + + +/* now define base types */ +#ifndef UCHAR_DEFINED +#define UCHAR_DEFINED /* to handle duplicate typedes */ +typedef unsigned char UCHAR; +typedef unsigned char UINT8; +typedef char INT8; +typedef unsigned short UINT16; +typedef short INT16; +typedef unsigned long UINT32; +typedef long INT32; +#endif /* UCHAR_DEFINED */ + +typedef long PID; /* generalized process id */ + +#ifndef True +# define True 1 +# define False 0 +typedef char Boolean; +#endif + +#define MAX_FILENAME 1024 /* largest filename with path */ +#define MAX_SEND 5 /* up to 5 pended outbound messages */ + +#define SERVER_VERS 1 + +typedef enum +{ /* message types */ + BMSG_WARM=1, /* warm test for network connection */ + BMSG_WAIT, /* wait change (stopped/started) */ + BMSG_BREAK, /* breakpoint changed */ + BMSG_EXEC_FAIL, /* exec failed from spawn */ + BMSG_DETACH, /* process detached from server */ + BMSG_KILLED, /* killed by server */ + BMSG_NOT_PRIM, /* no longer the primary owner */ + BMSG_NEW_PID /* the process was restart with new pid (in + context). Same ownership rules. */ +} BACK_MSG; + +typedef struct +{ /* this is the break_list[0] entry of pid */ + UCHAR clr_step; /* true if step off break in last_break */ + UCHAR pad1; /* Set if STEPEMUL breakpoints exist */ + UINT16 last_break; /* last breakpoint we stopped on (if break) */ + UINT32 range_start; /* start address of range */ + UINT32 range_end; /* end address inclusive */ +} BASE_BREAK; + +enum +{ /* last start values */ + LAST_NONE, /* stopped already */ + LAST_STEP, /* did a step last - do not send to prim */ + LAST_CONT, /* did a continue last */ + LAST_RANGE, /* in the middle of step-in-range */ + LAST_STEPOFF, /* stepped off break, now need to cont */ + LAST_KILLED, /* was killed by ptrace */ + LAST_DETACHED /* was detached by ptrace */ +}; +#define LAST_START 0x80 /* first execed. This is to handle MiX + bug where we need to start again */ + +typedef struct +{ /* one per open process */ + PID pid; /* process id (or 0 if free) */ + int state; /* status from last wait if stopped */ + UCHAR running; /* True if running, else stopped/term */ + /* now connection control over process */ + UCHAR owners; /* count of owners for notify and term release */ + UCHAR primary_conn; /* primary owner connection or 255=none */ + + UCHAR filler; /* Preserve alignment */ + + /* now break control and support */ + UINT8 last_start; /* LAST_xx start info for wait() */ + UINT8 flags; /* PIDFLG_xxx flags */ + UINT16 break_alloc; /* number of entries in break_list */ + xdr_break *break_list; /* list of breakpoints ([0] is BASE_BREAK) */ + /* now registers and other save information */ + xdr_regs regs; /* saved registers when stopped */ + int is_step; /* Was break or step (regs ambiguous often) */ + int stop_wanted; /* Don't ignore next stop */ + UINT32 thread; /* current stopped thread or -1 if none */ + char *name; /* full pathname or NULL if not known */ + INT32 child; /* child pid that manages the pid */ + UINT32 textStart; /* for relocating breakpoints at restart */ +} PID_LIST; +PID_LIST *pid_list; /* array of processes being managed */ +int pid_list_cnt; /* number of entries allocated */ +UINT16 last_break; /* unique handle generator for breaks */ +#define NO_PRIMARY ((UCHAR)-1) + +typedef union +{ /* an opaque net address */ + unsigned long l[4]; + unsigned char c[16]; /* corresponds to IP, enough for ChIPC */ +} NET_OPAQUE; + +typedef struct +{ /* one per connection */ + UCHAR in_use; /* True if in use */ + UCHAR debug_type; /* type of connection */ + UINT16 flags; /* flags for connection (CFLG_xxx) */ + NET_OPAQUE sender; /* opaque address for transport compare */ + NET_OPAQUE back_port; /* opaque address for transport event msgs */ + NET_OPAQUE route; /* optional route address */ + UINT32 pid_map[10]; /* map of pids owned relative to pid list */ + /* this allows up to 320 pids to be managed */ + UCHAR last_msg_num; /* msg number used last to handle multi-send */ + /* next field associated with UDP send messages */ + UCHAR retry; /* count of retries. If 0, ok. If not 0, we + are in active wait for reply to an event */ + UCHAR send_idx; /* current number of send's pended */ + struct SEND_LIST + { /* holds pending msgs */ + UCHAR send_type; /* BMSG_xxx type of message */ + UCHAR retry; /* number of times to retry */ + UINT16 spec; /* spec field */ + PID pid; /* pid if applies */ + UINT32 context; /* additional context if needed */ + } send_list[MAX_SEND]; /* pended list of messages being sent */ + char user_name[NAMEMAX]; /* name of user connecting in */ + /* next fields are managed at runtime to handle lists, command upload, and + command download. */ + enum {LST_NONE, LST_SPAWN, LST_INFO, LST_CMD_DOWN} list_type; + char *list; /* curr list we are sending/getting (malloced) */ + UINT16 list_sz; /* size of current list (string len) */ + UINT16 list_num; /* number of current list or position */ + UINT16 list_alloc; /* amount allocated so far */ + UINT16 list_save; /* used internally */ +} CONN_LIST; +CONN_LIST *conn_list; /* an array of connections */ +int conn_list_cnt; /* number allocated */ + + /* Operations over the PID map. Each indexes into long and then bit */ + /* 5 is log2 of 32, the number of bits in an int */ +#define PIDMAP_TEST(conn,idx) \ + (conn_list [conn].pid_map [(idx) >> 5] & (1 << ((idx) & 31))) + +#define PIDMAP_SET(conn,idx) \ + (conn_list [conn].pid_map [(idx) >> 5] |= 1 << ((idx) & 31)) + +#define PIDMAP_CLEAR(conn,idx) \ + (conn_list [conn].pid_map [(idx) >> 5] &= ~(1 << ((idx) &31))) + +#define PROC_TERMINATED(plst) \ + (!(plst)->running && !STS_SIGNALLED ((plst)->state)) + + +/* first define the Connection routines exported from servcon.c */ + +int ConnCreate (struct svc_req *rqstp, open_in *in); +void ConnDelete (int conn_idx, struct svc_req *rqstp, close_control control); + +void TspInit (int rpc_io_channel); +Boolean TspTranslateRpcAddr (struct svc_req *rqstp, NET_OPAQUE *opaque); +Boolean TspValidateAddr (NET_OPAQUE *opaque, NET_OPAQUE *sender); +int TspConnGetIndex (struct svc_req *rqstp); + +void TspSendWaitChange (int conn_idx, BACK_MSG msg, UINT16 spec, PID pid, + UINT32 context, Boolean force); +void TspSendMessage (int conn_idx, Boolean resend); +void TspMessageReceive (int conn_idx, PID pid); +char* TspGetHostName (int conn_idx); +void TgtCreateNew (PID pid, int conn_idx, INT32 child, + char *name, Boolean spawn); +Boolean TgtAttach (int conn_idx, PID pid); +void TgtNotifyWaitChange(PID pid, int status, Boolean exclude); +void TgtNotifyAll (int pid_idx, BACK_MSG msg, UINT16 spec, + UINT32 context, int exclude_conn, Boolean force); +void TgtDelete (PID_LIST*, int conn_idx, BACK_MSG notify); +int TgtKillAndDelete (PID_LIST *plst, struct svc_req *rqstp, Boolean term); +void TgtDetachCon (int conn_idx, int pid_idx, Boolean delete); +int TgtThreadList (PID_LIST*, unsigned* buf, unsigned int size); +int TgtGetThreadName (PID_LIST*, unsigned thLi, char* name); +int TgtPtrace (int req, PID pid, char *addr, int data, void *addr2); +int TgtRealPtrace (int req, PID pid, char *addr, int data, void *addr2); +Boolean TgtHandleChildChange(PID pid, int* status, int* unexp, + CPU_Exception_frame *ctx); +#ifdef DDEBUG + /* TgtDbgPtrace is a wrapper for RealPtrace() doing traces */ +int TgtDbgPtrace (int req, PID pid, char *addr, int data, void *addr2); +#endif + + +/* Information stored in "handle" */ +#define BKPT_INACTIVE 1 /* bkpt inactive for this execution */ +#define BKPT_ACTIVE 0 /* bkpt active for this execution */ + +int BreakOverwrite (const PID_LIST* plst,const char* addr, + unsigned int size); +int BreakSet (PID_LIST*, int conn_idx, xdr_break*); +int BreakSetAt (PID_LIST*, int conn_idx, unsigned long addr,break_type); +int BreakClear (PID_LIST*, int conn_idx, int handle); +int BreakGetIndex (PID_LIST*, void* addr); +int BreakGet (const PID_LIST*, int data, xdr_break*); +void BreakHide (const PID_LIST*, void*, int, void*); +int BreakStepOff (const PID_LIST*, void** paddr2); +void BreakSteppedOff (PID_LIST*); +int BreakRespawn (PID_LIST*); +int BreakIdentify (PID_LIST*, int adjust, int thread); +void BreakPcChanged (PID_LIST*); +int BreakStepRange (PID_LIST*, void* addr, int len); +void BreaksDisable (int pid); +void BreaksEnable (int pid); + +int TgtBreakRestoreOrig (int pid, void* addr, void* addr2); +void TgtBreakCancelStep (PID_LIST* plst); + +Boolean ListAlloc (char *buff, CONN_LIST *clst); +int FindPidEntry (int pid); + +open_out* RPCGENSRVNAME(open_connex_2_svc) (open_in *in, + struct svc_req *rqstp); +signal_out* RPCGENSRVNAME(send_signal_2_svc) (signal_in *in, + struct svc_req *rqstp); +ptrace_out* RPCGENSRVNAME(ptrace_2_svc) (ptrace_in *in, + struct svc_req *rqstp); +wait_out* RPCGENSRVNAME(wait_info_2_svc) (wait_in *in, + struct svc_req *rqstp); +#endif /* !SERVRPC_H */ + diff --git a/c/src/librdbg/src/Makefile.in b/c/src/librdbg/src/Makefile.in new file mode 100644 index 0000000000..8d4a72ca96 --- /dev/null +++ b/c/src/librdbg/src/Makefile.in @@ -0,0 +1,96 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +VPATH = @srcdir@:@srcdir@/$(RTEMS_CPU) +RTEMS_ROOT = @top_srcdir@ +PROJECT_ROOT = @PROJECT_ROOT@ + +LIBNAME=librdbg.a +LIB=${ARCH}/${LIBNAME} + +# C and C++ source names, if any, go here -- minus the .c or .cc +C_PIECES= rdbg servcon servbkpt servrpc excep \ + servtgt servtsp servutil _servtgt rdbg_f \ + ptrace +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +# Asm source names, if any, go here -- minus the .s +ASM_PIECES= rdbg_cpu_asm +ASM_FILES=$(ASM_PIECES:%=%.s) +ASM_O_FILES=$(ASM_PIECES:%=${ARCH}/%.o) + +# Generated C source names, if any, go here -- minus the .c +C_GEN_PIECES= remdeb_xdr remdeb_svc +C_GEN_FILES=$(C_GEN_PIECES:%=%.c) +C_GEN_O_FILES=$(C_GEN_PIECES:%=${ARCH}/%.o) + +# H source names, if any, go here -- minus the .h +H_PIECES=remdeb +H_FILES=$(H_PIECES:%=%.h) + +# X source names, if any, go here -- minus the .x +X_FILE1=remdeb.x +X_FILE2=remdeb_f.x +X_FILES=$(X_FILE1) $(X_FILE2) + +SRCS=$(C_FILES) $(ASM_FILES) +OBJS=$(X_FILES) $(H_FILES) $(C_GEN_FILES) $(C_GEN_O_FILES) $(C_O_FILES) $(ASM_O_FILES) + +RPCGEN=rpcgen +AWK=awk + +include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg +include $(RTEMS_ROOT)/make/lib.cfg + +# +# Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += $(LIB) $(H_FILES) $(X_FILES) $(C_GEN_FILES) +CLOBBER_ADDITIONS += + +all: ${ARCH} $(LIB) + $(INSTALL_VARIANT) -m 644 $(LIB) ${PROJECT_RELEASE}/lib + +$(LIB): $(SRCS) ${OBJS} + $(make-library) + +remdeb.h: $(X_FILES) + @rm -f $@ + $(RPCGEN) -h remdeb.x -o $@ + @rm -f $(PROJECT_INCLUDE)/rdbg/$@ + $(INSTALL) -m 444 $@ $(PROJECT_INCLUDE)/rdbg + +remdeb_xdr.c: $(X_FILES) + @rm -f $@ + $(RPCGEN) -c remdeb.x -o $@ + +remdeb_svc.c: $(X_FILES) + @rm -f $@ tmpSvc.c + $(RPCGEN) -s udp remdeb.x -o tmpSvc.c + $(AWK) -f @srcdir@/awk.svc THEPROG="remdeb.h" tmpSvc.c >$@ + @rm -f tmpSvc.c + +preinstall: + @rm -f $(X_FILES) + @cp @srcdir@/$(X_FILE1) . + @cp @srcdir@/$(RTEMS_CPU)/$(RTEMS_BSP)/$(X_FILE2) . + + + + diff --git a/c/src/librdbg/src/_servtgt.c b/c/src/librdbg/src/_servtgt.c new file mode 100644 index 0000000000..184415a1e2 --- /dev/null +++ b/c/src/librdbg/src/_servtgt.c @@ -0,0 +1,360 @@ +/* + ============================================================================ + _SERVTGT + ============================================================================ +*/ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +extern void rtems_exception_prologue_50(); + + +#ifdef DDEBUG +#define Ptrace TgtDbgPtrace +#else +#define Ptrace TgtRealPtrace +#endif + +extern int errno; + +rtems_id eventTaskId; +rtems_id serializeSemId; +rtems_id wakeupEventSemId; + +CPU_Exception_frame Idle_frame; + +cpuExcHandlerType old_currentExcHandler; + +/* ----------------------------------------------------------------- + TgtRealPtrace - lowest level ptrace() wrapper + ----------------------------------------------------------------- */ + + int +TgtRealPtrace(int req, PID aid, char* addr, int d, void* addr2) +{ + return ptrace(req, aid, addr, d, addr2); +} + + +/* ----------------------------------------------------------------- + Maping of hardware exceptions into Unix-like signal numbers. + It is identical to the one used by the PM and the AM. + ----------------------------------------------------------------- */ + + int +ExcepToSig (int excep) +{ + switch (excep) { + + case I386_EXCEPTION_MATH_COPROC_UNAVAIL: + case I386_EXCEPTION_I386_COPROC_SEG_ERR: + case I386_EXCEPTION_FLOAT_ERROR: + case I386_EXCEPTION_BOUND: + return SIGFPE; + + case I386_EXCEPTION_DEBUG: + case I386_EXCEPTION_BREAKPOINT: + case I386_EXCEPTION_ENTER_RDBG: + return SIGTRAP; + + case I386_EXCEPTION_OVERFLOW: + case I386_EXCEPTION_DIVIDE_BY_ZERO: + case I386_EXCEPTION_ILLEGAL_INSTR: + return SIGILL; + + case I386_EXCEPTION_SEGMENT_NOT_PRESENT: + case I386_EXCEPTION_STACK_SEGMENT_FAULT: + case I386_EXCEPTION_GENERAL_PROT_ERR: + case I386_EXCEPTION_PAGE_FAULT: + return SIGSEGV; + + default: + break; + } + return SIGKILL; +} + +/* ----------------------------------------------------------------------- + TgtChange() is called when the system stops. + It informs the generic layers must be informed of + that fact. + ----------------------------------------------------------------------- */ + + static int +TgtChange (PID pid, CPU_Exception_frame* ctx, int status) +{ + + if (TgtHandleChildChange (pid, &status, NULL, ctx)) { + TgtNotifyWaitChange (pid, status, -1); + } + + return 0; +} + +/* ----------------------------------------------------------------------- + eventTask + ----------------------------------------------------------------------- */ + +rtems_task eventTask( rtems_task_argument pid) +{ + Exception_context *ctx; + + DPRINTF (("event task: pid %d\n", pid)); + + + /* + * we spend all our time waiting for a semaphore. + * If wait change, we send info + */ + + for (;;){ + DPRINTF (("Event Task: wait event\n")); + rtems_semaphore_obtain(wakeupEventSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + DPRINTF (("Event Task: wake up !!!!!!!!!!!!!\n")); + + errno = 0; + ctx = GetExceptCtx(currentTargetThread); + + CheckForSingleStep(ctx->ctx); + + TgtChange(pid, ctx->ctx,STS_MAKESIG(ExcepToSig(ctx->ctx->idtIndex))); + + } +} + +/* ------------------------------------------------------------------- + MyThreadIdle - + + This task is used to initiate the exception mechanism: + It calls the enterDebug function with justSaveContext=1 + only to push a first valid context in the list + ---------------------------------------------------------------------*/ + +rtems_task MyThreadIdle(rtems_task_argument argument) +{ + enterRdbg(); + rtems_task_delete( RTEMS_SELF ); +} + +/* ----------------------------------------------------------------------- + TgtAttach - attach to a process that is running without control. + + Notes: + - this function performs a ptrace ATTACH equivalent (attaching to a + process that we do not control now). + ----------------------------------------------------------------------- */ + +Boolean TgtAttach( + int conn_idx, /* client that is requesting */ + PID pid) /* process to attach to */ +{ + rtems_name task_name; + rtems_status_code status; + rtems_id debugId; + interrupt_gate_descriptor *currentIdtEntry; + unsigned limit; + unsigned level; + + errno = 0; + + DPRINTF (("TgtAttach pid=%d\n",pid)); + + Ptrace(RPT_ATTACH, pid, NULL, 0, NULL); + if (errno) + return(False); /* failed */ + + TgtCreateNew(pid, conn_idx, 0, NULL, False); + + + /* + * Connect the Exception used to debug + */ + i386_get_info_from_IDTR (¤tIdtEntry, &limit); + + _CPU_ISR_Disable(level); + create_interrupt_gate_descriptor (¤tIdtEntry[50], rtems_exception_prologue_50); + _CPU_ISR_Enable(level); + + old_currentExcHandler = _currentExcHandler; + _currentExcHandler = BreakPointExcHdl ; + + + /* + * Create the attach debuger task + */ + task_name = rtems_build_name( 'E', 'v', 'n', 't' ); + if ((status = rtems_task_create( task_name, 10, 24576, + RTEMS_INTERRUPT_LEVEL(0), + RTEMS_DEFAULT_ATTRIBUTES | RTEMS_SYSTEM_TASK, + &eventTaskId )) + != RTEMS_SUCCESSFUL){ + printf("status = %d\n",status); + rtems_panic ("Can't create task.\n"); + } + + status = rtems_task_start(eventTaskId, eventTask, pid); + + status = rtems_semaphore_create (rtems_build_name('D', 'B', 'G', 's'), + 1, + RTEMS_FIFO | + RTEMS_COUNTING_SEMAPHORE | + RTEMS_NO_INHERIT_PRIORITY | + RTEMS_NO_PRIORITY_CEILING | + RTEMS_LOCAL, + 0, + &serializeSemId); + if (status != RTEMS_SUCCESSFUL) + rtems_panic ("Can't create serialize semaphore: `%s'\n",rtems_status_text(status)); + + status = rtems_semaphore_create (rtems_build_name('D', 'B', 'G', 'w'), + 0, + RTEMS_FIFO | + RTEMS_COUNTING_SEMAPHORE | + RTEMS_NO_INHERIT_PRIORITY | + RTEMS_NO_PRIORITY_CEILING | + RTEMS_LOCAL, + 0, + &wakeupEventSemId); + if (status != RTEMS_SUCCESSFUL) + rtems_panic ("Can't create wakeup semaphore: `%s'\n",rtems_status_text(status)); + + /* + * Create the MyThreadIdle task to init Exception mechanism + */ + task_name = rtems_build_name( 'R', 'i', 'n', 'i' ); + if ((status = rtems_task_create( task_name, 10, 24576, + RTEMS_INTERRUPT_LEVEL(0), + RTEMS_DEFAULT_ATTRIBUTES, + &debugId )) + != RTEMS_SUCCESSFUL){ + printf("status = %d\n",status); + rtems_panic ("Can't create task.\n"); + } + + status = rtems_task_start(debugId, MyThreadIdle, pid); + + return(True); +} + +/* ----------------------------------------------------------------------- + TgtPtrace - handle ptrace requests for server. + ----------------------------------------------------------------------- */ + +int TgtPtrace( + int req, + PID pid, + char *addr, + int data, + void *addr2) +{ + if ((req == RPT_SINGLESTEP || req == RPT_CONT) + && addr2) /* clear then step */ + { /* addr2 is the old value */ + int ret; + + errno = 0; + TgtBreakRestoreOrig (pid, addr, addr2); + ret = Ptrace(RPT_SINGLESTEP, pid, addr, data, NULL); /* step over */ + if (ret) /* error, cannot single-step */ + { + int pid_idx = FindPidEntry (pid); + TgtBreakCancelStep (&pid_list [pid_idx]); + } + return(ret); /* failed or done */ + } + else + return(Ptrace(req, pid, addr, data, addr2)); /* normal call */ +} + +/* ----------------------------------------------------------------- + TgtGetThreadName - get thread name + --------------------------------------------------------------- */ + +int TgtGetThreadName ( + PID_LIST *plst, /* Process entry */ + unsigned Id, /* Thread ID */ + char *ThrName) /* Thread name */ +{ + int index; + unsigned name; + + if ( Id <_Objects_Information_table[OBJECTS_RTEMS_TASKS]->maximum_id && + Id >_Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id) { + + index = Id - _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; + name = *(unsigned*)(_Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index]->name); + ThrName[0] = (char)((name >> 24) & 0xFF ); + ThrName[1] = (char)((name >> 16) & 0xFF ); + ThrName[2] = (char)((name >> 8) & 0xFF ); + ThrName[3] = (char)( name & 0xFF ); + ThrName[4] = 0x0; + return 0; + } + + if ( Id <_Objects_Information_table[OBJECTS_POSIX_THREADS]->maximum_id && + Id >_Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id) { + + index = Id - _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; + name = *(unsigned*)(_Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index]->name); + ThrName[0] = (char)((name >> 24) & 0xFF ); + ThrName[1] = (char)((name >> 16) & 0xFF ); + ThrName[2] = (char)((name >> 8) & 0xFF ); + ThrName[3] = (char)( name & 0xFF ); + ThrName[4] = 0x0; + return 0; + } + + + return -1; + +} + +/* ----------------------------------------------------------------- + TgtThreadList - return all the threads in the system + ----------------------------------------------------------------- */ + + int +TgtThreadList ( + PID_LIST* plst, /* Process entry */ + unsigned* threads, /* Output buffer */ + unsigned size) /* Output buffer size */ +{ + int curr = 0; + Objects_Id id; + unsigned index; + + id = _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; + + while (id < _Objects_Information_table[OBJECTS_RTEMS_TASKS]->maximum_id){ + index = id - _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; + if ( _Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index] != NULL){ + threads[curr] = (unsigned) id; + curr++; + } + id ++; + } + + id = _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; + + while (id < _Objects_Information_table[OBJECTS_POSIX_THREADS]->maximum_id){ + index = id - _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; + if ( _Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index] != NULL){ + threads[curr] = (unsigned) id; + curr++; + } + id ++; + } + + return curr; +} diff --git a/c/src/librdbg/src/awk.svc b/c/src/librdbg/src/awk.svc new file mode 100644 index 0000000000..79e24a9d90 --- /dev/null +++ b/c/src/librdbg/src/awk.svc @@ -0,0 +1,65 @@ +######################################################################### +# +# Component: RDBG +# Module: awk.svc +# +# Synopsis: AWK script which transforms the server skeleton produced +# by rpcgen(1) into something suitable for RDB servers. +# +######################################################################### + +BEGIN { + headerstarted = 0 + withinproc = 0 + brack = 0 +} + +$1 ~ /^\/\*HEADER_START\*\/$/ { + headerstarted = 1 + printf("#include \n"); + printf("#include \n"); + printf("#include \n"); + printf("#include \n"); + printf("#include \n"); + printf("#include \n"); + printf("#include \n"); + printf("#include \n", THEPROG); + printf("#define fprintf(a,b) printf(b)\n"); + printf("#define msgout(a) printf(a)\n") + printf("#define _msgout(a) fprintf(stderr,a)\n"); +} + +$1 ~ /^\/\*HEADER_END\*\/$/ { + headerstarted = 0 +} + +{ + if (headerstarted == 1) { + print $0 + } else if ($1 ~ /.*_2.*/) { + withinproc = 1 + printf("void\n"); + print $0 + } else if (withinproc == 1) { + if ($1 == "switch") { + print "\tDPRINTF ((\"remotedeb_2: %s (%d)\\n\", " + print "\t\t(unsigned) rqstp->rq_proc < " + print "\t\t(unsigned) (sizeof names / sizeof names[0]) ?" + print "\t\tnames [rqstp->rq_proc] : \"???\", " + print "\t\t(int) rqstp->rq_proc));\n" + } + for (i = 1; i <= NF; i++) { + if ($i == "{") { + brack++; + } else if ($i == "}") { + brack--; + if (brack == 0) { + withinproc = 0; + } + } + } + if ($1 != "_rpcsvcdirty" ) { + print $0 + } + } +} diff --git a/c/src/librdbg/src/i386/any/remdeb_f.x b/c/src/librdbg/src/i386/any/remdeb_f.x new file mode 100644 index 0000000000..0ff52d1307 --- /dev/null +++ b/c/src/librdbg/src/i386/any/remdeb_f.x @@ -0,0 +1,58 @@ +/* + ************************************************************************** + * + * Component = rdblib + * + * Synopsis = remdeb_f.x + * + * + ************************************************************************** + */ + +struct xdr_regs +{ + unsigned int tabreg[19]; +}; + +#ifdef RPC_HDR + +%/* now define register macros to apply to xdr_reg struct */ +% +%#define GS 0 +%#define FS 1 +%#define ES 2 +%#define DS 3 +%#define EDI 4 +%#define ESI 5 +%#define EBP 6 +%#define ESP 7 +%#define EBX 8 +%#define EDX 9 +%#define ECX 10 +%#define EAX 11 +%#define TRAPNO 12 +%#define ERR 13 +%#define EIP 14 +%#define CS 15 +%#define EFL 16 +%#define UESP 17 +%#define SS 18 +% +%#define REG_PC tabreg[EIP] /* PC (eip) register offset */ +%#define REG_SP tabreg[UESP] /* SP (uesp) register offset */ +%#define REG_FP tabreg[EBP] /* FP (ebp) register offset */ + +%/* now define the BREAKPOINT mask technique to a long word */ +%#define SET_BREAK(l) ((l&0xFFFFFF00) | 0xCC) +%#define IS_BREAK(l) (((l) & 0xFF) == 0xCC) +%#define ORG_BREAK(c,p) (((c) & 0xFFFFFF00) | ((p) & 0xFF)) +%#define IS_STEP(regs) (regs.tabreg[TRAPNO] == 1) /* was step and not break */ +%#define BREAK_ADJ 1 /* must subtract one from address after bp */ +%#define BREAK_SIZE 1 /* Breakpoint occupies one byte */ + +%#define TARGET_PROC_TYPE 0 + +#endif + + + diff --git a/c/src/librdbg/src/i386/excep.c b/c/src/librdbg/src/i386/excep.c new file mode 100644 index 0000000000..5ca1fd8df6 --- /dev/null +++ b/c/src/librdbg/src/i386/excep.c @@ -0,0 +1,233 @@ +/* + ************************************************************************** + * + * Component = + * + * Synopsis = rdbg/i386/excep.c + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include + + +extern rtems_id serializeSemId; +extern rtems_id wakeupEventSemId; + + +unsigned int NbExceptCtx; +volatile unsigned int NbSerializedCtx; +Exception_context *FirstCtx = NULL; +Exception_context *LastCtx = NULL; + +CPU_Exception_frame SavedContext; + + +/********* Save an exception context at the end of a list *****/ + +int PushExceptCtx ( Objects_Id Id, Objects_Id semId, CPU_Exception_frame *ctx ) { + + Exception_context *SaveCtx; + + SaveCtx = (Exception_context *)malloc(sizeof(Exception_context)); + if (SaveCtx == NULL) + rtems_panic("Can't allocate memory to save Exception context"); + + SaveCtx->id = Id; + SaveCtx->ctx = ctx; + SaveCtx->semaphoreId = semId; + SaveCtx->previous = NULL; + SaveCtx->next = NULL; + + if (FirstCtx == NULL){ /* initialization */ + FirstCtx = SaveCtx; + LastCtx = SaveCtx; + NbExceptCtx = 1; + } + else { + NbExceptCtx ++; + LastCtx->next = SaveCtx; + SaveCtx->previous = LastCtx; + LastCtx = SaveCtx; + } + return 0; +} + +/********* Save an temporary exception context in a ******/ +/********* global variable ******/ + +int PushSavedExceptCtx ( Objects_Id Id, CPU_Exception_frame *ctx ) { + + memcpy (&(SavedContext), ctx, sizeof(CPU_Exception_frame)); + return 0; +} + + +/****** Remove the context of the specified Id thread *********/ +/****** If Id = -1, then return the first context *********/ + + +int PopExceptCtx ( Objects_Id Id ) { + + Exception_context *ExtractCtx; + + if (FirstCtx == NULL) return -1; + + if (Id == -1) { + ExtractCtx = LastCtx; + LastCtx = LastCtx->previous; + free(ExtractCtx); + NbExceptCtx --; + return 0; + } + + ExtractCtx = LastCtx; + + while (ExtractCtx->id != Id && ExtractCtx != NULL) { + ExtractCtx = ExtractCtx->previous; + } + + if (ExtractCtx == NULL) + return -1; + + if ( ExtractCtx->previous != NULL) + (ExtractCtx->previous)->next = ExtractCtx->next; + + if ( ExtractCtx->next != NULL) + (ExtractCtx->next)->previous = ExtractCtx->previous; + + if (ExtractCtx == FirstCtx) + FirstCtx = FirstCtx->next; + else + if (ExtractCtx == LastCtx) + LastCtx = LastCtx->previous; + + free(ExtractCtx); + NbExceptCtx --; + return 0; +} + +/****** Return the context of the specified Id thread *********/ +/****** If Id = -1, then return the first context *********/ + + +Exception_context *GetExceptCtx ( Objects_Id Id ) { + + Exception_context *ExtractCtx; + + if (FirstCtx == NULL) return NULL; + + if (Id == -1) { + return LastCtx; + } + + ExtractCtx = LastCtx; + + while (ExtractCtx->id != Id && ExtractCtx != NULL) { + ExtractCtx = ExtractCtx->previous; + } + + if (ExtractCtx == NULL) + return NULL; + + return ExtractCtx; +} + +/*----- Breakpoint Exception management -----*/ + + /* + * Handler for Breakpoint Exceptions : + * software breakpoints. + */ + +void +BreakPointExcHdl(CPU_Exception_frame *ctx) +{ + rtems_status_code status; + rtems_id continueSemId; + + if ( (justSaveContext) && (ctx->idtIndex == I386_EXCEPTION_ENTER_RDBG) ) { + PushSavedExceptCtx (_Thread_Executing->Object.id, ctx); + justSaveContext = 0; + } + else { + if (ctx->idtIndex != DEBUG){ + NbSerializedCtx++; + rtems_semaphore_obtain(serializeSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + NbSerializedCtx--; + } + + currentTargetThread = _Thread_Executing->Object.id; + +#ifdef DDEBUG + printk("----------------------------------------------------------\n"); + printk("Exception %d caught at PC %x by thread %d\n", + ctx->idtIndex, + ctx->eip, + _Thread_Executing->Object.id); + printk("----------------------------------------------------------\n"); + printk("Processor execution context at time of the fault was :\n"); + printk("----------------------------------------------------------\n"); + printk(" EAX = %x EBX = %x ECX = %x EDX = %x\n", + ctx->eax, ctx->ebx, ctx->ecx, ctx->edx); + printk(" ESI = %x EDI = %x EBP = %x ESP = %x\n", + ctx->esi, ctx->edi, ctx->ebp, ctx->esp0); + printk("----------------------------------------------------------\n"); + printk("Error code pushed by processor itself (if not 0) = %x\n", + ctx->faultCode); + printk("----------------------------------------------------------\n\n"); +#endif + + status = rtems_semaphore_create (rtems_build_name('D', 'B', 'G', 'c'), + 0, + RTEMS_FIFO | + RTEMS_COUNTING_SEMAPHORE | + RTEMS_NO_INHERIT_PRIORITY | + RTEMS_NO_PRIORITY_CEILING | + RTEMS_LOCAL, + 0, + &continueSemId); + if (status != RTEMS_SUCCESSFUL) + rtems_panic ("Can't create continue semaphore: `%s'\n",rtems_status_text(status)); + + PushExceptCtx (_Thread_Executing->Object.id, continueSemId, ctx); + + switch (ctx->idtIndex){ + case I386_EXCEPTION_DEBUG: + DPRINTF((" DEBUG EXCEPTION !!!\n")); + ctx->eflags &= ~EFLAGS_TF; + ExitForSingleStep-- ; + rtems_semaphore_release( wakeupEventSemId ); + break; + + case I386_EXCEPTION_BREAKPOINT: + DPRINTF((" BREAKPOINT EXCEPTION !!!\n")); + rtems_semaphore_release( wakeupEventSemId ); + break; + + case I386_EXCEPTION_ENTER_RDBG: + DPRINTF((" ENTER RDBG !!!\n")); + rtems_semaphore_release( wakeupEventSemId ); + break; + + default: + DPRINTF((" OTHER EXCEPTION !!!\n")); + rtems_semaphore_release( wakeupEventSemId ); + break; + } + + rtems_semaphore_obtain(continueSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + + PopExceptCtx (_Thread_Executing->Object.id); + rtems_semaphore_delete(continueSemId); + } +} + + + diff --git a/c/src/librdbg/src/i386/pc386/remdeb_f.x b/c/src/librdbg/src/i386/pc386/remdeb_f.x new file mode 100644 index 0000000000..0ff52d1307 --- /dev/null +++ b/c/src/librdbg/src/i386/pc386/remdeb_f.x @@ -0,0 +1,58 @@ +/* + ************************************************************************** + * + * Component = rdblib + * + * Synopsis = remdeb_f.x + * + * + ************************************************************************** + */ + +struct xdr_regs +{ + unsigned int tabreg[19]; +}; + +#ifdef RPC_HDR + +%/* now define register macros to apply to xdr_reg struct */ +% +%#define GS 0 +%#define FS 1 +%#define ES 2 +%#define DS 3 +%#define EDI 4 +%#define ESI 5 +%#define EBP 6 +%#define ESP 7 +%#define EBX 8 +%#define EDX 9 +%#define ECX 10 +%#define EAX 11 +%#define TRAPNO 12 +%#define ERR 13 +%#define EIP 14 +%#define CS 15 +%#define EFL 16 +%#define UESP 17 +%#define SS 18 +% +%#define REG_PC tabreg[EIP] /* PC (eip) register offset */ +%#define REG_SP tabreg[UESP] /* SP (uesp) register offset */ +%#define REG_FP tabreg[EBP] /* FP (ebp) register offset */ + +%/* now define the BREAKPOINT mask technique to a long word */ +%#define SET_BREAK(l) ((l&0xFFFFFF00) | 0xCC) +%#define IS_BREAK(l) (((l) & 0xFF) == 0xCC) +%#define ORG_BREAK(c,p) (((c) & 0xFFFFFF00) | ((p) & 0xFF)) +%#define IS_STEP(regs) (regs.tabreg[TRAPNO] == 1) /* was step and not break */ +%#define BREAK_ADJ 1 /* must subtract one from address after bp */ +%#define BREAK_SIZE 1 /* Breakpoint occupies one byte */ + +%#define TARGET_PROC_TYPE 0 + +#endif + + + diff --git a/c/src/librdbg/src/i386/rdbg_cpu_asm.s b/c/src/librdbg/src/i386/rdbg_cpu_asm.s new file mode 100644 index 0000000000..f0942310ce --- /dev/null +++ b/c/src/librdbg/src/i386/rdbg_cpu_asm.s @@ -0,0 +1,70 @@ +/* cpu_asm.s + * + * This file contains all assembly code for the Intel i386 implementation + * of RDBG. + * + */ + +#include + + BEGIN_CODE + +/* + * void copyback_data_cache_and_invalidate_instr_cache() + * + * This routine performs a copy of the data cache + * and invalidate the instruction cache + */ + + .p2align 1 + PUBLIC (copyback_data_cache_and_invalidate_instr_cache) + +SYM (copyback_data_cache_and_invalidate_instr_cache): + wbinvd + ret + + + +/* + * void enterRdbg(void) + * + * This function perform a call to the exception 19 + * It is used : + * 1 - in the user code, to simulate a Breakpoint. + * (with justSaveContext = 0) + * 2 - in the RDBG code, to push a ctx in the list. + * (with justSaveContext = 1) + * + * In most of case, it will be use as described in 1. + * The 2nd possibility will be used by RDBG to obtain + * its own ctx + */ + + PUBLIC (enterRdbg) + +SYM (enterRdbg): + int $50 + ret + + +/* + * void rtems_exception_prologue_50(void) + * + * Exception 50 is used to enter Rdbg + * + */ + + .p2align 4 + + PUBLIC (rtems_exception_prologue_50) + PUBLIC (_Exception_Handler) + +SYM (rtems_exception_prologue_50): + pushl $ 0 + pushl $ 50 + jmp SYM(_Exception_Handler) ; + + +END_CODE + +END diff --git a/c/src/librdbg/src/i386/rdbg_f.c b/c/src/librdbg/src/i386/rdbg_f.c new file mode 100644 index 0000000000..aeb07fcbe8 --- /dev/null +++ b/c/src/librdbg/src/i386/rdbg_f.c @@ -0,0 +1,130 @@ +/* + ************************************************************************** + * + * Component = + * + * Synopsis = rdbg/i386/rdbg_f.c + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include + + +void +CtxToRegs (const CPU_Exception_frame* ctx, xdr_regs* regs) +{ + regs->tabreg [GS] = 0; + regs->tabreg [FS] = 0; + regs->tabreg [ES] = 0; + regs->tabreg [DS] = 0; + regs->tabreg [EDI] = ctx->edi; + regs->tabreg [ESI] = ctx->esi; + regs->tabreg [EBP] = ctx->ebp; + regs->tabreg [ESP] = ctx->esp0; + regs->tabreg [EBX] = ctx->ebx; + regs->tabreg [EDX] = ctx->edx; + regs->tabreg [ECX] = ctx->ecx; + regs->tabreg [EAX] = ctx->eax; + regs->tabreg [TRAPNO] = ctx->idtIndex; + regs->tabreg [ERR] = ctx->faultCode; + regs->tabreg [EIP] = ctx->eip; + regs->tabreg [CS] = ctx->cs & 0xFFFF; + regs->tabreg [EFL] = ctx->eflags; +} + + + void +RegsToCtx (const xdr_regs* regs, CPU_Exception_frame* ctx) +{ + ctx->edi = regs->tabreg [EDI]; + ctx->esi = regs->tabreg [ESI]; + ctx->ebp = regs->tabreg [EBP]; + ctx->esp0 = regs->tabreg [ESP]; + ctx->ebx = regs->tabreg [EBX]; + ctx->edx = regs->tabreg [EDX]; + ctx->ecx = regs->tabreg [ECX]; + ctx->eax = regs->tabreg [EAX]; + ctx->idtIndex = regs->tabreg [TRAPNO]; + ctx->faultCode = regs->tabreg [ERR]; + ctx->eip = regs->tabreg [EIP]; + ctx->cs = regs->tabreg [CS]; + ctx->eflags = regs->tabreg [EFL]; +} + +void +get_ctx_thread( Thread_Control *thread, CPU_Exception_frame* ctx) +{ + ctx->edi = thread->Registers.edi; + ctx->esi = thread->Registers.esi; + ctx->ebp = (unsigned32)(thread->Registers.ebp); + ctx->esp0 = (unsigned32)(thread->Registers.esp); + ctx->ebx = thread->Registers.ebx; + ctx->edx = 0; + ctx->ecx = 0; + ctx->eax = 0; + ctx->idtIndex = 0; + ctx->faultCode = 0; + ctx->eip = *(unsigned int*)(thread->Registers.esp); + ctx->cs = 0; + ctx->eflags = thread->Registers.eflags; +} + +void +set_ctx_thread( Thread_Control *thread, CPU_Exception_frame* ctx) +{ + thread->Registers.edi = ctx->edi; + thread->Registers.esi = ctx->esi; + thread->Registers.ebp = (void*)(ctx->ebp); + thread->Registers.esp = (void*)(ctx->esp0); + thread->Registers.ebx = ctx->ebx; + thread->Registers.eflags = ctx->eflags; +} + + + +int +Single_Step(CPU_Exception_frame* ctx) +{ + /* Check if not already set */ + if ((ctx->eflags & EFLAGS_TF) != 0 || ExitForSingleStep != 0) { + /* Check coherency */ + assert ((ctx->eflags & EFLAGS_TF) != 0); + assert (ExitForSingleStep != 0); + return 0; + } + ctx->eflags |= EFLAGS_TF; /* eflags */ + ++ExitForSingleStep; + + return 0; +} + + int +CheckForSingleStep (CPU_Exception_frame* ctx) +{ + if (ExitForSingleStep) { + /* + * This functions can be called both from + * INT1 and INT3 handlers. In case it is + * called from INT3, need to clear TF. + */ + ctx->eflags &= ~EFLAGS_TF; + ExitForSingleStep = 0; + return 1; + } + return 0; +} + +void +CancelSingleStep (CPU_Exception_frame* ctx) +{ + /* Cancel scheduled SS */ + ctx->eflags &= ~EFLAGS_TF; + ExitForSingleStep-- ; +} diff --git a/c/src/librdbg/src/ptrace.c b/c/src/librdbg/src/ptrace.c new file mode 100644 index 0000000000..158bd57cbb --- /dev/null +++ b/c/src/librdbg/src/ptrace.c @@ -0,0 +1,335 @@ +/* + ************************************************************************** + * + * Component = + * + * Synopsis = rkdb/rkdb.c + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include + +extern rtems_id serializeSemId; +extern rtems_id wakeupEventSemId; +extern rtems_id eventTaskId; +extern Exception_context *FirstCtx; +extern Exception_context *LastCtx; +extern CPU_Exception_frame SavedContext; +extern unsigned int NbExceptCtx; +extern unsigned int NbSerializedCtx; + + + +/* -------------------------------------------------------------------- + return a pointeur to the Tread Control structure of the specified + Id + -------------------------------------------------------------------- */ + +Thread_Control *Thread_Get_RDBG ( + Objects_Id Id +) +{ + unsigned index; + + if ( Id <_Objects_Information_table[OBJECTS_RTEMS_TASKS]->maximum_id && + Id >_Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id) { + + index = Id - _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; + if ( _Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index] != NULL) { + return (Thread_Control *)(_Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index]); + } + } + + if ( Id <_Objects_Information_table[OBJECTS_POSIX_THREADS]->maximum_id && + Id >_Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id) { + + index = Id - _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; + if ( _Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index] != NULL) + return (Thread_Control *)(_Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index]); + } + + return 0; + +} + + +/* -------------------------------------------------------------------- + Memory read + -------------------------------------------------------------------- */ + +int +safeMemRead(void *src, void *dest, int nbBytes){ + + /* + * safe because if it generates an exception, + * it must return normally + * TBD + */ + + memcpy(dest, src, nbBytes); + return 0; +} + +/* -------------------------------------------------------------------- + Memory write + -------------------------------------------------------------------- */ +int +safeMemWrite(void *src, void * dest, int nbBytes){ + + /* + * safe because if it generates an exception, + * it must return normally + * TBD + */ + + memcpy(dest, src, nbBytes); + return 0; +} + +/* -------------------------------------------------------------------- + Ptrace + -------------------------------------------------------------------- */ + +int +ptrace (int request, int pid, char* addr, int data, char* addr2) + { + int diag; + errno = 0 ; + if (pid != 1) { + errno = ESRCH; + return -1; + } + switch (request) { + + case RPT_SINGLESTEP:{ + Exception_context *ctx; + + if (CannotRestart == 1){ + setErrno(EIO); + return -1; + } + + if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { + Single_Step(ctx->ctx); + rtems_semaphore_release( ctx->semaphoreId ); + return 0; + } + break; + } + + case RPT_PEEKTEXT: + case RPT_PEEKDATA: { + diag = safeMemRead(addr, &data, sizeof data); + if (diag == 0) return data; + mem_error: + return -1; + } + + case RPT_POKETEXT: { + diag = safeMemWrite(&data, addr, sizeof data); + + /* + * We must flush the INSTR and DATA cache to be sure the + * opcode modification is taken into account, because + * the breakpoint opcode is written via the data cache + * while execution code is fetched via the instruction + * cache + */ + + if (diag == 0) { + copyback_data_cache_and_invalidate_instr_cache(); + return 0; + } + goto mem_error; + } + case RPT_POKEDATA: { + diag = safeMemWrite(&data, addr, sizeof data); + if (diag == 0) return 0; + goto mem_error; + } + case RPT_CONT: { + Exception_context *ctx; + + if (CannotRestart == 1){ + setErrno (EIO); + return -1; + } + + ctx = GetExceptCtx (currentTargetThread); + + if ( + ctx->ctx->idtIndex != I386_EXCEPTION_DEBUG && + ctx->ctx->idtIndex != I386_EXCEPTION_BREAKPOINT && + ctx->ctx->idtIndex != I386_EXCEPTION_ENTER_RDBG + ) { + CannotRestart = 1; + setErrno (EIO); + return -1; + } + + assert (data == 0); + assert (ExitForSingleStep == 0); + + rtems_semaphore_release( serializeSemId ); + + if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { + rtems_semaphore_release( ctx->semaphoreId ); + } + return 0; + } + + case RPT_ATTACH: + return 0; + + case RPT_DETACH:{ + Exception_context *ctx; + + if (NbExceptCtx || NbSerializedCtx) { + ctx = FirstCtx; + rtems_task_delete(eventTaskId); + rtems_semaphore_delete(serializeSemId); + rtems_semaphore_delete(wakeupEventSemId); + } + return 0; + } + + case RPT_GETREGS:{ + Exception_context *ctx; + + if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { + CtxToRegs (ctx->ctx, (xdr_regs*) addr); + return 0; + } + break; + } + + case RPT_SETREGS:{ + Exception_context *ctx; + + if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { + RegsToCtx ((xdr_regs*) addr, ctx->ctx); + return 0; + } + break; + } + + case RPT_READTEXT: + case RPT_READDATA: { + diag = safeMemRead(addr, addr2, data); + if (diag == 0) return 0; + goto mem_error; + } + case RPT_WRITETEXT: + case RPT_WRITEDATA: { + diag = safeMemWrite(addr2, addr, data); + if (diag == 0) return 0; + goto mem_error; + } + + case RPT_GETTARGETTHREAD: + if (!NbExceptCtx) { + errno = EBUSY; + return -1; + } + return currentTargetThread; + + case RPT_SETTARGETTHREAD: + if (!NbExceptCtx) { + errno = EBUSY; + return -1; + } + currentTargetThread = data; + return 0; + + case RPT_GETTHREADNAME: { + return TgtGetThreadName (NULL, (unsigned)(data), (char *) addr); + } + + case RPT_THREADLIST: { + int count = TgtThreadList (NULL, (unsigned*) addr, UTHREAD_MAX + * sizeof (unsigned)); + if (count < 0) { + errno = EINVAL; + return -1; + } + return count; + } + + case RPT_SETTHREADREGS: { + Exception_context *ctx; + CPU_Exception_frame Ectx; + Thread_Control *thread; + rtems_id id; + + rtems_task_ident(RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &id); + if (data == (unsigned)id) + break; + + if ((ctx = GetExceptCtx (data)) != NULL) { + RegsToCtx ((xdr_regs*) addr, ctx->ctx); + return 0; + } + thread = Thread_Get_RDBG ((Objects_Id)(data)); + if (thread != NULL) { + RegsToCtx ((xdr_regs*) addr, &Ectx); + set_ctx_thread (thread, &Ectx); + return 0; + } + break; + } + + case RPT_GETTHREADREGS: { + Exception_context *ctx; + CPU_Exception_frame Ectx; + Thread_Control *thread; + rtems_id id; + + rtems_task_ident(RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &id); + if (data == (unsigned)id){ + justSaveContext = 1; + enterRdbg(); + CtxToRegs (&(SavedContext), (xdr_regs*) addr); + return 0; + } + + if ((ctx = GetExceptCtx (data)) != NULL) { + CtxToRegs (ctx->ctx, (xdr_regs*) addr); + return 0; + } + thread = Thread_Get_RDBG ((Objects_Id)(data)); + if (thread != NULL) { + get_ctx_thread (thread, &Ectx); + CtxToRegs (&Ectx, (xdr_regs*) addr); + return 0; + } + break; + } + + case RPT_KILL: + TotalReboot = 1; + return 0; + + case RPT_TRACEME: + case RPT_PEEKUSER: + case RPT_POKEUSER: + case RPT_GETFPREGS: + case RPT_SETFPREGS: + case RPT_GETFPAREGS: + case RPT_SETFPAREGS: + case RPT_SYSCALL: + case RPT_DUMPCORE: + case RPT_GETUCODE: + case RPT_THREADSUSPEND: + case RPT_THREADRESUME: + case RPT_SETTHREADNAME: + default: + break; + } + errno = EINVAL; + return -1; +} diff --git a/c/src/librdbg/src/rdbg.c b/c/src/librdbg/src/rdbg.c new file mode 100644 index 0000000000..1f04119e8e --- /dev/null +++ b/c/src/librdbg/src/rdbg.c @@ -0,0 +1,139 @@ +/* + ************************************************************************** + * + * Component = + * + * Synopsis = rkdb/rkdb.c + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include +#include + +u_short rtemsPort = RTEMS_PORT; +int BackPort = RTEMS_BACK_PORT; +int rtemsActive = 0; +SVCXPRT* rtemsXprt; +int rtemsSock; +char ActName[] = "RTEMS"; +volatile int ExitForSingleStep = 0 ; +volatile int Continue; +volatile int justSaveContext; +volatile Objects_Id currentTargetThread; +volatile int CannotRestart = 0; +volatile int TotalReboot = 0; +int CONN_LIST_INC = 3; +int PID_LIST_INC = 1; +int TSP_RETRIES = 10; + + + int +getId() +{ + rtems_id id; + + rtems_task_ident(RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &id); + return (int)(id) ; +} + + static int +rdbgInit (void) +{ + int sock; + struct sockaddr_in addr; + + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock == -1) { + printf("%s: rkdbInit: cannot allocate socket\n", ActName); + return -1; + } + + bzero( (void *)&addr, sizeof(struct sockaddr_in)); + addr.sin_port = htons(rtemsPort); + if ((bind(sock, (struct sockaddr*) &addr, sizeof(addr))) == -1) { + printf("%s: rkdbInit: cannot bind socket\n", ActName); + return -2; + } + rtemsXprt = svcudp_create(sock); + if (svcudp_enablecache(rtemsXprt, 1) == 0) { + printf("%s: rkdbInit: cannot enable rpc cache\n", ActName); + return -3; + } + rtemsSock = sock; + return 0; +} + + rtems_task +rdbgDaemon (rtems_task_argument argument) +{ + for (;;){ + + if (TotalReboot == 1){ + rtemsReboot(); + } + + svc_processrequest( rtemsXprt, REMOTEDEB, REMOTEVERS, remotedeb_2); + } +} + + void +rtems_rdbg_initialize (void) +{ + rtems_name task_name; + rtems_id tid; + rtems_status_code status; + +#ifdef DDEBUG + rdb_debug = 1; /* DPRINTF now will display */ +#endif + + DPRINTF (("%s init starting\n", ActName)); + + /* Print version string */ +#ifdef DDEBUG + printk ("RDBG v.%d built on [%s %s]\n", SERVER_VERS, __DATE__, __TIME__); +#else + printk ("RDBG v.%d\n", SERVER_VERS); +#endif + + /* Create socket and init UDP RPC server */ + if (rdbgInit() != 0) goto error; + + Continue = 1; + justSaveContext = 0; + currentTargetThread = 0; + + task_name = rtems_build_name( 'R', 'D', 'B', 'G' ); + if ((status = rtems_task_create( task_name, 5, 24576, + RTEMS_INTERRUPT_LEVEL(0), + RTEMS_DEFAULT_ATTRIBUTES | RTEMS_SYSTEM_TASK + , &tid )) + != RTEMS_SUCCESSFUL){ + printf("status = %d\n",status); + rtems_panic ("Can't create task.\n"); + } + + status = rtems_task_start(tid, rdbgDaemon, 0); + + return; + +error: + printf ("initialization failed.\n"); +} + + void +setErrno (int error) +{ + errno = error; +} + + int +getErrno() +{ + return errno; +} diff --git a/c/src/librdbg/src/remdeb.x b/c/src/librdbg/src/remdeb.x new file mode 100644 index 0000000000..e4cb998ebc --- /dev/null +++ b/c/src/librdbg/src/remdeb.x @@ -0,0 +1,544 @@ +/* + ********************************************************************** + * + * Component: RDBG servers + * Module: remdeb.x + * + * Synopsis: XDR definitions for remote debug server RPC calls. + * XDR definitions for RPCGEN to build remote debug server. + * + ********************************************************************** + */ + +#ifdef RPC_SVC +%/*HEADER_START*/ +#endif + +%#define RTEMS_PORT 2071 +%#define RTEMS_BACK_PORT 2073 + +#ifdef RPC_HDR +%#ifndef REMDEB_H +%#define RPCGENSRVNAME(a) a +#endif + +enum rpc_type { + SUNRPC = 0, + BADRPCTYPE = 25 +}; + + +const NET_SAFE = 1400; /* this is safe for UDP messages */ + +struct UDP_MSG +{ /* format of UDP messages (should be in .h) */ + unsigned char type; /* type of message (BMSG_xx) */ + unsigned char msg_num; /* ringed number for resend detect */ + unsigned short spec; /* specific information for type */ + long pid; /* process this affects */ + unsigned long context; /* specific information to request */ +}; + + /* First we support the overhead structures and types needed for RPC + requests. Then, we have all RPC routines input/output args. */ + +%/* +% * Sun request values for the remote ptrace system call +% */ +% +enum ptracereq +{ /* these match PTRACE_xxx numbers */ + RPT_TRACEME = 0, /* 0, by tracee to begin tracing */ + RPT_CHILDDONE = 0, /* 0, tracee is done with his half */ + RPT_PEEKTEXT, /* 1, read word from text segment */ + RPT_PEEKDATA, /* 2, read word from data segment */ + RPT_PEEKUSER, /* 3, read word from user struct */ + RPT_POKETEXT, /* 4, write word into text segment */ + RPT_POKEDATA, /* 5, write word into data segment */ + RPT_POKEUSER, /* 6, write word into user struct */ + RPT_CONT, /* 7, continue process */ + RPT_KILL, /* 8, terminate process */ + RPT_SINGLESTEP, /* 9, single step process */ + RPT_ATTACH, /* 10, attach to an existing process (returns 2 if not primary)*/ + RPT_DETACH, /* 11, detach from a process */ + RPT_GETREGS, /* 12, get all registers */ + RPT_SETREGS, /* 13, set all registers */ + RPT_GETFPREGS, /* 14, get all floating point regs */ + RPT_SETFPREGS, /* 15, set all floating point regs */ + RPT_READDATA, /* 16, read data segment */ + RPT_WRITEDATA, /* 17, write data segment */ + RPT_READTEXT, /* 18, read text segment */ + RPT_WRITETEXT, /* 19, write text segment */ + RPT_GETFPAREGS, /* 20, get all fpa regs */ + RPT_SETFPAREGS, /* 21, set all fpa regs */ + RPT_22, /* 22, filler */ + RPT_23, /* 23, filler */ + RPT_SYSCALL, /* 24, trap next sys call */ + RPT_DUMPCORE, /* 25, dump process core */ + RPT_26, /* 26, filler */ + RPT_27, /* 27, filler */ + RPT_28, /* 28, filler */ + RPT_GETUCODE, /* 29, get u.u_code */ + /* Begin specific ptrace options */ + RPT_GETTARGETTHREAD = 50, /* get PM target thread identifier */ + RPT_SETTARGETTHREAD = 51, /* set PM target thread identifier */ + RPT_THREADSUSPEND = 52, /* suspend a thread */ + RPT_THREADRESUME = 53, /* resume a thread */ + RPT_THREADLIST = 54, /* get list of process's threads */ + RPT_GETTHREADNAME = 55, /* get the name of the thread */ + RPT_SETTHREADNAME = 56, /* set the name of the thread */ + RPT_SETTHREADREGS = 57, /* set all registers for a specific thread*/ + RPT_GETTHREADREGS = 58, /* get all registers for a specific thread*/ + /* Begin extended ptrace options for remote debug server */ + RPT_STEPRANGE = 75, /* step while in range (addr=start, data=len) */ + RPT_CONTTO = 76, /* cont from PC to temp break in addr */ + RPT_SETBREAK = 77, /* set a breakpoint (addr=break) */ + RPT_CLRBREAK = 78, /* clear a breakpoint (data=handle or 0 for all) */ + RPT_GETBREAK = 79, /* get breakpoint (data=handle, addr=buffer to + fill). Returns next break. If data=0, + returns number of breaks. */ + RPT_GETNAME = 80, /* get name of process (data 0=name, 1=path + as started, 2=fullpath). Return in addr + as mem) */ + RPT_STOP = 81, /* (C-actors) Stop the C-actor */ + RPT_PGETREGS = 82, /* portable version */ + RPT_PSETREGS = 83, /* portable version */ + RPT_PSETTHREADREGS = 84, /* portable version */ + RPT_PGETTHREADREGS = 85 /* portable version */ +}; + +#include "remdeb_f.x" + +const MAXDEBUGGEE= 150; +const NAMEMAX = 17; + +% /* +% * Memory data for read/write text or data. The size is in data. The target +% * addr is in the addr field. +% * Be careful before modifying because this value goes into internal +% * pipes and is allocated on stack too. Pipes and/or the stack could +% * become too small if this value gets incremented. +% */ + +const MEM_DATA_MAX = 256; + +#ifndef RPC_XDR + +struct xdr_mem { + u_long addr; + u_int dataNb; + unsigned char data[MEM_DATA_MAX]; +}; + +#else +/* manually define best XDR function for this */ +%bool_t xdr_xdr_mem(xdrs, objp) +% XDR *xdrs; +% struct xdr_mem *objp; +%{ +% if (!xdr_u_long(xdrs, &objp->addr)) { +% return (FALSE); +% } +% if (!xdr_u_int(xdrs, &objp->dataNb)) { +% return(FALSE); +% } +% return (xdr_opaque(xdrs, objp->data, objp->dataNb)); +%} + +#endif + +/* Breakpoint structure maps to same structure on host. Do not change one + without changing the other. */ + +enum break_type +{ /* types of breakpoints */ + BRKT_NONE, /* unused entry */ + BRKT_INSTR, /* general instruction break */ + BRKT_READ, /* read break */ + BRKT_WRITE, /* write breakpoint */ + BRKT_ACCESS, /* read-or-write break */ + BRKT_EXEC, /* execution HW breakpoint */ + BRKT_OS_CALL, /* break on OS call, addr is call number */ + BRKT_OS_SWITCH, /* dispatch breakpoint */ + BRKT_STEPEMUL /* emulate hardware single-step */ +}; +const MAX_THRD_BRK = 4; /* enough for 128 threads per process */ +struct xdr_break +{ /* one per process local breakpoint */ + u_char type; /* BRKT_xxx type of break */ + u_char thread_spec; /* 0=all, else count of threads it affects */ + u_short handle; /* handle of breakpoint returned */ + u_long ee_loc; /* address of start */ + u_long ee_type; /* type/method of address */ + u_short length; /* length of break if range, else 0 */ + u_char pass_count; /* pass count to initialize to (0=none) */ + u_char curr_pass; /* pass count current value */ + u_long thread_list[MAX_THRD_BRK]; /* bit map for thread list */ +}; /* 20 bytes+4 per thread_list (4x4=16) = 36 */ + +const UTHREAD_MAX = 64; + +const THREADNAMEMAX = 16; +typedef string thread_name ; + +struct KernThread { + unsigned int threadLi; +}; + +#ifndef RPC_XDR + +#ifdef RPC_HDR +%typedef KernThread *ptThreadList; +#endif + +struct thread_list { + unsigned int nbThread; + ptThreadList threads; +}; + +#else /* RPC_XDR */ + +/* must write this function by hand */ + +%bool_t xdr_thread_list(xdrs, objp) +% XDR *xdrs; +% struct thread_list *objp; +%{ +% return (xdr_array(xdrs, (char**)&objp->threads, &objp->nbThread, +% UTHREAD_MAX, sizeof(KernThread), xdr_KernThread)); +%} + +#endif /* not RPC_XDR */ + + +union ptrace_addr_data_in switch (ptracereq req) { + /* + * due to rpcgen poor features, we cannot put RPC_SETREGS + * AND RPC_SETTHREADREGS in the case list. So we use a hack (FIX rpcgen). + */ +#ifndef RPC_HDR + case RPT_SETTHREADREGS : + xdr_regs regs; +#endif + case RPT_SETREGS: + + xdr_regs regs; + +#ifndef RPC_HDR + case RPT_PSETTHREADREGS: + u_int pregs<>; +#endif + case RPT_PSETREGS: + u_int pregs<>; + +#ifdef LATER + case RPT_SETFPREGS: + xdr_fp_status fpregs; +#endif + case RPT_SETTHREADNAME: + thread_name name; +#ifndef RPC_HDR + case RPT_WRITETEXT: + xdr_mem mem; +#endif + case RPT_WRITEDATA: + xdr_mem mem; + case RPT_SETBREAK: + xdr_break breakp; + default: + u_int address; +}; + +union ptrace_addr_data_out switch (ptracereq req) { + case RPT_GETREGS: + xdr_regs regs; +#ifndef RPC_HDR + case RPT_GETTHREADREGS: + xdr_regs regs; +#endif + + case RPT_PGETREGS: + u_int pregs<>; + +#ifndef RPC_HDR + case RPT_PGETTHREADREGS: + u_int pregs<>; +#endif + +#ifdef LATER + case RPT_GETFPREGS: + xdr_fp_status fpregs; +#endif + case RPT_THREADLIST: + thread_list threads; + case RPT_GETTHREADNAME: + thread_name name; +#ifndef RPC_HDR + case RPT_READTEXT: + xdr_mem mem; + case RPT_GETNAME: + xdr_mem mem; +#endif + case RPT_READDATA: + xdr_mem mem; + case RPT_GETBREAK: + xdr_break breakp; + default: + u_int addr; +}; + +typedef opaque CHAR_DATA ; /* variable sized data */ + +const XRY_MAX_INST_BUFF = 128; +const XRY_MAX_INSTANCES = 16; +%#ifndef XRY_MAX_CMD_STR +const XRY_MAX_CMD_STR = 320; /* XRY_MAX_INST_BUFF+(XRY_MAX_INSTANCES*12) */ +%#endif /* REMDEB_H */ + + +struct xry_inst +{ + unsigned char flags; /* value2 interp, etc. INFL_xxx */ + unsigned char type; /* base type of data (str, val, etc) INST_xxx */ + unsigned char sub_type; /* specific type (task, res, etc). This is + set and defined by the user defined instance + processor and not the auto-processor */ + unsigned char res_type; + u_long value; /* pointer to value or value itself */ + u_long value2; /* second value (optional - based on flags) */ +}; + +struct instance +{ + struct xry_inst instances[XRY_MAX_INSTANCES]; + unsigned char buffer[XRY_MAX_INST_BUFF]; +}; + +union instance_union switch (bool instances) +{ + case TRUE: + instance inst; + case FALSE: + string buffer ; +}; + +typedef string one_arg ; + +const XRY_MAX_OBJ_NAME = 32; /* objname in some commands */ + +% /* now open_connex() routine which establishes a connection to server */ + +enum debug_type +{ /* type of connection requested */ + DEBTYP_PROCESS = 0, /* process connection */ + DEBTYP_C_ACTOR = 1, /* C-Actor connection */ + DEBTYP_KERNEL = 2, /* kernel debug connection */ + DEBTYP_OTHER = 3 /* other subsystem */ +}; + +%#define DEBUGGER_IS_GDB 0x2 /* */ + +struct open_in +{ /* input args to open a connection */ + u_char back_port[16]; /* opaque NET address format */ + u_short debug_type; /* type of process DEBTYP_xxx */ + u_short flags; /* connection information OPNFLG_xxx */ + u_char destination[16];/* opaque address if to router */ + one_arg user_name; /* name of user on host */ +}; + +struct open_out +{ /* return from open_connex */ + u_long port; /* connection number to server or -1 if error */ + u_int pad[4]; /* Planned to be KnIpcDest. Never used */ + u_int fp; /* True if floating point processor. If error, + set to errno for open error. */ + u_char cmd_table_num; /* command table used */ + u_char cmd_table_vers; /* version of command table */ + u_short server_vers; /* version number of server itself */ +}; + +% /* now close_connex() routine which detaches from server */ + +enum close_control +{ /* choice of how to handle owned processes */ + CLOSE_IGNORE = 0, /* ignore all controlled pids on close */ + CLOSE_KILL = 1, /* kill all controlled pids on close */ + CLOSE_DETACH = 2 /* detach free running all controlled pids */ +}; + +struct close_in +{ /* arg to close connection */ + close_control control; /* shutdown of owned processes control */ +}; + +% /* now send_signal() routine which sends signals to processes like kill(2) */ + +struct signal_in +{ /* input to send_signal */ + int pid; /* process/actor to send signal to */ + int sig; /* signal to send (from /usr/include/signal.h) */ +}; + +struct signal_out +{ /* return from send_signal */ + int kill_return; /* return code from kill(2) call */ + int errNo; /* error code if failed */ +}; + + +% /* now wait_info() routine which returns results of polling the wait status +% of a process/actor. It may return 0 if running, else pid or -1 */ + +enum stop_code +{ /* stop code information */ + STOP_ERROR = 0, /* error, errno set */ + STOP_NONE = 1, /* not stopped */ + STOP_UNKNOWN = 2, /* unknown stop reason */ + STOP_BREAK = 3, /* stopped on breakpoint */ + STOP_STEP = 4, /* stopped on step */ + STOP_SIGNAL = 5, /* stopped on signal receieve */ + STOP_TERM_EXIT = 6, /* terminated normally */ + STOP_TERM_SIG = 7, /* terminated by signal */ + STOP_DETACHED = 8, /* detached from server */ + STOP_KILLED = 9, /* killed by ptrace KILL */ + STOP_SPAWN_FAILED = 10 /* spawn failed in exec part, handle=errno */ +}; + +struct wait_in +{ /* input arg to wait is process */ + int pid; /* process/actor id */ +}; + +struct wait_out +{ /* result of wait_info call */ + int wait_return; /* -1=error,0=running,pid=stopped */ + int errNo; /* error code if error */ + int status; /* wait(2) status if stopped */ + stop_code reason; /* reason in more abstracted terms */ + int handle; /* handle of break if stopped on break, + or signal number or exit code */ + u_long PC; /* program counter if stopped */ + u_long SP; /* stack pointer if stopped */ + u_long FP; /* frame pointer if stopped */ + u_long thread; /* thread that stopped if applies (else -1) */ +}; + +% /* now ptrace() routine. This matches the Sun UNIX ptrace as well as +% some additions */ + +const PTRFLG_FORCE = 1; /* when set and process running, forces process + to stop, make the request, then start again. + This is used for breakpoints and the like */ +const PTRFLG_NON_OWNER = 2; /* do request even if not primary owner (will + notify all owners including caller if owns) */ +const PTRFLG_FREE = 4; /* free pid_list after KILL/DETACH */ + +const PTRDET_UNOWN = 0x100; /* data value in RPT_DETACH just disconnects + caller as an owner of process. */ + +struct ptrace_in +{ /* input args matches ptrace but for XDR */ + int pid; /* process to act on */ + ptrace_addr_data_in addr; /* mappings for addr and addr2 */ + u_int data; /* simple data arg of ptrace */ + u_int flags; /* mask of PTRFLG_xxx flags. */ +}; + +struct ptrace_out +{ /* return information from ptrace */ + ptrace_addr_data_out addr; /* return through addr/addr2 */ + int result; /* result of ptrace call (return value) */ + int errNo; /* error code if error */ +}; + + /* Data for GET_GLOBAL_SYMBOLS */ +struct one_symbol { /* Must match common/src/lib/ctx/ctx.h */ + string symbolName<>; + long symbolValue; +}; + +typedef one_symbol all_symbols<>; + +struct get_global_symbols_out { + all_symbols symbols; +}; + + /* Data for GET_TEXT_DATA */ +struct get_text_data_in { + int pid; /* process/actor id if non-zero */ + string actorName<16>; /* actor name for system mode */ +}; + +struct get_text_data_out { + int result; + int errNo; + u_long textStart; + u_long textSize; + u_long dataStart; + u_long dataSize; +}; + + /* Data for GET_SIGNAL_NAMES */ +struct one_signal { + u_int number; + string name<>; +}; + +typedef one_signal all_signals<>; + +struct get_signal_names_out { + all_signals signals; +}; + +% /* now define the actual calls we support */ + +program REMOTEDEB { + version REMOTEVERS { + + /* open a connection to server or router */ + open_out + OPEN_CONNEX(open_in) = 1; + + /* send a signal to a process */ + signal_out + SEND_SIGNAL(signal_in) = 2; + + /* all routines below require a connection first */ + + /* close the connection to the server */ + void + CLOSE_CONNEX(close_in) = 10; + + /* process ptrace request */ + ptrace_out + PTRACE(ptrace_in) = 11; + + /* poll for status of process */ + wait_out + WAIT_INFO(wait_in) = 13; + + get_signal_names_out + GET_SIGNAL_NAMES(void) = 17; + + } = 2; /* now version 2 */ +} = 0x20000fff; + +#ifdef RPC_HDR +%#define REMDEB_H +%#endif +#endif + +#ifdef RPC_SVC + +%const char* names [] = { +% "NULLPROC", "OPEN_CONNEX", "SEND_SIGNAL", "name3", +% "name4", "name5", "name6", "name7", +% "name8", "name9", "CLOSE_CONNEX", "PTRACE", +% "name12", "WAIT_INFO", "name14", "name15", +% "name16", "GET_SIGNAL_NAMES", "name18" +%}; +% + +%/*HEADER_END*/ +#endif diff --git a/c/src/librdbg/src/servbkpt.c b/c/src/librdbg/src/servbkpt.c new file mode 100644 index 0000000000..8d986751a2 --- /dev/null +++ b/c/src/librdbg/src/servbkpt.c @@ -0,0 +1,587 @@ +/* + ********************************************************************** + * + * Component: RDB servers + * Module: servbkpt.c + * + * Synopsis: Management of breakpoints + * + ********************************************************************** + */ + +#include +#include +#include +#include + +/*----- Macros -----*/ + +#define BKPT0(plst) ((BASE_BREAK*)(plst)->break_list) +#define BKPT_INCR 5 /* how many bkpt slots alloc at a time */ + +#define BKPT_OVER(plst,idx,addr,size) \ + ((plst)->break_list[idx].ee_loc + BREAK_SIZE > (UINT32) (addr) \ + && (plst)->break_list[idx].ee_loc < (UINT32) (addr) + (size)) + +#define BKPT_SLOTS \ + (sizeof ((xdr_break*) 0)->thread_list / \ + sizeof ((xdr_break*) 0)->thread_list [0]) + + + /* + * BreakAlloc - alloc a breakpoint entry. + * + * This is a generic routine to insert an entry in the + * breakpoint list. It returns the number of entry just + * created. It returns -1 if failed. + */ + + static int +BreakAlloc (PID_LIST* plst, Boolean normal) +{ + int idx, len; + xdr_break* blst; + + if (!normal) { /* want 0 entry */ + if (plst->break_list) { + return(0); /* already there */ + } + idx = 1; /* force alloc below */ + } else { + for (idx = 1; idx < (int)plst->break_alloc; idx++) { + if (plst->break_list[idx].type == BRKT_NONE) { + /* got a free one */ + memset(&plst->break_list[idx], 0, sizeof(xdr_break)); + return(idx); /* found one */ + } + } + } + /* idx is the requested entry */ + + if (idx >= (int)plst->break_alloc) { /* need more space */ + len = plst->break_alloc + BKPT_INCR; + blst = (xdr_break*)Realloc(plst->break_list, len*sizeof(xdr_break)); + if (!blst) { + return(-1); /* failed, no space */ + } + plst->break_alloc = len; /* got more */ + plst->break_list = blst; + + /* Clear new space */ + memset(blst + len - BKPT_INCR, 0, BKPT_INCR * sizeof(xdr_break)); + idx = len - BKPT_INCR; /* next available */ + if (!idx) { + idx = 1; /* for normal cases */ + } + } + return(normal ? idx : 0); /* return it */ +} + + /* + * BreakSet - set a breakpoint in process + * + * Returns the number or -1/errno. + */ + +#ifdef DDEBUG +static const char* BreakTypes[] = { + "NONE", "INSTR", "READ", "WRITE", + "ACCESS", "EXEC", "OS_CALL", "OS_SWITCH", + "STEPEMUL" +}; + +#define BN_MAX (sizeof BreakTypes / sizeof BreakTypes[0]) +#define BREAK_NAME(t) ((unsigned) (t) < BN_MAX ? BreakTypes[t] : "???") +#endif + + int +BreakSet (PID_LIST* plst, int conn_idx, xdr_break* bkpt) +{ + int pid = plst->pid; + int type = bkpt->type; + void* addr = (void *) bkpt->ee_loc; + int idx; + int data; + + DPRINTF(("BreakSet: type %d (%s) at 0x%x th %d ee_type %d len %d " + "pass %d curr %d list %d %d %d %d\n", type, BREAK_NAME(type), + (int) addr, + bkpt->thread_spec, bkpt->ee_type, bkpt->length, bkpt->pass_count, + bkpt->curr_pass, bkpt->thread_list [0], bkpt->thread_list [1], + bkpt->thread_list [2], bkpt->thread_list [3])); + + idx = BreakAlloc(plst, True); /* get entry */ + if (idx < 0) { /* no memory */ + setErrno(ENOMEM); /* set for safety */ + return -1; /* return the error */ + } + + data = TgtPtrace(RPT_PEEKTEXT, pid, addr, 0, NULL); /* current */ + if (getErrno()) { + return -1; /* failed, return the error */ + } + if (IS_BREAK(data)) { /* There is already a break here */ + DPRINTF(("BreakSet: already have soft bkpt at %x\n", addr)); + if (type == BRKT_STEPEMUL) { + ++BKPT0 (plst)->pad1; + return 1; /* Any non-error value is OK */ + } + setErrno(EBUSY); + return -1; + } + + TgtPtrace(RPT_POKETEXT, pid, addr, SET_BREAK(data), NULL); + + if (getErrno()) { + return -1; + } + + plst->break_list[idx] = *bkpt; + plst->break_list[idx].ee_type = data; /* saved data */ + + /* Inform other owners */ + if (type != BRKT_STEPEMUL) { + TgtNotifyAll (plst - pid_list, BMSG_BREAK, 1 /*added*/, idx, + conn_idx, False); + } else { + ++BKPT0 (plst)->pad1; + } + /* Return the number */ + setErrno(0); /* Just in case */ + return idx; +} + + int +BreakSetAt (PID_LIST* plst, int conn_idx, unsigned long addr, break_type type) +{ + xdr_break xb; + + memset (&xb, 0, sizeof xb); + xb.type = type; + xb.ee_loc = addr; + return BreakSet (plst, conn_idx, &xb); +} + +/*----- Find a breakpoint by address -----*/ + + int +BreakGetIndex(PID_LIST* plst, void* addr) +{ + int idx; + int data = -1; + + if (!plst->break_alloc) { + setErrno(EFAULT); + return -1; + } + for (idx = 1; idx < (int)plst->break_alloc; idx++) { + if ((u_long) addr == plst->break_list [idx].ee_loc) { + data = idx; + break; + } + } + return data; +} + +/*----- Getting information about breakpoint -----*/ + + /* + * If data > 0, fill "bkpt" with information about breakpoint + * and return the number of the next one. + * If data == 0, return the count of breakpoints. + */ + + int +BreakGet (const PID_LIST* plst, int data, xdr_break* bkpt) +{ + int idx; + + if (!data) { /* just count them */ + for (idx = 1; idx < (int)plst->break_alloc; idx++) { + if (plst->break_list[idx].type != BRKT_NONE) { + data++; + } + } + return data; /* count */ + } + if ((unsigned) data >= plst->break_alloc) { + /* out of range */ + setErrno(EFAULT); /* closest match */ + return -1; + } + /* get it and say which is next */ + *bkpt = plst->break_list[data]; + for (idx = (int)data+1; idx < (int)plst->break_alloc; idx++) { + if (plst->break_list[idx].type != BRKT_NONE) { + return idx; + } + } + return 0; /* otherwise returns 0 for no more */ +} + +/*----- Clearing bkpts -----*/ + + /* + * BreakClear - clear one (if data != 0) or all breakpoints + * (if data == 0). Return the number of bkpts cleared. + * If (data == -1), remove step-emulation breakpoints. + */ + + int +BreakClear (PID_LIST* plst, int conn_idx, int data) +{ + int pid_idx = plst - pid_list; + int idx; + int cleared = 0; + int clearStepEmul = 0; + int terminated = PROC_TERMINATED (plst); + int stepEmulCount = 0; + + /* break handle in data */ + if (!plst->break_alloc) { /* there are no breaks */ + DPRINTF (("BreakClear: no bkpts defined.\n")); + setErrno(EFAULT); /* closest match */ + return -1; /* return error */ + } + if (!data) { /* clear all */ + idx = 1; + data = plst->break_alloc-1; + + /* Inform other owners */ + DPRINTF (("BreakClear: clearing all bkpts.\n")); + TgtNotifyAll (pid_idx, BMSG_BREAK, 0 /*clr*/, 0, conn_idx, False); + + } else if (data == -1) { /* clear all step-emul bkpts */ + DPRINTF(("BreakClear: removing %d step-emul bkpts\n", + BKPT0 (plst)->pad1)); + + stepEmulCount = BKPT0 (plst)->pad1; + BKPT0 (plst)->pad1 = 0; + + clearStepEmul = 1; + idx = 1; + data = plst->break_alloc-1; + } else if ((unsigned) data >= plst->break_alloc + || plst->break_list[data].type == BRKT_NONE) { + + /* out of range */ + DPRINTF (("BreakClear: invalid bkpt %d\n", data)); + setErrno(EFAULT); /* closest match */ + return -1; /* return error */ + } else { + idx = data; + /* Inform other owners */ + TgtNotifyAll (pid_idx, BMSG_BREAK, 0 /*clr*/, idx, conn_idx, False); + DPRINTF (("BreakClear: clearing bkpt %d\n", data)); + } + + for (; idx <= data; idx++) { /* clear each one */ + int type = plst->break_list[idx].type; + + if (clearStepEmul && type != BRKT_STEPEMUL) continue; + + if (type == BRKT_INSTR || (clearStepEmul && type == BRKT_STEPEMUL)) { + /* just patch back */ + char* addr = (char *)plst->break_list[idx].ee_loc; + int val; + + if (BKPT0 (plst)->clr_step && BKPT0 (plst)->last_break == idx) { + BKPT0 (plst)->clr_step = 0; /* not needed */ + } + /* Neighboring bytes can have breakpoints too... */ + if (! terminated) { + setErrno (0); + val = TgtPtrace(RPT_PEEKTEXT, plst->pid, addr, 0, NULL); + if (getErrno()) { + DPRINTF (("BreakClear: addr %x not readable!\n", addr)); + setErrno (0); /* Forget bkpt */ + } else { + assert (IS_BREAK (val)); + val = ORG_BREAK (val, (int)plst->break_list[idx].ee_type); + TgtPtrace(RPT_POKETEXT, plst->pid, addr, val, NULL); + if (getErrno()) { + DPRINTF (("BreakClear: addr %x not writable!\n", addr)); + setErrno (0); + } + } + } + ++cleared; /* indicate cleared */ + } + memset(&plst->break_list[idx], 0, sizeof(xdr_break)); + } + assert (!clearStepEmul || cleared <= stepEmulCount); + if (stepEmulCount && cleared == 0) { + DPRINTF (("BreakClear: all STEPEMUL bkpts were shared\n")); + return 1; + } + return cleared; +} + +/*----- Hiding of breakpoints -----*/ + + /* + * PatchBreak - patch original data from break into data buffer. + * + * Notes: + * - this routine patches the original data under a break into the data + * buffer from a ptrace read/peek. + */ + + static void +PatchBreak (char* buff, UINT32 bstart, int bsize, UINT32 dstart, char* dvalue) +{ + int size = BREAK_SIZE; /* default size */ + + /* Must deal with all sorts of unalignments + * (3 full overlaps, 3 unaligns) + */ + if (bsize < BREAK_SIZE) { + /* case where buffer is smaller than data */ + memcpy(buff, dvalue+(bstart-dstart), bsize); /* copy over */ + return; + } + /* buffer larger than data. + * we need to see where break fits in buffer and whether + * we have part of it off the end. We set bstart to be the + * buffer offset, dtart to be the break data offset, and + * size to be the amount to copy + */ + if (dstart < bstart) { + /* break before actual buffer */ + dstart = bstart-dstart; /* offset in data */ + size -= dstart; /* amount to copy */ + bstart = 0; /* offset in buffer */ + + } else if (dstart + size > bstart + bsize) { + /* off end */ + bstart += bsize; /* end of buffer */ + size -= (dstart + size) - bstart; + bstart = bsize - size; /* come back into buffer enough */ + dstart = 0; /* start of data */ + + } else { /* normal case */ + bstart = dstart - bstart; /* offset in buffer */ + dstart = 0; + } + memcpy(buff+bstart, dvalue+dstart, size); +} + + void +BreakHide (const PID_LIST* plst, void* addr, int data, void* addr2) +{ + int idx; + + if (!plst->break_list) /* no breaks exist, so skip this */ + return; + + /* if breakpoints, replace */ + + for (idx = 1; idx < (int)plst->break_alloc; idx++) { + int type = plst->break_list[idx].type; + + if (type != BRKT_INSTR && type != BRKT_STEPEMUL) { + continue; + } + /* break, see if overlaps */ + if (BKPT_OVER (plst, idx, addr, data)) { + + /* overlaps, patch in old value */ + PatchBreak((char *)addr2, (UINT32)addr, data, + plst->break_list[idx].ee_loc, + (char *)&plst->break_list[idx].ee_type); + } + } +} + +/*----- Checking of breakpoint overwrites -----*/ + + /* + * BreakOverwrite - check if memory write does not involve addresses + * having software breakpoints. + */ + + int +BreakOverwrite (const PID_LIST* plst, const char* addr, unsigned int size) +{ + int idx; + + if (!plst->break_list) { /* No breaks exist */ + return 0; + } + + for (idx = 1; idx < (int)plst->break_alloc; idx++) { + int type = plst->break_list[idx].type; + + /* Consider only breakpoints involving modified memory */ + if (type != BRKT_INSTR && type != BRKT_STEPEMUL) { + continue; + } + if (BKPT_OVER (plst, idx, addr, size)) { + return -1; /* overlaps */ + } + } + return 0; +} + +/*----- Execution support -----*/ + + /* + * BreakStepRange - Start stepping in a range. + * + * Range is saved in breakpoint 0. + */ + + int +BreakStepRange (PID_LIST* plst, void* addr, int len) +{ + if (!plst->break_list) { + /* get list */ + if (BreakAlloc (plst, False) == -1) { /* must not be any memory */ + setErrno(ENOMEM); /* to be safe */ + return -1; /* fails */ + } + } + BKPT0 (plst)->range_start = (UINT32)addr; + BKPT0 (plst)->range_end = (UINT32)addr+(len-1); + return 0; +} + + /* + * If the Program Counter is changed, consider that the + * current breakpoint has not been reached yet. + */ + + void +BreakPcChanged (PID_LIST* plst) +{ + if (plst->break_list) { + /* clear break stuff */ + BKPT0 (plst)->clr_step = False; + } +} + + /* + * BreakStepOff - prepare stepping off a breakpoint. + */ + + int +BreakStepOff (const PID_LIST* plst, void** paddr2) +{ + if (plst->break_list && BKPT0 (plst)->clr_step) { + + /* need clear then step off break */ + int last = BKPT0 (plst)->last_break; + + /* clear break, step, then do exec */ + + *paddr2 = (void*) plst->break_list[last].ee_type; + + /* Need to clr_step after TgtPtrace() when wait() returns */ + return 1; + } + return 0; +} + + /* + * BreakSteppedOff - check if just stepped off a breakpoint + * and re-insert it into the code. + */ + + void +BreakSteppedOff (PID_LIST* plst) +{ + if (plst->break_list && BKPT0 (plst)->clr_step) { + int idx = BKPT0 (plst)->last_break; + int data; + + BKPT0 (plst)->clr_step = 0; + + /* + * Re-insert the breakpoint. + */ + data = TgtPtrace (RPT_PEEKTEXT, plst->pid, + (char *)plst->break_list [idx].ee_loc, 0, NULL); + assert (! IS_BREAK (data)); + TgtPtrace (RPT_POKETEXT, plst->pid, + (char *)plst->break_list[idx].ee_loc, + (int) SET_BREAK (data), NULL); + } +} + + + /* + * Returns whether a thread matches a breakpoint. + */ + + static int +BreakThreadMatch (xdr_break* xb, int thread) +{ + int slot; + + if (thread < 0) return 1; /* Break existence check only */ + + if (xb->thread_list [0] == 0) return 1; /* Universal break */ + + for (slot = 0; slot < BKPT_SLOTS; ++slot) { + if (xb->thread_list [slot] == 0) return 0; /* End of list */ + if (xb->thread_list [slot] == thread) return 1; /* Match */ + } + return 0; /* No matches found */ +} + + +int +BreakAdjustPC (PID_LIST* plst) +{ + /* + * BREAK_ADJ is the value by which the Program Counter + * has to be decremented after a software breakpoint + * is hit. It must be defined and can be zero. + */ +#if BREAK_ADJ + /* subtract back if necessary */ + plst->regs.REG_PC -= BREAK_ADJ; /* now write back */ + TgtPtrace(RPT_SETREGS, plst->pid, (char *)&plst->regs, 0, NULL); +#else + (void) plst; +#endif + return 0; +} + + +/* + * Identify the current breakpoint. The process just stopped. + */ + + int +BreakIdentify (PID_LIST* plst, int adjust, int thread) +{ + int foreignBkpt = 0; + int bidx; + + for (bidx = 1; bidx < (int) plst->break_alloc; bidx++) { + int type = plst->break_list[bidx].type; + + if ((type == BRKT_INSTR || type == BRKT_STEPEMUL) + && plst->regs.REG_PC - BREAK_ADJ + == plst->break_list[bidx].ee_loc) { /* found matching */ + if (!BreakThreadMatch (&plst->break_list[bidx], thread)) { + if (foreignBkpt == 0) { + foreignBkpt = bidx; + } + continue; + } + if (adjust) { + BreakAdjustPC (plst); + } + return bidx; + } + } + if (foreignBkpt) { + if (adjust) { + BreakAdjustPC (plst); + } + return -foreignBkpt; + } + return 0; +} diff --git a/c/src/librdbg/src/servcon.c b/c/src/librdbg/src/servcon.c new file mode 100644 index 0000000000..a26bfd2c7b --- /dev/null +++ b/c/src/librdbg/src/servcon.c @@ -0,0 +1,136 @@ +/* + ************************************************************************** + * + * Component: RDBG + * Module: servcon.c + * + * Synopsis: Management of RPC client connections. + * + ************************************************************************** + */ + +#include +#include +#include + + /* + * ConnCreate - create a new connection entry for a client. + * + * This function finds an empty entry in the connection array + * or makes space. It fills in the fields that are passed to it. + * It does not do any validation on net addresses nor does it + * start a validation cycle on other clients. This is done by + * the caller. + */ + + int +ConnCreate (struct svc_req* rqstp, open_in* in) +{ + NET_OPAQUE sender; + int idx; + CONN_LIST* clst; + + setErrno (0); + + /* Convert to valid Net address */ + if (! TspTranslateRpcAddr (rqstp, &sender)) { + DPRINTF (("ConnCreate: TspTranslateRpcAddr failed\n")); + return -1; + } + if (! TspValidateAddr ((NET_OPAQUE*) in->back_port, &sender)) { + DPRINTF (("ConnCreate: TspValidateAddr failed\n")); + return -1; /* errno now setup with error */ + } + + /* look for an empty connection entry */ + for (idx = 0; idx < conn_list_cnt; idx++) { + if (!conn_list[idx].in_use) + break; /* an empty one found */ + } + + if (idx >= conn_list_cnt) { /* no empties, create space */ + CONN_LIST* tmp_conn_list = conn_list; + + conn_list_cnt += CONN_LIST_INC; + if (conn_list) { + conn_list = (CONN_LIST *) Realloc (conn_list, /* extend */ + conn_list_cnt * sizeof (CONN_LIST)); + } else { + conn_list = (CONN_LIST *)Malloc(conn_list_cnt * sizeof(CONN_LIST)); + } + + if (!conn_list) { /* unable to get space */ + if ((conn_list_cnt -= CONN_LIST_INC)) { + /* was realloc, restore space */ + conn_list = tmp_conn_list; + } + return -1; /* errno set by failed alloc */ + } + /* clear newly created memory */ + memset (conn_list + idx, 0, CONN_LIST_INC * sizeof (CONN_LIST)); + } else { /* clear new entry */ + memset (conn_list + idx, 0, sizeof (CONN_LIST)); + } + clst = conn_list + idx; + + clst->in_use = True; /* now in use */ + clst->sender = sender; + memcpy (&clst->back_port, &in->back_port, sizeof (NET_OPAQUE)); + memcpy (&clst->route, &in->destination, sizeof (NET_OPAQUE)); + clst->debug_type = (UCHAR) in->debug_type; + clst->flags = in->flags; + strncpy (clst->user_name, in->user_name, NAMEMAX-1); + clst->user_name [NAMEMAX-1] = 0; + + return idx; +} + + /* + * ConnDelete - remove connection entry when shutdown. + * + */ + + void +ConnDelete (int conn, struct svc_req* rqstp, close_control control) +{ + CONN_LIST* clst = conn_list + conn; + int idx; + Boolean prim; + + if (! clst->in_use) return; /* not active */ + + for (idx = 0; idx < pid_list_cnt; idx++) { + PID_LIST* plst = pid_list + idx; + + if (! PIDMAP_TEST (conn, idx)) continue; + + /* found a controlled pid */ + prim = (plst->primary_conn == conn) ? True : False; + TgtDetachCon (conn, idx, True); + + /* if still running or alive, we use close control on it */ + if (! plst->pid) + continue; /* entry gone */ + + if (prim && control == CLOSE_KILL) { + /* kill off process */ + TgtKillAndDelete (plst, rqstp, True); + } else if (! plst->owners) { + /* no owners left */ + if (control == CLOSE_DETACH) { + TgtKillAndDelete (plst, rqstp, False); + } + if (control == CLOSE_DETACH || PROC_TERMINATED (plst)) { + TgtDelete (plst, conn, (control==CLOSE_DETACH) ? + BMSG_DETACH : 0); + } + } + } + if (clst->list) { + Free (clst->list); /* free allocated memory */ + } + DPRINTF (("ConnDelete: Connection closed for port %u\n", + HL_W(*((UINT16*) &clst->back_port.c[2])))); + + clst->in_use = False; /* free it back */ +} diff --git a/c/src/librdbg/src/servrpc.c b/c/src/librdbg/src/servrpc.c new file mode 100644 index 0000000000..f62a2ecbb8 --- /dev/null +++ b/c/src/librdbg/src/servrpc.c @@ -0,0 +1,720 @@ +/* + ********************************************************************** + * + * Component: RDBG + * Module: servrpc.c + * + * Synopsis: support routines for RPC dispatch for remote debug server. + * Main server dispatch routines from RPC to support remote debug. + * + ********************************************************************** + */ + +#include +#include +#include +#include +#include + +/************************************************************************/ + +/* ----------------------------------------------------------------------- + open_connex_2_svc - setup a new connection from a client. + + Notes: + - this function creates a new connection to a client. It allocates + an entry in the connection structure and fills in the information + sent and implied by the message. + - a client connection entry is needed for all further messages to work + properly. + ----------------------------------------------------------------------- */ + +open_out* RPCGENSRVNAME(open_connex_2_svc) (open_in *in, struct svc_req *rqstp) +{ + static open_out out; /* output response. This could be heap local */ + int idx; + static int one_time = 0; /* we do one-time setup on back port */ + + /* need to support in->debug_type, in->flags, and in->destination!!! */ + + if (!one_time) + { /* only setup one backport socket */ + /* now setup signals and the like for handling process changes */ + setErrno(0); + TspInit(rqstp->rq_xprt->xp_sock); /* init transport system */ + if (getErrno()) + { /* failed in setup */ + out.port = (u_long)-1; + out.fp = getErrno(); /* error causing to fail */ + return(&out); /* fail */ + } + one_time = True; /* disable doing this again */ + } + + DPRINTF(("open_connex_2_svc: Opening connection from '%s'\n", + in->user_name)); + + /* now setup a validation of all other connections */ + for (idx = 0; idx < conn_list_cnt; idx++) + if (conn_list[idx].in_use) + { /* setup retry timer */ + DPRINTF(("open_connex_2_svc: Still have connection %d with port %d\n", + idx, HL_W(*((UINT16*)&conn_list[idx].back_port.c[2])))); + } + + idx = ConnCreate(rqstp, in); /* setup the connection */ + out.port = idx; /* connection number */ + if (idx == -1) + out.fp = getErrno(); /* error causing to fail */ + else + out.fp = TARGET_PROC_TYPE; + + out.server_vers = SERVER_VERS; + return(&out); +} + +/* ----------------------------------------------------------------------- + send_signal_2_svc - send a kill/signal to the specified process. + + Notes: + - this function sends a signal to the process specified. This process + does not have to be under debug nor attached by this server. The kill + may be refused on other grounds though. + - kill(pid, 0) can be used to validate the process still exists if + needed. + ----------------------------------------------------------------------- */ + +signal_out *RPCGENSRVNAME(send_signal_2_svc) (signal_in *in, struct svc_req *rqstp) +{ + static signal_out out; /* return code from kill */ + + /* we do not care if connected */ + setErrno(0); + out.kill_return = 0; + out.errNo = 0; + TotalReboot = 1; + return(&out); +} + +/* ----------------------------------------------------------------------- + close_connex_2_svc - close a connection from a client. + ----------------------------------------------------------------------- */ + +void *RPCGENSRVNAME(close_connex_2_svc) (close_in *in, struct svc_req *rqstp) +{ + int conn_idx = TspConnGetIndex(rqstp); + + if (conn_idx != -1) /* found it, clear out */ + ConnDelete(conn_idx, rqstp, in->control); + + return (void*) ""; /* need to return something */ +} + +/* ----------------------------------------------------------------------- + ptrace_2_svc - control process under debug. + ----------------------------------------------------------------------- */ + +#define REG_COUNT \ + (sizeof (xdr_regs) / sizeof (int)) + +ptrace_out *RPCGENSRVNAME(ptrace_2_svc) (ptrace_in *in, struct svc_req *rqstp) +{ + int conn_idx = rqstp ? TspConnGetIndex(rqstp) : -1; + static ptrace_out out; /* outut response (error or data) */ + void *addr, *addr2; /* used for actual ptrace call */ + unsigned int data; + int req, pid, ret, pid_idx, idx; + static union + { /* local buffer for returned data */ + Objects_Id t_list[UTHREAD_MAX]; /* thread_list return */ + char t_name[THREADNAMEMAX]; /* thread name return */ + } local_buff; /* for return handling of strings and the like */ + PID_LIST *plst = NULL; /* current pid_list entry */ + + DPRINTF (("ptrace_2_svc: entered (%s (%d), %d, XXXX, %d, XXXX)\n", + PtraceName (in->addr.req), in->addr.req, in->pid, + in->data)); + + out.addr.ptrace_addr_data_out_u.addr = 0; + + /* validate the connection */ + if (conn_idx == -1 && rqstp != NULL) + { /* no connection, error */ + DPRINTF(("ptrace_2_svc: msg from unknown debugger!\n")); + out.result = -1; + out.errNo = ECHILD; /* closest error */ + out.addr.req = 0; /* to avoid copies that should not occur */ + return(&out); + } + /* Consider that the last back-message is acknowledged */ + if (conn_idx >= 0 && conn_list[conn_idx].retry) { + TspMessageReceive(conn_idx, in->pid); + } + + req = in->addr.req; + out.addr.req = req; /* needed for RPC */ + pid = in->pid; + addr = addr2 = NULL; + data = in->data; + setErrno(0); /* assume works */ + out.result = 0; /* assume worked ok */ + out.errNo = 0; + + /* lookup process to make sure we have under control */ + pid_idx = FindPidEntry (in->pid); + if (pid_idx >= 0) /* found it */ + { + plst = &pid_list[pid_idx]; + if (conn_idx < 0) + conn_idx = plst->primary_conn; + } + + /* now we handle the special case of ATTACH to a pid we already control */ + if (req == RPT_ATTACH) + { /* look it up first */ + if (plst) + { /* we have controlled , so return ok+show conn */ + ret = 2; /* normally secondary connection */ + if (! PIDMAP_TEST (conn_idx, pid_idx)) + { /* mark as an owner if not already */ + plst->owners++; + PIDMAP_SET (conn_idx, pid_idx); /* mask in */ + } + else if (plst->primary_conn != NO_PRIMARY) + { /* regrab makes primary */ + /* Only if not primary already */ + if (plst->primary_conn != conn_idx) { + TspSendWaitChange(plst->primary_conn, BMSG_NOT_PRIM, + conn_idx, plst->pid, 0, False); /* tell old owner */ + } + plst->primary_conn = NO_PRIMARY; + } + + if (plst->primary_conn == NO_PRIMARY) + { /* none now, so take over */ + plst->primary_conn = conn_idx; /* new primary */ + ret = 1; /* primary */ + } + out.result = ret; /* primary or secondary owner */ + return(&out); + } + /* else attach process using target code */ + setErrno(ESRCH); /* assume the worst */ + if (!TgtAttach(conn_idx, pid)) + { /* failed */ + out.errNo = getErrno(); + out.result = 0; + } + return(&out); + } + else if (req == RPT_DETACH) + { /* see which kind of detach */ + if (data == PTRDET_UNOWN) + { /* only want to disconnect from */ + TgtDetachCon(conn_idx, pid_idx, True); /* remove from control */ + return(&out); /* done */ + } + } + else if (plst && (req == RPT_GETNAME || req == RPT_GETBREAK)) + { + /* do nothing */ + } + + else if (plst && req == RPT_CLRBREAK) { + /* To be able to remove breakpoints from a "running" system */ + DPRINTF (("ptrace_2_svc: allowing RPT_CLRBREAK %d\n", data)); + /* do nothing */ + } + + else if (plst && plst->running) + { /* error, process is running and not detach */ + out.result = -1; + out.errNo = ETXTBSY; /* closest error */ + DPRINTF (("ptrace_2_svc: failed, still running.\n")); + return(&out); + } + if (plst == NULL) { + out.result = -1; + out.errNo = ESRCH; + DPRINTF (("ptrace_2_svc: No such process.\n")); + return (&out); + } + + /* now make sure secondary owner is not trying to modify */ + if (!(in->flags & PTRFLG_NON_OWNER)) /* if not overriden */ + if (conn_idx != plst->primary_conn + && ( (req >= RPT_POKETEXT && req <= RPT_SINGLESTEP) + || (req >= RPT_SETREGS && req <= RPT_SETFPAREGS && (req & 1)) + || (req >= RPT_SYSCALL && req <= RPT_DUMPCORE) + || (req >= RPT_SETTARGETTHREAD && req <= RPT_THREADRESUME) + || (req >= RPT_SETTHREADNAME && req <= RPT_SETTHREADREGS) + || (req >= RPT_STEPRANGE && req <= RPT_CLRBREAK) + || (req == RPT_STOP) + || (req >= RPT_PSETREGS && req <= RPT_PSETTHREADREGS))) + { /* not owner */ + out.result = -1; + out.errNo = EPERM; /* cannot alter as not primary */ + DPRINTF (("ptrace_2_svc: refused, not owner, flags %d conn_idx %d primary_conn %d\n", in->flags, conn_idx, + plst->primary_conn)); + return(&out); + } + + addr = (void *)in->addr.ptrace_addr_data_in_u.address; /* default */ + /* now setup normal ptrace request by unpacking. May execute here. */ + switch (req) + { /* handle unpacking or setup for real call */ + /* first the ones where addr points to input data */ + case RPT_SETREGS: + case RPT_SETTHREADREGS: + addr = (void *)&in->addr.ptrace_addr_data_in_u.regs; /* reg list */ + break; + + case RPT_PSETREGS: + case RPT_PSETTHREADREGS: + if (in->addr.ptrace_addr_data_in_u.pregs.pregs_len != REG_COUNT) { + DPRINTF(("ptrace_2_svc: pid %d got %d expected %d\n", pid, + in->addr.ptrace_addr_data_in_u.pregs.pregs_len, REG_COUNT)); + setErrno(EINVAL); + break; + } + req = req == RPT_PSETREGS ? RPT_SETREGS : RPT_SETTHREADREGS; + addr = (void *) in->addr.ptrace_addr_data_in_u.pregs.pregs_val; + break; + + case RPT_SETTHREADNAME: + addr = (void *)in->addr.ptrace_addr_data_in_u.name; + break; + case RPT_WRITETEXT: + case RPT_WRITEDATA: + if ((int) data < 0) { + setErrno(EINVAL); + break; + } + addr = (void *)in->addr.ptrace_addr_data_in_u.mem.addr; /* targ addr */ + addr2 = (void *)in->addr.ptrace_addr_data_in_u.mem.data; /* buff */ + + /* Forbid writing over breakpoints */ + if (BreakOverwrite (plst, addr, data)) { + setErrno(EBUSY); + } + break; + + case RPT_POKETEXT: + case RPT_POKEDATA: + /* Forbid writing over breakpoints */ + if (BreakOverwrite (plst, addr, sizeof (int))) { + setErrno(EBUSY); + } + break; + + /* now ones where we handle locally */ + case RPT_GETTARGETTHREAD: + out.result = plst->thread; + req = 0; /* force exit */ + break; + + case RPT_PGETREGS: /* return from our buffer */ + out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT; + out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (u_int*) &plst->regs; + req = 0; /* force exit */ + break; + + case RPT_GETREGS: + /* return directly from our buffer */ + /* this buffer is refreshed when changing target thread */ + out.addr.ptrace_addr_data_out_u.regs = plst->regs; + req = 0; /* force exit */ + break; + + case RPT_SETBREAK: + idx = BreakSet (plst, conn_idx, &in->addr.ptrace_addr_data_in_u.breakp); + if (idx < 0) break; + req = 0; /* force exit */ + out.result = idx; /* return break index (>0) */ + break; + + case RPT_CLRBREAK: + if (conn_list[conn_idx].flags & DEBUGGER_IS_GDB) { + data = BreakGetIndex (plst, addr); + } + out.result = BreakClear (plst, conn_idx, data); + /* if errored, errno will still be set */ + req = 0; + break; + + case RPT_GETBREAK: + /* data=handle, addr=in_buffer, returns next break. Data=0, returns cnt */ + out.result = BreakGet (plst, data, &out.addr. + ptrace_addr_data_out_u.breakp); + req = 0; /* handle locally */ + break; + + case RPT_GETNAME: /* get the name of the process */ + if (!plst->name) + out.addr.ptrace_addr_data_out_u.mem.dataNb = 0; + else + { + int maxLen = sizeof out.addr.ptrace_addr_data_out_u.mem.data - 1; + data = strlen(plst->name); + if (data > maxLen) + data = maxLen; + out.addr.ptrace_addr_data_out_u.mem.dataNb = data+1; + memcpy(out.addr.ptrace_addr_data_out_u.mem.data, plst->name, data+1); + out.addr.ptrace_addr_data_out_u.mem.data [maxLen] = '\0'; + } + req = 0; + break; + + case RPT_CONTTO: + if (BreakSetAt (plst, conn_idx, (u_long) addr, BRKT_STEPEMUL) < 0) + { + DPRINTF(("ptrace_2_svc: BreakSet failed at %x", addr)); + break; + } + req = RPT_CONT; + /* data can contain a signal number, addr2 is unused */ + goto case_RPT_CONT; + + case RPT_STEPRANGE: + /* convert to step */ + if (!data) + data = 1; /* should we give an error?? */ + BreakStepRange (plst, addr, data); + if (getErrno()) break; + + req = RPT_SINGLESTEP; /* do by stepping */ + addr = (void*) 1; /* start from current PC */ + data = -2; /* want non-atomic stepping */ + /* fall through to other exec cases */ + + case RPT_CONT: + case_RPT_CONT: + case RPT_SINGLESTEP: + + if (BreakStepOff (plst, &addr2)) + { /* need clear then step off break */ + /* clear break, step, then do exec */ + if (addr == (void*) 1) + addr = (void*) plst->regs.REG_PC;/* need for patch */ + + /* data is always 0, so atomic single-step */ + } else if (req == RPT_SINGLESTEP) { + data = -2; /* want non-atomic stepping */ + } + break; + + /* now ones where addr points to an output area */ + case RPT_PGETTHREADREGS: + addr = (void*) out.addr.ptrace_addr_data_out_u.mem.data; + if (sizeof out.addr.ptrace_addr_data_out_u.mem.data < + REG_COUNT * sizeof(int)) { + setErrno(EINVAL); + break; + } + if (data == plst->thread) { + out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT; + out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (u_int*) &plst->regs; + req = 0; /* force exit */ + break; + } + req = RPT_GETTHREADREGS; + break; + + case RPT_GETTHREADREGS: + addr = (void*) &out.addr.ptrace_addr_data_out_u.regs; + break; + case RPT_GETTHREADNAME: + out.addr.ptrace_addr_data_out_u.name = local_buff.t_name; + addr = (void*) out.addr.ptrace_addr_data_out_u.name; + break; + case RPT_THREADLIST: + out.addr.ptrace_addr_data_out_u.threads.threads =(ptThreadList) local_buff.t_list; + addr = (void*) out.addr.ptrace_addr_data_out_u.threads.threads; + break; + case RPT_READTEXT: + case RPT_READDATA: + if ((int) data < 0) { + setErrno(EINVAL); + break; + } + addr = (void *)in->addr.ptrace_addr_data_in_u.address; + addr2 = (void *)out.addr.ptrace_addr_data_out_u.mem.data; + out.addr.ptrace_addr_data_out_u.mem.dataNb = data; + break; + case RPT_DETACH: + /* Do not allow detaching if breakpoints still there */ + if (BreakGet (plst, 0, NULL)) + { /* some bkpts still set */ + setErrno(EINVAL); /* cannot detach safely */ + break; + } + /* fall through */ + case RPT_KILL: + /* in the event they are trying to detach or kill a terminated process, + we just delete the entry. */ + if (PROC_TERMINATED (plst)) + { + TgtDelete(plst, -1, BMSG_KILLED); /* just blow off */ + req = 0; /* now exit */ + } + break; + } + + if (getErrno()) + { /* failed in code above */ + out.result = -1; + out.errNo = getErrno(); + DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); + return(&out); + } + else if (!req) + { /* bail out now */ + DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); + return(&out); + } + + /* OK, make the call */ + out.result = TgtPtrace(req, pid, addr, data, addr2); + out.errNo = getErrno(); + + /* if no error, cleanup afterwards */ + if (getErrno()) + { + /* Remove step-emul breakpoints if any */ + if (req == RPT_SINGLESTEP || req == RPT_CONT) { + BreakClear (plst, -1, -1); + } + DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); + return(&out); /* return error */ + } + + switch (in->addr.req) + { /* handle some special calls that affect state */ + case RPT_CONT: + case RPT_STEPRANGE: + /* change to running */ + if (in->addr.req == RPT_STEPRANGE) + plst->last_start = LAST_RANGE; /* so range steps */ + else if (addr2) + plst->last_start = LAST_STEPOFF; /* now continue after wait */ + else + plst->last_start = LAST_CONT; + plst->running = 1; /* mark as running */ + if (!rqstp) /* Called internally to restart bkpt, no msg to anybody */ + break; + TgtNotifyAll(pid_idx, BMSG_WAIT, 0, 0, (in->flags & PTRFLG_NON_OWNER) + ? -1 : conn_idx, True); + break; + case RPT_SINGLESTEP: + /* mark as step */ + plst->last_start = LAST_STEP; /* so we know how started */ + plst->running = 1; /* mark as running (wait should catch fast) */ + break; + case RPT_DETACH: /* mark as disconnected */ + case RPT_KILL: /* mark as killed */ + if (in->flags & PTRFLG_FREE) /* notify and delete entry */ + TgtDelete(plst, -1, (in->addr.req==RPT_KILL) ? BMSG_KILLED : BMSG_DETACH); + else + { /* notify and mark */ + plst->last_start = (in->addr.req==RPT_KILL) ? + LAST_KILLED : LAST_DETACHED; + plst->state = -1; + plst->running = False; + TgtNotifyAll(pid_idx, (in->addr.req==RPT_KILL) ? + BMSG_KILLED : BMSG_DETACH, 0, 0, -1, True); + } + break; + case RPT_SETTHREADREGS: + case RPT_PSETTHREADREGS: + if (data != plst->thread) + break; + DPRINTF(("ptrace_2_svc: pid %d target thread regs changed!\n", pid)); + + case RPT_SETREGS: + case RPT_PSETREGS: + /* change our buffer as well */ + if (plst->regs.REG_PC != ((xdr_regs*)addr)->REG_PC) + BreakPcChanged (plst); + plst->regs = *(xdr_regs*) addr; /* copy in */ + break; + + /* case RPT_PGETREGS has been handled locally above */ + case RPT_PGETTHREADREGS: + /* We need to update pointer so that XDR works on return */ + out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT; + out.addr.ptrace_addr_data_out_u.pregs.pregs_val = + (void*) out.addr.ptrace_addr_data_out_u.mem.data; + break; + + case RPT_PEEKTEXT: + case RPT_PEEKDATA: + case RPT_READDATA: + case RPT_READTEXT: + if (req < RPT_READDATA) + { /* peek */ + /* addr is start */ + data = sizeof(int); + addr2 = &out.result; /* data buffer */ + /* Like read: addr is start, data is length, addr2 is buffer */ + } + BreakHide (plst, addr, data, addr2); + break; + + case RPT_SETTARGETTHREAD: + DPRINTF(("ptrace_2_svc: pid %d new target thread %d\n", pid, data)); + TgtPtrace (RPT_GETREGS, pid, (char*) &plst->regs, 0, NULL); + plst->thread = data; + if (plst->break_list) { /* Forget we had to step off breakpoint */ + BASE_BREAK* base = (BASE_BREAK*) plst->break_list; + DPRINTF(("ptrace_2_svc: clr_step %d last_break %d\n", base->clr_step, + base->last_break)); + base->clr_step = 0; /* Not stopped on break */ + base->last_break = 0; + } + break; + + case RPT_THREADLIST: + out.addr.ptrace_addr_data_out_u.threads.nbThread = out.result; + break; + + default: + break; + } /* end switch */ + DPRINTF(("ptrace_2_svc 2: result %d errNo %d\n", out.result, out.errNo)); + return(&out); +} + +/* ----------------------------------------------------------------------- + wait_info_2_svc - non-blocking wait request to check status. + ----------------------------------------------------------------------- */ + +wait_out *RPCGENSRVNAME(wait_info_2_svc) (in, rqstp) + wait_in *in; + struct svc_req *rqstp; /* server info */ +{ + int conn_idx = TspConnGetIndex(rqstp); + static wait_out out; /* output of pid and status */ + int idx; + PID_LIST *plst; + + memset(&out, 0, sizeof(out)); /* zero for safety */ + out.reason = STOP_ERROR; /* assume the worst */ + + if (conn_idx == -1) + { /* no connection, error */ + DPRINTF(("wait_info_2_svc: msg from unknown debugger!\n")); + out.wait_return = -1; + out.errNo = ECHILD; /* closest error */ + return(&out); + } + else + { /* see if confirming message received */ + if (conn_list[conn_idx].retry) + TspMessageReceive(conn_idx, in->pid); + } + + if (!in->pid) + { /* warm test verify only */ + /* this call (pid==0) is made to confirm that that connection is still + active. */ + /* we let it fall through as an error since any use other than connection + reset would be an error (there is no pid0). */ + } + else + { /* normal request */ + idx = FindPidEntry (in->pid); + if (idx >= 0) + { /* found process they requested on */ + plst = &pid_list[idx]; + out.wait_return = plst->running ? 0 : in->pid; + /* return: 0 is running, pid is stopped/term */ + out.errNo = 0; + out.status = plst->state; /* last stopped reason if stopped */ + out.thread = plst->thread;/* current thread (or -1 if none) from stop */ + if (!out.wait_return) + out.reason = STOP_NONE; /* running, no action */ + else if (STS_SIGNALLED (out.status)) + { /* stopped on signal */ + out.handle = STS_GETSIG (out.status); /* signal number */ + if (out.handle == SIGTRAP) + if (plst->is_step) + { /* single step with hitting a break */ + out.reason = STOP_STEP; + out.handle = 0; /* no information */ + } + else + { /* stopped on break */ + out.reason = STOP_BREAK; + if (plst->break_list) + out.handle = ((BASE_BREAK*)plst->break_list)->last_break; + else + out.handle = 0; /* no break */ + } + else + out.reason = STOP_SIGNAL; + out.PC = plst->regs.REG_PC; /* copy standard regs */ + out.SP = plst->regs.REG_SP; + out.FP = plst->regs.REG_FP; + } + else + { /* terminated, so lower use count */ + if (plst->last_start == LAST_KILLED) + out.reason = STOP_KILLED; + else if (plst->last_start == LAST_DETACHED) + out.reason = STOP_DETACHED; + else if (plst->last_start == LAST_START) + { /* failed in exec */ + out.reason = STOP_SPAWN_FAILED; + out.handle = STS_GETCODE (out.status); /* errno reason */ + } + else if (STS_TERMONSIG (out.status)) + { /* terminated on signal */ + out.reason = STOP_TERM_SIG; + /* mask off the core-dumped bit 7 */ + out.handle = (int)(unsigned)(u_char) STS_TERMGETSIG (out.status); + } + else + { /* exit(2)ed */ + out.reason = STOP_TERM_EXIT; + out.handle = STS_GETCODE (out.status); /* code */ + } + } + DPRINTF(("wait_info_2_svc: pid %d return %d status %x errNo %d" + " reason %d handle %d pc %x sp %x fp %x thread %d\n", + in->pid, out.wait_return, out.status, out.errNo, out.reason, + out.handle, out.PC, out.SP, out.FP, out.thread)); + return(&out); + } + } + /* if not found in list, we return error: no such process */ + out.wait_return = -1; + out.errNo = ESRCH; /* no process */ + out.status = 0; + return(&out); +} + +/* ----------------------------------------------------------------------- + get_signal_names_2_svc - return names for signals + ----------------------------------------------------------------------- */ + +static one_signal SignalNames[] = { + {SIGILL, "SIGILL/EVT_ILL"}, + {SIGTRAP, "SIGTRAP/EVT_BKPT"}, + {SIGFPE, "SIGFPE/EVT_FPE"}, + {SIGKILL, "SIGKILL/EVT_AKILL"}, + {SIGSEGV, "SIGSEGV/EVT_SEGV"}, + {17, "SIGSTOP"}, + {23, "SIGSTOP"} +}; + +get_signal_names_out* RPCGENSRVNAME(get_signal_names_2_svc) (in, rqstp) + void* in; + struct svc_req *rqstp; /* server info */ +{ + static get_signal_names_out out; + + out.signals.all_signals_len = sizeof SignalNames / sizeof SignalNames[0]; + out.signals.all_signals_val = SignalNames; + + return(&out); +} diff --git a/c/src/librdbg/src/servtgt.c b/c/src/librdbg/src/servtgt.c new file mode 100644 index 0000000000..7a8471e3e2 --- /dev/null +++ b/c/src/librdbg/src/servtgt.c @@ -0,0 +1,550 @@ +/* + ************************************************************************** + * + * Component: RDB servers + * Module: servtgt.c + * + ************************************************************************** + */ + + +#include +#include +#include +#include +#include +#include + +#ifdef DDEBUG +#define Ptrace TgtDbgPtrace +#else +#define Ptrace TgtRealPtrace +#endif + +/* ---------------------------------------------------------------- + TgtBreakRestoreOrig - Restore original instruction at "addr" + just before single-stepping it. + ---------------------------------------------------------------- */ + +int TgtBreakRestoreOrig (int pid, void *addr, void *addr2) + /* Process identifier */ + /* Breakpoint address */ + /* Original instruction or bkpt number */ +{ + int ret; + int l; + + l = (long)Ptrace(RPT_PEEKTEXT, pid, addr, 0, NULL); /* assume ok */ + ret = ORG_BREAK (l, (UINT32) addr2); /* reconstruct old instr */ + ret = Ptrace(RPT_POKETEXT, pid, addr, ret, NULL); /* poke back old */ + return ret; +} + +/* ----------------------------------------------------------------------- + TgtBreakCancelStep - Restore the breakpoint at "addr" if the single-step + has failed at the ptrace level. + ----------------------------------------------------------------------- */ + +#define BKPT0(plst) ((BASE_BREAK*)(plst)->break_list) + +void TgtBreakCancelStep (PID_LIST* plst) +{ + assert (plst->break_list); + assert (BKPT0 (plst)->clr_step); + + if (plst->break_list && BKPT0 (plst)->clr_step) { + int idx = BKPT0 (plst)->last_break; + int data; + + data = Ptrace (RPT_PEEKTEXT, plst->pid, + (char *)plst->break_list [idx].ee_loc, 0, NULL); + assert (! IS_BREAK (data)); + Ptrace (RPT_POKETEXT, plst->pid, + (char *)plst->break_list[idx].ee_loc, + (int) SET_BREAK (data), NULL); + } +} + +/* ----------------------------------------------------------------------- + TgtCreateNew - add a new process into the process management lists. + ----------------------------------------------------------------------- */ + + void +TgtCreateNew(PID pid, int conn, INT32 child, char *name, Boolean spawn) +{ + int idx; + + for (idx = 0; idx < pid_list_cnt; idx++) + if (!pid_list[idx].pid) + break; /* find empty */ + + if (idx >= pid_list_cnt) + { /* no empties, add more */ + PID_LIST *tmp_pid_list = pid_list; + + pid_list_cnt += PID_LIST_INC; + pid_list = (PID_LIST*) Realloc(pid_list, /* get new or extend */ + pid_list_cnt * sizeof(PID_LIST)); + if (!pid_list) + { /* out of memory */ + pid_list_cnt -= PID_LIST_INC; + if (pid_list_cnt) + { /* realloc failed - malloc again */ + pid_list = tmp_pid_list; + /* above relies on old pointer being valid after failed realloc */ + } + return; /* failed */ + } + /* now clear newly added space */ + memset(pid_list+pid_list_cnt-PID_LIST_INC, 0, + PID_LIST_INC * sizeof(PID_LIST)); + idx = pid_list_cnt - PID_LIST_INC; + } + else /* clear entry we found */ + memset(&pid_list[idx], 0, sizeof(PID_LIST)); + + /* now fill in empty entry */ + pid_list[idx].pid = pid; + pid_list[idx].running = 1; /* we have not called wait yet */ + pid_list[idx].primary_conn = (UCHAR)conn; /* primary owner */ + if (conn != -1) + { /* found caller */ + pid_list[idx].owners = 1; + PIDMAP_SET (conn, idx); /* mask in */ + } + pid_list[idx].thread = (UINT32)-1; /* no thread for now */ + pid_list[idx].last_start = LAST_START; /* handle MiX bug */ + + pid_list[idx].name = name ? (char *)StrDup(name) : (char *)NULL; + +} + +/* ----------------------------------------------------------------------- + TgtNotifyWaitChange - send event to clients indicating child changed state. + ----------------------------------------------------------------------- */ + + void +TgtNotifyWaitChange( PID pid, int status, Boolean exclude) +{ + int conn, idx; + + idx = FindPidEntry (pid); /* locate the pid that changed */ + if (idx < 0) + { + DPRINTF(("TgtNotifyWaitChange: pid %d not in our list\n", + (int) pid)); + return; /* not in our list */ + } + pid_list[idx].running = 0; /* not running */ + pid_list[idx].state = status; /* save status of stop/term */ + if (!pid_list[idx].owners && !STS_SIGNALLED(status)) + TgtDelete(&pid_list[idx], -1, 0); /* terminated and no owners */ + else + { /* normal cases */ + for (conn = 0; conn < conn_list_cnt; conn++) + { /* now find all interested clients */ + if (!conn_list[conn].in_use /* free entry */ + || ! PIDMAP_TEST (conn, idx)) + continue; /* not using this pid */ + if (conn == exclude) + continue; /* do not do this one */ + TspSendWaitChange(conn, BMSG_WAIT, 1, pid, 0, False);/* notify of change */ + } + } +} + +/* ----------------------------------------------------------------------- + TgtNotifyAll - send a message to all clients interested in process. + ----------------------------------------------------------------------- */ + + void + TgtNotifyAll( int pid_idx, BACK_MSG msg, UINT16 spec, + UINT32 context, int exclude, Boolean force) +{ + int conn; + + DPRINTF(("TgtNotifyAll: msg %d (%s) for pid_idx=%d (%d,%d)\n", + msg, BmsgNames [msg], pid_idx, exclude, force)); + for (conn = 0; conn < conn_list_cnt; conn++) + if (conn_list[conn].in_use /* not free */ + && PIDMAP_TEST (conn, pid_idx)) + { + if (conn != exclude) + TspSendWaitChange(conn, msg, spec, pid_list[pid_idx].pid, context, + force); + } +} + +/* ----------------------------------------------------------------------- + TgtDelete - mark process as now uncontrolled. + + Notes: + - this function removes a process from the process list. + - the notify argument indicates a message to send if needed. + ----------------------------------------------------------------------- */ + +void TgtDelete(PID_LIST *plst, int conn_idx, BACK_MSG notify) +{ + int idx = plst - pid_list, cnt, conn; + + /* found */ + cnt = pid_list[idx].owners; + if (cnt) + { /* some connections to break */ + for (conn = 0; cnt && conn < conn_list_cnt; conn++) + if (conn_list[conn].in_use /* not free */ + && PIDMAP_TEST (conn, idx)) + { /* found one that uses it */ + PIDMAP_CLEAR (conn, idx); + if (notify && conn != conn_idx) + TspSendWaitChange(conn, notify, 0, plst->pid, 0, True); + if (!--cnt) + break; + } + } + if (pid_list[idx].name) + Free(pid_list[idx].name); /* free string name back */ + /* Free breakpoint list */ + if (pid_list [idx].break_list != NULL) { + Free (pid_list [idx].break_list); + } + pid_list[idx].pid = 0; /* gone */ +} + + +/* ----------------------------------------------------------------------- + TgtKillAndDelete - kill or detach process and remove entry. + ----------------------------------------------------------------------- */ + + int +TgtKillAndDelete( PID_LIST *plst, struct svc_req *rqstp, Boolean term) +{ + ptrace_in pin; /* used for ptrace call */ + ptrace_out *pout; + + /* Remove breakpoints */ + if (plst->break_alloc > 0) { + pin.pid = plst->pid; + pin.addr.req = RPT_CLRBREAK; + pin.data = 0; /* clear all */ + pin.flags = PTRFLG_NON_OWNER; + pout = RPCGENSRVNAME(ptrace_2_svc) (&pin, rqstp); + if (pout->result < 0) { + DPRINTF (("TgtKillAndDelete: RPT_CLRBREAK failed %d\n", + getErrno())); + return -1; + } + } + + if (term) + { /* kill */ + pin.addr.ptrace_addr_data_in_u.address = 0; + pin.data = -1; /* Don't want notification from slave */ + pin.addr.req = RPT_KILL; + } + else + { /* detach */ + pin.addr.ptrace_addr_data_in_u.address = 1; + pin.data = 0; + pin.addr.req = RPT_DETACH; + } + pin.pid = plst->pid; + pin.flags = PTRFLG_FREE | PTRFLG_NON_OWNER; + + DPRINTF (("TgtKillAndDelete: ptrace_2_svc (%s (%d), %d)\n", + PtraceName (pin.addr.req), pin.addr.req, pin.pid)); + + pout = RPCGENSRVNAME(ptrace_2_svc) (&pin, rqstp);/* start it */ + if (pout->errNo == ESRCH && plst->pid) + TgtDelete(plst, -1, BMSG_KILLED); /* only entry remains */ + return 0; +} + +/* ----------------------------------------------------------------------- + TgtDetachCon - detach a connection's ownership of a process. + ----------------------------------------------------------------------- */ + + void +TgtDetachCon( int conn_idx, int pid_idx, Boolean delete) +{ + if ((unsigned) pid_idx >= pid_list_cnt + || !pid_list[pid_idx].pid) + return; /* not valid */ + if (PIDMAP_TEST (conn_idx, pid_idx)) + { /* if an owner, release control */ + PIDMAP_CLEAR (conn_idx, pid_idx); + + if (pid_list[pid_idx].owners) + pid_list[pid_idx].owners--; + if (pid_list[pid_idx].primary_conn == conn_idx) + pid_list[pid_idx].primary_conn = NO_PRIMARY; + if (delete + && !pid_list[pid_idx].owners + && PROC_TERMINATED (pid_list + pid_idx)) + TgtDelete(&pid_list[pid_idx], -1, 0); /* remove entry */ + } +} + +/* ----------------------------------------------------------------------- + TgtHandleChildChange - decide what action to take after wait() returns. + Used in the master only. + ----------------------------------------------------------------------- */ + +#ifdef DDEBUG +static char* LastStartNames[] = { + "NONE", "STEP", "CONT", "RANGE", + "STEPOFF", "KILLED", "DETACHED" +}; + +char* GetLastStartName (int last_start) +{ + static char buf [32]; + + strcpy (buf, LastStartNames [last_start & ~LAST_START]); + if (last_start & LAST_START) { + strcat (buf, "+START"); + } + return buf; +} +#endif + +Boolean TgtHandleChildChange(PID pid, int* status, int *unexp, + CPU_Exception_frame* ctx) +{ /* return False if continue, else stop */ + int idx, sig; + int bidx = 0; + PID_LIST *plst; + unsigned long PC; + BASE_BREAK *base = NULL; /* break_list[0] is really BASE_BREAK */ + int hadStepEmul; + int origHadStepEmul; + int stopWanted; + + DPRINTF (("TgtHandleChildChange: pid %d status %x cap\n", + (int) pid, *status)); + if (unexp) + *unexp = 0; /* initialize to ok */ + + /* first, find pid in question */ + idx = FindPidEntry (pid); + if (idx < 0) + { /* cannot locate this process */ + DPRINTF (("TgtHandleChildChange: unknown process (%s pid)\n", + FindPidEntry (pid) >= 0 ? "stale" : "unknown")); + if (unexp) + *unexp = 1; /* Unexpected change */ + return(False); /* unknown: ignore (used to stop and notify) */ + } + + /* found */ + plst = &pid_list[idx]; /* pointer to entry */ + /* first we see if just stopped */ + + /* copy ctxt */ + CtxToRegs(ctx, &(plst->regs)); + + stopWanted = plst->stop_wanted; + plst->stop_wanted = 0; /* For the next time */ + + hadStepEmul = BreakClear (plst, -1, -1) > 0; + origHadStepEmul = hadStepEmul; /* hadStepEmul is cleared if real bkpt met */ + + if (STS_SIGNALLED (*status)) + { /* stopped, not terminated */ + sig = STS_GETSIG (*status); /* signal that stopped us */ + + /* now, we read the registers and see what to do next */ + if (TgtPtrace(RPT_GETREGS, pid, (void *)&plst->regs, 0, NULL) < 0) { + memset (&plst->regs, 0, sizeof plst->regs); + } + + /* Get current thread */ + plst->thread = TgtPtrace(RPT_GETTARGETTHREAD, pid, NULL, 0, NULL); + + if (sig == SIGTRAP) + { /* stopped from break/step */ + PC = plst->regs.REG_PC; + /* Must check PC to see whether in situations where we had + step emulation we are on a breakpoint or just + have returned from an emulated single-step */ + if (BreakIdentify (plst, 0 /*no adjust*/, -1 /*no thread*/) > 0) { + hadStepEmul = 0; + } + plst->is_step = hadStepEmul || IS_STEP(plst->regs) + || plst->last_start == LAST_START; + DPRINTF (("TgtHandleChildChange: %s last_start %s\n", plst->is_step + ? "step": "break", GetLastStartName (plst->last_start))); + + if ((plst->is_step || origHadStepEmul || stopWanted) + && (plst->last_start == LAST_STEP + || plst->last_start == LAST_STEPOFF + || plst->last_start == LAST_RANGE)) + { + DPRINTF (("TgtHandleChildChange: restoring stepped-off bkpt\n")); + BreakSteppedOff (plst); + } + + if (plst->last_start == LAST_STEPOFF && (plst->is_step||origHadStepEmul)) + { /* stepped off break and now need cont */ + DPRINTF (("TgtHandleChildChange: auto-resuming after step-off\n")); + plst->last_start = LAST_CONT; /* convert to normal cont */ + if (!stopWanted) { + if (TgtPtrace(RPT_CONT, pid, (char *)1, 0, NULL)) + return True; /* tell people */ + return(False); /* wait for change */ + } + DPRINTF (("TgtHandleChildChange: stop_wanted %d in step-off\n", + stopWanted)); + *status = STS_MAKESIG (stopWanted); + return True; /* Stop and notify */ + } + + base = plst->break_list ? ((BASE_BREAK*)plst->break_list) : + ((BASE_BREAK*)NULL); + /* now see if step in range */ + + if (plst->last_start == LAST_RANGE /* step in range */ + && (plst->is_step || origHadStepEmul) /* not a breakpoint */ + && PC >= base->range_start + && PC <= base->range_end) + { /* still in range, keep going */ + if (stopWanted) { + DPRINTF (("TgtHandleChildChange: stop_wanted %d in step-range\n", + stopWanted)); + } else { + DPRINTF (("TgtHandleChildChange: Reservation at %x\n", + plst->regs.REG_PC)); + } + } + if (!plst->is_step) /* was break */ + { + bidx = BreakIdentify (plst, 1 /*adjust*/, plst->thread); + if (bidx == 0) { + DPRINTF (("TgtHandleChildChange: forwarding bkpt to kernel\n")); + if (unexp) { + *unexp = 1; + } + return False; + } + if (bidx < 0) { /* Unwanted breakpoint, must step it off */ + ptrace_in pin; + ptrace_out* out; + if (origHadStepEmul) + { + DPRINTF (("TgtHandleChildChange: bkpt %x becomes step\n", + plst->regs.REG_PC)); + bidx = -bidx; + plst->is_step = 1; + base->clr_step = plst->break_list [bidx].type == BRKT_INSTR; + base->last_break = bidx; + return True; + } + if (stopWanted) { + DPRINTF (("TgtHandleChildChange: stop_wanted %d at bkpt %x\n", + stopWanted, plst->regs.REG_PC)); + /* The PC has already been adjusted by BreakIdentify */ + *status = STS_MAKESIG (stopWanted); + return True; + } + /* All the handling is done in ptrace_2_svc() so call it */ + bidx = -bidx; + DPRINTF (("TgtHandleChildChange: last %d (%s) restarting bkpt %d\n", + plst->last_start, GetLastStartName (plst->last_start), bidx)); + base->clr_step = 1; + base->last_break = bidx; /* remember which one */ + plst->running = 0; /* So that ptrace is accepted */ + pin.pid = plst->pid; + + if (plst->last_start == LAST_STEP) { + pin.addr.req = RPT_SINGLESTEP; + } else { + pin.addr.req = RPT_CONT; + } + pin.addr.ptrace_addr_data_in_u.address = 1; + pin.data = 0; + pin.flags = PTRFLG_NON_OWNER; + out = RPCGENSRVNAME(ptrace_2_svc) (&pin, NULL); + if (out->result == 0) return False; /* Continue waiting */ + DPRINTF(("TgtHandleChildChange: failed to restart bkpt!\n")); + /* If something went wrong, just stop on breakpoint */ + } + } + } /* else sig != SIGTRAP */ + + /* finally, fill in stop info in break point array base */ + if (bidx > 0) + { /* store break info */ + /* will need to get off the break for SW breakpoints only */ + base->clr_step = plst->break_list [bidx].type == BRKT_INSTR; + base->last_break = bidx; /* remember which one */ + } + else if (base) + { /* clear break info */ + base->clr_step = False; /* not stopped on break */ + base->last_break = 0; + } + /* decision to notify owner based on last_start */ + } /* stopped */ + else /* terminated */ + { + if (plst->last_start == LAST_START) + { /* spawn failed */ + TgtNotifyAll(idx, BMSG_EXEC_FAIL, 0, 0, -1, True); + plst->running = False; /* not running - dead */ + plst->state = *status; /* contains errno in high word */ + return(False); + } + + else if ((UCHAR)(plst->last_start & ~LAST_START) < (UCHAR)LAST_KILLED) + plst->last_start = LAST_NONE; /* doesn't matter anymore */ + else + return(False); /* killed and detach already notified */ + } + return(True); /* stop and notify */ +} + +#ifdef DDEBUG + +/* ----------------------------------------------------------------------- + TgtDbgPtrace - debug version of ptrace. + ----------------------------------------------------------------------- */ + +int TgtDbgPtrace(int request, PID pid, char *addr, int data, void *addr2) +{ + int diag; + + DPRINTF (("TgtDbgPtrace: entered (%s (%d), %d, %x, %d, %x)\n", + PtraceName (request), request, pid, (int) addr, data, + (int) addr2)); + + if (request == RPT_WRITETEXT || request == RPT_WRITEDATA) { + int i; + + DPRINTF (("TgtDbgPtrace:")); + if (rdb_debug) { + for (i = 0; i < data && i < 16; ++i) { + printf (" %02x", ((char*) addr2) [i] & 0xFF); + } + printf ("\n"); + } + } + + diag = TgtRealPtrace (request, pid, addr, data, addr2); + + DPRINTF (("TgtDbgPtrace: returned %d (%x) errno %d\n", + diag, diag, getErrno())); + + if (request == RPT_GETREGS || request == RPT_GETTHREADREGS + || request == RPT_SETREGS || request == RPT_SETTHREADREGS) + { + /* Use DPRINTF() so as to have the id prefix */ + DPRINTF (("TgtDbgPtrace: (%s) PC = %x, SP = %x, FP = %x\n", + PtraceName (request), + ((xdr_regs*)addr)->REG_PC, + ((xdr_regs*)addr)->REG_SP, + ((xdr_regs*)addr)->REG_FP)); + } + + return(diag); +} +#endif /* DDEBUG */ diff --git a/c/src/librdbg/src/servtsp.c b/c/src/librdbg/src/servtsp.c new file mode 100644 index 0000000000..6a83c6caf5 --- /dev/null +++ b/c/src/librdbg/src/servtsp.c @@ -0,0 +1,329 @@ +/* + ************************************************************************** + * + * Component: RDBG + * Module: servtsp.c + * + * Synopsis: Transport management for remote debug server. + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int out_sock; +static int warm_test; + +static void TimeTestHandler(); + + /* + * TspInit - Initialize the transport system. + * + */ + + void +TspInit (int id) +{ + struct sigaction sa; + + /* setup a socket to send event messages back through */ + out_sock = socket (PF_INET, SOCK_DGRAM, 0); + if (out_sock < 0) { + DPRINTF (("TspInit: socket() failed %d errno %d\n", + out_sock, getErrno())); + return; /* failed to open socket, let caller deal with */ + } + { + struct sockaddr_in addr; + + bzero ((void *)(&addr), sizeof addr); + addr.sin_family = AF_INET; + addr.sin_port = htons (BackPort); + if (bind (out_sock, (struct sockaddr*) &addr, sizeof addr) < 0) { + DPRINTF (("TspInit: bind() failed\n")); + } + } + /* setup alarm timer for warm testing */ + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = TimeTestHandler; + sigaction (SIGALRM, &sa, 0); +} + + /* + * TspTranslateRpcAddr - translate from an RPC handle to an + * opaque address. + * + * Converts the sender's address into the opaque data structure + * used for network addresses. This is used to look up the sender + * on each call. + */ + + Boolean +TspTranslateRpcAddr (struct svc_req* rqstp, NET_OPAQUE* opaque) +{ + struct sockaddr_in* addr; /* used as template to extract net info */ + unsigned char* up; + + memset (opaque, 0, sizeof (NET_OPAQUE)); + /* + * We interpret the remote address as a standard netbuf name. + * The format is 2 bytes of address family (normally AF_INET) + * and then a length (5) and then the IP address. + */ + if (rqstp->rq_xprt->xp_addrlen != 16) + { + DPRINTF (("TspTranslateRpcAddr: Unknown remote address!!!\n")); + setErrno (EPROTONOSUPPORT); + return False; /* invalid, so fails */ + } + /* addr = &rqstp->rq_xprt->xp_raddr; */ + addr = svc_getcaller (rqstp->rq_xprt); + /* verify it is AF_INET */ + if (addr->sin_family != AF_INET) { /* no, error */ + DPRINTF (("TspTranslateRpcAddr: Not an internet address!!\n")); + setErrno (EAFNOSUPPORT);/* invalid addr family */ + return False; + } + /* good address type */ + up = (unsigned char *) &addr->sin_addr.s_addr; + DPRINTF (("TspTranslateRpcAddr: Sent by %u.%u.%u.%u port #%u\n", + up[0], up[1], up[2], up[3], htons (addr->sin_port))); + memcpy (opaque, addr, sizeof (struct sockaddr_in)); + return True; +} + + /* + * TspValidateAddr - validate a passed in opaque address. + * + * Checks that the passed in address is in the format + * expected. + */ + + Boolean +TspValidateAddr (NET_OPAQUE* opaque, NET_OPAQUE* sender) +{ + struct sockaddr_in* addr; /* used as template to extract net info */ + + addr = (struct sockaddr_in*) opaque; + /* Verify it is AF_INET. Should check against sender IP address too */ + if (addr->sin_family != AF_INET) { + DPRINTF (("TspValidateAddr: Back port invalid: %d\n", + htons (addr->sin_port))); + return False; /* not valid */ + } + /* otherwise, we copy in the IP address, since client may not know it */ + addr->sin_addr.s_addr = ((struct sockaddr_in*) sender)->sin_addr.s_addr; + DPRINTF (("TspValidateAddr: Back port is %d\n", htons (addr->sin_port))); + return True; +} + + /* + * TspConnGetIndex - lookup an rpc caller's address as a connection entry. + * + * Looks up an ip address of a caller to locate the + * connection index in our connection array. + */ + + int +TspConnGetIndex (struct svc_req* rqstp) +{ + int conn; + /* &rqstp->rq_xprt->xp_raddr; */ + struct sockaddr_in *addr = svc_getcaller (rqstp->rq_xprt); + + for (conn = 0; conn < conn_list_cnt; conn++) { + if (!conn_list[conn].in_use) + continue; /* not used */ + + if (addr->sin_addr.s_addr == ((struct sockaddr_in *) + &conn_list [conn].sender)->sin_addr.s_addr + && addr->sin_port == ((struct sockaddr_in *) + &conn_list[conn].sender)->sin_port) { + return conn; + } + } + return -1; +} + + + /* + * TspSendWaitChange - send wait-change message to clients to + * notify change. + */ + + void +TspSendWaitChange( + int conn, /* connection to send to */ + BACK_MSG msg, /* BMSG type */ + UINT16 spec, /* special information */ + PID pid, /* pid it refers to */ + UINT32 context, /* additional context for message */ + Boolean force) /* force into being only message */ +{ + int idx; + struct SEND_LIST* snd_ptr; + + if (force) { + /* force to top, which means others gone */ + idx = 0; + conn_list [conn].send_idx = 1; + conn_list[conn].retry = 0; + } else { + for (idx = 0; idx < (int) conn_list[conn].send_idx; idx++) { + if (conn_list[conn].send_list[idx].send_type == msg + && conn_list[conn].send_list[idx].pid == pid) + return; /* already pended for this pid */ + } + idx = conn_list[conn].send_idx; + if (idx+1 > MAX_SEND) + return; /* we lose it, what should we do??? */ + conn_list[conn].send_idx++; + } + snd_ptr = &conn_list[conn].send_list[idx]; + snd_ptr->send_type = msg; /* message to send */ + snd_ptr->retry = TSP_RETRIES; /* about 1 minute of retries */ + snd_ptr->spec = htons ((u_short) spec); + snd_ptr->pid = htonl (pid); + snd_ptr->context = htonl (context); + TspSendMessage (conn, False); /* now do the send */ +} + + /* + * TspSendMessage - send message at top of send list for connection. + */ + + void +TspSendMessage( int conn, Boolean resend) +{ + struct sockaddr_in addr; + struct UDP_MSG msg; + int cnt; + + if (!resend && conn_list[conn].retry) + return; /* already waiting for reply */ + + /* + * Note on above: if no back port we can't remove unless + * someone blows off. + */ + if (!resend) { + /* first time, setup. Set retry count: */ + conn_list[conn].retry = conn_list[conn].send_list[0].retry; + conn_list[conn].last_msg_num++; /* new sequence number */ + if (!warm_test++) { /* starting, so enable timer */ + alarm (2); /* resend every 2 seconds as needed */ + } + } + + msg.type = conn_list[conn].send_list[0].send_type; + msg.msg_num = conn_list[conn].last_msg_num; + msg.spec = conn_list[conn].send_list[0].spec; + msg.pid = conn_list[conn].send_list[0].pid; + msg.context = conn_list[conn].send_list[0].context; + + memset (&addr, 0, sizeof addr); + addr.sin_family = AF_INET; + addr.sin_port = ((struct sockaddr_in*)&conn_list[conn].back_port)->sin_port; + addr.sin_addr.s_addr = + ((struct sockaddr_in*)&conn_list[conn].back_port)->sin_addr.s_addr; + + DPRINTF (("TspSendMessage: Sending msg %d (%s) to port %d\n", + msg.type, BmsgNames [msg.type], HL_W (addr.sin_port))); + + cnt = sendto (out_sock, &msg, sizeof msg, 0, (struct sockaddr*) &addr, + sizeof addr); + if (cnt != sizeof msg) { /* failed on send */ + printf ("%s: Failed to send msg %d to conn %d (%d vs. %d)\n", + ActName, msg.type, conn, cnt, sizeof msg); + } +} + + /* + * TspMessageReceive - confirmation received, now send next if any. + * + * - since UDP is connectionless, we batch up the sends and use + * one at a time until we get a message indicating ready for + * next (from ack). + */ + + void +TspMessageReceive (int conn, PID pid) +{ + /* We remove the send list entry and use next if any */ + conn_list[conn].retry = 0; /* reset */ + if (!warm_test || !--warm_test) { + alarm (0); /* reset timer if not used */ + } +#ifdef DDEBUG + if (conn_list[conn].send_list[0].send_type == BMSG_WARM) { + DPRINTF (("TspMessageReceive: Connection reset for conn %d\n", conn)); + } +#endif + /* Move up by one if needed */ + if (!--conn_list[conn].send_idx) + return; /* no more to do */ + + memcpy (conn_list[conn].send_list, conn_list[conn].send_list+1, + conn_list[conn].send_idx * sizeof(struct SEND_LIST)); /* copy down */ + TspSendMessage (conn, 0); +} + + /* + * TspGetHostName - return client's host name. + * + * - this routine returns the name of the client's host or the net + * number of unknown. + */ + + char* +TspGetHostName (conn_idx) + int conn_idx; /* client connection number */ +{ + static char buff [30]; /* largest net num */ + unsigned char* cp; + + cp = conn_list[conn_idx].sender.c+4; + sprintf (buff, "%u.%u.%u.%u", cp[0], cp[1], cp[2], cp[3]); + return buff; +} + + /* + * TimeTestHandler - alarm timer handler to resend warm/wait test. + */ + + static void +TimeTestHandler() +{ + int conn; + + if (!warm_test) + return; /* no longer enabled */ + + for (conn = 0; conn < conn_list_cnt; conn++) { + /* locate all that are using this */ + if (!conn_list[conn].in_use) + continue; /* not used */ + + if (!conn_list[conn].retry) continue; + /* found one that we are testing */ + if (!--conn_list[conn].retry) { + /* + * Counted down the retries: blow off. + * Need to have connection flag to indicate not blowing + * off for cases where client is stopped due to being + * debugged. + */ + ConnDelete (conn, NULL, CLOSE_IGNORE); + continue; + } + TspSendMessage (conn, True); /* send another message */ + } + alarm (2); /* setup for 2 seconds from now */ +} diff --git a/c/src/librdbg/src/servutil.c b/c/src/librdbg/src/servutil.c new file mode 100644 index 0000000000..40187faead --- /dev/null +++ b/c/src/librdbg/src/servutil.c @@ -0,0 +1,130 @@ +/* + ********************************************************************** + * + * Component: RDB + * Module: servutil.c + * + * Synopsis: Various utility routines + * + ********************************************************************** + */ + +#include +#include +#include + +/*----- Management of per-process list ----*/ + + /* + * ListAlloc - build up list entry. + * + * Notes: + * - this is a generic routine to build up entries in the per-connection + * list. The fields list, list_sz and list_alloc are affected. + */ + + Boolean +ListAlloc(buff, clst) + char *buff; + CONN_LIST *clst; /* place to copy it */ +{ + int tmp; + char* name; + int new_len; + int len; + + tmp = strlen(buff); + new_len = (int)clst->list_sz + 1 + tmp; + if (clst->list_alloc < (unsigned)new_len) { + /* need more space */ + name = (char *)Realloc(clst->list, len = new_len + MAX_FILENAME); + if (name == NULL) { + return(False); /* failed, no space */ + } + clst->list_alloc = len; + clst->list = name; + } + strcpy(clst->list + clst->list_sz, buff); + clst->list_sz += tmp; + return(True); +} + +/*----- Management of processes -----*/ + + /* + * FindPidEntry - locate pid_list entry from pid + */ + + int +FindPidEntry (pid) + int pid; /* process identifier */ +{ + int idx; + + /* pid 0 is invalid, and signals a free slot */ + if (pid_list == NULL || pid == 0) { + return -1; + } + for (idx = 0; idx < pid_list_cnt; idx++) { + if (pid_list [idx].pid == pid ) + return idx; + } + return -1; +} + +/*----- Debug suport -----*/ + +#ifdef DDEBUG + + /* + * Names of debug primitives + */ + +const char* PtraceNames [] = { + +"RPT_TRACEME", "RPT_PEEKTEXT", "RPT_PEEKDATA", "RPT_PEEKUSER", +"RPT_POKETEXT", "RPT_POKEDATA", "RPT_POKEUSER", "RPT_CONT", +"RPT_KILL", "RPT_SINGLESTEP", "RPT_ATTACH", "RPT_DETACH", +"RPT_GETREGS", "RPT_SETREGS", "RPT_GETFPREGS", "RPT_SETFPREGS", +"RPT_READDATA", "RPT_WRITEDATA", "RPT_READTEXT", "RPT_WRITETEXT", +"RPT_GETFPAREGS", "RPT_SETFPAREGS", "RPT_22", "RPT_23", +"RPT_SYSCALL", "RPT_DUMPCORE", "RPT_26", "RPT_27", +"RPT_28", "RPT_GETUCODE", "RPT_30", "RPT_31", +"RPT_32", "RPT_33", "RPT_34", "RPT_35", +"RPT_36", "RPT_37", "RPT_38", "RPT_39", +"RPT_40", "RPT_41", "RPT_42", "RPT_43", +"RPT_44", "RPT_45", "RPT_46", "RPT_47", +"RPT_48", "RPT_49", "RPT_GETTARGETTHREAD", "RPT_SETTARGETTHREAD", +"RPT_THREADSUSPEND", "RPT_THREADRESUME", "RPT_THREADLIST", "RPT_GETTHREADNAME", +"RPT_SETTHREADNAME", "RPT_SETTHREADREGS", "RPT_GETTHREADREGS", + "RPT_59", +"RPT_60", "RPT_61", "RPT_62", "RPT_63", +"RPT_64", "RPT_65", "RPT_66", "RPT_67", +"RPT_68", "RPT_69", "RPT_70", "RPT_71", +"RPT_72", "RPT_73", "RPT_74", "RPT_STEPRANGE", +"RPT_CONTTO", "RPT_SETBREAK", "RPT_CLRBREAK", "RPT_GETBREAK", +"RPT_GETNAME", "RPT_STOP", +"RPT_PGETREGS", "RPT_PSETREGS", +"RPT_PSETTHREADREGS", "RPT_PGETTHREADREGS" +}; + +const char* +PtraceName(req) + int req; +{ + static char bufret[40]; + + if ((req < 0) || (req >= sizeof(PtraceNames)/sizeof(char*))) { + sprintf(bufret, "BAD_REQ_%d", req); + return bufret; + } + return PtraceNames[req]; +} + +const char* BmsgNames [] = { + "?", "WARM", "WAIT", "BREAK", + "EXEC_FAIL", "DETACH", "KILLED", "NOT_PRIM", + "NEW_PID" +}; + +#endif /* DDEBUG */ diff --git a/c/src/librpc/include/rpc/auth.h b/c/src/librpc/include/rpc/auth.h new file mode 100644 index 0000000000..8f14d144f6 --- /dev/null +++ b/c/src/librpc/include/rpc/auth.h @@ -0,0 +1,167 @@ +#ifndef RPC_AUTH_H +#define RPC_AUTH_H + +/* @(#)auth.h 2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * auth.h, Authentication interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * The data structures are completely opaque to the client. The client + * is required to pass a AUTH * to routines that create rpc + * "sessions". + */ + + +#define MAX_AUTH_BYTES 400 +#define MAXNETNAMELEN 255 /* maximum length of network user's name */ + +/* + * Status returned from authentication check + */ +enum auth_stat { + AUTH_OK=0, + /* + * failed at remote end + */ + AUTH_BADCRED=1, /* bogus credentials (seal broken) */ + AUTH_REJECTEDCRED=2, /* client should begin new session */ + AUTH_BADVERF=3, /* bogus verifier (seal broken) */ + AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ + AUTH_TOOWEAK=5, /* rejected due to security reasons */ + /* + * failed locally + */ + AUTH_INVALIDRESP=6, /* bogus response verifier */ + AUTH_FAILED=7 /* some unknown reason */ +}; + +union des_block { + struct { + u_int32 high; + u_int32 low; + } key; + char c[8]; +}; +typedef union des_block des_block; +extern bool_t xdr_des_block(); + +/* + * Authentication info. Opaque to client. + */ +struct opaque_auth { + enum_t oa_flavor; /* flavor of auth */ + caddr_t oa_base; /* address of more auth stuff */ + u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ +}; + + +/* + * Auth handle, interface to client side authenticators. + */ +typedef struct { + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + struct auth_ops { + void (*ah_nextverf)(); + int (*ah_marshal)(); /* nextverf & serialize */ + int (*ah_validate)(); /* validate varifier */ + int (*ah_refresh)(); /* refresh credentials */ + void (*ah_destroy)(); /* destroy this structure */ + } *ah_ops; + caddr_t ah_private; +} AUTH; + + +/* + * Authentication ops. + * The ops and the auth handle provide the interface to the authenticators. + * + * AUTH *auth; + * XDR *xdrs; + * struct opaque_auth verf; + */ +#define AUTH_NEXTVERF(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) +#define auth_nextverf(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) + +#define AUTH_MARSHALL(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) +#define auth_marshall(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) + +#define AUTH_VALIDATE(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) +#define auth_validate(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) + +#define AUTH_REFRESH(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) +#define auth_refresh(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) + +#define AUTH_DESTROY(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) +#define auth_destroy(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) + + +extern struct opaque_auth _null_auth; + + +/* + * These are the various implementations of client side authenticators. + */ + +/* + * Unix style authentication + * AUTH *authunix_create(machname, uid, gid, len, aup_gids) + * char *machname; + * int uid; + * int gid; + * int len; + * int *aup_gids; + */ +extern AUTH *authunix_create(); +extern AUTH *authunix_create_default(); /* takes no parameters */ +extern AUTH *authnone_create(); /* takes no parameters */ +extern AUTH *authdes_create(); + +#define AUTH_NONE 0 /* no authentication */ +#define AUTH_NULL 0 /* backward compatibility */ +#define AUTH_UNIX 1 /* unix style (uid, gids) */ +#define AUTH_SHORT 2 /* short hand unix style */ +#define AUTH_DES 3 /* des style (encrypted timestamps) */ + +#endif /* RPC_AUTH_H */ diff --git a/c/src/librpc/include/rpc/clnt.h b/c/src/librpc/include/rpc/clnt.h new file mode 100644 index 0000000000..faefdb5d50 --- /dev/null +++ b/c/src/librpc/include/rpc/clnt.h @@ -0,0 +1,336 @@ +#ifndef RPC_CLNT_H +#define RPC_CLNT_H + +/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * clnt.h - Client side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _CLNT_ +#define _CLNT_ + +/* + * Rpc calls return an enum clnt_stat. This should be looked at more, + * since each implementation is required to live with this (implementation + * independent) list of errors. + */ +enum clnt_stat { + RPC_SUCCESS=0, /* call succeeded */ + /* + * local errors + */ + RPC_CANTENCODEARGS=1, /* can't encode arguments */ + RPC_CANTDECODERES=2, /* can't decode results */ + RPC_CANTSEND=3, /* failure in sending call */ + RPC_CANTRECV=4, /* failure in receiving result */ + RPC_TIMEDOUT=5, /* call timed out */ + /* + * remote errors + */ + RPC_VERSMISMATCH=6, /* rpc versions not compatible */ + RPC_AUTHERROR=7, /* authentication error */ + RPC_PROGUNAVAIL=8, /* program not available */ + RPC_PROGVERSMISMATCH=9, /* program version mismatched */ + RPC_PROCUNAVAIL=10, /* procedure unavailable */ + RPC_CANTDECODEARGS=11, /* decode arguments error */ + RPC_SYSTEMERROR=12, /* generic "other problem" */ + + /* + * callrpc & clnt_create errors + */ + RPC_UNKNOWNHOST=13, /* unknown host name */ + RPC_UNKNOWNPROTO=17, /* unkown protocol */ + + /* + * _ create errors + */ + RPC_PMAPFAILURE=14, /* the pmapper failed in its call */ + RPC_PROGNOTREGISTERED=15, /* remote program is not registered */ + /* + * unspecified error + */ + RPC_FAILED=16 +}; + + +/* + * Error info. + */ +struct rpc_err { + enum clnt_stat re_status; + union { + int RE_errno; /* realated system error */ + enum auth_stat RE_why; /* why the auth error occurred */ + struct { + u_long low; /* lowest verion supported */ + u_long high; /* highest verion supported */ + } RE_vers; + struct { /* maybe meaningful if RPC_FAILED */ + long s1; + long s2; + } RE_lb; /* life boot & debugging only */ + } ru; +#define re_errno ru.RE_errno +#define re_why ru.RE_why +#define re_vers ru.RE_vers +#define re_lb ru.RE_lb +}; + + +/* + * Client rpc handle. + * Created by individual implementations, see e.g. rpc_udp.c. + * Client is responsible for initializing auth, see e.g. auth_none.c. + */ +typedef struct { + AUTH *cl_auth; /* authenticator */ + struct clnt_ops { + enum clnt_stat (*cl_call)(); /* call remote procedure */ + void (*cl_abort)(); /* abort a call */ + void (*cl_geterr)(); /* get specific error code */ + bool_t (*cl_freeres)(); /* frees results */ + void (*cl_destroy)();/* destroy this structure */ + bool_t (*cl_control)();/* the ioctl() of rpc */ + } *cl_ops; + caddr_t cl_private; /* private stuff */ +} CLIENT; + + +/* + * client side rpc interface ops + * + * Parameter types are: + * + */ + +/* + * enum clnt_stat + * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) + * CLIENT *rh; + * u_long proc; + * xdrproc_t xargs; + * caddr_t argsp; + * xdrproc_t xres; + * caddr_t resp; + * struct timeval timeout; + */ +#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) +#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) + +/* + * void + * CLNT_ABORT(rh); + * CLIENT *rh; + */ +#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) +#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) + +/* + * struct rpc_err + * CLNT_GETERR(rh); + * CLIENT *rh; + */ +#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) +#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) + + +/* + * bool_t + * CLNT_FREERES(rh, xres, resp); + * CLIENT *rh; + * xdrproc_t xres; + * caddr_t resp; + */ +#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) +#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) + +/* + * bool_t + * CLNT_CONTROL(cl, request, info) + * CLIENT *cl; + * u_int request; + * char *info; + */ +#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) +#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) + +/* + * control operations that apply to both udp and tcp transports + */ +#define CLSET_TIMEOUT 1 /* set timeout (timeval) */ +#define CLGET_TIMEOUT 2 /* get timeout (timeval) */ +#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */ +/* + * udp only control operations + */ +#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ +#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ + +/* + * void + * CLNT_DESTROY(rh); + * CLIENT *rh; + */ +#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) +#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) + + +/* + * RPCTEST is a test program which is accessable on every rpc + * transport/port. It is used for testing, performance evaluation, + * and network administration. + */ + +#define RPCTEST_PROGRAM ((u_long)1) +#define RPCTEST_VERSION ((u_long)1) +#define RPCTEST_NULL_PROC ((u_long)2) +#define RPCTEST_NULL_BATCH_PROC ((u_long)3) + +/* + * By convention, procedure 0 takes null arguments and returns them + */ + +#define NULLPROC ((u_long)0) + +/* + * Below are the client handle creation routines for the various + * implementations of client side rpc. They can return NULL if a + * creation failure occurs. + */ + +/* + * Memory based rpc (for speed check and testing) + * CLIENT * + * clntraw_create(prog, vers) + * u_long prog; + * u_long vers; + */ +extern CLIENT *clntraw_create(); + + +/* + * Generic client creation routine. Supported protocols are "udp" and "tcp" + */ +extern CLIENT * +clnt_create(/*host, prog, vers, prot*/); /* + char *host; -- hostname + u_long prog; -- program number + u_long vers; -- version number + char *prot; -- protocol +*/ + + + + +/* + * TCP based rpc + * CLIENT * + * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clnttcp_create(); + +/* + * UDP based rpc. + * CLIENT * + * clntudp_create(raddr, program, version, wait, sockp) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait; + * int *sockp; + * + * Same as above, but you specify max packet sizes. + * CLIENT * + * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait; + * int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clntudp_create(); +extern CLIENT *clntudp_bufcreate(); + +/* + * Print why creation failed + */ +void clnt_pcreateerror(/* char *msg */); /* stderr */ +char *clnt_spcreateerror(/* char *msg */); /* string */ + +/* + * Like clnt_perror(), but is more verbose in its output + */ +void clnt_perrno(/* enum clnt_stat num */); /* stderr */ + +/* + * Print an English error message, given the client error code + */ +void clnt_perror(/* CLIENT *clnt, char *msg */); /* stderr */ +char *clnt_sperror(/* CLIENT *clnt, char *msg */); /* string */ + +/* + * If a creation fails, the following allows the user to figure out why. + */ +struct rpc_createerr { + enum clnt_stat cf_stat; + struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ +}; + +extern struct rpc_createerr rpc_createerr; + + + +/* + * Copy error message to buffer. + */ +char *clnt_sperrno(/* enum clnt_stat num */); /* string */ + + + +#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ +#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ + +#endif /*!_CLNT_*/ + +#endif /* RPC_CLNT_H */ diff --git a/c/src/librpc/include/rpc/rpc.h b/c/src/librpc/include/rpc/rpc.h new file mode 100644 index 0000000000..0a0affd82a --- /dev/null +++ b/c/src/librpc/include/rpc/rpc.h @@ -0,0 +1,86 @@ +#ifndef RPC_H +#define RPC_H + +/* @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC; from 1.9 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * rpc.h, Just includes the billions of rpc header files necessary to + * do remote procedure calling. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +#ifndef __RPC_HEADER__ +#define __RPC_HEADER__ + +#include /* some typedefs */ +#include +#include + +/* external data representation interfaces */ +#include /* generic (de)serializer */ + +/* Client side only authentication */ +#include /* generic authenticator (client side) */ + +/* Client side (mostly) remote procedure call */ +#include /* generic rpc stuff */ + +/* semi-private protocol headers */ +#include /* protocol for rpc messages */ +/*#include "auth_unix.h" * protocol for unix style cred */ +/* + * Uncomment-out the next line if you are building the rpc library with + * DES Authentication (see the README file in the secure_rpc/ directory). + */ +/*#include "auth_des.h" * protocol for des style cred */ + +/* Server side only remote procedure callee */ +#include /* service manager and multiplexer */ +#include /* service side authenticator */ + +/* + * COMMENT OUT THE NEXT INCLUDE (or add to the #ifndef) IF RUNNING ON + * A VERSION OF UNIX THAT USES SUN'S NFS SOURCE. These systems will + * already have the structures defined by included in . + */ +/* routines for parsing /etc/rpc */ + +struct rpcent { + char *r_name; /* name of server for this rpc program */ + char **r_aliases; /* alias list */ + int r_number; /* rpc program number */ +}; + +struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent(); + +#endif /* ndef __RPC_HEADER__ */ + +#endif /* RPC_H */ diff --git a/c/src/librpc/include/rpc/rpc_msg.h b/c/src/librpc/include/rpc/rpc_msg.h new file mode 100644 index 0000000000..2f34fb614c --- /dev/null +++ b/c/src/librpc/include/rpc/rpc_msg.h @@ -0,0 +1,192 @@ +#ifndef RPC_MSG_H +#define RPC_MSG_H + +/* @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)rpc_msg.h 1.7 86/07/16 SMI */ + +/* + * rpc_msg.h + * rpc message definition + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define RPC_MSG_VERSION ((u_long) 2) +#define RPC_SERVICE_PORT ((u_short) 2048) + +/* + * Bottom up definition of an rpc message. + * NOTE: call and reply use the same overall stuct but + * different parts of unions within it. + */ + +enum msg_type { + CALL=0, + REPLY=1 +}; + +enum reply_stat { + MSG_ACCEPTED=0, + MSG_DENIED=1 +}; + +enum accept_stat { + SUCCESS=0, + PROG_UNAVAIL=1, + PROG_MISMATCH=2, + PROC_UNAVAIL=3, + GARBAGE_ARGS=4, + SYSTEM_ERR=5 +}; + +enum reject_stat { + RPC_MISMATCH=0, + AUTH_ERROR=1 +}; + +/* + * Reply part of an rpc exchange + */ + +/* + * Reply to an rpc request that was accepted by the server. + * Note: there could be an error even though the request was + * accepted. + */ +struct accepted_reply { + struct opaque_auth ar_verf; + enum accept_stat ar_stat; + union { + struct { + u_long low; + u_long high; + } AR_versions; + struct { + caddr_t where; + xdrproc_t proc; + } AR_results; + /* and many other null cases */ + } ru; +#define ar_results ru.AR_results +#define ar_vers ru.AR_versions +}; + +/* + * Reply to an rpc request that was rejected by the server. + */ +struct rejected_reply { + enum reject_stat rj_stat; + union { + struct { + u_long low; + u_long high; + } RJ_versions; + enum auth_stat RJ_why; /* why authentication did not work */ + } ru; +#define rj_vers ru.RJ_versions +#define rj_why ru.RJ_why +}; + +/* + * Body of a reply to an rpc request. + */ +struct reply_body { + enum reply_stat rp_stat; + union { + struct accepted_reply RP_ar; + struct rejected_reply RP_dr; + } ru; +#define rp_acpt ru.RP_ar +#define rp_rjct ru.RP_dr +}; + +/* + * Body of an rpc request call. + */ +struct call_body { + u_long cb_rpcvers; /* must be equal to two */ + u_long cb_prog; + u_long cb_vers; + u_long cb_proc; + struct opaque_auth cb_cred; + struct opaque_auth cb_verf; /* protocol specific - provided by client */ +}; + +/* + * The rpc message + */ +struct rpc_msg { + u_long rm_xid; + enum msg_type rm_direction; + union { + struct call_body RM_cmb; + struct reply_body RM_rmb; + } ru; +#define rm_call ru.RM_cmb +#define rm_reply ru.RM_rmb +}; +#define acpted_rply ru.RM_rmb.ru.RP_ar +#define rjcted_rply ru.RM_rmb.ru.RP_dr + + +/* + * XDR routine to handle a rpc message. + * xdr_callmsg(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callmsg(); + +/* + * XDR routine to pre-serialize the static part of a rpc message. + * xdr_callhdr(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callhdr(); + +/* + * XDR routine to handle a rpc reply. + * xdr_replymsg(xdrs, rmsg) + * XDR *xdrs; + * struct rpc_msg *rmsg; + */ +extern bool_t xdr_replymsg(); + +/* + * Fills in the error part of a reply message. + * _seterr_reply(msg, error) + * struct rpc_msg *msg; + * struct rpc_err *error; + */ +extern void _seterr_reply(); + +#endif /* RPC_MSG_H */ diff --git a/c/src/librpc/include/rpc/svc.h b/c/src/librpc/include/rpc/svc.h new file mode 100644 index 0000000000..c576b5538b --- /dev/null +++ b/c/src/librpc/include/rpc/svc.h @@ -0,0 +1,291 @@ + +#ifndef RPC_SVC_H +#define RPC_SVC_H + +/* @(#)svc.h 2.2 88/07/29 4.0 RPCSRC; from 1.20 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc.h, Server-side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef __SVC_HEADER__ +#define __SVC_HEADER__ + +/* + * This interface must manage two items concerning remote procedure calling: + * + * 1) An arbitrary number of transport connections upon which rpc requests + * are received. The two most notable transports are TCP and UDP; they are + * created and registered by routines in svc_tcp.c and svc_udp.c, respectively; + * they in turn call xprt_register and xprt_unregister. + * + * 2) An arbitrary number of locally registered services. Services are + * described by the following four data: program number, version number, + * "service dispatch" function, a transport handle, and a boolean that + * indicates whether or not the exported program should be registered with a + * local binder service; if true the program's number and version and the + * port number from the transport handle are registered with the binder. + * These data are registered with the rpc svc system via svc_register. + * + * A service's dispatch function is called whenever an rpc request comes in + * on a transport. The request's program and version numbers must match + * those of the registered service. The dispatch function is passed two + * parameters, struct svc_req * and SVCXPRT *, defined below. + */ + +enum xprt_stat { + XPRT_DIED, + XPRT_MOREREQS, + XPRT_IDLE +}; + +/* + * Server side transport handle + */ +typedef struct { + int xp_sock; + u_short xp_port; /* associated port number */ + struct xp_ops { + bool_t (*xp_recv)(); /* receive incomming requests */ + enum xprt_stat (*xp_stat)(); /* get transport status */ + bool_t (*xp_getargs)(); /* get arguments */ + bool_t (*xp_reply)(); /* send reply */ + bool_t (*xp_freeargs)();/* free mem allocated for args */ + void (*xp_destroy)(); /* destroy this struct */ + } *xp_ops; + int xp_addrlen; /* length of remote address */ + struct sockaddr_in xp_raddr; /* remote address */ + struct opaque_auth xp_verf; /* raw response verifier */ + caddr_t xp_p1; /* private */ + caddr_t xp_p2; /* private */ +} SVCXPRT; + +/* + * Approved way of getting address of caller + */ +#define svc_getcaller(x) (&(x)->xp_raddr) + +/* + * Operations defined on an SVCXPRT handle + * + * SVCXPRT *xprt; + * struct rpc_msg *msg; + * xdrproc_t xargs; + * caddr_t argsp; + */ +#define SVC_RECV(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) +#define svc_recv(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) + +#define SVC_STAT(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) +#define svc_stat(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) + +#define SVC_GETARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) +#define svc_getargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) + +#define SVC_REPLY(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) +#define svc_reply(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) + +#define SVC_FREEARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) +#define svc_freeargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) + +#define SVC_DESTROY(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) +#define svc_destroy(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) + + +/* + * Service request + */ +struct svc_req { + u_long rq_prog; /* service program number */ + u_long rq_vers; /* service protocol version */ + u_long rq_proc; /* the desired procedure */ + struct opaque_auth rq_cred; /* raw creds from the wire */ + caddr_t rq_clntcred; /* read only cooked cred */ + SVCXPRT *rq_xprt; /* associated transport */ +}; + + +/* + * Service registration + * + * svc_register(xprt, prog, vers, dispatch, protocol) + * SVCXPRT *xprt; + * u_long prog; + * u_long vers; + * void (*dispatch)(); + * int protocol; (like TCP or UDP, zero means do not register) + */ +extern bool_t svc_register(); + +/* + * Service un-registration + * + * svc_unregister(prog, vers) + * u_long prog; + * u_long vers; + */ +extern void svc_unregister(); + +/* + * Transport registration. + * + * xprt_register(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_register(); + +/* + * Transport un-register + * + * xprt_unregister(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_unregister(); + + + + +/* + * When the service routine is called, it must first check to see if it + * knows about the procedure; if not, it should call svcerr_noproc + * and return. If so, it should deserialize its arguments via + * SVC_GETARGS (defined above). If the deserialization does not work, + * svcerr_decode should be called followed by a return. Successful + * decoding of the arguments should be followed the execution of the + * procedure's code and a call to svc_sendreply. + * + * Also, if the service refuses to execute the procedure due to too- + * weak authentication parameters, svcerr_weakauth should be called. + * Note: do not confuse access-control failure with weak authentication! + * + * NB: In pure implementations of rpc, the caller always waits for a reply + * msg. This message is sent when svc_sendreply is called. + * Therefore pure service implementations should always call + * svc_sendreply even if the function logically returns void; use + * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows + * for the abuse of pure rpc via batched calling or pipelining. In the + * case of a batched call, svc_sendreply should NOT be called since + * this would send a return message, which is what batching tries to avoid. + * It is the service/protocol writer's responsibility to know which calls are + * batched and which are not. Warning: responding to batch calls may + * deadlock the caller and server processes! + */ + +extern bool_t svc_sendreply(); +extern void svcerr_decode(); +extern void svcerr_weakauth(); +extern void svcerr_noproc(); +extern void svcerr_progvers(); +extern void svcerr_auth(); +extern void svcerr_noprog(); +extern void svcerr_systemerr(); + +/* + * Lowest level dispatching -OR- who owns this process anyway. + * Somebody has to wait for incoming requests and then call the correct + * service routine. The routine svc_run does infinite waiting; i.e., + * svc_run never returns. + * Since another (co-existant) package may wish to selectively wait for + * incoming calls or other events outside of the rpc architecture, the + * routine svc_getreq is provided. It must be passed readfds, the + * "in-place" results of a select system call (see select, section 2). + */ + +/* + * Global keeper of rpc service descriptors in use + * dynamic; must be inspected before each call to select + */ +#ifdef FD_SETSIZE +extern fd_set svc_fdset; +#define svc_fds svc_fdset.fds_bits[0] /* compatibility */ +#else +extern int svc_fds; +#endif /* def FD_SETSIZE */ + +/* + * a small program implemented by the svc_rpc implementation itself; + * also see clnt.h for protocol numbers. + */ +extern void rpctest_service(); + +extern void svc_getreq(); +extern void svc_getreqset(); /* takes fdset instead of int */ +extern void svc_run(); /* never returns */ + +/* + * Socket to use on svcxxx_create call to get default socket + */ +#define RPC_ANYSOCK -1 + +/* + * These are the existing service side transport implementations + */ + +/* + * Memory based rpc for testing and timing. + */ +extern SVCXPRT *svcraw_create(); + +/* + * Udp based rpc. + */ +extern SVCXPRT *svcudp_create(); +extern SVCXPRT *svcudp_bufcreate(); +extern int svcudp_enablecache(SVCXPRT *transp, u_long size); + +/* + * Tcp based rpc. + */ +extern SVCXPRT *svctcp_create(); + + + +#endif /* !__SVC_HEADER__ */ + +extern int _rpcsvccount; +extern int _rpcsvcstate; +extern int _SERVED; + +#endif /* RPC_SVC_H */ diff --git a/c/src/librpc/include/rpc/svc_auth.h b/c/src/librpc/include/rpc/svc_auth.h new file mode 100644 index 0000000000..5c233a6a47 --- /dev/null +++ b/c/src/librpc/include/rpc/svc_auth.h @@ -0,0 +1,47 @@ +#ifndef RPC_SVC_AUTH_H +#define RPC_SVC_AUTH_H + +/* @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)svc_auth.h 1.6 86/07/16 SMI */ + +/* + * svc_auth.h, Service side of rpc authentication. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + + +/* + * Server side authenticator + */ +extern enum auth_stat _authenticate(); + +#endif /* SVC_AUTH_H */ diff --git a/c/src/librpc/include/rpc/types.h b/c/src/librpc/include/rpc/types.h new file mode 100644 index 0000000000..b6d7eb3ccc --- /dev/null +++ b/c/src/librpc/include/rpc/types.h @@ -0,0 +1,75 @@ +#ifndef RPC_TYPES_H +#define RPC_TYPES_H + +/* @(#)types.h 2.3 88/08/15 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)types.h 1.18 87/07/24 SMI */ + +/* + * Rpc additions to + */ +#ifndef __TYPES_RPC_HEADER__ +#define __TYPES_RPC_HEADER__ + +/*#include */ +typedef unsigned long u_int32; /* 32-bit unsigned integers */ + +#define bool_t int +#define enum_t int +#ifndef FALSE +# define FALSE (0) +#endif +#ifndef TRUE +# define TRUE (1) +#endif +#define __dontcare__ -1 +#ifndef NULL +# define NULL 0 +#endif + +void *malloc(); +#define mem_alloc(bsize) malloc(bsize) +#define mem_free(ptr, bsize) free(ptr) + +#ifndef makedev /* ie, we haven't already included it */ +#include +#endif +#include + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK (u_long)0x7F000001 +#endif +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#endif /* ndef __TYPES_RPC_HEADER__ */ + +#endif /* RPC_TYPES_H */ diff --git a/c/src/librpc/include/rpc/xdr.h b/c/src/librpc/include/rpc/xdr.h new file mode 100644 index 0000000000..ef2df51d93 --- /dev/null +++ b/c/src/librpc/include/rpc/xdr.h @@ -0,0 +1,275 @@ +#ifndef RPC_XDR_H +#define RPC_XDR_H + +/* @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)xdr.h 1.19 87/04/22 SMI */ + +/* + * xdr.h, External Data Representation Serialization Routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef __XDR_HEADER__ +#define __XDR_HEADER__ + +/* + * XDR provides a conventional way for converting between C data + * types and an external bit-string representation. Library supplied + * routines provide for the conversion on built-in C data types. These + * routines and utility routines defined here are used to help implement + * a type encode/decode routine for each user-defined type. + * + * Each data type provides a single procedure which takes two arguments: + * + * bool_t + * xdrproc(xdrs, argresp) + * XDR *xdrs; + * *argresp; + * + * xdrs is an instance of a XDR handle, to which or from which the data + * type is to be converted. argresp is a pointer to the structure to be + * converted. The XDR handle contains an operation field which indicates + * which of the operations (ENCODE, DECODE * or FREE) is to be performed. + * + * XDR_DECODE may allocate space if the pointer argresp is null. This + * data can be freed with the XDR_FREE operation. + * + * We write only one procedure per data type to make it easy + * to keep the encode and decode procedures for a data type consistent. + * In many cases the same code performs all operations on a user defined type, + * because all the hard work is done in the component type routines. + * decode as a series of calls on the nested data types. + */ + +/* + * Xdr operations. XDR_ENCODE causes the type to be encoded into the + * stream. XDR_DECODE causes the type to be extracted from the stream. + * XDR_FREE can be used to release the space allocated by an XDR_DECODE + * request. + */ +enum xdr_op { + XDR_ENCODE=0, + XDR_DECODE=1, + XDR_FREE=2 +}; + +/* + * This is the number of bytes per unit of external data. + */ +#define BYTES_PER_XDR_UNIT (4) +#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ + * BYTES_PER_XDR_UNIT) + +/* + * A xdrproc_t exists for each data type which is to be encoded or decoded. + * + * The second argument to the xdrproc_t is a pointer to an opaque pointer. + * The opaque pointer generally points to a structure of the data type + * to be decoded. If this pointer is 0, then the type routines should + * allocate dynamic storage of the appropriate size and return it. + * bool_t (*xdrproc_t)(XDR *, caddr_t *); + */ +typedef bool_t (*xdrproc_t)(); + +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the paticular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular impelementation. + */ +typedef struct { + enum xdr_op x_op; /* operation; fast additional param */ + struct xdr_ops { + bool_t (*x_getlong)(); /* get a long from underlying stream */ + bool_t (*x_putlong)(); /* put a long to " */ + bool_t (*x_getbytes)();/* get some bytes from " */ + bool_t (*x_putbytes)();/* put some bytes to " */ + u_int (*x_getpostn)();/* returns bytes off from beginning */ + bool_t (*x_setpostn)();/* lets you reposition the stream */ + long * (*x_inline)(); /* buf quick ptr to buffered data */ + void (*x_destroy)(); /* free privates of this xdr_stream */ + } *x_ops; + caddr_t x_public; /* users' data */ + caddr_t x_private; /* pointer to private data */ + caddr_t x_base; /* private used for position info */ + int x_handy; /* extra private word */ +} XDR; + +/* + * Operations defined on a XDR handle + * + * XDR *xdrs; + * long *longp; + * caddr_t addr; + * u_int len; + * u_int pos; + */ +#define XDR_GETLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) +#define xdr_getlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) + +#define XDR_PUTLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) +#define xdr_putlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) + +#define XDR_GETBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) +#define xdr_getbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) + +#define XDR_PUTBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) +#define xdr_putbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) + +#define XDR_GETPOS(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) +#define xdr_getpos(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) + +#define XDR_SETPOS(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) +#define xdr_setpos(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) + +#define XDR_INLINE(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) +#define xdr_inline(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) + +#define XDR_DESTROY(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) +#define xdr_destroy(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) + +/* + * Support struct for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * a entry with a null procedure pointer. The xdr_union routine gets + * the discriminant value and then searches the array of structures + * for a matching value. If a match is found the associated xdr routine + * is called to handle that part of the union. If there is + * no match, then a default routine may be called. + * If there is no match and no default routine it is an error. + */ +#define NULL_xdrproc_t ((xdrproc_t)0) +struct xdr_discrim { + int value; + xdrproc_t proc; +}; + +/* + * In-line routines for fast encode/decode of primitve data types. + * Caveat emptor: these use single memory cycles to get the + * data from the underlying buffer, and will fail to operate + * properly if the data is not aligned. The standard way to use these + * is to say: + * if ((buf = XDR_INLINE(xdrs, count)) == NULL) + * return (FALSE); + * <<< macro calls >>> + * where ``count'' is the number of bytes of data occupied + * by the primitive data types. + * + * N.B. and frozen for all time: each data type here uses 4 bytes + * of external representation. + */ +#define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*(buf)++)) +#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((u_long)v)) + +#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) +#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) +#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) + +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) + +/* + * These are the "generic" xdr routines. + */ +extern bool_t xdr_void(); +extern bool_t xdr_int(); +extern bool_t xdr_u_int(); +extern bool_t xdr_long(); +extern bool_t xdr_u_long(); +extern bool_t xdr_short(); +extern bool_t xdr_u_short(); +extern bool_t xdr_bool(); +extern bool_t xdr_enum(); +extern bool_t xdr_array(); +extern bool_t xdr_bytes(); +extern bool_t xdr_opaque(); +extern bool_t xdr_string(); +extern bool_t xdr_union(); +extern bool_t xdr_char(); +extern bool_t xdr_u_char(); +extern bool_t xdr_vector(); +extern bool_t xdr_float(); +extern bool_t xdr_double(); +extern bool_t xdr_reference(); +extern bool_t xdr_pointer(); +extern bool_t xdr_wrapstring(); + +/* + * Common opaque bytes objects used by many rpc protocols; + * declared here due to commonality. + */ +#define MAX_NETOBJ_SZ 1024 +struct netobj { + u_int n_len; + char *n_bytes; +}; +typedef struct netobj netobj; +extern bool_t xdr_netobj(); + +/* + * These are the public routines for the various implementations of + * xdr streams. + */ +extern void xdrmem_create(); /* XDR using memory buffers */ +extern void xdrstdio_create(); /* XDR using stdio library */ +extern void xdrrec_create(); /* XDR pseudo records for tcp */ +extern bool_t xdrrec_endofrecord(); /* make end of xdr record */ +extern bool_t xdrrec_skiprecord(); /* move to beginning of next record */ +extern bool_t xdrrec_eof(); /* true if no more input */ + +#endif /* !__XDR_HEADER__ */ + +#endif /* RPC_XDR_H */ diff --git a/c/src/librpc/src/Makefile.in b/c/src/librpc/src/Makefile.in new file mode 100644 index 0000000000..9c3f0986f0 --- /dev/null +++ b/c/src/librpc/src/Makefile.in @@ -0,0 +1,49 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @top_srcdir@ +PROJECT_ROOT = @PROJECT_ROOT@ + +LIBNAME=librpc.a +LIB=${ARCH}/${LIBNAME} + +# C and C++ source names, if any, go here -- minus the .c or .cc +C_PIECES= rpc_callmsg rpc_prot svc svc_auth svc_udp xdr xdr_array xdr_mem +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) + +SRCS=$(C_FILES) +OBJS=$(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg +include $(RTEMS_ROOT)/make/lib.cfg + +# +# Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += $(LIBC_DEFINES) + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += $(LIB) +CLOBBER_ADDITIONS += + +all: ${ARCH} $(LIB) + $(INSTALL_VARIANT) -m 644 ${LIB} ${PROJECT_RELEASE}/lib + +$(LIB): $(SRCS) ${OBJS} + $(make-library) + + diff --git a/c/src/librpc/src/rpc_callmsg.c b/c/src/librpc/src/rpc_callmsg.c new file mode 100644 index 0000000000..4f95254e82 --- /dev/null +++ b/c/src/librpc/src/rpc_callmsg.c @@ -0,0 +1,191 @@ +/* @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * rpc_callmsg.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + */ + +#include /* bcopy */ +#include + +bool_t xdr_opaque_auth (register XDR *xdrs, register struct + opaque_auth *ap); +/* + * XDR a call message + */ +bool_t +xdr_callmsg(xdrs, cmsg) + register XDR *xdrs; + register struct rpc_msg *cmsg; +{ + register long *buf; + register struct opaque_auth *oa; + + if (xdrs->x_op == XDR_ENCODE) { + if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) { + return (FALSE); + } + if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) { + return (FALSE); + } + buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + + RNDUP(cmsg->rm_call.cb_cred.oa_length) + + 2 * BYTES_PER_XDR_UNIT + + RNDUP(cmsg->rm_call.cb_verf.oa_length)); + if (buf != NULL) { + IXDR_PUT_LONG(buf, cmsg->rm_xid); + IXDR_PUT_ENUM(buf, cmsg->rm_direction); + if (cmsg->rm_direction != CALL) { + return (FALSE); + } + IXDR_PUT_LONG(buf, cmsg->rm_call.cb_rpcvers); + if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { + return (FALSE); + } + IXDR_PUT_LONG(buf, cmsg->rm_call.cb_prog); + IXDR_PUT_LONG(buf, cmsg->rm_call.cb_vers); + IXDR_PUT_LONG(buf, cmsg->rm_call.cb_proc); + oa = &cmsg->rm_call.cb_cred; + IXDR_PUT_ENUM(buf, oa->oa_flavor); + IXDR_PUT_LONG(buf, oa->oa_length); + if (oa->oa_length) { + bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); + buf += RNDUP(oa->oa_length) / sizeof (long); + } + oa = &cmsg->rm_call.cb_verf; + IXDR_PUT_ENUM(buf, oa->oa_flavor); + IXDR_PUT_LONG(buf, oa->oa_length); + if (oa->oa_length) { + bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); + /* no real need.... + buf += RNDUP(oa->oa_length) / sizeof (long); + */ + } + return (TRUE); + } + } + if (xdrs->x_op == XDR_DECODE) { + buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT); + if (buf != NULL) { + cmsg->rm_xid = IXDR_GET_LONG(buf); + cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type); + if (cmsg->rm_direction != CALL) { + return (FALSE); + } + cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG(buf); + if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { + return (FALSE); + } + cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf); + cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf); + cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf); + oa = &cmsg->rm_call.cb_cred; + oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); + oa->oa_length = IXDR_GET_LONG(buf); + if (oa->oa_length) { + if (oa->oa_length > MAX_AUTH_BYTES) { + return (FALSE); + } + if (oa->oa_base == NULL) { + oa->oa_base = (caddr_t) + mem_alloc(oa->oa_length); + } + buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); + if (buf == NULL) { + if (xdr_opaque(xdrs, oa->oa_base, + oa->oa_length) == FALSE) { + return (FALSE); + } + } else { + bcopy((caddr_t)buf, oa->oa_base, + oa->oa_length); + /* no real need.... + buf += RNDUP(oa->oa_length) / + sizeof (long); + */ + } + } + oa = &cmsg->rm_call.cb_verf; + buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); + if (buf == NULL) { + if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE || + xdr_u_int(xdrs, &oa->oa_length) == FALSE) { + return (FALSE); + } + } else { + oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); + oa->oa_length = IXDR_GET_LONG(buf); + } + if (oa->oa_length) { + if (oa->oa_length > MAX_AUTH_BYTES) { + return (FALSE); + } + if (oa->oa_base == NULL) { + oa->oa_base = (caddr_t) + mem_alloc(oa->oa_length); + } + buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); + if (buf == NULL) { + if (xdr_opaque(xdrs, oa->oa_base, + oa->oa_length) == FALSE) { + return (FALSE); + } + } else { + bcopy((caddr_t)buf, oa->oa_base, + oa->oa_length); + /* no real need... + buf += RNDUP(oa->oa_length) / + sizeof (long); + */ + } + } + return (TRUE); + } + } + if ( + xdr_u_long(xdrs, &(cmsg->rm_xid)) && + xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && + (cmsg->rm_direction == CALL) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) && + (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers)) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_proc)) && + xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) ) + return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf))); + return (FALSE); +} + diff --git a/c/src/librpc/src/rpc_prot.c b/c/src/librpc/src/rpc_prot.c new file mode 100644 index 0000000000..8d2fde7116 --- /dev/null +++ b/c/src/librpc/src/rpc_prot.c @@ -0,0 +1,271 @@ +/* @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + */ + +/* + * rpc_prot.c + */ + +#include + +/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ + +struct opaque_auth _null_auth; + +/* + * XDR an opaque authentication struct + * (see auth.h) + */ +bool_t +xdr_opaque_auth(xdrs, ap) + register XDR *xdrs; + register struct opaque_auth *ap; +{ + + if (xdr_enum(xdrs, &(ap->oa_flavor))) + return (xdr_bytes(xdrs, &ap->oa_base, + &ap->oa_length, MAX_AUTH_BYTES)); + return (FALSE); +} + +/* + * XDR a DES block + */ +bool_t +xdr_des_block(xdrs, blkp) + register XDR *xdrs; + register des_block *blkp; +{ + return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block))); +} + +/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ + +/* + * XDR the MSG_ACCEPTED part of a reply message union + */ +bool_t +xdr_accepted_reply(xdrs, ar) + register XDR *xdrs; + register struct accepted_reply *ar; +{ + + /* personalized union, rather than calling xdr_union */ + if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) + return (FALSE); + if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat))) + return (FALSE); + switch (ar->ar_stat) { + + case SUCCESS: + return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); + + case PROG_MISMATCH: + if (! xdr_u_long(xdrs, &(ar->ar_vers.low))) + return (FALSE); + return (xdr_u_long(xdrs, &(ar->ar_vers.high))); + default: + break; + } + return (TRUE); /* TRUE => open ended set of problems */ +} + +/* + * XDR the MSG_DENIED part of a reply message union + */ +bool_t +xdr_rejected_reply(xdrs, rr) + register XDR *xdrs; + register struct rejected_reply *rr; +{ + + /* personalized union, rather than calling xdr_union */ + if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat))) + return (FALSE); + switch (rr->rj_stat) { + + case RPC_MISMATCH: + if (! xdr_u_long(xdrs, &(rr->rj_vers.low))) + return (FALSE); + return (xdr_u_long(xdrs, &(rr->rj_vers.high))); + + case AUTH_ERROR: + return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why))); + } + return (FALSE); +} + +static struct xdr_discrim reply_dscrm[3] = { + { (int)MSG_ACCEPTED, xdr_accepted_reply }, + { (int)MSG_DENIED, xdr_rejected_reply }, + { __dontcare__, NULL_xdrproc_t } }; + +/* + * XDR a reply message + */ +bool_t +xdr_replymsg(xdrs, rmsg) + register XDR *xdrs; + register struct rpc_msg *rmsg; +{ + if ( + xdr_u_long(xdrs, &(rmsg->rm_xid)) && + xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) && + (rmsg->rm_direction == REPLY) ) + return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat), + (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t)); + return (FALSE); +} + + +/* + * Serializes the "static part" of a call message header. + * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. + * The rm_xid is not really static, but the user can easily munge on the fly. + */ +bool_t +xdr_callhdr(xdrs, cmsg) + register XDR *xdrs; + register struct rpc_msg *cmsg; +{ + + cmsg->rm_direction = CALL; + cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; + if ( + (xdrs->x_op == XDR_ENCODE) && + xdr_u_long(xdrs, &(cmsg->rm_xid)) && + xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) && + xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) ) + return (xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers))); + return (FALSE); +} + +/* ************************** Client utility routine ************* */ + +static void +accepted(acpt_stat, error) + register enum accept_stat acpt_stat; + register struct rpc_err *error; +{ + + switch (acpt_stat) { + + case PROG_UNAVAIL: + error->re_status = RPC_PROGUNAVAIL; + return; + + case PROG_MISMATCH: + error->re_status = RPC_PROGVERSMISMATCH; + return; + + case PROC_UNAVAIL: + error->re_status = RPC_PROCUNAVAIL; + return; + + case GARBAGE_ARGS: + error->re_status = RPC_CANTDECODEARGS; + return; + + case SYSTEM_ERR: + error->re_status = RPC_SYSTEMERROR; + return; + + case SUCCESS: + error->re_status = RPC_SUCCESS; + return; + } + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long)MSG_ACCEPTED; + error->re_lb.s2 = (long)acpt_stat; +} + +static void +rejected(rjct_stat, error) + register enum reject_stat rjct_stat; + register struct rpc_err *error; +{ + + switch (rjct_stat) { + + case RPC_VERSMISMATCH: + error->re_status = RPC_VERSMISMATCH; + return; + + case AUTH_ERROR: + error->re_status = RPC_AUTHERROR; + return; + + default: + break; + } + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long)MSG_DENIED; + error->re_lb.s2 = (long)rjct_stat; +} + +/* + * given a reply message, fills in the error + */ +void +_seterr_reply(msg, error) + register struct rpc_msg *msg; + register struct rpc_err *error; +{ + + /* optimized for normal, SUCCESSful case */ + switch (msg->rm_reply.rp_stat) { + + case MSG_ACCEPTED: + if (msg->acpted_rply.ar_stat == SUCCESS) { + error->re_status = RPC_SUCCESS; + return; + }; + accepted(msg->acpted_rply.ar_stat, error); + break; + + case MSG_DENIED: + rejected(msg->rjcted_rply.rj_stat, error); + break; + + default: + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long)(msg->rm_reply.rp_stat); + break; + } + switch (error->re_status) { + + case RPC_VERSMISMATCH: + error->re_vers.low = msg->rjcted_rply.rj_vers.low; + error->re_vers.high = msg->rjcted_rply.rj_vers.high; + break; + + case RPC_AUTHERROR: + error->re_why = msg->rjcted_rply.rj_why; + break; + + case RPC_PROGVERSMISMATCH: + error->re_vers.low = msg->acpted_rply.ar_vers.low; + error->re_vers.high = msg->acpted_rply.ar_vers.high; + break; + + default: + break; + } +} diff --git a/c/src/librpc/src/svc.c b/c/src/librpc/src/svc.c new file mode 100644 index 0000000000..c4ccb46aa5 --- /dev/null +++ b/c/src/librpc/src/svc.c @@ -0,0 +1,259 @@ +/* @(#)svc.c 2.4 88/08/11 4.0 RPCSRC; from 1.44 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)svc.c 1.41 87/10/13 Copyr 1984 Sun Micro"; +#endif + +/* + * svc.c, Server-side remote procedure call interface. + * + * There are two sets of procedures here. The xprt routines are + * for handling transport handles. The svc routines handle the + * list of service routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include + +#define RQCRED_SIZE 400 /* this size is excessive */ + +/* ******************* REPLY GENERATION ROUTINES ************ */ + +/* + * Send a reply to an rpc request + */ +bool_t +svc_sendreply(xprt, xdr_results, xdr_location) + register SVCXPRT *xprt; + xdrproc_t xdr_results; + caddr_t xdr_location; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = SUCCESS; + rply.acpted_rply.ar_results.where = xdr_location; + rply.acpted_rply.ar_results.proc = xdr_results; + return (SVC_REPLY(xprt, &rply)); +} + +/* + * No procedure error reply + */ +void +svcerr_noproc(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROC_UNAVAIL; + SVC_REPLY(xprt, &rply); +} + +/* + * Can't decode args error reply + */ +void +svcerr_decode(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = GARBAGE_ARGS; + SVC_REPLY(xprt, &rply); +} + +/* + * Some system error + */ +void +svcerr_systemerr(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = SYSTEM_ERR; + SVC_REPLY(xprt, &rply); +} + +/* + * Authentication error reply + */ +void +svcerr_auth(xprt, why) + SVCXPRT *xprt; + enum auth_stat why; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_DENIED; + rply.rjcted_rply.rj_stat = AUTH_ERROR; + rply.rjcted_rply.rj_why = why; + SVC_REPLY(xprt, &rply); +} + +/* + * Auth too weak error reply + */ +void +svcerr_weakauth(xprt) + SVCXPRT *xprt; +{ + + svcerr_auth(xprt, AUTH_TOOWEAK); +} + +/* + * Program unavailable error reply + */ +void +svcerr_noprog(xprt) + register SVCXPRT *xprt; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROG_UNAVAIL; + SVC_REPLY(xprt, &rply); +} + +/* + * Program version mismatch error reply + */ +void +svcerr_progvers(xprt, low_vers, high_vers) + register SVCXPRT *xprt; + u_long low_vers; + u_long high_vers; +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROG_MISMATCH; + rply.acpted_rply.ar_vers.low = low_vers; + rply.acpted_rply.ar_vers.high = high_vers; + SVC_REPLY(xprt, &rply); +} + + void +svc_processrequest(xprt, prog, vers, dispatch) + SVCXPRT *xprt; + u_long prog; + u_long vers; + void (*dispatch)(); +{ + struct rpc_msg msg; + int prog_found = FALSE; + u_long low_vers = 0; /* dummy init */ + u_long high_vers = 0; /* dummy init */ + struct svc_req r; + /*static char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];*/ + char *cred_area; + + cred_area = (char *)malloc(2*MAX_AUTH_BYTES + RQCRED_SIZE); + msg.rm_call.cb_cred.oa_base = cred_area; + msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); + r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); + + if (SVC_RECV(xprt, &msg)) { + + /* now find the exported program and call it */ + /* register struct svc_callout *s; */ + enum auth_stat why; + + r.rq_xprt = xprt; + r.rq_prog = msg.rm_call.cb_prog; + r.rq_vers = msg.rm_call.cb_vers; + r.rq_proc = msg.rm_call.cb_proc; + r.rq_cred = msg.rm_call.cb_cred; + + /* first authenticate the message */ + if ((why= _authenticate(&r, &msg)) != AUTH_OK) { + svcerr_auth(xprt, why); + free(cred_area); + return; + } + + /* now match message with a registered service*/ + prog_found = FALSE; + low_vers = 0 - 1; + high_vers = 0; + if (prog == r.rq_prog) { + if (vers == r.rq_vers) { + (*dispatch)(&r, xprt); + free(cred_area); + return; + } /* found correct version */ + prog_found = TRUE; + if (vers < low_vers) + low_vers = vers; + if (vers > high_vers) + high_vers = vers; + } /* found correct program */ + } + /* + * if we got here, the program or version + * is not served ... + */ + if (prog_found) { + svcerr_progvers(xprt, + low_vers, high_vers); + } else { + svcerr_noprog(xprt); + } + + free(cred_area); + +} + +/* stubs for solaris rpcgen */ +/*int _rpcsvccount; +int _rpcsvcstate; +int _SERVED; +*/ diff --git a/c/src/librpc/src/svc_auth.c b/c/src/librpc/src/svc_auth.c new file mode 100644 index 0000000000..f5634d8c37 --- /dev/null +++ b/c/src/librpc/src/svc_auth.c @@ -0,0 +1,122 @@ + +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)svc_auth.c 2.1 88/08/07 4.0 RPCSRC; from 1.19 87/08/11 Copyr 1984 Sun Micro"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc_auth_nodes.c, Server-side rpc authenticator interface, + * *WITHOUT* DES authentication. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include + +/* + * svcauthsw is the bdevsw of server side authentication. + * + * Server side authenticators are called from authenticate by + * using the client auth struct flavor field to index into svcauthsw. + * The server auth flavors must implement a routine that looks + * like: + * + * enum auth_stat + * flavorx_auth(rqst, msg) + * register struct svc_req *rqst; + * register struct rpc_msg *msg; + * + */ + +enum auth_stat _svcauth_null(); /* no authentication */ +enum auth_stat _svcauth_unix(); /* unix style (uid, gids) */ +enum auth_stat _svcauth_short(); /* short hand unix style */ + +static struct { + enum auth_stat (*authenticator)(); +} svcauthsw[] = { + _svcauth_null, /* AUTH_NULL */ +#ifdef MR + _svcauth_unix, /* AUTH_UNIX */ + _svcauth_short /* AUTH_SHORT */ +#endif +}; + +#ifdef MR +#define AUTH_MAX 2 /* HIGHEST AUTH NUMBER */ +#else +#define AUTH_MAX 0 /* HIGHEST AUTH NUMBER */ +#endif + + +/* + * The call rpc message, msg has been obtained from the wire. The msg contains + * the raw form of credentials and verifiers. authenticate returns AUTH_OK + * if the msg is successfully authenticated. If AUTH_OK then the routine also + * does the following things: + * set rqst->rq_xprt->verf to the appropriate response verifier; + * sets rqst->rq_client_cred to the "cooked" form of the credentials. + * + * NB: rqst->rq_cxprt->verf must be pre-alloctaed; + * its length is set appropriately. + * + * The caller still owns and is responsible for msg->u.cmb.cred and + * msg->u.cmb.verf. The authentication system retains ownership of + * rqst->rq_client_cred, the cooked credentials. + * + * There is an assumption that any flavour less than AUTH_NULL is + * invalid. + */ +enum auth_stat +_authenticate(rqst, msg) + register struct svc_req *rqst; + struct rpc_msg *msg; +{ + register int cred_flavor; + + rqst->rq_cred = msg->rm_call.cb_cred; + rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; + rqst->rq_xprt->xp_verf.oa_length = 0; + cred_flavor = rqst->rq_cred.oa_flavor; + if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) { + return ((*(svcauthsw[cred_flavor].authenticator))(rqst, msg)); + } + + return (AUTH_REJECTEDCRED); +} + +enum auth_stat +_svcauth_null(/*rqst, msg*/) + /*struct svc_req *rqst; + struct rpc_msg *msg;*/ +{ + + return (AUTH_OK); +} diff --git a/c/src/librpc/src/svc_udp.c b/c/src/librpc/src/svc_udp.c new file mode 100644 index 0000000000..70e874335b --- /dev/null +++ b/c/src/librpc/src/svc_udp.c @@ -0,0 +1,476 @@ +/* @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_udp.c, + * Server side for UDP/IP based RPC. (Does some caching in the hopes of + * achieving execute-at-most-once semantics.) + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +/* + * Adapted for rgdb specifi purposes. + * Modifications are under #ifndef NO_RGDB. + */ + +#include /* printf */ +#include /* free */ +#include /* bzero, bcmp */ +#include +#include + +#define rpc_buffer(xprt) ((xprt)->xp_p1) +#define MAX(a, b) ((a > b) ? a : b) + +static bool_t svcudp_recv(); +static bool_t svcudp_reply(); +static enum xprt_stat svcudp_stat(); +static bool_t svcudp_getargs(); +static bool_t svcudp_freeargs(); +static void svcudp_destroy(); +static int cache_get(); +static void cache_set(); + +static struct xp_ops svcudp_op = { + svcudp_recv, + svcudp_stat, + svcudp_getargs, + svcudp_reply, + svcudp_freeargs, + svcudp_destroy +}; + +extern int errno; + +/* + * kept in xprt->xp_p2 + */ +struct svcudp_data { + u_int su_iosz; /* byte size of send.recv buffer */ + u_long su_xid; /* transaction id */ + XDR su_xdrs; /* XDR handle */ + char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */ + char * su_cache; /* cached data, NULL if no cache */ +}; +#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2)) + +/* + * Usage: + * xprt = svcudp_create(sock); + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svcudp_create + * binds it to an arbitrary port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * Once *xprt is initialized, it is registered as a transporter; + * see (svc.h, xprt_register). + * The routines returns NULL if a problem occurred. + */ +SVCXPRT * +svcudp_bufcreate(sock, sendsz, recvsz) + register int sock; + u_int sendsz, recvsz; +{ + register SVCXPRT *xprt; + register struct svcudp_data *su; + struct sockaddr_in addr; + int len = sizeof(struct sockaddr_in); + + if (sock == RPC_ANYSOCK) { + (void)printf + ("svcudp_create: socket should be created and bound\n"); + return ((SVCXPRT *) NULL); + } + + if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) { + (void)printf("svcudp_create - cannot getsockname"); + return ((SVCXPRT *)NULL); + } + + xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); + + if (xprt == NULL) { + (void)printf("svcudp_create: out of memory\n"); + return (NULL); + } + su = (struct svcudp_data *)mem_alloc(sizeof(*su)); + if (su == NULL) { + (void)printf("svcudp_create: out of memory\n"); + return (NULL); + } + su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4; + if ((rpc_buffer(xprt) = (caddr_t) mem_alloc(su->su_iosz)) == NULL) { + (void)printf("svcudp_create: out of memory\n"); + return (NULL); + } + xdrmem_create( + &(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE); + su->su_cache = NULL; + xprt->xp_p2 = (caddr_t)su; + xprt->xp_verf.oa_base = su->su_verfbody; + xprt->xp_ops = &svcudp_op; + xprt->xp_port = ntohs(addr.sin_port); + xprt->xp_sock = sock; + return (xprt); +} + +SVCXPRT * +svcudp_create(sock) + int sock; +{ + +/* return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE));*/ + return(svcudp_bufcreate(sock, 1500, 1500)); +} + +static enum xprt_stat +svcudp_stat(xprt) + SVCXPRT *xprt; +{ + + return (XPRT_IDLE); +} + +static bool_t +svcudp_recv(xprt, msg) + register SVCXPRT *xprt; + struct rpc_msg *msg; +{ + register struct svcudp_data *su = su_data(xprt); + register XDR *xdrs = &(su->su_xdrs); + register int rlen; + char *reply; + u_long replylen; + + again: + xprt->xp_addrlen = sizeof(struct sockaddr_in); + rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz, + 0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen)); + if (rlen == -1 /* && errno == EINTR */) + goto again; + if (rlen < 4*sizeof(u_long)) + return (FALSE); + xdrs->x_op = XDR_DECODE; + XDR_SETPOS(xdrs, 0); + if (! xdr_callmsg(xdrs, msg)) + return (FALSE); + su->su_xid = msg->rm_xid; + if (su->su_cache != NULL) { + if (cache_get(xprt, msg, &reply, &replylen)) { + (void) sendto(xprt->xp_sock, reply, (int) replylen, 0, + (struct sockaddr *) &xprt->xp_raddr, xprt->xp_addrlen); + return (FALSE); + } + } + return (TRUE); +} + +static bool_t +svcudp_reply(xprt, msg) + register SVCXPRT *xprt; + struct rpc_msg *msg; +{ + register struct svcudp_data *su = su_data(xprt); + register XDR *xdrs = &(su->su_xdrs); + register int slen; + register bool_t stat = FALSE; + + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS(xdrs, 0); + msg->rm_xid = su->su_xid; + if (xdr_replymsg(xdrs, msg)) { + slen = (int)XDR_GETPOS(xdrs); + if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0, + (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen) + == slen) { + stat = TRUE; + if (su->su_cache && slen >= 0) { + cache_set(xprt, (u_long) slen); + } + } + } + return (stat); +} + +static bool_t +svcudp_getargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + + return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr)); +} + +static bool_t +svcudp_freeargs(xprt, xdr_args, args_ptr) + SVCXPRT *xprt; + xdrproc_t xdr_args; + caddr_t args_ptr; +{ + register XDR *xdrs = &(su_data(xprt)->su_xdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_args)(xdrs, args_ptr)); +} + +static void +svcudp_destroy(xprt) + register SVCXPRT *xprt; +{ + register struct svcudp_data *su = su_data(xprt); +/* + xprt_unregister(xprt); + (void)close(xprt->xp_sock); +*/ + XDR_DESTROY(&(su->su_xdrs)); + mem_free(rpc_buffer(xprt), su->su_iosz); + mem_free((caddr_t)su, sizeof(struct svcudp_data)); + mem_free((caddr_t)xprt, sizeof(SVCXPRT)); +} + + +/***********this could be a separate file*********************/ + +/* + * Fifo cache for udp server + * Copies pointers to reply buffers into fifo cache + * Buffers are sent again if retransmissions are detected. + */ + +#define SPARSENESS 4 /* 75% sparse */ + +#define CACHE_PERROR(msg) \ + (void) printf("%s\n", msg) + +#define ALLOC(type, size) \ + (type *) mem_alloc((unsigned) (sizeof(type) * (size))) + +#define BZERO(addr, type, size) \ + bzero((char *) addr, sizeof(type) * (int) (size)) + +/* + * An entry in the cache + */ +typedef struct cache_node *cache_ptr; +struct cache_node { + /* + * Index into cache is xid, proc, vers, prog and address + */ + u_long cache_xid; + u_long cache_proc; + u_long cache_vers; + u_long cache_prog; + struct sockaddr_in cache_addr; + /* + * The cached reply and length + */ + char * cache_reply; + u_long cache_replylen; + /* + * Next node on the list, if there is a collision + */ + cache_ptr cache_next; +}; + + + +/* + * The entire cache + */ +struct udp_cache { + u_long uc_size; /* size of cache */ + cache_ptr *uc_entries; /* hash table of entries in cache */ + cache_ptr *uc_fifo; /* fifo list of entries in cache */ + u_long uc_nextvictim; /* points to next victim in fifo list */ + u_long uc_prog; /* saved program number */ + u_long uc_vers; /* saved version number */ + u_long uc_proc; /* saved procedure number */ + struct sockaddr_in uc_addr; /* saved caller's address */ +}; + + +/* + * the hashing function + */ +#define CACHE_LOC(transp, xid) \ + (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size)) + + +/* + * Enable use of the cache. + * Note: there is no disable. + */ + int +svcudp_enablecache(transp, size) + SVCXPRT *transp; + u_long size; +{ + struct svcudp_data *su = su_data(transp); + struct udp_cache *uc; + + if (su->su_cache != NULL) { + CACHE_PERROR("enablecache: cache already enabled"); + return(0); + } + uc = ALLOC(struct udp_cache, 1); + if (uc == NULL) { + CACHE_PERROR("enablecache: could not allocate cache"); + return(0); + } + uc->uc_size = size; + uc->uc_nextvictim = 0; + uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS); + if (uc->uc_entries == NULL) { + CACHE_PERROR("enablecache: could not allocate cache data"); + return(0); + } + BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS); + uc->uc_fifo = ALLOC(cache_ptr, size); + if (uc->uc_fifo == NULL) { + CACHE_PERROR("enablecache: could not allocate cache fifo"); + return(0); + } + BZERO(uc->uc_fifo, cache_ptr, size); + su->su_cache = (char *) uc; + return(1); +} + + +/* + * Set an entry in the cache + */ +static void +cache_set(xprt, replylen) + SVCXPRT *xprt; + u_long replylen; +{ + register cache_ptr victim; + register cache_ptr *vicp; + register struct svcudp_data *su = su_data(xprt); + struct udp_cache *uc = (struct udp_cache *) su->su_cache; + u_int loc; + char *newbuf; + + /* + * Find space for the new entry, either by + * reusing an old entry, or by mallocing a new one + */ + victim = uc->uc_fifo[uc->uc_nextvictim]; + if (victim != NULL) { + loc = CACHE_LOC(xprt, victim->cache_xid); + for (vicp = &uc->uc_entries[loc]; + *vicp != NULL && *vicp != victim; + vicp = &(*vicp)->cache_next) + ; + if (*vicp == NULL) { + CACHE_PERROR("cache_set: victim not found"); + return; + } + *vicp = victim->cache_next; /* remote from cache */ + newbuf = victim->cache_reply; + } else { + victim = ALLOC(struct cache_node, 1); + if (victim == NULL) { + CACHE_PERROR("cache_set: victim alloc failed"); + return; + } + newbuf = (char*) mem_alloc(su->su_iosz); + if (newbuf == NULL) { + CACHE_PERROR("cache_set: could not allocate new rpc_buffer"); + return; + } + } + + /* + * Store it away + */ + victim->cache_replylen = replylen; + victim->cache_reply = rpc_buffer(xprt); + rpc_buffer(xprt) = newbuf; + xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_ENCODE); + victim->cache_xid = su->su_xid; + victim->cache_proc = uc->uc_proc; + victim->cache_vers = uc->uc_vers; + victim->cache_prog = uc->uc_prog; + victim->cache_addr = uc->uc_addr; + loc = CACHE_LOC(xprt, victim->cache_xid); + victim->cache_next = uc->uc_entries[loc]; + uc->uc_entries[loc] = victim; + uc->uc_fifo[uc->uc_nextvictim++] = victim; + uc->uc_nextvictim %= uc->uc_size; +} + +/* + * Try to get an entry from the cache + * return 1 if found, 0 if not found + */ +static int +cache_get(xprt, msg, replyp, replylenp) + SVCXPRT *xprt; + struct rpc_msg *msg; + char **replyp; + u_long *replylenp; +{ + u_int loc; + register cache_ptr ent; + register struct svcudp_data *su = su_data(xprt); + register struct udp_cache *uc = (struct udp_cache *) su->su_cache; + +# define EQADDR(a1, a2) (bcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0) + + loc = CACHE_LOC(xprt, su->su_xid); + for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) { + if (ent->cache_xid == su->su_xid && + ent->cache_proc == uc->uc_proc && + ent->cache_vers == uc->uc_vers && + ent->cache_prog == uc->uc_prog && + EQADDR(ent->cache_addr, uc->uc_addr)) { + *replyp = ent->cache_reply; + *replylenp = ent->cache_replylen; + return(1); + } + } + /* + * Failed to find entry + * Remember a few things so we can do a set later + */ + uc->uc_proc = msg->rm_call.cb_proc; + uc->uc_vers = msg->rm_call.cb_vers; + uc->uc_prog = msg->rm_call.cb_prog; + uc->uc_addr = xprt->xp_raddr; + return(0); +} + diff --git a/c/src/librpc/src/xdr.c b/c/src/librpc/src/xdr.c new file mode 100644 index 0000000000..cc8caf7785 --- /dev/null +++ b/c/src/librpc/src/xdr.c @@ -0,0 +1,578 @@ +/* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr.c 1.35 87/08/12"; +#endif + +/* + * xdr.c, Generic XDR routines implementation. + * + * Copyright (C) 1986, Sun Microsystems, Inc. + * + * These are the "generic" xdr routines used to serialize and de-serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#include +#include +#include +#include + +/* + * constants specific to the xdr "protocol" + */ +#define XDR_FALSE ((long) 0) +#define XDR_TRUE ((long) 1) +#define LASTUNSIGNED ((u_int) 0-1) + +/* + * for unit alignment + */ +static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; + +/* + * Free a data structure using XDR + * Not a filter, but a convenient utility nonetheless + */ +void +xdr_free(proc, objp) + xdrproc_t proc; + char *objp; +{ + XDR x; + + x.x_op = XDR_FREE; + (*proc)(&x, objp); +} + +/* + * XDR nothing + */ +bool_t +xdr_void(/* xdrs, addr */) + /* XDR *xdrs; */ + /* caddr_t addr; */ +{ + + return (TRUE); +} + +/* + * XDR integers + */ +bool_t +xdr_int(xdrs, ip) + XDR *xdrs; + int *ip; +{ + +#ifdef lint + (void) (xdr_short(xdrs, (short *)ip)); + return (xdr_long(xdrs, (long *)ip)); +#else + if (sizeof (int) == sizeof (long)) { + return (xdr_long(xdrs, (long *)ip)); + } else { + return (xdr_short(xdrs, (short *)ip)); + } +#endif +} + +/* + * XDR unsigned integers + */ +bool_t +xdr_u_int(xdrs, up) + XDR *xdrs; + u_int *up; +{ + +#ifdef lint + (void) (xdr_short(xdrs, (short *)up)); + return (xdr_u_long(xdrs, (u_long *)up)); +#else + if (sizeof (u_int) == sizeof (u_long)) { + return (xdr_u_long(xdrs, (u_long *)up)); + } else { + return (xdr_short(xdrs, (short *)up)); + } +#endif +} + +/* + * XDR long integers + * same as xdr_u_long - open coded to save a proc call! + */ +bool_t +xdr_long(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + + if (xdrs->x_op == XDR_ENCODE) + return (XDR_PUTLONG(xdrs, lp)); + + if (xdrs->x_op == XDR_DECODE) + return (XDR_GETLONG(xdrs, lp)); + + if (xdrs->x_op == XDR_FREE) + return (TRUE); + + return (FALSE); +} + +/* + * XDR unsigned long integers + * same as xdr_long - open coded to save a proc call! + */ +bool_t +xdr_u_long(xdrs, ulp) + register XDR *xdrs; + u_long *ulp; +{ + + if (xdrs->x_op == XDR_DECODE) + return (XDR_GETLONG(xdrs, (long *)ulp)); + if (xdrs->x_op == XDR_ENCODE) + return (XDR_PUTLONG(xdrs, (long *)ulp)); + if (xdrs->x_op == XDR_FREE) + return (TRUE); + return (FALSE); +} + +/* + * XDR short integers + */ +bool_t +xdr_short(xdrs, sp) + register XDR *xdrs; + short *sp; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *sp; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *sp = (short) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR unsigned short integers + */ +bool_t +xdr_u_short(xdrs, usp) + register XDR *xdrs; + u_short *usp; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *usp; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *usp = (u_short) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + + +/* + * XDR a char + */ +bool_t +xdr_char(xdrs, cp) + XDR *xdrs; + char *cp; +{ + int i; + + i = (*cp); + if (!xdr_int(xdrs, &i)) { + return (FALSE); + } + *cp = i; + return (TRUE); +} + +/* + * XDR an unsigned char + */ +bool_t +xdr_u_char(xdrs, cp) + XDR *xdrs; + char *cp; +{ + u_int u; + + u = (*cp); + if (!xdr_u_int(xdrs, &u)) { + return (FALSE); + } + *cp = u; + return (TRUE); +} + +/* + * XDR booleans + */ +bool_t +xdr_bool(xdrs, bp) + register XDR *xdrs; + bool_t *bp; +{ + long lb; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + lb = *bp ? XDR_TRUE : XDR_FALSE; + return (XDR_PUTLONG(xdrs, &lb)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &lb)) { + return (FALSE); + } + *bp = (lb == XDR_FALSE) ? FALSE : TRUE; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR enumerations + */ +bool_t +xdr_enum(xdrs, ep) + XDR *xdrs; + enum_t *ep; +{ +#ifndef lint + enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ + + /* + * enums are treated as ints + */ + if (sizeof (enum sizecheck) == sizeof (long)) { + return (xdr_long(xdrs, (long *)ep)); + } else if (sizeof (enum sizecheck) == sizeof (short)) { + return (xdr_short(xdrs, (short *)ep)); + } else { + return (FALSE); + } +#else + (void) (xdr_short(xdrs, (short *)ep)); + return (xdr_long(xdrs, (long *)ep)); +#endif +} + +/* + * XDR opaque data + * Allows the specification of a fixed size sequence of opaque bytes. + * cp points to the opaque object and cnt gives the byte length. + */ +bool_t +xdr_opaque(xdrs, cp, cnt) + register XDR *xdrs; + caddr_t cp; + register u_int cnt; +{ + register u_int rndup; + static int crud[BYTES_PER_XDR_UNIT]; + + /* + * if no data we are done + */ + if (cnt == 0) + return (TRUE); + + /* + * round byte count to full xdr units + */ + rndup = cnt % BYTES_PER_XDR_UNIT; + if (rndup > 0) + rndup = BYTES_PER_XDR_UNIT - rndup; + + if (xdrs->x_op == XDR_DECODE) { + if (!XDR_GETBYTES(xdrs, cp, cnt)) { + return (FALSE); + } + if (rndup == 0) + return (TRUE); + return (XDR_GETBYTES(xdrs, crud, rndup)); + } + + if (xdrs->x_op == XDR_ENCODE) { + if (!XDR_PUTBYTES(xdrs, cp, cnt)) { + return (FALSE); + } + if (rndup == 0) + return (TRUE); + return (XDR_PUTBYTES(xdrs, xdr_zero, rndup)); + } + + if (xdrs->x_op == XDR_FREE) { + return (TRUE); + } + + return (FALSE); +} + +/* + * XDR counted bytes + * *cpp is a pointer to the bytes, *sizep is the count. + * If *cpp is NULL maxsize bytes are allocated + */ +bool_t +xdr_bytes(xdrs, cpp, sizep, maxsize) + register XDR *xdrs; + char **cpp; + register u_int *sizep; + u_int maxsize; +{ + register char *sp = *cpp; /* sp is the actual string pointer */ + register u_int nodesize; + + /* + * first deal with the length since xdr bytes are counted + */ + if (! xdr_u_int(xdrs, sizep)) { + return (FALSE); + } + nodesize = *sizep; + if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) { + return (FALSE); + } + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) { + + case XDR_DECODE: + if (nodesize == 0) { + return (TRUE); + } + if (sp == NULL) { + *cpp = sp = (char *)mem_alloc(nodesize); + } + if (sp == NULL) { + (void) printf("xdr_bytes: out of memory\n"); + return (FALSE); + } + /* fall into ... */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, nodesize)); + + case XDR_FREE: + if (sp != NULL) { + mem_free(sp, nodesize); + *cpp = NULL; + } + return (TRUE); + } + return (FALSE); +} + +/* + * Implemented here due to commonality of the object. + */ +bool_t +xdr_netobj(xdrs, np) + XDR *xdrs; + struct netobj *np; +{ + + return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); +} + +/* + * XDR a descriminated union + * Support routine for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * an entry with a null procedure pointer. The routine gets + * the discriminant value and then searches the array of xdrdiscrims + * looking for that value. It calls the procedure given in the xdrdiscrim + * to handle the discriminant. If there is no specific routine a default + * routine may be called. + * If there is no specific or default routine an error is returned. + */ +bool_t +xdr_union(xdrs, dscmp, unp, choices, dfault) + register XDR *xdrs; + enum_t *dscmp; /* enum to decide which arm to work on */ + char *unp; /* the union itself */ + struct xdr_discrim *choices; /* [value, xdr proc] for each arm */ + xdrproc_t dfault; /* default xdr routine */ +{ + register enum_t dscm; + + /* + * we deal with the discriminator; it's an enum + */ + if (! xdr_enum(xdrs, dscmp)) { + return (FALSE); + } + dscm = *dscmp; + + /* + * search choices for a value that matches the discriminator. + * if we find one, execute the xdr routine for that value. + */ + for (; choices->proc != NULL_xdrproc_t; choices++) { + if (choices->value == dscm) + return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED)); + } + + /* + * no match - execute the default xdr routine if there is one + */ + return ((dfault == NULL_xdrproc_t) ? FALSE : + (*dfault)(xdrs, unp, LASTUNSIGNED)); +} + + +/* + * Non-portable xdr primitives. + * Care should be taken when moving these routines to new architectures. + */ + + +/* + * XDR null terminated ASCII strings + * xdr_string deals with "C strings" - arrays of bytes that are + * terminated by a NULL character. The parameter cpp references a + * pointer to storage; If the pointer is null, then the necessary + * storage is allocated. The last parameter is the max allowed length + * of the string as specified by a protocol. + */ +bool_t +xdr_string(xdrs, cpp, maxsize) + register XDR *xdrs; + char **cpp; + u_int maxsize; +{ + register char *sp = *cpp; /* sp is the actual string pointer */ + u_int size; + u_int nodesize; + + /* + * first deal with the length since xdr strings are counted-strings + */ + switch (xdrs->x_op) { + case XDR_FREE: + if (sp == NULL) { + return(TRUE); /* already free */ + } + /* fall through... */ + case XDR_ENCODE: + size = strlen(sp); + break; + default: + break; + } + if (! xdr_u_int(xdrs, &size)) { + return (FALSE); + } + if (size > maxsize) { + return (FALSE); + } + nodesize = size + 1; + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) { + + case XDR_DECODE: + if (nodesize == 0) { + return (TRUE); + } + if (sp == NULL) + *cpp = sp = (char *)mem_alloc(nodesize); + if (sp == NULL) { + (void) printf("xdr_string: out of memory\n"); + return (FALSE); + } + sp[size] = 0; + /* fall into ... */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, size)); + + case XDR_FREE: + mem_free(sp, nodesize); + *cpp = NULL; + return (TRUE); + } + return (FALSE); +} + +/* + * Wrapper for xdr_string that can be called directly from + * routines like clnt_call + */ +bool_t +xdr_wrapstring(xdrs, cpp) + XDR *xdrs; + char **cpp; +{ + if (xdr_string(xdrs, cpp, LASTUNSIGNED)) { + return (TRUE); + } + return (FALSE); +} diff --git a/c/src/librpc/src/xdr_array.c b/c/src/librpc/src/xdr_array.c new file mode 100644 index 0000000000..b3cd21f2f4 --- /dev/null +++ b/c/src/librpc/src/xdr_array.c @@ -0,0 +1,157 @@ +/* @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_array.c, Generic XDR routines impelmentation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * arrays. See xdr.h for more info on the interface to xdr. + */ + + +#include /* printf */ +#include /* bcmp */ +#include /* free */ +#include +#include + +#define LASTUNSIGNED ((u_int)0-1) + + +/* + * XDR an array of arbitrary elements + * *addrp is a pointer to the array, *sizep is the number of elements. + * If addrp is NULL (*sizep * elsize) bytes are allocated. + * elsize is the size (in bytes) of each element, and elproc is the + * xdr procedure to call to handle each element of the array. + */ +bool_t +xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc) + register XDR *xdrs; + caddr_t *addrp; /* array pointer */ + u_int *sizep; /* number of elements */ + u_int maxsize; /* max numberof elements */ + u_int elsize; /* size in bytes of each element */ + xdrproc_t elproc; /* xdr routine to handle each element */ +{ + register u_int i; + register caddr_t target = *addrp; + register u_int c; /* the actual element count */ + register bool_t stat = TRUE; + register u_int nodesize; + + /* like strings, arrays are really counted arrays */ + if (! xdr_u_int(xdrs, sizep)) { + return (FALSE); + } + c = *sizep; + if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) { + return (FALSE); + } + nodesize = c * elsize; + + /* + * if we are deserializing, we may need to allocate an array. + * We also save time by checking for a null array if we are freeing. + */ + if (target == NULL) + switch (xdrs->x_op) { + case XDR_DECODE: + if (c == 0) + return (TRUE); + *addrp = target = mem_alloc(nodesize); + if (target == NULL) { + (void) printf( + "xdr_array: out of memory\n"); + return (FALSE); + } + bzero(target, nodesize); + break; + + case XDR_FREE: + return (TRUE); + default: + break; + } + + /* + * now we xdr each element of array + */ + for (i = 0; (i < c) && stat; i++) { + stat = (*elproc)(xdrs, target, LASTUNSIGNED); + target += elsize; + } + + /* + * the array may need freeing + */ + if (xdrs->x_op == XDR_FREE) { + mem_free(*addrp, nodesize); + *addrp = NULL; + } + return (stat); +} + +/* + * xdr_vector(): + * + * XDR a fixed length array. Unlike variable-length arrays, + * the storage of fixed length arrays is static and unfreeable. + * > basep: base of the array + * > size: size of the array + * > elemsize: size of each element + * > xdr_elem: routine to XDR each element + */ +bool_t +xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem) + register XDR *xdrs; + register char *basep; + register u_int nelem; + register u_int elemsize; + register xdrproc_t xdr_elem; +{ + register u_int i; + register char *elptr; + + elptr = basep; + for (i = 0; i < nelem; i++) { + if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) { + return(FALSE); + } + elptr += elemsize; + } + return(TRUE); +} + diff --git a/c/src/librpc/src/xdr_mem.c b/c/src/librpc/src/xdr_mem.c new file mode 100644 index 0000000000..280451a349 --- /dev/null +++ b/c/src/librpc/src/xdr_mem.c @@ -0,0 +1,185 @@ +/* @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_mem.h, XDR implementation using memory buffers. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * If you have some data to be interpreted as external data representation + * or to be converted to external data representation in a memory buffer, + * then this is the package for you. + * + */ + + +#include /* bcopy */ +#include +#include +#include + +static bool_t xdrmem_getlong(); +static bool_t xdrmem_putlong(); +static bool_t xdrmem_getbytes(); +static bool_t xdrmem_putbytes(); +static u_int xdrmem_getpos(); +static bool_t xdrmem_setpos(); +static long * xdrmem_inline(); +static void xdrmem_destroy(); + +static struct xdr_ops xdrmem_ops = { + xdrmem_getlong, + xdrmem_putlong, + xdrmem_getbytes, + xdrmem_putbytes, + xdrmem_getpos, + xdrmem_setpos, + xdrmem_inline, + xdrmem_destroy +}; + +/* + * The procedure xdrmem_create initializes a stream descriptor for a + * memory buffer. + */ +void +xdrmem_create(xdrs, addr, size, op) + register XDR *xdrs; + caddr_t addr; + u_int size; + enum xdr_op op; +{ + + xdrs->x_op = op; + xdrs->x_ops = &xdrmem_ops; + xdrs->x_private = xdrs->x_base = addr; + xdrs->x_handy = size; +} + +static void +xdrmem_destroy(/*xdrs*/) + /*XDR *xdrs;*/ +{ +} + +static bool_t +xdrmem_getlong(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + + if ((xdrs->x_handy -= sizeof(long)) < 0) + return (FALSE); + *lp = (long)ntohl((u_long)(*((long *)(xdrs->x_private)))); + xdrs->x_private += sizeof(long); + return (TRUE); +} + +static bool_t +xdrmem_putlong(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + + if ((xdrs->x_handy -= sizeof(long)) < 0) + return (FALSE); + *(long *)xdrs->x_private = (long)htonl((u_long)(*lp)); + xdrs->x_private += sizeof(long); + return (TRUE); +} + +static bool_t +xdrmem_getbytes(xdrs, addr, len) + register XDR *xdrs; + caddr_t addr; + register u_int len; +{ + + if ((xdrs->x_handy -= len) < 0) + return (FALSE); + bcopy(xdrs->x_private, addr, len); + xdrs->x_private += len; + return (TRUE); +} + +static bool_t +xdrmem_putbytes(xdrs, addr, len) + register XDR *xdrs; + caddr_t addr; + register u_int len; +{ + + if ((xdrs->x_handy -= len) < 0) + return (FALSE); + bcopy(addr, xdrs->x_private, len); + xdrs->x_private += len; + return (TRUE); +} + +static u_int +xdrmem_getpos(xdrs) + register XDR *xdrs; +{ + + return ((u_int)xdrs->x_private - (u_int)xdrs->x_base); +} + +static bool_t +xdrmem_setpos(xdrs, pos) + register XDR *xdrs; + u_int pos; +{ + register caddr_t newaddr = xdrs->x_base + pos; + register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; + + if ((long)newaddr > (long)lastaddr) + return (FALSE); + xdrs->x_private = newaddr; + xdrs->x_handy = (int)lastaddr - (int)newaddr; + return (TRUE); +} + +static long * +xdrmem_inline(xdrs, len) + register XDR *xdrs; + int len; +{ + long *buf = 0; + + if (xdrs->x_handy >= len) { + xdrs->x_handy -= len; + buf = (long *) xdrs->x_private; + xdrs->x_private += len; + } + return (buf); +} diff --git a/c/src/wrapup/Makefile.in b/c/src/wrapup/Makefile.in index d7c6fcdaf9..5e73848490 100644 --- a/c/src/wrapup/Makefile.in +++ b/c/src/wrapup/Makefile.in @@ -19,6 +19,8 @@ SRCS=$(wildcard $(PROJECT_RELEASE)/lib/libbsp$(LIB_VARIANT).a) \ $(PROJECT_RELEASE)/lib/librtems$(LIB_VARIANT).a \ $(wildcard $(PROJECT_RELEASE)/lib/libposix$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/libnetworking$(LIB_VARIANT).a) \ + $(wildcard $(PROJECT_RELEASE)/lib/librpc$(LIB_VARIANT).a) \ + $(wildcard $(PROJECT_RELEASE)/lib/librdbg$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/libcpu$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/librtcio$(LIB_VARIANT).a) \ $(wildcard $(PROJECT_RELEASE)/lib/libserialio$(LIB_VARIANT).a) \ diff --git a/configure b/configure index cb87569c7c..c54cb6bf1a 100644 --- a/configure +++ b/configure @@ -60,6 +60,9 @@ ac_help="$ac_help \ --enable-networking enable TCP/IP stack" ac_help="$ac_help +\ + --enable-rdbg enable remote debugger" +ac_help="$ac_help \ --enable-rtems-inlines enable RTEMS inline functions (use macros)" ac_help="$ac_help @@ -595,7 +598,7 @@ fi echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:599: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:602: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -668,7 +671,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:672: checking host system type" >&5 +echo "configure:675: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -689,7 +692,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking target system type""... $ac_c" 1>&6 -echo "configure:693: checking target system type" >&5 +echo "configure:696: checking target system type" >&5 target_alias=$target case "$target_alias" in @@ -707,7 +710,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$target" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:711: checking build system type" >&5 +echo "configure:714: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -793,6 +796,20 @@ else fi +# Check whether --enable-rdbg or --disable-rdbg was given. +if test "${enable_rdbg+set}" = set; then + enableval="$enable_rdbg" + \ +case "${enableval}" in + yes) RTEMS_HAS_RDBG=yes ;; + no) RTEMS_HAS_RDBG=no ;; + *) { echo "configure: error: bad value ${enableval} for enable-rdbg option" 1>&2; exit 1; } ;; +esac +else + RTEMS_HAS_RDBG=yes +fi + + # Check whether --enable-rtems-inlines or --disable-rtems-inlines was given. if test "${enable_rtems_inlines+set}" = set; then enableval="$enable_rtems_inlines" @@ -874,7 +891,7 @@ RTEMS_PREFIX=${target_cpu}-${target_vendor} # Extract the first word of "cat", so it can be a program name with args. set dummy cat; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:878: checking for $ac_word" >&5 +echo "configure:895: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_CAT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -905,7 +922,7 @@ fi # Extract the first word of "rm", so it can be a program name with args. set dummy rm; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:909: checking for $ac_word" >&5 +echo "configure:926: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_RM'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -936,7 +953,7 @@ fi # Extract the first word of "cp", so it can be a program name with args. set dummy cp; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:940: checking for $ac_word" >&5 +echo "configure:957: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_CP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -967,7 +984,7 @@ fi # Extract the first word of "mv", so it can be a program name with args. set dummy mv; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:971: checking for $ac_word" >&5 +echo "configure:988: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MV'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -998,7 +1015,7 @@ fi # Extract the first word of "ln", so it can be a program name with args. set dummy ln; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1002: checking for $ac_word" >&5 +echo "configure:1019: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_LN'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1027,7 +1044,7 @@ else fi echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:1031: checking whether ln -s works" >&5 +echo "configure:1048: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1050,7 +1067,7 @@ fi # Extract the first word of "chmod", so it can be a program name with args. set dummy chmod; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1054: checking for $ac_word" >&5 +echo "configure:1071: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_CHMOD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1081,7 +1098,7 @@ fi # Extract the first word of "sort", so it can be a program name with args. set dummy sort; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1085: checking for $ac_word" >&5 +echo "configure:1102: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_SORT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1120,7 +1137,7 @@ fi # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:1124: checking for a BSD compatible install" >&5 +echo "configure:1141: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1172,7 +1189,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' # Extract the first word of "perl", so it can be a program name with args. set dummy perl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1176: checking for $ac_word" >&5 +echo "configure:1193: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1209,7 +1226,7 @@ fi # Extract the first word of "mkdir", so it can be a program name with args. set dummy mkdir; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1213: checking for $ac_word" >&5 +echo "configure:1230: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MKDIR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1241,7 +1258,7 @@ fi echo $ac_n "checking for working $MKDIR -m 0755""... $ac_c" 1>&6 -echo "configure:1245: checking for working $MKDIR -m 0755" >&5 +echo "configure:1262: checking for working $MKDIR -m 0755" >&5 if eval "test \"`echo '$''{'rtems_cv_prog_MKDIR_P'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1258,7 +1275,7 @@ echo "$ac_t""$rtems_cv_prog_MKDIR_M" 1>&6 echo $ac_n "checking for working $MKDIR -p""... $ac_c" 1>&6 -echo "configure:1262: checking for working $MKDIR -p" >&5 +echo "configure:1279: checking for working $MKDIR -p" >&5 if eval "test \"`echo '$''{'rtems_cv_prog_mkdir_p'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1278,7 +1295,7 @@ test "$rtems_cv_prog_MKDIR_P" = "yes" && MKDIR="$MKDIR -p" # Extract the first word of "touch", so it can be a program name with args. set dummy touch; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1282: checking for $ac_word" >&5 +echo "configure:1299: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_TOUCH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1309,7 +1326,7 @@ fi # Extract the first word of "cmp", so it can be a program name with args. set dummy cmp; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1313: checking for $ac_word" >&5 +echo "configure:1330: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_CMP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1341,7 +1358,7 @@ fi # Extract the first word of "sed", so it can be a program name with args. set dummy sed; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1345: checking for $ac_word" >&5 +echo "configure:1362: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_SED'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1374,7 +1391,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1378: checking for $ac_word" >&5 +echo "configure:1395: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_M4'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1411,7 +1428,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1415: checking for $ac_word" >&5 +echo "configure:1432: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_KSH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1489,7 +1506,7 @@ case "${target}" in ;; *) echo $ac_n "checking rtems target cpu""... $ac_c" 1>&6 -echo "configure:1493: checking rtems target cpu" >&5 +echo "configure:1510: checking rtems target cpu" >&5 target_cpu=`echo $target | sed 's%^\([^-]*\)-\(.*\)$%\1%'` echo "$ac_t""$target_cpu" 1>&6 @@ -1508,7 +1525,7 @@ fi # Is this a supported CPU? echo $ac_n "checking if cpu $target_cpu is supported""... $ac_c" 1>&6 -echo "configure:1512: checking if cpu $target_cpu is supported" >&5 +echo "configure:1529: checking if cpu $target_cpu is supported" >&5 if test -d "$srcdir/c/src/exec/score/cpu/$target_cpu"; then echo "$ac_t""yes" 1>&6 makefiles="$makefiles c/src/exec/score/cpu/$target_cpu/Makefile" @@ -1533,7 +1550,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1537: checking for $ac_word" >&5 +echo "configure:1554: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_CC_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1573,7 +1590,7 @@ rtems_save_CFLAGS=$CFLAGS CC=$CC_FOR_TARGET echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1577: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1594: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -1583,11 +1600,11 @@ ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1608: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1607,12 +1624,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1611: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1628: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1616: checking whether we are using GNU C" >&5 +echo "configure:1633: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1621,7 +1638,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1625: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1642: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1636,7 +1653,7 @@ if test $ac_cv_prog_gcc = yes; then ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1640: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1657: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1678,7 +1695,7 @@ unset ac_cv_prog_cc_cross echo $ac_n "checking whether $CC_FOR_TARGET accepts -specs""... $ac_c" 1>&6 -echo "configure:1682: checking whether $CC_FOR_TARGET accepts -specs" >&5 +echo "configure:1699: checking whether $CC_FOR_TARGET accepts -specs" >&5 if eval "test \"`echo '$''{'rtems_cv_gcc_specs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1699,7 +1716,7 @@ echo "$ac_t""$rtems_cv_gcc_specs" 1>&6 echo $ac_n "checking whether $CC_FOR_TARGET accepts --pipe""... $ac_c" 1>&6 -echo "configure:1703: checking whether $CC_FOR_TARGET accepts --pipe" >&5 +echo "configure:1720: checking whether $CC_FOR_TARGET accepts --pipe" >&5 if eval "test \"`echo '$''{'rtems_cv_gcc_pipe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1740,7 +1757,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1744: checking for $ac_word" >&5 +echo "configure:1761: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_CXX_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1780,7 +1797,7 @@ rtems_save_CXXFLAGS=$CXXFLAGS CXX=$CXX_FOR_TARGET echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1784: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 +echo "configure:1801: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 ac_ext=C # CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -1790,11 +1807,11 @@ ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $L cross_compiling=$ac_cv_prog_cxx_cross cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1815: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cxx_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1820,12 +1837,12 @@ if test $ac_cv_prog_cxx_works = no; then { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1824: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1841: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 cross_compiling=$ac_cv_prog_cxx_cross echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 -echo "configure:1829: checking whether we are using GNU C++" >&5 +echo "configure:1846: checking whether we are using GNU C++" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1834,7 +1851,7 @@ else yes; #endif EOF -if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1838: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1855: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gxx=yes else ac_cv_prog_gxx=no @@ -1849,7 +1866,7 @@ if test $ac_cv_prog_gxx = yes; then ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS= echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 -echo "configure:1853: checking whether ${CXX-g++} accepts -g" >&5 +echo "configure:1870: checking whether ${CXX-g++} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1903,7 +1920,7 @@ fi echo $ac_n "checking target's ar""... $ac_c" 1>&6 -echo "configure:1907: checking target's ar" >&5 +echo "configure:1924: checking target's ar" >&5 if eval "test \"`echo '$''{'ac_cv_path_AR_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1936,7 +1953,7 @@ else # will override the environment variable, which isn't what the user # intends echo $ac_n "checking whether environment variable AR_FOR_TARGET is an absolute path""... $ac_c" 1>&6 -echo "configure:1940: checking whether environment variable AR_FOR_TARGET is an absolute path" >&5 +echo "configure:1957: checking whether environment variable AR_FOR_TARGET is an absolute path" >&5 case "$AR_FOR_TARGET" in /*) # valid echo "$ac_t"""yes"" 1>&6 @@ -1953,7 +1970,7 @@ echo "configure:1940: checking whether environment variable AR_FOR_TARGET is an # Extract the first word of ""$program_prefix"ar", so it can be a program name with args. set dummy "$program_prefix"ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1957: checking for $ac_word" >&5 +echo "configure:1974: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_AR_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1986,7 +2003,7 @@ fi echo $ac_n "checking target's as""... $ac_c" 1>&6 -echo "configure:1990: checking target's as" >&5 +echo "configure:2007: checking target's as" >&5 if eval "test \"`echo '$''{'ac_cv_path_AS_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2019,7 +2036,7 @@ else # will override the environment variable, which isn't what the user # intends echo $ac_n "checking whether environment variable AS_FOR_TARGET is an absolute path""... $ac_c" 1>&6 -echo "configure:2023: checking whether environment variable AS_FOR_TARGET is an absolute path" >&5 +echo "configure:2040: checking whether environment variable AS_FOR_TARGET is an absolute path" >&5 case "$AS_FOR_TARGET" in /*) # valid echo "$ac_t"""yes"" 1>&6 @@ -2036,7 +2053,7 @@ echo "configure:2023: checking whether environment variable AS_FOR_TARGET is an # Extract the first word of ""$program_prefix"as", so it can be a program name with args. set dummy "$program_prefix"as; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2040: checking for $ac_word" >&5 +echo "configure:2057: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_AS_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2069,7 +2086,7 @@ fi echo $ac_n "checking target's ld""... $ac_c" 1>&6 -echo "configure:2073: checking target's ld" >&5 +echo "configure:2090: checking target's ld" >&5 if eval "test \"`echo '$''{'ac_cv_path_LD_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2102,7 +2119,7 @@ else # will override the environment variable, which isn't what the user # intends echo $ac_n "checking whether environment variable LD_FOR_TARGET is an absolute path""... $ac_c" 1>&6 -echo "configure:2106: checking whether environment variable LD_FOR_TARGET is an absolute path" >&5 +echo "configure:2123: checking whether environment variable LD_FOR_TARGET is an absolute path" >&5 case "$LD_FOR_TARGET" in /*) # valid echo "$ac_t"""yes"" 1>&6 @@ -2119,7 +2136,7 @@ echo "configure:2106: checking whether environment variable LD_FOR_TARGET is an # Extract the first word of ""$program_prefix"ld", so it can be a program name with args. set dummy "$program_prefix"ld; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2123: checking for $ac_word" >&5 +echo "configure:2140: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_LD_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2152,7 +2169,7 @@ fi echo $ac_n "checking target's nm""... $ac_c" 1>&6 -echo "configure:2156: checking target's nm" >&5 +echo "configure:2173: checking target's nm" >&5 if eval "test \"`echo '$''{'ac_cv_path_NM_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2185,7 +2202,7 @@ else # will override the environment variable, which isn't what the user # intends echo $ac_n "checking whether environment variable NM_FOR_TARGET is an absolute path""... $ac_c" 1>&6 -echo "configure:2189: checking whether environment variable NM_FOR_TARGET is an absolute path" >&5 +echo "configure:2206: checking whether environment variable NM_FOR_TARGET is an absolute path" >&5 case "$NM_FOR_TARGET" in /*) # valid echo "$ac_t"""yes"" 1>&6 @@ -2202,7 +2219,7 @@ echo "configure:2189: checking whether environment variable NM_FOR_TARGET is an # Extract the first word of ""$program_prefix"nm", so it can be a program name with args. set dummy "$program_prefix"nm; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2206: checking for $ac_word" >&5 +echo "configure:2223: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_NM_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2236,7 +2253,7 @@ fi echo $ac_n "checking target's ranlib""... $ac_c" 1>&6 -echo "configure:2240: checking target's ranlib" >&5 +echo "configure:2257: checking target's ranlib" >&5 if eval "test \"`echo '$''{'ac_cv_path_RANLIB_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2269,7 +2286,7 @@ else # will override the environment variable, which isn't what the user # intends echo $ac_n "checking whether environment variable RANLIB_FOR_TARGET is an absolute path""... $ac_c" 1>&6 -echo "configure:2273: checking whether environment variable RANLIB_FOR_TARGET is an absolute path" >&5 +echo "configure:2290: checking whether environment variable RANLIB_FOR_TARGET is an absolute path" >&5 case "$RANLIB_FOR_TARGET" in /*) # valid echo "$ac_t"""yes"" 1>&6 @@ -2286,7 +2303,7 @@ echo "configure:2273: checking whether environment variable RANLIB_FOR_TARGET is # Extract the first word of ""$program_prefix"ranlib", so it can be a program name with args. set dummy "$program_prefix"ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2290: checking for $ac_word" >&5 +echo "configure:2307: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_RANLIB_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2321,7 +2338,7 @@ fi # ranlib wasn't found; check if ar -s is available echo $ac_n "checking whether $AR_FOR_TARGET -s works""... $ac_c" 1>&6 -echo "configure:2325: checking whether $AR_FOR_TARGET -s works" >&5 +echo "configure:2342: checking whether $AR_FOR_TARGET -s works" >&5 if eval "test \"`echo '$''{'rtems_cv_AR_FOR_TARGET_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2330,8 +2347,8 @@ cat > conftest.$ac_ext <&5; (eval $ac_try) 2>&5; }; } \ - && { ac_try='$AR_FOR_TARGET -sr conftest.a conftest.o'; { (eval echo configure:2335: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } \ +if { ac_try='$CC_FOR_TARGET -o conftest.o -c conftest.$ac_ext'; { (eval echo configure:2351: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } \ + && { ac_try='$AR_FOR_TARGET -sr conftest.a conftest.o'; { (eval echo configure:2352: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } \ && test -s conftest.a ; \ then rtems_cv_AR_FOR_TARGET_S="yes" @@ -2356,7 +2373,7 @@ echo "$ac_t""$rtems_cv_AR_FOR_TARGET_S" 1>&6 echo $ac_n "checking target's objcopy""... $ac_c" 1>&6 -echo "configure:2360: checking target's objcopy" >&5 +echo "configure:2377: checking target's objcopy" >&5 if eval "test \"`echo '$''{'ac_cv_path_OBJCOPY_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2389,7 +2406,7 @@ else # will override the environment variable, which isn't what the user # intends echo $ac_n "checking whether environment variable OBJCOPY_FOR_TARGET is an absolute path""... $ac_c" 1>&6 -echo "configure:2393: checking whether environment variable OBJCOPY_FOR_TARGET is an absolute path" >&5 +echo "configure:2410: checking whether environment variable OBJCOPY_FOR_TARGET is an absolute path" >&5 case "$OBJCOPY_FOR_TARGET" in /*) # valid echo "$ac_t"""yes"" 1>&6 @@ -2406,7 +2423,7 @@ echo "configure:2393: checking whether environment variable OBJCOPY_FOR_TARGET i # Extract the first word of ""$program_prefix"objcopy", so it can be a program name with args. set dummy "$program_prefix"objcopy; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2410: checking for $ac_word" >&5 +echo "configure:2427: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_OBJCOPY_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2439,7 +2456,7 @@ fi echo $ac_n "checking target's size""... $ac_c" 1>&6 -echo "configure:2443: checking target's size" >&5 +echo "configure:2460: checking target's size" >&5 if eval "test \"`echo '$''{'ac_cv_path_SIZE_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2472,7 +2489,7 @@ else # will override the environment variable, which isn't what the user # intends echo $ac_n "checking whether environment variable SIZE_FOR_TARGET is an absolute path""... $ac_c" 1>&6 -echo "configure:2476: checking whether environment variable SIZE_FOR_TARGET is an absolute path" >&5 +echo "configure:2493: checking whether environment variable SIZE_FOR_TARGET is an absolute path" >&5 case "$SIZE_FOR_TARGET" in /*) # valid echo "$ac_t"""yes"" 1>&6 @@ -2489,7 +2506,7 @@ echo "configure:2476: checking whether environment variable SIZE_FOR_TARGET is a # Extract the first word of ""$program_prefix"size", so it can be a program name with args. set dummy "$program_prefix"size; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2493: checking for $ac_word" >&5 +echo "configure:2510: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_SIZE_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2522,7 +2539,7 @@ fi echo $ac_n "checking target's strip""... $ac_c" 1>&6 -echo "configure:2526: checking target's strip" >&5 +echo "configure:2543: checking target's strip" >&5 if eval "test \"`echo '$''{'ac_cv_path_STRIP_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2555,7 +2572,7 @@ else # will override the environment variable, which isn't what the user # intends echo $ac_n "checking whether environment variable STRIP_FOR_TARGET is an absolute path""... $ac_c" 1>&6 -echo "configure:2559: checking whether environment variable STRIP_FOR_TARGET is an absolute path" >&5 +echo "configure:2576: checking whether environment variable STRIP_FOR_TARGET is an absolute path" >&5 case "$STRIP_FOR_TARGET" in /*) # valid echo "$ac_t"""yes"" 1>&6 @@ -2572,7 +2589,7 @@ echo "configure:2559: checking whether environment variable STRIP_FOR_TARGET is # Extract the first word of ""$program_prefix"strip", so it can be a program name with args. set dummy "$program_prefix"strip; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2576: checking for $ac_word" >&5 +echo "configure:2593: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_STRIP_FOR_TARGET'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2607,7 +2624,7 @@ fi if test "${target_cpu}" = "i386"; then echo $ac_n "checking for 16 bit mode assembler support""... $ac_c" 1>&6 -echo "configure:2611: checking for 16 bit mode assembler support" >&5 +echo "configure:2628: checking for 16 bit mode assembler support" >&5 if eval "test \"`echo '$''{'rtems_cv_prog_gas_code16'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2617,7 +2634,7 @@ else addr32 lgdt 0 EOF - if { ac_try='$AS_FOR_TARGET -o conftest.o conftest.s'; { (eval echo configure:2621: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + if { ac_try='$AS_FOR_TARGET -o conftest.o conftest.s'; { (eval echo configure:2638: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then rtems_cv_prog_gas_code16=yes else rtems_cv_prog_gas_code16=no @@ -2632,7 +2649,7 @@ echo "$ac_t""$rtems_cv_prog_gas_code16" 1>&6 # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2636: checking for $ac_word" >&5 +echo "configure:2653: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2661,7 +2678,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2665: checking for $ac_word" >&5 +echo "configure:2682: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2709,7 +2726,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:2713: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:2730: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -2719,11 +2736,11 @@ ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2744: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -2743,12 +2760,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:2747: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:2764: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:2752: checking whether we are using GNU C" >&5 +echo "configure:2769: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2757,7 +2774,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2761: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2778: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -2772,7 +2789,7 @@ if test $ac_cv_prog_gcc = yes; then ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:2776: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:2793: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2801,19 +2818,19 @@ fi echo $ac_n "checking for Cygwin32 environment""... $ac_c" 1>&6 -echo "configure:2805: checking for Cygwin32 environment" >&5 +echo "configure:2822: checking for Cygwin32 environment" >&5 if eval "test \"`echo '$''{'rtems_cv_cygwin32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2834: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* rtems_cv_cygwin32=yes else @@ -2831,7 +2848,7 @@ CYGWIN32= test "$rtems_cv_cygwin32" = yes && CYGWIN32=yes echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 -echo "configure:2835: checking for executable suffix" >&5 +echo "configure:2852: checking for executable suffix" >&5 if eval "test \"`echo '$''{'rtems_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2872,12 +2889,12 @@ test "$ac_cv_prog_cc_g" = "yes" && CC_CFLAGS_DEBUG_V=${CC_CFLAGS_DEBUG_V-"-g"} for ac_func in strerror do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2876: checking for $ac_func" >&5 +echo "configure:2893: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2921: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2929,7 +2946,7 @@ if test "$target_cpu" = "unix" ; then echo $ac_n "checking whether $RTEMS_HOST supports System V semaphores""... $ac_c" 1>&6 -echo "configure:2933: checking whether $RTEMS_HOST supports System V semaphores" >&5 +echo "configure:2950: checking whether $RTEMS_HOST supports System V semaphores" >&5 if eval "test \"`echo '$''{'rtems_cv_sysv_sem'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2938,7 +2955,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < @@ -2964,7 +2981,7 @@ int main () { } EOF -if { (eval echo configure:2968: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2985: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then rtems_cv_sysv_sem="yes" else @@ -2987,7 +3004,7 @@ echo "$ac_t""$rtems_cv_sysv_sem" 1>&6 echo $ac_n "checking whether $RTEMS_HOST supports System V shared memory""... $ac_c" 1>&6 -echo "configure:2991: checking whether $RTEMS_HOST supports System V shared memory" >&5 +echo "configure:3008: checking whether $RTEMS_HOST supports System V shared memory" >&5 if eval "test \"`echo '$''{'rtems_cv_sysv_shm'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2996,7 +3013,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < @@ -3012,7 +3029,7 @@ int main () { } EOF -if { (eval echo configure:3016: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3033: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then rtems_cv_sysv_shm="yes" else @@ -3035,7 +3052,7 @@ echo "$ac_t""$rtems_cv_sysv_shm" 1>&6 echo $ac_n "checking whether $RTEMS_HOST supports System V messages""... $ac_c" 1>&6 -echo "configure:3039: checking whether $RTEMS_HOST supports System V messages" >&5 +echo "configure:3056: checking whether $RTEMS_HOST supports System V messages" >&5 if eval "test \"`echo '$''{'rtems_cv_sysv_msg'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3044,7 +3061,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < @@ -3060,7 +3077,7 @@ int main () { } EOF -if { (eval echo configure:3064: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3081: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then rtems_cv_sysv_msg="yes" else @@ -3085,7 +3102,7 @@ fi # find all the Executive Makefiles echo $ac_n "checking for Makefile.in in c/src/exec/score/tools/$target_cpu""... $ac_c" 1>&6 -echo "configure:3089: checking for Makefile.in in c/src/exec/score/tools/$target_cpu" >&5 +echo "configure:3106: checking for Makefile.in in c/src/exec/score/tools/$target_cpu" >&5 if test -d $srcdir/c/src/exec/score/tools/$target_cpu; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3100,7 +3117,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/exec/rtems""... $ac_c" 1>&6 -echo "configure:3104: checking for Makefile.in in c/src/exec/rtems" >&5 +echo "configure:3121: checking for Makefile.in in c/src/exec/rtems" >&5 if test -d $srcdir/c/src/exec/rtems; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3115,7 +3132,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/exec/sapi""... $ac_c" 1>&6 -echo "configure:3119: checking for Makefile.in in c/src/exec/sapi" >&5 +echo "configure:3136: checking for Makefile.in in c/src/exec/sapi" >&5 if test -d $srcdir/c/src/exec/sapi; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3132,7 +3149,7 @@ fi if test "$RTEMS_HAS_POSIX_API" = "yes"; then echo $ac_n "checking for Makefile.in in c/src/exec/posix""... $ac_c" 1>&6 -echo "configure:3136: checking for Makefile.in in c/src/exec/posix" >&5 +echo "configure:3153: checking for Makefile.in in c/src/exec/posix" >&5 if test -d $srcdir/c/src/exec/posix; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3154,7 +3171,7 @@ if test -d "$srcdir/c/src/lib/libbsp/$target_cpu"; then if test -z "$rtems_bsp"; then echo $ac_n "checking for bsps""... $ac_c" 1>&6 -echo "configure:3158: checking for bsps" >&5 +echo "configure:3175: checking for bsps" >&5 files=`ls $srcdir/c/src/lib/libbsp/$target_cpu` for file in $files; do case $file in @@ -3219,7 +3236,7 @@ echo "configure:3158: checking for bsps" >&5 bspdirs="$bspdirs $bspdir" echo $ac_n "checking for Makefile.in in c/src/lib/libbsp/$bspcpudir$bspdir""... $ac_c" 1>&6 -echo "configure:3223: checking for Makefile.in in c/src/lib/libbsp/$bspcpudir$bspdir" >&5 +echo "configure:3240: checking for Makefile.in in c/src/lib/libbsp/$bspcpudir$bspdir" >&5 if test -d $srcdir/c/src/lib/libbsp/$bspcpudir$bspdir; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3234,7 +3251,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/lib/libbsp/${bspcpudir}shared""... $ac_c" 1>&6 -echo "configure:3238: checking for Makefile.in in c/src/lib/libbsp/${bspcpudir}shared" >&5 +echo "configure:3255: checking for Makefile.in in c/src/lib/libbsp/${bspcpudir}shared" >&5 if test -d $srcdir/c/src/lib/libbsp/${bspcpudir}shared; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3257,7 +3274,7 @@ fi # find all the CPU dependent library Makefiles echo $ac_n "checking for Makefile.in in c/src/lib/libcpu/$target_cpu""... $ac_c" 1>&6 -echo "configure:3261: checking for Makefile.in in c/src/lib/libcpu/$target_cpu" >&5 +echo "configure:3278: checking for Makefile.in in c/src/lib/libcpu/$target_cpu" >&5 if test -d $srcdir/c/src/lib/libcpu/$target_cpu; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3274,7 +3291,7 @@ fi if test "$skip_startfiles" != "yes"; then echo $ac_n "checking for Makefile.in in c/src/lib/start/$target_cpu""... $ac_c" 1>&6 -echo "configure:3278: checking for Makefile.in in c/src/lib/start/$target_cpu" >&5 +echo "configure:3295: checking for Makefile.in in c/src/lib/start/$target_cpu" >&5 if test -d $srcdir/c/src/lib/start/$target_cpu; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3306,12 +3323,12 @@ fi # If the TCP/IP stack is enabled, then find all TCP/IP Makefiles echo $ac_n "checking if networking is enabled? ""... $ac_c" 1>&6 -echo "configure:3310: checking if networking is enabled? " >&5 +echo "configure:3327: checking if networking is enabled? " >&5 echo "$ac_t""$RTEMS_HAS_NETWORKING" 1>&6 if test "$RTEMS_HAS_NETWORKING" = "yes"; then echo $ac_n "checking for Makefile.in in c/src/lib/libnetworking""... $ac_c" 1>&6 -echo "configure:3315: checking for Makefile.in in c/src/lib/libnetworking" >&5 +echo "configure:3332: checking for Makefile.in in c/src/lib/libnetworking" >&5 if test -d $srcdir/c/src/lib/libnetworking; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3324,6 +3341,38 @@ else fi + +echo $ac_n "checking for Makefile.in in c/src/lib/librpc""... $ac_c" 1>&6 +echo "configure:3347: checking for Makefile.in in c/src/lib/librpc" >&5 +if test -d $srcdir/c/src/lib/librpc; then + rtems_av_save_dir=`pwd`; + cd $srcdir; + rtems_av_tmp=`find c/src/lib/librpc -name "Makefile.in" -print | sed "s/Makefile\.in/%/" | sort | sed "s/%/Makefile/"` + makefiles="$makefiles $rtems_av_tmp"; + cd $rtems_av_save_dir; + echo "$ac_t""done" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + + if test "$RTEMS_HAS_RDBG" = "yes"; then + +echo $ac_n "checking for Makefile.in in c/src/lib/librdbg""... $ac_c" 1>&6 +echo "configure:3363: checking for Makefile.in in c/src/lib/librdbg" >&5 +if test -d $srcdir/c/src/lib/librdbg; then + rtems_av_save_dir=`pwd`; + cd $srcdir; + rtems_av_tmp=`find c/src/lib/librdbg -name "Makefile.in" -print | sed "s/Makefile\.in/%/" | sort | sed "s/%/Makefile/"` + makefiles="$makefiles $rtems_av_tmp"; + cd $rtems_av_save_dir; + echo "$ac_t""done" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + + fi fi # If the C++ support is enabled, then include the Makefiles @@ -3333,7 +3382,7 @@ fi # If the tests are enabled, then find all the test suite Makefiles echo $ac_n "checking if the test suites are enabled? ""... $ac_c" 1>&6 -echo "configure:3337: checking if the test suites are enabled? " >&5 +echo "configure:3386: checking if the test suites are enabled? " >&5 tests_enabled=yes # Check whether --enable-tests or --disable-tests was given. if test "${enable_tests+set}" = set; then @@ -3352,7 +3401,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/tests/tools/$target_cpu""... $ac_c" 1>&6 -echo "configure:3356: checking for Makefile.in in c/src/tests/tools/$target_cpu" >&5 +echo "configure:3405: checking for Makefile.in in c/src/tests/tools/$target_cpu" >&5 if test -d $srcdir/c/src/tests/tools/$target_cpu; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3369,7 +3418,7 @@ fi if test "$tests_enabled" = "yes"; then echo $ac_n "checking for Makefile.in in c/src/tests/libtests""... $ac_c" 1>&6 -echo "configure:3373: checking for Makefile.in in c/src/tests/libtests" >&5 +echo "configure:3422: checking for Makefile.in in c/src/tests/libtests" >&5 if test -d $srcdir/c/src/tests/libtests; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3384,7 +3433,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/tests/sptests""... $ac_c" 1>&6 -echo "configure:3388: checking for Makefile.in in c/src/tests/sptests" >&5 +echo "configure:3437: checking for Makefile.in in c/src/tests/sptests" >&5 if test -d $srcdir/c/src/tests/sptests; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3399,7 +3448,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/tests/tmtests""... $ac_c" 1>&6 -echo "configure:3403: checking for Makefile.in in c/src/tests/tmtests" >&5 +echo "configure:3452: checking for Makefile.in in c/src/tests/tmtests" >&5 if test -d $srcdir/c/src/tests/tmtests; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3415,7 +3464,7 @@ fi if test "$RTEMS_HAS_MULTIPROCESSING" = "yes"; then echo $ac_n "checking for Makefile.in in c/src/tests/mptests""... $ac_c" 1>&6 -echo "configure:3419: checking for Makefile.in in c/src/tests/mptests" >&5 +echo "configure:3468: checking for Makefile.in in c/src/tests/mptests" >&5 if test -d $srcdir/c/src/tests/mptests; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3432,7 +3481,7 @@ fi if test "$RTEMS_HAS_POSIX_API" = "yes"; then echo $ac_n "checking for Makefile.in in c/src/tests/psxtests""... $ac_c" 1>&6 -echo "configure:3436: checking for Makefile.in in c/src/tests/psxtests" >&5 +echo "configure:3485: checking for Makefile.in in c/src/tests/psxtests" >&5 if test -d $srcdir/c/src/tests/psxtests; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3450,7 +3499,7 @@ fi # If the HWAPI is enabled, the find the HWAPI Makefiles echo $ac_n "checking if the HWAPI is enabled? ""... $ac_c" 1>&6 -echo "configure:3454: checking if the HWAPI is enabled? " >&5 +echo "configure:3503: checking if the HWAPI is enabled? " >&5 # Check whether --enable-hwapi or --disable-hwapi was given. if test "${enable_hwapi+set}" = set; then enableval="$enable_hwapi" @@ -3461,7 +3510,7 @@ if test "${enable_hwapi+set}" = set; then makefiles="$makefiles c/src/lib/libhwapi/Makefile" echo $ac_n "checking for Makefile.in in c/src/lib/libhwapi/analog""... $ac_c" 1>&6 -echo "configure:3465: checking for Makefile.in in c/src/lib/libhwapi/analog" >&5 +echo "configure:3514: checking for Makefile.in in c/src/lib/libhwapi/analog" >&5 if test -d $srcdir/c/src/lib/libhwapi/analog; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3476,7 +3525,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/lib/libhwapi/discrete""... $ac_c" 1>&6 -echo "configure:3480: checking for Makefile.in in c/src/lib/libhwapi/discrete" >&5 +echo "configure:3529: checking for Makefile.in in c/src/lib/libhwapi/discrete" >&5 if test -d $srcdir/c/src/lib/libhwapi/discrete; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3491,7 +3540,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/lib/libhwapi/drivers""... $ac_c" 1>&6 -echo "configure:3495: checking for Makefile.in in c/src/lib/libhwapi/drivers" >&5 +echo "configure:3544: checking for Makefile.in in c/src/lib/libhwapi/drivers" >&5 if test -d $srcdir/c/src/lib/libhwapi/drivers; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3506,7 +3555,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/lib/libhwapi/non_volatile_memory""... $ac_c" 1>&6 -echo "configure:3510: checking for Makefile.in in c/src/lib/libhwapi/non_volatile_memory" >&5 +echo "configure:3559: checking for Makefile.in in c/src/lib/libhwapi/non_volatile_memory" >&5 if test -d $srcdir/c/src/lib/libhwapi/non_volatile_memory; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3521,7 +3570,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/lib/libhwapi/serial""... $ac_c" 1>&6 -echo "configure:3525: checking for Makefile.in in c/src/lib/libhwapi/serial" >&5 +echo "configure:3574: checking for Makefile.in in c/src/lib/libhwapi/serial" >&5 if test -d $srcdir/c/src/lib/libhwapi/serial; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3536,7 +3585,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/lib/libhwapi/support""... $ac_c" 1>&6 -echo "configure:3540: checking for Makefile.in in c/src/lib/libhwapi/support" >&5 +echo "configure:3589: checking for Makefile.in in c/src/lib/libhwapi/support" >&5 if test -d $srcdir/c/src/lib/libhwapi/support; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3551,7 +3600,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/lib/libhwapi/wrapup""... $ac_c" 1>&6 -echo "configure:3555: checking for Makefile.in in c/src/lib/libhwapi/wrapup" >&5 +echo "configure:3604: checking for Makefile.in in c/src/lib/libhwapi/wrapup" >&5 if test -d $srcdir/c/src/lib/libhwapi/wrapup; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3596,12 +3645,13 @@ fi + # pick up all the Makefiles in required parts of the tree echo $ac_n "checking for Makefile.in in c/build-tools""... $ac_c" 1>&6 -echo "configure:3605: checking for Makefile.in in c/build-tools" >&5 +echo "configure:3655: checking for Makefile.in in c/build-tools" >&5 if test -d $srcdir/c/build-tools; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3616,7 +3666,7 @@ fi echo $ac_n "checking for Makefile.in in make""... $ac_c" 1>&6 -echo "configure:3620: checking for Makefile.in in make" >&5 +echo "configure:3670: checking for Makefile.in in make" >&5 if test -d $srcdir/make; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3631,7 +3681,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/lib/libchip""... $ac_c" 1>&6 -echo "configure:3635: checking for Makefile.in in c/src/lib/libchip" >&5 +echo "configure:3685: checking for Makefile.in in c/src/lib/libchip" >&5 if test -d $srcdir/c/src/lib/libchip; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3646,7 +3696,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/lib/libmisc""... $ac_c" 1>&6 -echo "configure:3650: checking for Makefile.in in c/src/lib/libmisc" >&5 +echo "configure:3700: checking for Makefile.in in c/src/lib/libmisc" >&5 if test -d $srcdir/c/src/lib/libmisc; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3661,7 +3711,7 @@ fi echo $ac_n "checking for Makefile.in in c/src/tests/samples""... $ac_c" 1>&6 -echo "configure:3665: checking for Makefile.in in c/src/tests/samples" >&5 +echo "configure:3715: checking for Makefile.in in c/src/tests/samples" >&5 if test -d $srcdir/c/src/tests/samples; then rtems_av_save_dir=`pwd`; cd $srcdir; @@ -3896,6 +3946,7 @@ s%@RTEMS_LIBC_DIR@%$RTEMS_LIBC_DIR%g s%@RTEMS_USE_OWN_PDIR@%$RTEMS_USE_OWN_PDIR%g s%@RTEMS_HAS_POSIX_API@%$RTEMS_HAS_POSIX_API%g s%@RTEMS_HAS_NETWORKING@%$RTEMS_HAS_NETWORKING%g +s%@RTEMS_HAS_RDBG@%$RTEMS_HAS_RDBG%g s%@RTEMS_USE_MACROS@%$RTEMS_USE_MACROS%g s%@RTEMS_HAS_CPLUSPLUS@%$RTEMS_HAS_CPLUSPLUS%g s%@RTEMS_USE_GCC272@%$RTEMS_USE_GCC272%g diff --git a/configure.in b/configure.in index a796507327..36d1dc17f6 100644 --- a/configure.in +++ b/configure.in @@ -43,6 +43,14 @@ AC_ARG_ENABLE(networking, \ *) AC_MSG_ERROR(bad value ${enableval} for enable-networking option) ;; esac],[RTEMS_HAS_NETWORKING=yes]) +AC_ARG_ENABLE(rdbg, \ +[ --enable-rdbg enable remote debugger], \ +[case "${enableval}" in + yes) RTEMS_HAS_RDBG=yes ;; + no) RTEMS_HAS_RDBG=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for enable-rdbg option) ;; +esac],[RTEMS_HAS_RDBG=yes]) + AC_ARG_ENABLE(rtems-inlines, \ [ --enable-rtems-inlines enable RTEMS inline functions (use macros)], \ [case "${enableval}" in @@ -408,6 +416,10 @@ AC_MSG_CHECKING([if networking is enabled? ]) AC_MSG_RESULT($RTEMS_HAS_NETWORKING) if test "$RTEMS_HAS_NETWORKING" = "yes"; then RTEMS_CHECK_MAKEFILE(c/src/lib/libnetworking) + RTEMS_CHECK_MAKEFILE(c/src/lib/librpc) + if test "$RTEMS_HAS_RDBG" = "yes"; then + RTEMS_CHECK_MAKEFILE(c/src/lib/librdbg) + fi fi # If the C++ support is enabled, then include the Makefiles @@ -475,6 +487,7 @@ AC_SUBST(RTEMS_LIBC_DIR) AC_SUBST(RTEMS_USE_OWN_PDIR) AC_SUBST(RTEMS_HAS_POSIX_API) AC_SUBST(RTEMS_HAS_NETWORKING) +AC_SUBST(RTEMS_HAS_RDBG) AC_SUBST(RTEMS_USE_MACROS) AC_SUBST(RTEMS_HAS_CPLUSPLUS) AC_SUBST(RTEMS_USE_GCC272) diff --git a/cpukit/librpc/include/rpc/auth.h b/cpukit/librpc/include/rpc/auth.h new file mode 100644 index 0000000000..8f14d144f6 --- /dev/null +++ b/cpukit/librpc/include/rpc/auth.h @@ -0,0 +1,167 @@ +#ifndef RPC_AUTH_H +#define RPC_AUTH_H + +/* @(#)auth.h 2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * auth.h, Authentication interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * The data structures are completely opaque to the client. The client + * is required to pass a AUTH * to routines that create rpc + * "sessions". + */ + + +#define MAX_AUTH_BYTES 400 +#define MAXNETNAMELEN 255 /* maximum length of network user's name */ + +/* + * Status returned from authentication check + */ +enum auth_stat { + AUTH_OK=0, + /* + * failed at remote end + */ + AUTH_BADCRED=1, /* bogus credentials (seal broken) */ + AUTH_REJECTEDCRED=2, /* client should begin new session */ + AUTH_BADVERF=3, /* bogus verifier (seal broken) */ + AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ + AUTH_TOOWEAK=5, /* rejected due to security reasons */ + /* + * failed locally + */ + AUTH_INVALIDRESP=6, /* bogus response verifier */ + AUTH_FAILED=7 /* some unknown reason */ +}; + +union des_block { + struct { + u_int32 high; + u_int32 low; + } key; + char c[8]; +}; +typedef union des_block des_block; +extern bool_t xdr_des_block(); + +/* + * Authentication info. Opaque to client. + */ +struct opaque_auth { + enum_t oa_flavor; /* flavor of auth */ + caddr_t oa_base; /* address of more auth stuff */ + u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ +}; + + +/* + * Auth handle, interface to client side authenticators. + */ +typedef struct { + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + struct auth_ops { + void (*ah_nextverf)(); + int (*ah_marshal)(); /* nextverf & serialize */ + int (*ah_validate)(); /* validate varifier */ + int (*ah_refresh)(); /* refresh credentials */ + void (*ah_destroy)(); /* destroy this structure */ + } *ah_ops; + caddr_t ah_private; +} AUTH; + + +/* + * Authentication ops. + * The ops and the auth handle provide the interface to the authenticators. + * + * AUTH *auth; + * XDR *xdrs; + * struct opaque_auth verf; + */ +#define AUTH_NEXTVERF(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) +#define auth_nextverf(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) + +#define AUTH_MARSHALL(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) +#define auth_marshall(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) + +#define AUTH_VALIDATE(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) +#define auth_validate(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) + +#define AUTH_REFRESH(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) +#define auth_refresh(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) + +#define AUTH_DESTROY(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) +#define auth_destroy(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) + + +extern struct opaque_auth _null_auth; + + +/* + * These are the various implementations of client side authenticators. + */ + +/* + * Unix style authentication + * AUTH *authunix_create(machname, uid, gid, len, aup_gids) + * char *machname; + * int uid; + * int gid; + * int len; + * int *aup_gids; + */ +extern AUTH *authunix_create(); +extern AUTH *authunix_create_default(); /* takes no parameters */ +extern AUTH *authnone_create(); /* takes no parameters */ +extern AUTH *authdes_create(); + +#define AUTH_NONE 0 /* no authentication */ +#define AUTH_NULL 0 /* backward compatibility */ +#define AUTH_UNIX 1 /* unix style (uid, gids) */ +#define AUTH_SHORT 2 /* short hand unix style */ +#define AUTH_DES 3 /* des style (encrypted timestamps) */ + +#endif /* RPC_AUTH_H */ diff --git a/cpukit/librpc/include/rpc/clnt.h b/cpukit/librpc/include/rpc/clnt.h new file mode 100644 index 0000000000..faefdb5d50 --- /dev/null +++ b/cpukit/librpc/include/rpc/clnt.h @@ -0,0 +1,336 @@ +#ifndef RPC_CLNT_H +#define RPC_CLNT_H + +/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * clnt.h - Client side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _CLNT_ +#define _CLNT_ + +/* + * Rpc calls return an enum clnt_stat. This should be looked at more, + * since each implementation is required to live with this (implementation + * independent) list of errors. + */ +enum clnt_stat { + RPC_SUCCESS=0, /* call succeeded */ + /* + * local errors + */ + RPC_CANTENCODEARGS=1, /* can't encode arguments */ + RPC_CANTDECODERES=2, /* can't decode results */ + RPC_CANTSEND=3, /* failure in sending call */ + RPC_CANTRECV=4, /* failure in receiving result */ + RPC_TIMEDOUT=5, /* call timed out */ + /* + * remote errors + */ + RPC_VERSMISMATCH=6, /* rpc versions not compatible */ + RPC_AUTHERROR=7, /* authentication error */ + RPC_PROGUNAVAIL=8, /* program not available */ + RPC_PROGVERSMISMATCH=9, /* program version mismatched */ + RPC_PROCUNAVAIL=10, /* procedure unavailable */ + RPC_CANTDECODEARGS=11, /* decode arguments error */ + RPC_SYSTEMERROR=12, /* generic "other problem" */ + + /* + * callrpc & clnt_create errors + */ + RPC_UNKNOWNHOST=13, /* unknown host name */ + RPC_UNKNOWNPROTO=17, /* unkown protocol */ + + /* + * _ create errors + */ + RPC_PMAPFAILURE=14, /* the pmapper failed in its call */ + RPC_PROGNOTREGISTERED=15, /* remote program is not registered */ + /* + * unspecified error + */ + RPC_FAILED=16 +}; + + +/* + * Error info. + */ +struct rpc_err { + enum clnt_stat re_status; + union { + int RE_errno; /* realated system error */ + enum auth_stat RE_why; /* why the auth error occurred */ + struct { + u_long low; /* lowest verion supported */ + u_long high; /* highest verion supported */ + } RE_vers; + struct { /* maybe meaningful if RPC_FAILED */ + long s1; + long s2; + } RE_lb; /* life boot & debugging only */ + } ru; +#define re_errno ru.RE_errno +#define re_why ru.RE_why +#define re_vers ru.RE_vers +#define re_lb ru.RE_lb +}; + + +/* + * Client rpc handle. + * Created by individual implementations, see e.g. rpc_udp.c. + * Client is responsible for initializing auth, see e.g. auth_none.c. + */ +typedef struct { + AUTH *cl_auth; /* authenticator */ + struct clnt_ops { + enum clnt_stat (*cl_call)(); /* call remote procedure */ + void (*cl_abort)(); /* abort a call */ + void (*cl_geterr)(); /* get specific error code */ + bool_t (*cl_freeres)(); /* frees results */ + void (*cl_destroy)();/* destroy this structure */ + bool_t (*cl_control)();/* the ioctl() of rpc */ + } *cl_ops; + caddr_t cl_private; /* private stuff */ +} CLIENT; + + +/* + * client side rpc interface ops + * + * Parameter types are: + * + */ + +/* + * enum clnt_stat + * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) + * CLIENT *rh; + * u_long proc; + * xdrproc_t xargs; + * caddr_t argsp; + * xdrproc_t xres; + * caddr_t resp; + * struct timeval timeout; + */ +#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) +#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) + +/* + * void + * CLNT_ABORT(rh); + * CLIENT *rh; + */ +#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) +#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) + +/* + * struct rpc_err + * CLNT_GETERR(rh); + * CLIENT *rh; + */ +#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) +#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) + + +/* + * bool_t + * CLNT_FREERES(rh, xres, resp); + * CLIENT *rh; + * xdrproc_t xres; + * caddr_t resp; + */ +#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) +#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) + +/* + * bool_t + * CLNT_CONTROL(cl, request, info) + * CLIENT *cl; + * u_int request; + * char *info; + */ +#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) +#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) + +/* + * control operations that apply to both udp and tcp transports + */ +#define CLSET_TIMEOUT 1 /* set timeout (timeval) */ +#define CLGET_TIMEOUT 2 /* get timeout (timeval) */ +#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */ +/* + * udp only control operations + */ +#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ +#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ + +/* + * void + * CLNT_DESTROY(rh); + * CLIENT *rh; + */ +#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) +#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) + + +/* + * RPCTEST is a test program which is accessable on every rpc + * transport/port. It is used for testing, performance evaluation, + * and network administration. + */ + +#define RPCTEST_PROGRAM ((u_long)1) +#define RPCTEST_VERSION ((u_long)1) +#define RPCTEST_NULL_PROC ((u_long)2) +#define RPCTEST_NULL_BATCH_PROC ((u_long)3) + +/* + * By convention, procedure 0 takes null arguments and returns them + */ + +#define NULLPROC ((u_long)0) + +/* + * Below are the client handle creation routines for the various + * implementations of client side rpc. They can return NULL if a + * creation failure occurs. + */ + +/* + * Memory based rpc (for speed check and testing) + * CLIENT * + * clntraw_create(prog, vers) + * u_long prog; + * u_long vers; + */ +extern CLIENT *clntraw_create(); + + +/* + * Generic client creation routine. Supported protocols are "udp" and "tcp" + */ +extern CLIENT * +clnt_create(/*host, prog, vers, prot*/); /* + char *host; -- hostname + u_long prog; -- program number + u_long vers; -- version number + char *prot; -- protocol +*/ + + + + +/* + * TCP based rpc + * CLIENT * + * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clnttcp_create(); + +/* + * UDP based rpc. + * CLIENT * + * clntudp_create(raddr, program, version, wait, sockp) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait; + * int *sockp; + * + * Same as above, but you specify max packet sizes. + * CLIENT * + * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait; + * int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clntudp_create(); +extern CLIENT *clntudp_bufcreate(); + +/* + * Print why creation failed + */ +void clnt_pcreateerror(/* char *msg */); /* stderr */ +char *clnt_spcreateerror(/* char *msg */); /* string */ + +/* + * Like clnt_perror(), but is more verbose in its output + */ +void clnt_perrno(/* enum clnt_stat num */); /* stderr */ + +/* + * Print an English error message, given the client error code + */ +void clnt_perror(/* CLIENT *clnt, char *msg */); /* stderr */ +char *clnt_sperror(/* CLIENT *clnt, char *msg */); /* string */ + +/* + * If a creation fails, the following allows the user to figure out why. + */ +struct rpc_createerr { + enum clnt_stat cf_stat; + struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ +}; + +extern struct rpc_createerr rpc_createerr; + + + +/* + * Copy error message to buffer. + */ +char *clnt_sperrno(/* enum clnt_stat num */); /* string */ + + + +#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ +#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ + +#endif /*!_CLNT_*/ + +#endif /* RPC_CLNT_H */ diff --git a/cpukit/librpc/include/rpc/rpc.h b/cpukit/librpc/include/rpc/rpc.h new file mode 100644 index 0000000000..0a0affd82a --- /dev/null +++ b/cpukit/librpc/include/rpc/rpc.h @@ -0,0 +1,86 @@ +#ifndef RPC_H +#define RPC_H + +/* @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC; from 1.9 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * rpc.h, Just includes the billions of rpc header files necessary to + * do remote procedure calling. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +#ifndef __RPC_HEADER__ +#define __RPC_HEADER__ + +#include /* some typedefs */ +#include +#include + +/* external data representation interfaces */ +#include /* generic (de)serializer */ + +/* Client side only authentication */ +#include /* generic authenticator (client side) */ + +/* Client side (mostly) remote procedure call */ +#include /* generic rpc stuff */ + +/* semi-private protocol headers */ +#include /* protocol for rpc messages */ +/*#include "auth_unix.h" * protocol for unix style cred */ +/* + * Uncomment-out the next line if you are building the rpc library with + * DES Authentication (see the README file in the secure_rpc/ directory). + */ +/*#include "auth_des.h" * protocol for des style cred */ + +/* Server side only remote procedure callee */ +#include /* service manager and multiplexer */ +#include /* service side authenticator */ + +/* + * COMMENT OUT THE NEXT INCLUDE (or add to the #ifndef) IF RUNNING ON + * A VERSION OF UNIX THAT USES SUN'S NFS SOURCE. These systems will + * already have the structures defined by included in . + */ +/* routines for parsing /etc/rpc */ + +struct rpcent { + char *r_name; /* name of server for this rpc program */ + char **r_aliases; /* alias list */ + int r_number; /* rpc program number */ +}; + +struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent(); + +#endif /* ndef __RPC_HEADER__ */ + +#endif /* RPC_H */ diff --git a/cpukit/librpc/include/rpc/rpc_msg.h b/cpukit/librpc/include/rpc/rpc_msg.h new file mode 100644 index 0000000000..2f34fb614c --- /dev/null +++ b/cpukit/librpc/include/rpc/rpc_msg.h @@ -0,0 +1,192 @@ +#ifndef RPC_MSG_H +#define RPC_MSG_H + +/* @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)rpc_msg.h 1.7 86/07/16 SMI */ + +/* + * rpc_msg.h + * rpc message definition + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define RPC_MSG_VERSION ((u_long) 2) +#define RPC_SERVICE_PORT ((u_short) 2048) + +/* + * Bottom up definition of an rpc message. + * NOTE: call and reply use the same overall stuct but + * different parts of unions within it. + */ + +enum msg_type { + CALL=0, + REPLY=1 +}; + +enum reply_stat { + MSG_ACCEPTED=0, + MSG_DENIED=1 +}; + +enum accept_stat { + SUCCESS=0, + PROG_UNAVAIL=1, + PROG_MISMATCH=2, + PROC_UNAVAIL=3, + GARBAGE_ARGS=4, + SYSTEM_ERR=5 +}; + +enum reject_stat { + RPC_MISMATCH=0, + AUTH_ERROR=1 +}; + +/* + * Reply part of an rpc exchange + */ + +/* + * Reply to an rpc request that was accepted by the server. + * Note: there could be an error even though the request was + * accepted. + */ +struct accepted_reply { + struct opaque_auth ar_verf; + enum accept_stat ar_stat; + union { + struct { + u_long low; + u_long high; + } AR_versions; + struct { + caddr_t where; + xdrproc_t proc; + } AR_results; + /* and many other null cases */ + } ru; +#define ar_results ru.AR_results +#define ar_vers ru.AR_versions +}; + +/* + * Reply to an rpc request that was rejected by the server. + */ +struct rejected_reply { + enum reject_stat rj_stat; + union { + struct { + u_long low; + u_long high; + } RJ_versions; + enum auth_stat RJ_why; /* why authentication did not work */ + } ru; +#define rj_vers ru.RJ_versions +#define rj_why ru.RJ_why +}; + +/* + * Body of a reply to an rpc request. + */ +struct reply_body { + enum reply_stat rp_stat; + union { + struct accepted_reply RP_ar; + struct rejected_reply RP_dr; + } ru; +#define rp_acpt ru.RP_ar +#define rp_rjct ru.RP_dr +}; + +/* + * Body of an rpc request call. + */ +struct call_body { + u_long cb_rpcvers; /* must be equal to two */ + u_long cb_prog; + u_long cb_vers; + u_long cb_proc; + struct opaque_auth cb_cred; + struct opaque_auth cb_verf; /* protocol specific - provided by client */ +}; + +/* + * The rpc message + */ +struct rpc_msg { + u_long rm_xid; + enum msg_type rm_direction; + union { + struct call_body RM_cmb; + struct reply_body RM_rmb; + } ru; +#define rm_call ru.RM_cmb +#define rm_reply ru.RM_rmb +}; +#define acpted_rply ru.RM_rmb.ru.RP_ar +#define rjcted_rply ru.RM_rmb.ru.RP_dr + + +/* + * XDR routine to handle a rpc message. + * xdr_callmsg(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callmsg(); + +/* + * XDR routine to pre-serialize the static part of a rpc message. + * xdr_callhdr(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callhdr(); + +/* + * XDR routine to handle a rpc reply. + * xdr_replymsg(xdrs, rmsg) + * XDR *xdrs; + * struct rpc_msg *rmsg; + */ +extern bool_t xdr_replymsg(); + +/* + * Fills in the error part of a reply message. + * _seterr_reply(msg, error) + * struct rpc_msg *msg; + * struct rpc_err *error; + */ +extern void _seterr_reply(); + +#endif /* RPC_MSG_H */ diff --git a/cpukit/librpc/include/rpc/svc.h b/cpukit/librpc/include/rpc/svc.h new file mode 100644 index 0000000000..c576b5538b --- /dev/null +++ b/cpukit/librpc/include/rpc/svc.h @@ -0,0 +1,291 @@ + +#ifndef RPC_SVC_H +#define RPC_SVC_H + +/* @(#)svc.h 2.2 88/07/29 4.0 RPCSRC; from 1.20 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc.h, Server-side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef __SVC_HEADER__ +#define __SVC_HEADER__ + +/* + * This interface must manage two items concerning remote procedure calling: + * + * 1) An arbitrary number of transport connections upon which rpc requests + * are received. The two most notable transports are TCP and UDP; they are + * created and registered by routines in svc_tcp.c and svc_udp.c, respectively; + * they in turn call xprt_register and xprt_unregister. + * + * 2) An arbitrary number of locally registered services. Services are + * described by the following four data: program number, version number, + * "service dispatch" function, a transport handle, and a boolean that + * indicates whether or not the exported program should be registered with a + * local binder service; if true the program's number and version and the + * port number from the transport handle are registered with the binder. + * These data are registered with the rpc svc system via svc_register. + * + * A service's dispatch function is called whenever an rpc request comes in + * on a transport. The request's program and version numbers must match + * those of the registered service. The dispatch function is passed two + * parameters, struct svc_req * and SVCXPRT *, defined below. + */ + +enum xprt_stat { + XPRT_DIED, + XPRT_MOREREQS, + XPRT_IDLE +}; + +/* + * Server side transport handle + */ +typedef struct { + int xp_sock; + u_short xp_port; /* associated port number */ + struct xp_ops { + bool_t (*xp_recv)(); /* receive incomming requests */ + enum xprt_stat (*xp_stat)(); /* get transport status */ + bool_t (*xp_getargs)(); /* get arguments */ + bool_t (*xp_reply)(); /* send reply */ + bool_t (*xp_freeargs)();/* free mem allocated for args */ + void (*xp_destroy)(); /* destroy this struct */ + } *xp_ops; + int xp_addrlen; /* length of remote address */ + struct sockaddr_in xp_raddr; /* remote address */ + struct opaque_auth xp_verf; /* raw response verifier */ + caddr_t xp_p1; /* private */ + caddr_t xp_p2; /* private */ +} SVCXPRT; + +/* + * Approved way of getting address of caller + */ +#define svc_getcaller(x) (&(x)->xp_raddr) + +/* + * Operations defined on an SVCXPRT handle + * + * SVCXPRT *xprt; + * struct rpc_msg *msg; + * xdrproc_t xargs; + * caddr_t argsp; + */ +#define SVC_RECV(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) +#define svc_recv(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) + +#define SVC_STAT(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) +#define svc_stat(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) + +#define SVC_GETARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) +#define svc_getargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) + +#define SVC_REPLY(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) +#define svc_reply(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) + +#define SVC_FREEARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) +#define svc_freeargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) + +#define SVC_DESTROY(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) +#define svc_destroy(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) + + +/* + * Service request + */ +struct svc_req { + u_long rq_prog; /* service program number */ + u_long rq_vers; /* service protocol version */ + u_long rq_proc; /* the desired procedure */ + struct opaque_auth rq_cred; /* raw creds from the wire */ + caddr_t rq_clntcred; /* read only cooked cred */ + SVCXPRT *rq_xprt; /* associated transport */ +}; + + +/* + * Service registration + * + * svc_register(xprt, prog, vers, dispatch, protocol) + * SVCXPRT *xprt; + * u_long prog; + * u_long vers; + * void (*dispatch)(); + * int protocol; (like TCP or UDP, zero means do not register) + */ +extern bool_t svc_register(); + +/* + * Service un-registration + * + * svc_unregister(prog, vers) + * u_long prog; + * u_long vers; + */ +extern void svc_unregister(); + +/* + * Transport registration. + * + * xprt_register(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_register(); + +/* + * Transport un-register + * + * xprt_unregister(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_unregister(); + + + + +/* + * When the service routine is called, it must first check to see if it + * knows about the procedure; if not, it should call svcerr_noproc + * and return. If so, it should deserialize its arguments via + * SVC_GETARGS (defined above). If the deserialization does not work, + * svcerr_decode should be called followed by a return. Successful + * decoding of the arguments should be followed the execution of the + * procedure's code and a call to svc_sendreply. + * + * Also, if the service refuses to execute the procedure due to too- + * weak authentication parameters, svcerr_weakauth should be called. + * Note: do not confuse access-control failure with weak authentication! + * + * NB: In pure implementations of rpc, the caller always waits for a reply + * msg. This message is sent when svc_sendreply is called. + * Therefore pure service implementations should always call + * svc_sendreply even if the function logically returns void; use + * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows + * for the abuse of pure rpc via batched calling or pipelining. In the + * case of a batched call, svc_sendreply should NOT be called since + * this would send a return message, which is what batching tries to avoid. + * It is the service/protocol writer's responsibility to know which calls are + * batched and which are not. Warning: responding to batch calls may + * deadlock the caller and server processes! + */ + +extern bool_t svc_sendreply(); +extern void svcerr_decode(); +extern void svcerr_weakauth(); +extern void svcerr_noproc(); +extern void svcerr_progvers(); +extern void svcerr_auth(); +extern void svcerr_noprog(); +extern void svcerr_systemerr(); + +/* + * Lowest level dispatching -OR- who owns this process anyway. + * Somebody has to wait for incoming requests and then call the correct + * service routine. The routine svc_run does infinite waiting; i.e., + * svc_run never returns. + * Since another (co-existant) package may wish to selectively wait for + * incoming calls or other events outside of the rpc architecture, the + * routine svc_getreq is provided. It must be passed readfds, the + * "in-place" results of a select system call (see select, section 2). + */ + +/* + * Global keeper of rpc service descriptors in use + * dynamic; must be inspected before each call to select + */ +#ifdef FD_SETSIZE +extern fd_set svc_fdset; +#define svc_fds svc_fdset.fds_bits[0] /* compatibility */ +#else +extern int svc_fds; +#endif /* def FD_SETSIZE */ + +/* + * a small program implemented by the svc_rpc implementation itself; + * also see clnt.h for protocol numbers. + */ +extern void rpctest_service(); + +extern void svc_getreq(); +extern void svc_getreqset(); /* takes fdset instead of int */ +extern void svc_run(); /* never returns */ + +/* + * Socket to use on svcxxx_create call to get default socket + */ +#define RPC_ANYSOCK -1 + +/* + * These are the existing service side transport implementations + */ + +/* + * Memory based rpc for testing and timing. + */ +extern SVCXPRT *svcraw_create(); + +/* + * Udp based rpc. + */ +extern SVCXPRT *svcudp_create(); +extern SVCXPRT *svcudp_bufcreate(); +extern int svcudp_enablecache(SVCXPRT *transp, u_long size); + +/* + * Tcp based rpc. + */ +extern SVCXPRT *svctcp_create(); + + + +#endif /* !__SVC_HEADER__ */ + +extern int _rpcsvccount; +extern int _rpcsvcstate; +extern int _SERVED; + +#endif /* RPC_SVC_H */ diff --git a/cpukit/librpc/include/rpc/svc_auth.h b/cpukit/librpc/include/rpc/svc_auth.h new file mode 100644 index 0000000000..5c233a6a47 --- /dev/null +++ b/cpukit/librpc/include/rpc/svc_auth.h @@ -0,0 +1,47 @@ +#ifndef RPC_SVC_AUTH_H +#define RPC_SVC_AUTH_H + +/* @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)svc_auth.h 1.6 86/07/16 SMI */ + +/* + * svc_auth.h, Service side of rpc authentication. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + + +/* + * Server side authenticator + */ +extern enum auth_stat _authenticate(); + +#endif /* SVC_AUTH_H */ diff --git a/cpukit/librpc/include/rpc/types.h b/cpukit/librpc/include/rpc/types.h new file mode 100644 index 0000000000..b6d7eb3ccc --- /dev/null +++ b/cpukit/librpc/include/rpc/types.h @@ -0,0 +1,75 @@ +#ifndef RPC_TYPES_H +#define RPC_TYPES_H + +/* @(#)types.h 2.3 88/08/15 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)types.h 1.18 87/07/24 SMI */ + +/* + * Rpc additions to + */ +#ifndef __TYPES_RPC_HEADER__ +#define __TYPES_RPC_HEADER__ + +/*#include */ +typedef unsigned long u_int32; /* 32-bit unsigned integers */ + +#define bool_t int +#define enum_t int +#ifndef FALSE +# define FALSE (0) +#endif +#ifndef TRUE +# define TRUE (1) +#endif +#define __dontcare__ -1 +#ifndef NULL +# define NULL 0 +#endif + +void *malloc(); +#define mem_alloc(bsize) malloc(bsize) +#define mem_free(ptr, bsize) free(ptr) + +#ifndef makedev /* ie, we haven't already included it */ +#include +#endif +#include + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK (u_long)0x7F000001 +#endif +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#endif /* ndef __TYPES_RPC_HEADER__ */ + +#endif /* RPC_TYPES_H */ diff --git a/cpukit/librpc/include/rpc/xdr.h b/cpukit/librpc/include/rpc/xdr.h new file mode 100644 index 0000000000..ef2df51d93 --- /dev/null +++ b/cpukit/librpc/include/rpc/xdr.h @@ -0,0 +1,275 @@ +#ifndef RPC_XDR_H +#define RPC_XDR_H + +/* @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)xdr.h 1.19 87/04/22 SMI */ + +/* + * xdr.h, External Data Representation Serialization Routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef __XDR_HEADER__ +#define __XDR_HEADER__ + +/* + * XDR provides a conventional way for converting between C data + * types and an external bit-string representation. Library supplied + * routines provide for the conversion on built-in C data types. These + * routines and utility routines defined here are used to help implement + * a type encode/decode routine for each user-defined type. + * + * Each data type provides a single procedure which takes two arguments: + * + * bool_t + * xdrproc(xdrs, argresp) + * XDR *xdrs; + * *argresp; + * + * xdrs is an instance of a XDR handle, to which or from which the data + * type is to be converted. argresp is a pointer to the structure to be + * converted. The XDR handle contains an operation field which indicates + * which of the operations (ENCODE, DECODE * or FREE) is to be performed. + * + * XDR_DECODE may allocate space if the pointer argresp is null. This + * data can be freed with the XDR_FREE operation. + * + * We write only one procedure per data type to make it easy + * to keep the encode and decode procedures for a data type consistent. + * In many cases the same code performs all operations on a user defined type, + * because all the hard work is done in the component type routines. + * decode as a series of calls on the nested data types. + */ + +/* + * Xdr operations. XDR_ENCODE causes the type to be encoded into the + * stream. XDR_DECODE causes the type to be extracted from the stream. + * XDR_FREE can be used to release the space allocated by an XDR_DECODE + * request. + */ +enum xdr_op { + XDR_ENCODE=0, + XDR_DECODE=1, + XDR_FREE=2 +}; + +/* + * This is the number of bytes per unit of external data. + */ +#define BYTES_PER_XDR_UNIT (4) +#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ + * BYTES_PER_XDR_UNIT) + +/* + * A xdrproc_t exists for each data type which is to be encoded or decoded. + * + * The second argument to the xdrproc_t is a pointer to an opaque pointer. + * The opaque pointer generally points to a structure of the data type + * to be decoded. If this pointer is 0, then the type routines should + * allocate dynamic storage of the appropriate size and return it. + * bool_t (*xdrproc_t)(XDR *, caddr_t *); + */ +typedef bool_t (*xdrproc_t)(); + +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the paticular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular impelementation. + */ +typedef struct { + enum xdr_op x_op; /* operation; fast additional param */ + struct xdr_ops { + bool_t (*x_getlong)(); /* get a long from underlying stream */ + bool_t (*x_putlong)(); /* put a long to " */ + bool_t (*x_getbytes)();/* get some bytes from " */ + bool_t (*x_putbytes)();/* put some bytes to " */ + u_int (*x_getpostn)();/* returns bytes off from beginning */ + bool_t (*x_setpostn)();/* lets you reposition the stream */ + long * (*x_inline)(); /* buf quick ptr to buffered data */ + void (*x_destroy)(); /* free privates of this xdr_stream */ + } *x_ops; + caddr_t x_public; /* users' data */ + caddr_t x_private; /* pointer to private data */ + caddr_t x_base; /* private used for position info */ + int x_handy; /* extra private word */ +} XDR; + +/* + * Operations defined on a XDR handle + * + * XDR *xdrs; + * long *longp; + * caddr_t addr; + * u_int len; + * u_int pos; + */ +#define XDR_GETLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) +#define xdr_getlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) + +#define XDR_PUTLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) +#define xdr_putlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) + +#define XDR_GETBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) +#define xdr_getbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) + +#define XDR_PUTBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) +#define xdr_putbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) + +#define XDR_GETPOS(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) +#define xdr_getpos(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) + +#define XDR_SETPOS(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) +#define xdr_setpos(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) + +#define XDR_INLINE(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) +#define xdr_inline(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) + +#define XDR_DESTROY(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) +#define xdr_destroy(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) + +/* + * Support struct for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * a entry with a null procedure pointer. The xdr_union routine gets + * the discriminant value and then searches the array of structures + * for a matching value. If a match is found the associated xdr routine + * is called to handle that part of the union. If there is + * no match, then a default routine may be called. + * If there is no match and no default routine it is an error. + */ +#define NULL_xdrproc_t ((xdrproc_t)0) +struct xdr_discrim { + int value; + xdrproc_t proc; +}; + +/* + * In-line routines for fast encode/decode of primitve data types. + * Caveat emptor: these use single memory cycles to get the + * data from the underlying buffer, and will fail to operate + * properly if the data is not aligned. The standard way to use these + * is to say: + * if ((buf = XDR_INLINE(xdrs, count)) == NULL) + * return (FALSE); + * <<< macro calls >>> + * where ``count'' is the number of bytes of data occupied + * by the primitive data types. + * + * N.B. and frozen for all time: each data type here uses 4 bytes + * of external representation. + */ +#define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*(buf)++)) +#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((u_long)v)) + +#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) +#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) +#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) + +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) + +/* + * These are the "generic" xdr routines. + */ +extern bool_t xdr_void(); +extern bool_t xdr_int(); +extern bool_t xdr_u_int(); +extern bool_t xdr_long(); +extern bool_t xdr_u_long(); +extern bool_t xdr_short(); +extern bool_t xdr_u_short(); +extern bool_t xdr_bool(); +extern bool_t xdr_enum(); +extern bool_t xdr_array(); +extern bool_t xdr_bytes(); +extern bool_t xdr_opaque(); +extern bool_t xdr_string(); +extern bool_t xdr_union(); +extern bool_t xdr_char(); +extern bool_t xdr_u_char(); +extern bool_t xdr_vector(); +extern bool_t xdr_float(); +extern bool_t xdr_double(); +extern bool_t xdr_reference(); +extern bool_t xdr_pointer(); +extern bool_t xdr_wrapstring(); + +/* + * Common opaque bytes objects used by many rpc protocols; + * declared here due to commonality. + */ +#define MAX_NETOBJ_SZ 1024 +struct netobj { + u_int n_len; + char *n_bytes; +}; +typedef struct netobj netobj; +extern bool_t xdr_netobj(); + +/* + * These are the public routines for the various implementations of + * xdr streams. + */ +extern void xdrmem_create(); /* XDR using memory buffers */ +extern void xdrstdio_create(); /* XDR using stdio library */ +extern void xdrrec_create(); /* XDR pseudo records for tcp */ +extern bool_t xdrrec_endofrecord(); /* make end of xdr record */ +extern bool_t xdrrec_skiprecord(); /* move to beginning of next record */ +extern bool_t xdrrec_eof(); /* true if no more input */ + +#endif /* !__XDR_HEADER__ */ + +#endif /* RPC_XDR_H */ diff --git a/make/custom/default.cfg b/make/custom/default.cfg index dcb7a92c3a..d8c56518d2 100644 --- a/make/custom/default.cfg +++ b/make/custom/default.cfg @@ -71,6 +71,13 @@ else HAS_NETWORKING=no endif +# Define this to yes if this target wants the remote debugger +ifeq ($(RTEMS_HAS_RDBG),yes) +HAS_RDBG=yes +else +HAS_RDBG=no +endif + # Define this to yes if this target wants the posix api ifeq ($(RTEMS_HAS_POSIX_API),yes) HAS_POSIX_API=yes diff --git a/make/target.cfg.in b/make/target.cfg.in index 2da16b15cc..9042611d58 100644 --- a/make/target.cfg.in +++ b/make/target.cfg.in @@ -43,6 +43,7 @@ RTEMS_HAS_MULTIPROCESSING = @RTEMS_HAS_MULTIPROCESSING@ RTEMS_HAS_POSIX_API = @RTEMS_HAS_POSIX_API@ RTEMS_HAS_POSIX_1H_API = @RTEMS_HAS_POSIX_1H_API@ RTEMS_HAS_NETWORKING = @RTEMS_HAS_NETWORKING@ +RTEMS_HAS_RDBG = @RTEMS_HAS_RDBG@ RTEMS_HAS_CPLUSPLUS = @RTEMS_HAS_CPLUSPLUS@ RTEMS_USE_MACROS = @RTEMS_USE_MACROS@ RTEMS_USE_GCC272 = @RTEMS_USE_GCC272@ -- cgit v1.2.3