/*
* Copyright (c) 2005-2006 Institute for System Programming
* Russian Academy of Sciences
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Portions of this text are reprinted and reproduced in electronic form
* from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology
* -- Portable Operating System Interface (POSIX), The Open Group Base
* Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
* Electrical and Electronics Engineers, Inc and The Open Group. In the
* event of any discrepancy between this version and the original IEEE and
* The Open Group Standard, the original IEEE and The Open Group Standard
* is the referee document. The original Standard can be obtained online at
* http://www.opengroup.org/unix/online.html.
*/
#include "socket/rpc/svc_model.seh"
#include "process/process/process_model.seh"
#pragma SEC subsystem rpc "socket.rpc"
/*
The group of functions 'socket.rpc.svc' consists of:
svc_getreqset [2]
svcerr_auth [2]
svcerr_decode [2]
svcerr_noproc [2]
svcerr_noprog [2]
svcerr_progvers [2]
svcerr_systemerr [2]
svcerr_weakauth [2]
svc_register [3]
svc_run [3]
svc_sendreply [3]
svctcp_create [3]
svcudp_create [3]
*/
/********************************************************************/
/** Interface Functions **/
/********************************************************************/
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
refers
System V Interface Definition, Fourth Edition
FINAL COPY June 15, 1995
Copyright (c) 1983, 1984, 1985, 1986,1987, 1988, 1995 Novell, Inc.
SYNOPSIS
#include <rpc/rpc.h>
extern void svc_getreqset(fd_set *);
extern void svcerr_auth(SVCXPRT *, enum auth_stat);
extern void svcerr_decode(SVCXPRT *);
extern void svcerr_noproc(SVCXPRT *);
extern void svcerr_noprog(SVCXPRT *);
extern void svcerr_progvers(SVCXPRT *, rpcvers_t, rpcvers_t);
extern void svcerr_systemerr(SVCXPRT *);
extern void svcerr_weakauth(SVCXPRT *);
#define svc_freeargs(xprt,xargs, argsp) \
(*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
#define svc_getargs(xprt,xargs, argsp) \
(*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
DESCRIPTION
void
svc_getreqset(fd_set *rdfds);
This routine is only of interest if a service implementor does not call
svc_run(), but instead implements custom asynchronous event processing. It is
called when poll() has determined that an RPC request has arrived on some RPC
file descriptors; rdfds is the resultant read file descriptor bit mask. The
routine returns when all file descriptors associated with the value of rdfds
have been serviced
void
svcerr_auth(const SVCXPRT *xprt, const enum auth_stat why);
Called by a service dispatch routine that refuses to perform a remote procedure
call due to an authentication error.
void
svcerr_decode(const SVCXPRT *xprt);
Called by a service dispatch routine that cannot successfully decode the
remote parameters [see svc_getargs() in rpc_svc_reg(RS_LIB)].
void
svcerr_noproc(const SVCXPRT *xprt);
Called by a service dispatch routine that does not implement the procedure
number that the caller requests.
void
svcerr_noprog(const SVCXPRT *xprt);
Called when the desired program is not registered with the RPC package.
Service implementors usually do not need this routine.
void
svcerr_progvers(const SVCXPRT *xprt);
Called when the desired version of a program is not registered with the RPC
package. Service implementors usually do not need this routine.
void
svcerr_systemerr(const SVCXPRT *xprt);
Called by a service dispatch routine when it detects a system error not
covered by any particular protocol. For example, if a service can no longer
allocate storage, it may call this routine.
void
svcerr_weakauth(const SVCXPRT *xprt);
Called by a service dispatch routine that refuses to perform a remote procedure
call due to insufficient (but correct) authentication parameters. The routine
calls svcerr_auth(xprt, AUTH_TOOWEAK).
bool_t
svc_freeargs(const SVCXPRT *xprt, const xdrproc_t inproc, char *in);
A function macro that frees any data allocated by the RPC/XDR system when it
decoded the arguments to a service procedure using svc_getargs(). This routine
returns 1 if the results were successfully freed, and 0 otherwise.
bool_t
svc_getargs(const SVCXPRT *xprt, const xdrproc_t inproc, char *in);
A function macro that decodes the arguments of an RPC request associated with
the RPC service transport handle xprt. The parameter in is the address where
the arguments will be placed; inproc is the XDR routine used to decode the
arguments. This routine returns 1 if decoding succeeds, and 0 otherwise.
*/
specification
void svc_getreqset_spec(CallContext context, FdSetTPtr rdfds)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* This routine is only of interest if a service implementor does not call
* svc_run(), but instead implements custom asynchronous event processing.
*/
REQ("svc_getreqset.01", "", TODO_REQ());
/*
* It is called when poll() has determined that an RPC request has arrived on some
* RPC file descriptors;
*/
REQ("svc_getreqset.02", "", TODO_REQ());
/*
* The routine returns when all file descriptors associated with the value of
* rdfds have been serviced
*/
REQ("svc_getreqset.03", "", TODO_REQ());
return true;
}
}
specification
void svcerr_auth_spec(CallContext context, SvcXprtTPtr xprt, enum AuthStatT why)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* Called by a service dispatch routine that refuses to perform a remote procedure
* call due to an authentication error.
*/
REQ("svcerr_auth.01", "", TODO_REQ());
return true;
}
}
specification
void svcerr_decode_spec(CallContext context, SvcXprtTPtr xprt)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* Called by a service dispatch routine that cannot successfully decode the remote
* parameters [see svc_getargs() in rpc_svc_reg(RS_LIB)].
*/
REQ("svcerr_decode.01", "", TODO_REQ());
return true;
}
}
specification
void svcerr_noproc_spec(CallContext context, SvcXprtTPtr xprt)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* Called by a service dispatch routine that does not implement the procedure
* number that the caller requests.
*/
REQ("svcerr_noproc.01", "", TODO_REQ());
return true;
}
}
specification
void svcerr_noprog_spec(CallContext context, SvcXprtTPtr xprt)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* Called when the desired program is not registered with the RPC package.
*/
REQ("svcerr_noprog.01", "", TODO_REQ());
return true;
}
}
specification
void svcerr_progvers_spec(CallContext context, SvcXprtTPtr xprt, RpcVersT low_vers, RpcVersT high_vers)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* Called when the desired version of a program is not registered with the RPC
* package.
*/
REQ("svcerr_progvers.01", "", TODO_REQ());
return true;
}
}
specification
void svcerr_systemerr_spec(CallContext context, SvcXprtTPtr xprt)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* Called by a service dispatch routine when it detects a system error not covered
* by any particular protocol. For example, if a service can no longer allocate
* storage, it may call this routine.
*/
REQ("svcerr_systemerr.01", "", TODO_REQ());
return true;
}
}
specification
void svcerr_weakauth_spec(CallContext context, SvcXprtTPtr xprt)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* Called by a service dispatch routine that refuses to perform a remote procedure
* call due to insufficient (but correct) authentication parameters.
*/
REQ("svcerr_weakauth.01", "", TODO_REQ());
/*
* The routine calls svcerr_auth(xprt, AUTH_TOOWEAK).
*/
REQ("svcerr_weakauth.02", "", TODO_REQ());
return true;
}
}
specification
BoolT svc_freeargs_spec(CallContext context, SvcXprtTPtr xprt, XdrProcTPtr inproc, CharTPtr in)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
return true;
}
}
specification
BoolT svc_getargs_spec(CallContext context, SvcXprtTPtr xprt, XdrProcTPtr inproc, CharTPtr in)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
return true;
}
}
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
svc_register -- register Remote Procedure Call interface
SYNOPSIS
#include <rpc/rpc.h>
bool_t svc_register(SVCXPRT * xprt, rpcprog_t prognum, rpcvers_t versnum, __dispatch_fn_t dispatch, rpcprot_t protocol);
DESCRIPTION
The svc_register() function shall associate the program identified by prognum
at version versnum with the service dispatch procedure, dispatch. If protocol
is zero, the service is not registered with the portmap service. If protocol is
non-zero, then a mapping of the triple [prognum, versnum, protocol] to xprt->
xp_port is established with the local portmap service.
The procedure dispatch has the following form:
int dispatch(struct svc_req * request, SVCXPRT * xprt);
RETURN VALUE
svc_register() returns 1 if it succeeds, and zero otherwise.
*/
specification
BoolT svc_register_spec(CallContext context, SvcXprtTPtr xprt, RpcProgT prog, RpcVersT vers, DispatchFnTPtr dispatch, RpcProtT protocol)
{
pre
{
/*
* The procedure dispatch has the following form:
* int dispatch(struct svc_req * request, SVCXPRT * xprt);
*/
REQ("app.svc_register.04", "", TODO_REQ());
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* The svc_register() function shall associate the program identified by prognum
* at version versnum with the service dispatch procedure, dispatch.
*/
REQ("svc_register.01", "", TODO_REQ());
/*
* If protocol is zero, the service is not registered with the portmap service.
*/
REQ("svc_register.02", "", TODO_REQ());
/*
* If protocol is non-zero, then a mapping of the triple [prognum, versnum,
* protocol] to xprt->xp_port is established with the local portmap service.
*/
REQ("svc_register.03", "", TODO_REQ());
/*
* svc_register() returns 1 if it succeeds,
*/
REQ("svc_register.05", "", TODO_REQ());
/*
* and zero otherwise.
*/
REQ("svc_register.06", "", TODO_REQ());
return true;
}
}
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
svc_run -- waits for RPC requests to arrive and calls service procedure
SYNOPSIS
#include <rpc/svc.h>
void svc_run(void);
DESCRIPTION
The svc_run() function shall wait for RPC requests to arrive, read and unpack
each request, and dispatch it to the appropriate registered handler. Under
normal conditions, svc_run() shall not return; it shall only return if serious
errors occur that prevent further processing.
*/
specification
void svc_run_spec(CallContext context)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
return true;
}
}
void onSvcRun(CallContext context)
{
startBlockedCall(context, create_IntTObj(0));
}
reaction SvcRunReturnType* svc_run_return(void)
{
post
{
verbose("svc_run STOPPED!\n");
/*
* The svc_run() function shall wait for RPC requests to arrive, read and unpack
* each request, and dispatch it to the appropriate registered handler.
*/
REQ("svc_run.01", "", TODO_REQ());
/*
* it shall only return if serious errors occur that prevent further processing.
*/
REQ("svc_run.03", "", TODO_REQ());
return true;
}
}
void onSvcRunReturn(CallContext context)
{
finishBlockedCall(context);
}
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
svc_sendreply -- called by RPC service's dispatch routine
SYNOPSIS
bool_t svc_sendreply(SVCXPRT *xprt, xdrproc_t outproc, caddr_t out);
DESCRIPTION
Called by an RPC service's dispatch routine to send the results of a remote
procedure call. The parameter xprt is the request's associated transport handle;
outproc is the XDR routine which is used to encode the results; and out is the
address of the results. This routine returns one if it succeeds, zero other-
wise.
*/
specification
BoolT svc_sendreply_spec(CallContext context, SvcXprtTPtr xprt, XdrProcTPtr outproc, CaddrT out)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* This routine returns one if it succeeds,
*/
REQ("svc_sendreply.01", "", TODO_REQ());
/*
* zero other-wise.
*/
REQ("svc_sendreply.02", "", TODO_REQ());
return true;
}
}
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
svctcp_create -- create a TCP/IP-based RPC service transport
SYNOPSIS
#include <rpc/rpc.h>
SVCXPRT * svctcp_create(int sock, u_int send_buf_size, u_int recv_buf_size);
DESCRIPTION
svctcp_create() cretes a TCP/IP-based RPC service transport, to which it
returns a pointer. The transport is associated with the socket sock, which may
be RPC_ANYSOCK, in which case a new socket is created. If the socket is not
bound to a local TCP port, then this routine binds it to an arbitrary port.
Upon completion, xprt->xp_sock is the transport's socket descriptor, and
xprt->xp_port is the transport's port number. Since TCP-based RPC uses
buffered I/O, users may specify the size of buffers; values of zero choose
suitable defaults.
RETURN VALUE
svctcp_create() returns NULL if it fails, or a pointer to the RPC service
transport otherwise.
*/
specification
SvcXprtTPtr svctcp_create_spec(CallContext context, IntT sock, UIntT sendsize, UIntT recvsize)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* svctcp_create() cretes a TCP/IP-based RPC service transport, to which it
* returns a pointer.
*/
REQ("svctcp_create.01", "", TODO_REQ());
/*
* The transport is associated with the socket sock
*/
REQ("svctcp_create.02", "", TODO_REQ());
/*
* which may be RPC_ANYSOCK, in which case a new socket is created.
*/
REQ("svctcp_create.03", "", TODO_REQ());
/*
* If the socket is not bound to a local TCP port, then this routine binds it to
* an arbitrary port.
*/
REQ("svctcp_create.04", "", TODO_REQ());
/*
* Upon completion, xprt->xp_sock is the transport's socket descriptor,
*/
REQ("svctcp_create.05", "", TODO_REQ());
/*
* and xprt->xp_port is the transport's port number.
*/
REQ("svctcp_create.06", "", TODO_REQ());
/*
* Since TCP-based RPC uses buffered I/O, users may specify the size of buffers;
* values of zero choose suitable defaults.
*/
REQ("svctcp_create.07", "", TODO_REQ());
/*
* svctcp_create() returns NULL if it fails,
*/
REQ("svctcp_create.08", "", TODO_REQ());
/*
* or a pointer to the RPC service transport otherwise.
*/
REQ("svctcp_create.09", "", TODO_REQ());
return true;
}
}
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group
NAME
svcudp_create -- create a UDP-based RPC service transport
SYNOPSIS
SVCXPRT * svcudp_create(int sock);
DESCRIPTION
This call is equivalent to svcudp_bufcreate( sock, SZ, SZ) for some default
size SZ.
*/
specification
SvcXprtTPtr svcudp_create_spec(CallContext context, IntT sock)
{
pre
{
return true;
}
coverage C
{
return {TheOnlyBranch, "The only branch"};
}
post
{
/*
* This call is equivalent to svcudp_bufcreate( sock, SZ, SZ) for some default
* size SZ.
*/
REQ("svcudp_create.01", "", TODO_REQ());
return true;
}
}
/********************************************************************/
/** Svc Types **/
/********************************************************************/
specification typedef struct SvcRunReturnType SvcRunReturnType = {};
SvcRunReturnType *create_SvcRunReturnType(
CallContext context
)
{
return create(&type_SvcRunReturnType, context);
}
/********************************************************************/
/** Helper Functions **/
/********************************************************************/