forked from Imagelibrary/rtems
Patch from Emmanuel Raguet <raguet@crf.canon.fr> 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.
This commit is contained in:
167
c/src/exec/librpc/include/rpc/auth.h
Normal file
167
c/src/exec/librpc/include/rpc/auth.h
Normal file
@@ -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 */
|
||||
336
c/src/exec/librpc/include/rpc/clnt.h
Normal file
336
c/src/exec/librpc/include/rpc/clnt.h
Normal file
@@ -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 */
|
||||
86
c/src/exec/librpc/include/rpc/rpc.h
Normal file
86
c/src/exec/librpc/include/rpc/rpc.h
Normal file
@@ -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 <rpc/types.h> /* some typedefs */
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/* external data representation interfaces */
|
||||
#include <rpc/xdr.h> /* generic (de)serializer */
|
||||
|
||||
/* Client side only authentication */
|
||||
#include <rpc/auth.h> /* generic authenticator (client side) */
|
||||
|
||||
/* Client side (mostly) remote procedure call */
|
||||
#include <rpc/clnt.h> /* generic rpc stuff */
|
||||
|
||||
/* semi-private protocol headers */
|
||||
#include <rpc/rpc_msg.h> /* 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 <rpc/svc.h> /* service manager and multiplexer */
|
||||
#include <rpc/svc_auth.h> /* 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 <rpc/netdb.h> included in <netdb.h>.
|
||||
*/
|
||||
/* 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 */
|
||||
192
c/src/exec/librpc/include/rpc/rpc_msg.h
Normal file
192
c/src/exec/librpc/include/rpc/rpc_msg.h
Normal file
@@ -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 */
|
||||
291
c/src/exec/librpc/include/rpc/svc.h
Normal file
291
c/src/exec/librpc/include/rpc/svc.h
Normal file
@@ -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 */
|
||||
47
c/src/exec/librpc/include/rpc/svc_auth.h
Normal file
47
c/src/exec/librpc/include/rpc/svc_auth.h
Normal file
@@ -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 */
|
||||
75
c/src/exec/librpc/include/rpc/types.h
Normal file
75
c/src/exec/librpc/include/rpc/types.h
Normal file
@@ -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 <sys/types.h>
|
||||
*/
|
||||
#ifndef __TYPES_RPC_HEADER__
|
||||
#define __TYPES_RPC_HEADER__
|
||||
|
||||
/*#include <network/types.h>*/
|
||||
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 <sys/types.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
|
||||
#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 */
|
||||
275
c/src/exec/librpc/include/rpc/xdr.h
Normal file
275
c/src/exec/librpc/include/rpc/xdr.h
Normal file
@@ -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;
|
||||
* <type> *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 */
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
53
c/src/lib/include/rdbg/i386/rdbg_f.h
Normal file
53
c/src/lib/include/rdbg/i386/rdbg_f.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component = RDBG
|
||||
* Module = rdbg_f.h
|
||||
*
|
||||
* Synopsis = Machine-dependent header file
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef RDBG_F_H
|
||||
#define RDBG_F_H
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rdbg/remdeb.h>
|
||||
|
||||
#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
|
||||
|
||||
|
||||
|
||||
32
c/src/lib/include/rdbg/i386/reg.h
Normal file
32
c/src/lib/include/rdbg/i386/reg.h
Normal file
@@ -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;
|
||||
|
||||
|
||||
|
||||
|
||||
53
c/src/lib/include/rdbg/rdbg.h
Normal file
53
c/src/lib/include/rdbg/rdbg.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component = RDBG
|
||||
*
|
||||
* Synopsis = rdbg.h
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef RDBG_H
|
||||
#define RDBG_H
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <rdbg/rdbg_f.h>
|
||||
#include <stdlib.h> /* For malloc() and free() prototypes */
|
||||
#include <bsp.h>
|
||||
|
||||
#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 */
|
||||
|
||||
268
c/src/lib/include/rdbg/servrpc.h
Normal file
268
c/src/lib/include/rdbg/servrpc.h
Normal file
@@ -0,0 +1,268 @@
|
||||
|
||||
#ifndef SERVRPC_H
|
||||
#define SERVRPC_H
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rdbg/remdeb.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/svc.h>
|
||||
|
||||
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 */
|
||||
|
||||
167
c/src/lib/include/rpc/auth.h
Normal file
167
c/src/lib/include/rpc/auth.h
Normal file
@@ -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 */
|
||||
336
c/src/lib/include/rpc/clnt.h
Normal file
336
c/src/lib/include/rpc/clnt.h
Normal file
@@ -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 */
|
||||
86
c/src/lib/include/rpc/rpc.h
Normal file
86
c/src/lib/include/rpc/rpc.h
Normal file
@@ -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 <rpc/types.h> /* some typedefs */
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/* external data representation interfaces */
|
||||
#include <rpc/xdr.h> /* generic (de)serializer */
|
||||
|
||||
/* Client side only authentication */
|
||||
#include <rpc/auth.h> /* generic authenticator (client side) */
|
||||
|
||||
/* Client side (mostly) remote procedure call */
|
||||
#include <rpc/clnt.h> /* generic rpc stuff */
|
||||
|
||||
/* semi-private protocol headers */
|
||||
#include <rpc/rpc_msg.h> /* 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 <rpc/svc.h> /* service manager and multiplexer */
|
||||
#include <rpc/svc_auth.h> /* 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 <rpc/netdb.h> included in <netdb.h>.
|
||||
*/
|
||||
/* 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 */
|
||||
192
c/src/lib/include/rpc/rpc_msg.h
Normal file
192
c/src/lib/include/rpc/rpc_msg.h
Normal file
@@ -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 */
|
||||
291
c/src/lib/include/rpc/svc.h
Normal file
291
c/src/lib/include/rpc/svc.h
Normal file
@@ -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 */
|
||||
47
c/src/lib/include/rpc/svc_auth.h
Normal file
47
c/src/lib/include/rpc/svc_auth.h
Normal file
@@ -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 */
|
||||
75
c/src/lib/include/rpc/types.h
Normal file
75
c/src/lib/include/rpc/types.h
Normal file
@@ -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 <sys/types.h>
|
||||
*/
|
||||
#ifndef __TYPES_RPC_HEADER__
|
||||
#define __TYPES_RPC_HEADER__
|
||||
|
||||
/*#include <network/types.h>*/
|
||||
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 <sys/types.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
|
||||
#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 */
|
||||
275
c/src/lib/include/rpc/xdr.h
Normal file
275
c/src/lib/include/rpc/xdr.h
Normal file
@@ -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;
|
||||
* <type> *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 */
|
||||
96
c/src/lib/librdbg/Makefile.in
Normal file
96
c/src/lib/librdbg/Makefile.in
Normal file
@@ -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) .
|
||||
|
||||
|
||||
|
||||
|
||||
360
c/src/lib/librdbg/_servtgt.c
Normal file
360
c/src/lib/librdbg/_servtgt.c
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
============================================================================
|
||||
_SERVTGT
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/rdbg_f.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <assert.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
|
||||
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;
|
||||
}
|
||||
65
c/src/lib/librdbg/awk.svc
Normal file
65
c/src/lib/librdbg/awk.svc
Normal file
@@ -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 <rpc/types.h>\n");
|
||||
printf("#include <rpc/rpc.h>\n");
|
||||
printf("#include <stdio.h>\n");
|
||||
printf("#include <stdlib.h>\n");
|
||||
printf("#include <string.h>\n");
|
||||
printf("#include <bsp.h>\n");
|
||||
printf("#include <rdbg/servrpc.h>\n");
|
||||
printf("#include <rdbg/%s>\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
|
||||
}
|
||||
}
|
||||
}
|
||||
233
c/src/lib/librdbg/i386/excep.c
Normal file
233
c/src/lib/librdbg/i386/excep.c
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component =
|
||||
*
|
||||
* Synopsis = rdbg/i386/excep.c
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
#include <rdbg/rdbg_f.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
58
c/src/lib/librdbg/i386/pc386/remdeb_f.x
Normal file
58
c/src/lib/librdbg/i386/pc386/remdeb_f.x
Normal file
@@ -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
|
||||
|
||||
|
||||
|
||||
70
c/src/lib/librdbg/i386/rdbg_cpu_asm.s
Normal file
70
c/src/lib/librdbg/i386/rdbg_cpu_asm.s
Normal file
@@ -0,0 +1,70 @@
|
||||
/* cpu_asm.s
|
||||
*
|
||||
* This file contains all assembly code for the Intel i386 implementation
|
||||
* of RDBG.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asm.h>
|
||||
|
||||
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
|
||||
130
c/src/lib/librdbg/i386/rdbg_f.c
Normal file
130
c/src/lib/librdbg/i386/rdbg_f.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component =
|
||||
*
|
||||
* Synopsis = rdbg/i386/rdbg_f.c
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <rdbg/reg.h>
|
||||
#include <rdbg/remdeb.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <rtems/score/thread.h>
|
||||
|
||||
|
||||
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-- ;
|
||||
}
|
||||
335
c/src/lib/librdbg/ptrace.c
Normal file
335
c/src/lib/librdbg/ptrace.c
Normal file
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component =
|
||||
*
|
||||
* Synopsis = rkdb/rkdb.c
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/rdbg_f.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
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;
|
||||
}
|
||||
139
c/src/lib/librdbg/rdbg.c
Normal file
139
c/src/lib/librdbg/rdbg.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component =
|
||||
*
|
||||
* Synopsis = rkdb/rkdb.c
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
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;
|
||||
}
|
||||
544
c/src/lib/librdbg/remdeb.x
Normal file
544
c/src/lib/librdbg/remdeb.x
Normal file
@@ -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 <THREADNAMEMAX>;
|
||||
|
||||
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 <NET_SAFE>; /* 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 <XRY_MAX_CMD_STR>;
|
||||
};
|
||||
|
||||
typedef string one_arg <NET_SAFE>;
|
||||
|
||||
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
|
||||
587
c/src/lib/librdbg/servbkpt.c
Normal file
587
c/src/lib/librdbg/servbkpt.c
Normal file
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* Component: RDB servers
|
||||
* Module: servbkpt.c
|
||||
*
|
||||
* Synopsis: Management of breakpoints
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#include <sys/errno.h>
|
||||
#include <assert.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
/*----- 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;
|
||||
}
|
||||
136
c/src/lib/librdbg/servcon.c
Normal file
136
c/src/lib/librdbg/servcon.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component: RDBG
|
||||
* Module: servcon.c
|
||||
*
|
||||
* Synopsis: Management of RPC client connections.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <sys/errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
}
|
||||
720
c/src/lib/librdbg/servrpc.c
Normal file
720
c/src/lib/librdbg/servrpc.c
Normal file
@@ -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 <string.h>
|
||||
#include <sys/errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/remdeb.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
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);
|
||||
}
|
||||
550
c/src/lib/librdbg/servtgt.c
Normal file
550
c/src/lib/librdbg/servtgt.c
Normal file
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component: RDB servers
|
||||
* Module: servtgt.c
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
#include <sys/socket.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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 */
|
||||
329
c/src/lib/librdbg/servtsp.c
Normal file
329
c/src/lib/librdbg/servtsp.c
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component: RDBG
|
||||
* Module: servtsp.c
|
||||
*
|
||||
* Synopsis: Transport management for remote debug server.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <sys/errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
#include <signal.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/svc.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
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 */
|
||||
}
|
||||
130
c/src/lib/librdbg/servutil.c
Normal file
130
c/src/lib/librdbg/servutil.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* Component: RDB
|
||||
* Module: servutil.c
|
||||
*
|
||||
* Synopsis: Various utility routines
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
/*----- 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 */
|
||||
49
c/src/lib/librpc/Makefile.in
Normal file
49
c/src/lib/librpc/Makefile.in
Normal file
@@ -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)
|
||||
|
||||
|
||||
191
c/src/lib/librpc/rpc_callmsg.c
Normal file
191
c/src/lib/librpc/rpc_callmsg.c
Normal file
@@ -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 <string.h> /* bcopy */
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
271
c/src/lib/librpc/rpc_prot.c
Normal file
271
c/src/lib/librpc/rpc_prot.c
Normal file
@@ -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 <rpc/rpc.h>
|
||||
|
||||
/* * * * * * * * * * * * * * 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;
|
||||
}
|
||||
}
|
||||
259
c/src/lib/librpc/svc.c
Normal file
259
c/src/lib/librpc/svc.c
Normal file
@@ -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 <rpc/rpc.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
*/
|
||||
122
c/src/lib/librpc/svc_auth.c
Normal file
122
c/src/lib/librpc/svc_auth.c
Normal file
@@ -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 <rpc/rpc.h>
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
476
c/src/lib/librpc/svc_udp.c
Normal file
476
c/src/lib/librpc/svc_udp.c
Normal file
@@ -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 <stdio.h> /* printf */
|
||||
#include <stdlib.h> /* free */
|
||||
#include <string.h> /* bzero, bcmp */
|
||||
#include <rpc/rpc.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
578
c/src/lib/librpc/xdr.c
Normal file
578
c/src/lib/librpc/xdr.c
Normal file
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
157
c/src/lib/librpc/xdr_array.c
Normal file
157
c/src/lib/librpc/xdr_array.c
Normal file
@@ -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 <stdio.h> /* printf */
|
||||
#include <string.h> /* bcmp */
|
||||
#include <stdlib.h> /* free */
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
185
c/src/lib/librpc/xdr_mem.c
Normal file
185
c/src/lib/librpc/xdr_mem.c
Normal file
@@ -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 <string.h> /* bcopy */
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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) \
|
||||
|
||||
53
c/src/librdbg/include/rdbg/i386/rdbg_f.h
Normal file
53
c/src/librdbg/include/rdbg/i386/rdbg_f.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component = RDBG
|
||||
* Module = rdbg_f.h
|
||||
*
|
||||
* Synopsis = Machine-dependent header file
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef RDBG_F_H
|
||||
#define RDBG_F_H
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rdbg/remdeb.h>
|
||||
|
||||
#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
|
||||
|
||||
|
||||
|
||||
32
c/src/librdbg/include/rdbg/i386/reg.h
Normal file
32
c/src/librdbg/include/rdbg/i386/reg.h
Normal file
@@ -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;
|
||||
|
||||
|
||||
|
||||
|
||||
53
c/src/librdbg/include/rdbg/rdbg.h
Normal file
53
c/src/librdbg/include/rdbg/rdbg.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component = RDBG
|
||||
*
|
||||
* Synopsis = rdbg.h
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef RDBG_H
|
||||
#define RDBG_H
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <rdbg/rdbg_f.h>
|
||||
#include <stdlib.h> /* For malloc() and free() prototypes */
|
||||
#include <bsp.h>
|
||||
|
||||
#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 */
|
||||
|
||||
268
c/src/librdbg/include/rdbg/servrpc.h
Normal file
268
c/src/librdbg/include/rdbg/servrpc.h
Normal file
@@ -0,0 +1,268 @@
|
||||
|
||||
#ifndef SERVRPC_H
|
||||
#define SERVRPC_H
|
||||
|
||||
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rdbg/remdeb.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/svc.h>
|
||||
|
||||
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 */
|
||||
|
||||
96
c/src/librdbg/src/Makefile.in
Normal file
96
c/src/librdbg/src/Makefile.in
Normal file
@@ -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) .
|
||||
|
||||
|
||||
|
||||
|
||||
360
c/src/librdbg/src/_servtgt.c
Normal file
360
c/src/librdbg/src/_servtgt.c
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
============================================================================
|
||||
_SERVTGT
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/rdbg_f.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <assert.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
|
||||
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;
|
||||
}
|
||||
65
c/src/librdbg/src/awk.svc
Normal file
65
c/src/librdbg/src/awk.svc
Normal file
@@ -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 <rpc/types.h>\n");
|
||||
printf("#include <rpc/rpc.h>\n");
|
||||
printf("#include <stdio.h>\n");
|
||||
printf("#include <stdlib.h>\n");
|
||||
printf("#include <string.h>\n");
|
||||
printf("#include <bsp.h>\n");
|
||||
printf("#include <rdbg/servrpc.h>\n");
|
||||
printf("#include <rdbg/%s>\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
|
||||
}
|
||||
}
|
||||
}
|
||||
58
c/src/librdbg/src/i386/any/remdeb_f.x
Normal file
58
c/src/librdbg/src/i386/any/remdeb_f.x
Normal file
@@ -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
|
||||
|
||||
|
||||
|
||||
233
c/src/librdbg/src/i386/excep.c
Normal file
233
c/src/librdbg/src/i386/excep.c
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component =
|
||||
*
|
||||
* Synopsis = rdbg/i386/excep.c
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
#include <rdbg/rdbg_f.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
58
c/src/librdbg/src/i386/pc386/remdeb_f.x
Normal file
58
c/src/librdbg/src/i386/pc386/remdeb_f.x
Normal file
@@ -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
|
||||
|
||||
|
||||
|
||||
70
c/src/librdbg/src/i386/rdbg_cpu_asm.s
Normal file
70
c/src/librdbg/src/i386/rdbg_cpu_asm.s
Normal file
@@ -0,0 +1,70 @@
|
||||
/* cpu_asm.s
|
||||
*
|
||||
* This file contains all assembly code for the Intel i386 implementation
|
||||
* of RDBG.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asm.h>
|
||||
|
||||
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
|
||||
130
c/src/librdbg/src/i386/rdbg_f.c
Normal file
130
c/src/librdbg/src/i386/rdbg_f.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component =
|
||||
*
|
||||
* Synopsis = rdbg/i386/rdbg_f.c
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <rdbg/reg.h>
|
||||
#include <rdbg/remdeb.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <rtems/score/thread.h>
|
||||
|
||||
|
||||
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-- ;
|
||||
}
|
||||
335
c/src/librdbg/src/ptrace.c
Normal file
335
c/src/librdbg/src/ptrace.c
Normal file
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component =
|
||||
*
|
||||
* Synopsis = rkdb/rkdb.c
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/rdbg_f.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
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;
|
||||
}
|
||||
139
c/src/librdbg/src/rdbg.c
Normal file
139
c/src/librdbg/src/rdbg.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component =
|
||||
*
|
||||
* Synopsis = rkdb/rkdb.c
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
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;
|
||||
}
|
||||
544
c/src/librdbg/src/remdeb.x
Normal file
544
c/src/librdbg/src/remdeb.x
Normal file
@@ -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 <THREADNAMEMAX>;
|
||||
|
||||
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 <NET_SAFE>; /* 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 <XRY_MAX_CMD_STR>;
|
||||
};
|
||||
|
||||
typedef string one_arg <NET_SAFE>;
|
||||
|
||||
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
|
||||
587
c/src/librdbg/src/servbkpt.c
Normal file
587
c/src/librdbg/src/servbkpt.c
Normal file
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* Component: RDB servers
|
||||
* Module: servbkpt.c
|
||||
*
|
||||
* Synopsis: Management of breakpoints
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#include <sys/errno.h>
|
||||
#include <assert.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
/*----- 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;
|
||||
}
|
||||
136
c/src/librdbg/src/servcon.c
Normal file
136
c/src/librdbg/src/servcon.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component: RDBG
|
||||
* Module: servcon.c
|
||||
*
|
||||
* Synopsis: Management of RPC client connections.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <sys/errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
}
|
||||
720
c/src/librdbg/src/servrpc.c
Normal file
720
c/src/librdbg/src/servrpc.c
Normal file
@@ -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 <string.h>
|
||||
#include <sys/errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/remdeb.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
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);
|
||||
}
|
||||
550
c/src/librdbg/src/servtgt.c
Normal file
550
c/src/librdbg/src/servtgt.c
Normal file
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component: RDB servers
|
||||
* Module: servtgt.c
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
#include <sys/socket.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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 */
|
||||
329
c/src/librdbg/src/servtsp.c
Normal file
329
c/src/librdbg/src/servtsp.c
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
**************************************************************************
|
||||
*
|
||||
* Component: RDBG
|
||||
* Module: servtsp.c
|
||||
*
|
||||
* Synopsis: Transport management for remote debug server.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <sys/errno.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
#include <signal.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/svc.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
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 */
|
||||
}
|
||||
130
c/src/librdbg/src/servutil.c
Normal file
130
c/src/librdbg/src/servutil.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* Component: RDB
|
||||
* Module: servutil.c
|
||||
*
|
||||
* Synopsis: Various utility routines
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <rdbg/rdbg.h>
|
||||
#include <rdbg/servrpc.h>
|
||||
|
||||
/*----- 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 */
|
||||
167
c/src/librpc/include/rpc/auth.h
Normal file
167
c/src/librpc/include/rpc/auth.h
Normal file
@@ -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 */
|
||||
336
c/src/librpc/include/rpc/clnt.h
Normal file
336
c/src/librpc/include/rpc/clnt.h
Normal file
@@ -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 */
|
||||
86
c/src/librpc/include/rpc/rpc.h
Normal file
86
c/src/librpc/include/rpc/rpc.h
Normal file
@@ -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 <rpc/types.h> /* some typedefs */
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/* external data representation interfaces */
|
||||
#include <rpc/xdr.h> /* generic (de)serializer */
|
||||
|
||||
/* Client side only authentication */
|
||||
#include <rpc/auth.h> /* generic authenticator (client side) */
|
||||
|
||||
/* Client side (mostly) remote procedure call */
|
||||
#include <rpc/clnt.h> /* generic rpc stuff */
|
||||
|
||||
/* semi-private protocol headers */
|
||||
#include <rpc/rpc_msg.h> /* 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 <rpc/svc.h> /* service manager and multiplexer */
|
||||
#include <rpc/svc_auth.h> /* 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 <rpc/netdb.h> included in <netdb.h>.
|
||||
*/
|
||||
/* 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 */
|
||||
192
c/src/librpc/include/rpc/rpc_msg.h
Normal file
192
c/src/librpc/include/rpc/rpc_msg.h
Normal file
@@ -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 */
|
||||
291
c/src/librpc/include/rpc/svc.h
Normal file
291
c/src/librpc/include/rpc/svc.h
Normal file
@@ -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 */
|
||||
47
c/src/librpc/include/rpc/svc_auth.h
Normal file
47
c/src/librpc/include/rpc/svc_auth.h
Normal file
@@ -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 */
|
||||
75
c/src/librpc/include/rpc/types.h
Normal file
75
c/src/librpc/include/rpc/types.h
Normal file
@@ -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 <sys/types.h>
|
||||
*/
|
||||
#ifndef __TYPES_RPC_HEADER__
|
||||
#define __TYPES_RPC_HEADER__
|
||||
|
||||
/*#include <network/types.h>*/
|
||||
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 <sys/types.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
|
||||
#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 */
|
||||
275
c/src/librpc/include/rpc/xdr.h
Normal file
275
c/src/librpc/include/rpc/xdr.h
Normal file
@@ -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;
|
||||
* <type> *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 */
|
||||
49
c/src/librpc/src/Makefile.in
Normal file
49
c/src/librpc/src/Makefile.in
Normal file
@@ -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)
|
||||
|
||||
|
||||
191
c/src/librpc/src/rpc_callmsg.c
Normal file
191
c/src/librpc/src/rpc_callmsg.c
Normal file
@@ -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 <string.h> /* bcopy */
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
271
c/src/librpc/src/rpc_prot.c
Normal file
271
c/src/librpc/src/rpc_prot.c
Normal file
@@ -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 <rpc/rpc.h>
|
||||
|
||||
/* * * * * * * * * * * * * * 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;
|
||||
}
|
||||
}
|
||||
259
c/src/librpc/src/svc.c
Normal file
259
c/src/librpc/src/svc.c
Normal file
@@ -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 <rpc/rpc.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
*/
|
||||
122
c/src/librpc/src/svc_auth.c
Normal file
122
c/src/librpc/src/svc_auth.c
Normal file
@@ -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 <rpc/rpc.h>
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
476
c/src/librpc/src/svc_udp.c
Normal file
476
c/src/librpc/src/svc_udp.c
Normal file
@@ -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 <stdio.h> /* printf */
|
||||
#include <stdlib.h> /* free */
|
||||
#include <string.h> /* bzero, bcmp */
|
||||
#include <rpc/rpc.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
578
c/src/librpc/src/xdr.c
Normal file
578
c/src/librpc/src/xdr.c
Normal file
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
157
c/src/librpc/src/xdr_array.c
Normal file
157
c/src/librpc/src/xdr_array.c
Normal file
@@ -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 <stdio.h> /* printf */
|
||||
#include <string.h> /* bcmp */
|
||||
#include <stdlib.h> /* free */
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
185
c/src/librpc/src/xdr_mem.c
Normal file
185
c/src/librpc/src/xdr_mem.c
Normal file
@@ -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 <string.h> /* bcopy */
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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) \
|
||||
|
||||
Reference in New Issue
Block a user