#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sdt.h>
#include <rpcsvc/nlm_prot.h>
#include "nlm_impl.h"
typedef bool_t (*nlm_svc_func_t)(void *, void *, struct svc_req *);
typedef void (*nlm_freeres_func_t)(void *);
struct dispatch_entry {
nlm_svc_func_t de_svc;
xdrproc_t de_xargs;
xdrproc_t de_xres;
nlm_freeres_func_t de_resfree;
int de_ressz;
uint_t de_flags;
};
#define NLM_DISP_NOREMOTE 1
#define NLM_SVC_FUNC(func) (nlm_svc_func_t)func
#define NLM_FREERES_FUNC(func) (nlm_freeres_func_t)func
static bool_t
nlm_null_svc(void *args, void *resp, struct svc_req *sr)
{
return (TRUE);
}
void
nlm_dispatch(
struct svc_req *rqstp,
SVCXPRT *transp,
const struct dispatch_entry *de)
{
union {
nlm_cancargs au_cancargs;
nlm_lockargs au_lockargs;
nlm_notify au_notify;
nlm_res au_res;
nlm_shareargs au_shareargs;
nlm_sm_status au_sm_status;
nlm_testargs au_testargs;
nlm_testres au_testres;
nlm_unlockargs au_unlockargs;
nlm4_cancargs au_cancargs4;
nlm4_lockargs au_lockargs4;
nlm4_notify au_notify4;
nlm4_res au_res4;
nlm4_shareargs au_shareargs4;
nlm4_testargs au_testargs4;
nlm4_testres au_testres4;
nlm4_unlockargs au_unlockargs4;
} argu;
void *args = &argu;
union {
int ru_int;
nlm_res ru_res;
nlm_shareres ru_shareres;
nlm_testres ru_testres;
nlm4_res ru_res4;
nlm4_shareres ru_shareres4;
nlm4_testres ru_testres4;
} resu;
void *res = &resu;
nlm_svc_func_t func;
bool_t do_reply = FALSE;
bool_t dupcached = FALSE;
struct dupreq *dr;
int dupstat;
if ((func = de->de_svc) == NULL) {
svcerr_noproc(transp);
return;
}
if ((de->de_flags & NLM_DISP_NOREMOTE) &&
!nlm_caller_is_local(transp)) {
svcerr_noproc(transp);
return;
}
bzero(&argu, sizeof (argu));
if (!SVC_GETARGS(transp, de->de_xargs, args)) {
svcerr_decode(transp);
return;
}
dupstat = SVC_DUP_EXT(transp, rqstp, res, de->de_ressz, &dr,
&dupcached);
switch (dupstat) {
case DUP_ERROR:
svcerr_systemerr(transp);
break;
case DUP_INPROGRESS:
break;
case DUP_NEW:
case DUP_DROP:
curthread->t_flag |= T_DONTPEND;
bzero(&resu, sizeof (resu));
do_reply = (*func)(args, res, rqstp);
curthread->t_flag &= ~T_DONTPEND;
if (curthread->t_flag & T_WOULDBLOCK) {
curthread->t_flag &= ~T_WOULDBLOCK;
SVC_DUPDONE_EXT(transp, dr, res, NULL,
de->de_ressz, DUP_DROP);
do_reply = FALSE;
break;
}
SVC_DUPDONE_EXT(transp, dr, res, de->de_resfree,
de->de_ressz, DUP_DONE);
dupcached = TRUE;
break;
case DUP_DONE:
if (de->de_xres != NULL_xdrproc_t) {
do_reply = TRUE;
}
break;
}
if (do_reply) {
ASSERT(de->de_xres != NULL_xdrproc_t);
DTRACE_PROBE3(sendreply, struct svc_req *, rqstp,
SVCXPRT *, transp, struct dispatch_entry *, de);
if (!svc_sendreply(transp, de->de_xres, res)) {
svcerr_systemerr(transp);
NLM_ERR("nlm_dispatch(): svc_sendreply() failed!\n");
}
if (!dupcached) {
xdr_free(de->de_xres, res);
}
}
if (!SVC_FREEARGS(transp, de->de_xargs, args))
NLM_WARN("nlm_dispatch(): unable to free arguments");
}
static void
nlm_res_free(nlm_res *resp)
{
xdr_free(xdr_nlm_res, (char *)resp);
}
static void
nlm_shareres_free(nlm_shareres *resp)
{
xdr_free(xdr_nlm_shareres, (char *)resp);
}
static void
nlm_testres_free(nlm_testres *resp)
{
xdr_free(xdr_nlm_testres, (char *)resp);
}
static void
nlm4_res_free(nlm4_res *resp)
{
xdr_free(xdr_nlm4_res, (char *)resp);
}
static void
nlm4_shareres_free(nlm4_shareres *resp)
{
xdr_free(xdr_nlm4_shareres, (char *)resp);
}
static void
nlm4_testres_free(nlm4_testres *resp)
{
xdr_free(xdr_nlm4_testres, (char *)resp);
}
static const struct dispatch_entry
nlm_prog_3_dtable[] = {
{
NLM_SVC_FUNC(nlm_null_svc),
(xdrproc_t)xdr_void,
(xdrproc_t)xdr_void,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_test_1_svc),
(xdrproc_t)xdr_nlm_testargs,
(xdrproc_t)xdr_nlm_testres,
NLM_FREERES_FUNC(nlm_testres_free),
sizeof (nlm_testres),
0 },
{
NLM_SVC_FUNC(nlm_lock_1_svc),
(xdrproc_t)xdr_nlm_lockargs,
(xdrproc_t)xdr_nlm_res,
NLM_FREERES_FUNC(nlm_res_free),
sizeof (nlm_res),
0 },
{
NLM_SVC_FUNC(nlm_cancel_1_svc),
(xdrproc_t)xdr_nlm_cancargs,
(xdrproc_t)xdr_nlm_res,
NLM_FREERES_FUNC(nlm_res_free),
sizeof (nlm_res),
0 },
{
NLM_SVC_FUNC(nlm_unlock_1_svc),
(xdrproc_t)xdr_nlm_unlockargs,
(xdrproc_t)xdr_nlm_res,
NLM_FREERES_FUNC(nlm_res_free),
sizeof (nlm_res),
0 },
{
NLM_SVC_FUNC(nlm_granted_1_svc),
(xdrproc_t)xdr_nlm_testargs,
(xdrproc_t)xdr_nlm_res,
NLM_FREERES_FUNC(nlm_res_free),
sizeof (nlm_res),
0 },
{
NLM_SVC_FUNC(nlm_test_msg_1_svc),
(xdrproc_t)xdr_nlm_testargs,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_lock_msg_1_svc),
(xdrproc_t)xdr_nlm_lockargs,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_cancel_msg_1_svc),
(xdrproc_t)xdr_nlm_cancargs,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_unlock_msg_1_svc),
(xdrproc_t)xdr_nlm_unlockargs,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_granted_msg_1_svc),
(xdrproc_t)xdr_nlm_testargs,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_test_res_1_svc),
(xdrproc_t)xdr_nlm_testres,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_lock_res_1_svc),
(xdrproc_t)xdr_nlm_res,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_cancel_res_1_svc),
(xdrproc_t)xdr_nlm_res,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_unlock_res_1_svc),
(xdrproc_t)xdr_nlm_res,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_granted_res_1_svc),
(xdrproc_t)xdr_nlm_res,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(0),
(xdrproc_t)0,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_sm_notify1_2_svc),
(xdrproc_t)xdr_nlm_sm_status,
(xdrproc_t)xdr_void,
NULL,
0,
NLM_DISP_NOREMOTE },
{
NLM_SVC_FUNC(nlm_sm_notify2_2_svc),
(xdrproc_t)xdr_nlm_sm_status,
(xdrproc_t)xdr_void,
NULL,
0,
NLM_DISP_NOREMOTE },
{
NLM_SVC_FUNC(0),
(xdrproc_t)0,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm_share_3_svc),
(xdrproc_t)xdr_nlm_shareargs,
(xdrproc_t)xdr_nlm_shareres,
NLM_FREERES_FUNC(nlm_shareres_free),
sizeof (nlm_shareres),
0 },
{
NLM_SVC_FUNC(nlm_unshare_3_svc),
(xdrproc_t)xdr_nlm_shareargs,
(xdrproc_t)xdr_nlm_shareres,
NLM_FREERES_FUNC(nlm_shareres_free),
sizeof (nlm_shareres),
0 },
{
NLM_SVC_FUNC(nlm_nm_lock_3_svc),
(xdrproc_t)xdr_nlm_lockargs,
(xdrproc_t)xdr_nlm_res,
NLM_FREERES_FUNC(nlm_res_free),
sizeof (nlm_res),
0 },
{
NLM_SVC_FUNC(nlm_free_all_3_svc),
(xdrproc_t)xdr_nlm_notify,
(xdrproc_t)xdr_void,
NULL,
0,
0 },
};
static int nlm_prog_3_dtsize =
sizeof (nlm_prog_3_dtable) /
sizeof (nlm_prog_3_dtable[0]);
void
nlm_prog_3(struct svc_req *rqstp, register SVCXPRT *transp)
{
const struct dispatch_entry *de;
rpcproc_t max_proc;
switch (rqstp->rq_vers) {
case NLM_VERS:
max_proc = NLM_GRANTED_RES;
break;
case NLM_SM:
max_proc = NLM_SM_NOTIFY2;
break;
case NLM_VERSX:
max_proc = NLM_FREE_ALL;
break;
default:
ASSERT(0);
svcerr_noprog(transp);
return;
}
ASSERT(max_proc < nlm_prog_3_dtsize);
if (rqstp->rq_proc > max_proc) {
svcerr_noproc(transp);
return;
}
de = &nlm_prog_3_dtable[rqstp->rq_proc];
nlm_dispatch(rqstp, transp, de);
}
static const struct dispatch_entry
nlm_prog_4_dtable[] = {
{
NLM_SVC_FUNC(nlm_null_svc),
(xdrproc_t)xdr_void,
(xdrproc_t)xdr_void,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm4_test_4_svc),
(xdrproc_t)xdr_nlm4_testargs,
(xdrproc_t)xdr_nlm4_testres,
NLM_FREERES_FUNC(nlm4_testres_free),
sizeof (nlm4_testres),
0 },
{
NLM_SVC_FUNC(nlm4_lock_4_svc),
(xdrproc_t)xdr_nlm4_lockargs,
(xdrproc_t)xdr_nlm4_res,
NLM_FREERES_FUNC(nlm4_res_free),
sizeof (nlm4_res),
0 },
{
NLM_SVC_FUNC(nlm4_cancel_4_svc),
(xdrproc_t)xdr_nlm4_cancargs,
(xdrproc_t)xdr_nlm4_res,
NLM_FREERES_FUNC(nlm4_res_free),
sizeof (nlm4_res),
0 },
{
NLM_SVC_FUNC(nlm4_unlock_4_svc),
(xdrproc_t)xdr_nlm4_unlockargs,
(xdrproc_t)xdr_nlm4_res,
NLM_FREERES_FUNC(nlm4_res_free),
sizeof (nlm4_res),
0 },
{
NLM_SVC_FUNC(nlm4_granted_4_svc),
(xdrproc_t)xdr_nlm4_testargs,
(xdrproc_t)xdr_nlm4_res,
NLM_FREERES_FUNC(nlm4_res_free),
sizeof (nlm4_res),
0 },
{
NLM_SVC_FUNC(nlm4_test_msg_4_svc),
(xdrproc_t)xdr_nlm4_testargs,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm4_lock_msg_4_svc),
(xdrproc_t)xdr_nlm4_lockargs,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm4_cancel_msg_4_svc),
(xdrproc_t)xdr_nlm4_cancargs,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm4_unlock_msg_4_svc),
(xdrproc_t)xdr_nlm4_unlockargs,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm4_granted_msg_4_svc),
(xdrproc_t)xdr_nlm4_testargs,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm4_test_res_4_svc),
(xdrproc_t)xdr_nlm4_testres,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm4_lock_res_4_svc),
(xdrproc_t)xdr_nlm4_res,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm4_cancel_res_4_svc),
(xdrproc_t)xdr_nlm4_res,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm4_unlock_res_4_svc),
(xdrproc_t)xdr_nlm4_res,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm4_granted_res_4_svc),
(xdrproc_t)xdr_nlm4_res,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(0),
(xdrproc_t)0,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(0),
(xdrproc_t)0,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(0),
(xdrproc_t)0,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(0),
(xdrproc_t)0,
(xdrproc_t)0,
NULL,
0,
0 },
{
NLM_SVC_FUNC(nlm4_share_4_svc),
(xdrproc_t)xdr_nlm4_shareargs,
(xdrproc_t)xdr_nlm4_shareres,
NLM_FREERES_FUNC(nlm4_shareres_free),
sizeof (nlm4_shareres),
0 },
{
NLM_SVC_FUNC(nlm4_unshare_4_svc),
(xdrproc_t)xdr_nlm4_shareargs,
(xdrproc_t)xdr_nlm4_shareres,
NLM_FREERES_FUNC(nlm4_shareres_free),
sizeof (nlm4_shareres),
0 },
{
NLM_SVC_FUNC(nlm4_nm_lock_4_svc),
(xdrproc_t)xdr_nlm4_lockargs,
(xdrproc_t)xdr_nlm4_res,
NLM_FREERES_FUNC(nlm4_res_free),
sizeof (nlm4_res),
0 },
{
NLM_SVC_FUNC(nlm4_free_all_4_svc),
(xdrproc_t)xdr_nlm4_notify,
(xdrproc_t)xdr_void,
NULL,
0,
0 },
};
static int nlm_prog_4_dtsize =
sizeof (nlm_prog_4_dtable) /
sizeof (nlm_prog_4_dtable[0]);
void
nlm_prog_4(struct svc_req *rqstp, register SVCXPRT *transp)
{
const struct dispatch_entry *de;
if (rqstp->rq_vers != NLM4_VERS) {
ASSERT(0);
svcerr_noprog(transp);
return;
}
if (rqstp->rq_proc >= nlm_prog_4_dtsize) {
svcerr_noproc(transp);
return;
}
de = &nlm_prog_4_dtable[rqstp->rq_proc];
nlm_dispatch(rqstp, transp, de);
}