Пример #1
0
static int32_t *
svc_clts_kgetres(SVCXPRT *clone_xprt, int size)
{
	/* LINTED pointer alignment */
	struct udp_data *ud = (struct udp_data *)clone_xprt->xp_p2buf;
	XDR *xdrs = &clone_xprt->xp_xdrout;
	mblk_t *mp;
	int32_t *buf;
	struct rpc_msg rply;

	/*
	 * Allocate an initial mblk for the response data.
	 */
	while ((mp = allocb(UD_INITSIZE, BPRI_LO)) == NULL) {
		if (strwaitbuf(UD_INITSIZE, BPRI_LO)) {
			return (FALSE);
		}
	}

	mp->b_cont = NULL;

	/*
	 * Initialize the XDR decode stream.  Additional mblks
	 * will be allocated if necessary.  They will be UD_MAXSIZE
	 * sized.
	 */
	xdrmblk_init(xdrs, mp, XDR_ENCODE, UD_MAXSIZE);

	/*
	 * Leave some space for protocol headers.
	 */
	(void) XDR_SETPOS(xdrs, 512);
	mp->b_rptr += 512;

	/*
	 * Assume a successful RPC since most of them are.
	 */
	rply.rm_xid = clone_xprt->xp_xid;
	rply.rm_direction = REPLY;
	rply.rm_reply.rp_stat = MSG_ACCEPTED;
	rply.acpted_rply.ar_verf = clone_xprt->xp_verf;
	rply.acpted_rply.ar_stat = SUCCESS;

	if (!xdr_replymsg_hdr(xdrs, &rply)) {
		freeb(mp);
		return (NULL);
	}

	buf = XDR_INLINE(xdrs, size);

	if (buf == NULL)
		freeb(mp);
	else
		ud->ud_resp->b_cont = mp;

	return (buf);
}
Пример #2
0
static int
nd_get_reply(TIUSER *tiptr, XDR *xdrp, uint32_t call_xid, int *badmsg)
{
	static struct rpc_msg		reply_msg;
	static struct rpc_err		rpc_err;
	static struct nfsattrstat	na;
	static struct WRITE3res		wres;
	static struct t_kunitdata	rudata;
	int				uderr;
	int				type;
	int				error;

	*badmsg = 0;

	rudata.addr.maxlen = 0;
	rudata.opt.maxlen = 0;
	rudata.udata.udata_mp = (mblk_t *)NULL;

	nd_log("nfs_dump: calling t_krcvudata\n");

	if (error = t_krcvudata(tiptr, &rudata, &type, &uderr)) {
		if (error == EBADMSG) {
			cmn_err(CE_WARN, "\tnfs_dump:  received EBADMSG");
			*badmsg = 1;
			return (0);
		}
		nfs_perror(error, "\nnfs_dump: t_krcvudata failed: %m\n");
		return (EIO);
	}
	if (type != T_DATA) {
		cmn_err(CE_WARN, "\tnfs_dump:  received type %d", type);
		*badmsg = 1;
		return (0);
	}
	if (!rudata.udata.udata_mp) {
		cmn_err(CE_WARN, "\tnfs_dump: null receive");
		*badmsg = 1;
		return (0);
	}

	/*
	 * Decode results.
	 */
	xdrmblk_init(xdrp, rudata.udata.udata_mp, XDR_DECODE, 0);

	reply_msg.acpted_rply.ar_verf = _null_auth;
	switch (nfsdump_version) {
	case NFS_VERSION:
		reply_msg.acpted_rply.ar_results.where = (caddr_t)&na;
		reply_msg.acpted_rply.ar_results.proc = xdr_attrstat;
		break;
	case NFS_V3:
		reply_msg.acpted_rply.ar_results.where = (caddr_t)&wres;
		reply_msg.acpted_rply.ar_results.proc = xdr_WRITE3res;
		break;
	default:
		XDR_DESTROY(xdrp);
		return (EIO);
	}

	if (!xdr_replymsg(xdrp, &reply_msg)) {
		XDR_DESTROY(xdrp);
		cmn_err(CE_WARN, "\tnfs_dump: xdr_replymsg failed");
		return (EIO);
	}

	if (reply_msg.rm_xid != call_xid) {
		XDR_DESTROY(xdrp);
		*badmsg = 1;
		return (0);
	}

	_seterr_reply(&reply_msg, &rpc_err);

	if (rpc_err.re_status != RPC_SUCCESS) {
		XDR_DESTROY(xdrp);
		cmn_err(CE_WARN, "\tnfs_dump: RPC error %d (%s)",
		    rpc_err.re_status, clnt_sperrno(rpc_err.re_status));
		return (EIO);
	}

	switch (nfsdump_version) {
	case NFS_VERSION:
		if (na.ns_status) {
			XDR_DESTROY(xdrp);
			cmn_err(CE_WARN, "\tnfs_dump: status %d", na.ns_status);
			return (EIO);
		}
		break;
	case NFS_V3:
		if (wres.status != NFS3_OK) {
			XDR_DESTROY(xdrp);
			cmn_err(CE_WARN, "\tnfs_dump: status %d", wres.status);
			return (EIO);
		}
		break;
	default:
		XDR_DESTROY(xdrp);
		return (EIO);
	}

	if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
		/* free auth handle */
		xdrp->x_op = XDR_FREE;
		(void) xdr_opaque_auth(xdrp, &(reply_msg.acpted_rply.ar_verf));
	}

	XDR_DESTROY(xdrp);

	freemsg(rudata.udata.udata_mp);

	return (0);
}
Пример #3
0
/*
 * Send rpc reply.
 * Serialize the reply packet into the output buffer then
 * call t_ksndudata to send it.
 */
static bool_t
svc_clts_ksend(SVCXPRT *clone_xprt, struct rpc_msg *msg)
{
	/* LINTED pointer alignment */
	struct udp_data *ud = (struct udp_data *)clone_xprt->xp_p2buf;
	XDR *xdrs = &clone_xprt->xp_xdrout;
	int stat = FALSE;
	mblk_t *mp;
	int msgsz;
	struct T_unitdata_req *udreq;
	xdrproc_t xdr_results;
	caddr_t xdr_location;
	bool_t has_args;

	TRACE_0(TR_FAC_KRPC, TR_SVC_CLTS_KSEND_START,
	    "svc_clts_ksend_start:");

	ASSERT(ud->ud_resp != NULL);

	/*
	 * If there is a result procedure specified in the reply message,
	 * it will be processed in the xdr_replymsg and SVCAUTH_WRAP.
	 * We need to make sure it won't be processed twice, so we null
	 * it for xdr_replymsg here.
	 */
	has_args = FALSE;
	if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
		msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
		if ((xdr_results = msg->acpted_rply.ar_results.proc) != NULL) {
			has_args = TRUE;
			xdr_location = msg->acpted_rply.ar_results.where;
			msg->acpted_rply.ar_results.proc = xdr_void;
			msg->acpted_rply.ar_results.where = NULL;
		}
	}

	if (ud->ud_resp->b_cont == NULL) {
		/*
		 * Allocate an initial mblk for the response data.
		 */
		while ((mp = allocb(UD_INITSIZE, BPRI_LO)) == NULL) {
			if (strwaitbuf(UD_INITSIZE, BPRI_LO)) {
				TRACE_1(TR_FAC_KRPC, TR_SVC_CLTS_KSEND_END,
				    "svc_clts_ksend_end:(%S)", "strwaitbuf");
				return (FALSE);
			}
		}

		/*
		 * Initialize the XDR decode stream.  Additional mblks
		 * will be allocated if necessary.  They will be UD_MAXSIZE
		 * sized.
		 */
		xdrmblk_init(xdrs, mp, XDR_ENCODE, UD_MAXSIZE);

		/*
		 * Leave some space for protocol headers.
		 */
		(void) XDR_SETPOS(xdrs, 512);
		mp->b_rptr += 512;

		msg->rm_xid = clone_xprt->xp_xid;

		ud->ud_resp->b_cont = mp;

		TRACE_0(TR_FAC_KRPC, TR_XDR_REPLYMSG_START,
		    "xdr_replymsg_start:");
		if (!(xdr_replymsg(xdrs, msg) &&
			(!has_args || SVCAUTH_WRAP(&clone_xprt->xp_auth, xdrs,
				xdr_results, xdr_location)))) {
			TRACE_1(TR_FAC_KRPC, TR_XDR_REPLYMSG_END,
			    "xdr_replymsg_end:(%S)", "bad");
			RPCLOG0(1, "xdr_replymsg/SVCAUTH_WRAP failed\n");
			goto out;
		}
		TRACE_1(TR_FAC_KRPC, TR_XDR_REPLYMSG_END,
		    "xdr_replymsg_end:(%S)", "good");

	} else if (!(xdr_replymsg_body(xdrs, msg) &&
		    (!has_args || SVCAUTH_WRAP(&clone_xprt->xp_auth, xdrs,
				xdr_results, xdr_location)))) {
		RPCLOG0(1, "xdr_replymsg_body/SVCAUTH_WRAP failed\n");
		goto out;
	}

	msgsz = (int)xmsgsize(ud->ud_resp->b_cont);

	if (msgsz <= 0 || (clone_xprt->xp_msg_size != -1 &&
	    msgsz > clone_xprt->xp_msg_size)) {
#ifdef	DEBUG
		cmn_err(CE_NOTE,
"KRPC: server response message of %d bytes; transport limits are [0, %d]",
			msgsz, clone_xprt->xp_msg_size);
#endif
		goto out;
	}

	/*
	 * Construct the T_unitdata_req.  We take advantage
	 * of the fact that T_unitdata_ind looks just like
	 * T_unitdata_req, except for the primitive type.
	 */
	udreq = (struct T_unitdata_req *)ud->ud_resp->b_rptr;
	udreq->PRIM_type = T_UNITDATA_REQ;

	put(clone_xprt->xp_wq, ud->ud_resp);
	stat = TRUE;
	ud->ud_resp = NULL;

out:
	if (stat == FALSE) {
		freemsg(ud->ud_resp);
		ud->ud_resp = NULL;
	}

	/*
	 * This is completely disgusting.  If public is set it is
	 * a pointer to a structure whose first field is the address
	 * of the function to free that structure and any related
	 * stuff.  (see rrokfree in nfs_xdr.c).
	 */
	if (xdrs->x_public) {
		/* LINTED pointer alignment */
		(**((int (**)())xdrs->x_public))(xdrs->x_public);
	}

	TRACE_1(TR_FAC_KRPC, TR_SVC_CLTS_KSEND_END,
	    "svc_clts_ksend_end:(%S)", "done");
	return (stat);
}
Пример #4
0
/*
 * Receive rpc requests.
 * Pulls a request in off the socket, checks if the packet is intact,
 * and deserializes the call packet.
 */
static bool_t
svc_clts_krecv(SVCXPRT *clone_xprt, mblk_t *mp, struct rpc_msg *msg)
{
	/* LINTED pointer alignment */
	struct udp_data *ud = (struct udp_data *)clone_xprt->xp_p2buf;
	XDR *xdrs = &clone_xprt->xp_xdrin;
	struct rpc_clts_server *stats = CLONE2STATS(clone_xprt);
	union T_primitives *pptr;
	int hdrsz;

	TRACE_0(TR_FAC_KRPC, TR_SVC_CLTS_KRECV_START,
	    "svc_clts_krecv_start:");

	RSSTAT_INCR(stats, rscalls);

	/*
	 * The incoming request should start with an M_PROTO message.
	 */
	if (mp->b_datap->db_type != M_PROTO) {
		goto bad;
	}

	/*
	 * The incoming request should be an T_UNITDTA_IND.  There
	 * might be other messages coming up the stream, but we can
	 * ignore them.
	 */
	pptr = (union T_primitives *)mp->b_rptr;
	if (pptr->type != T_UNITDATA_IND) {
		goto bad;
	}
	/*
	 * Do some checking to make sure that the header at least looks okay.
	 */
	hdrsz = (int)(mp->b_wptr - mp->b_rptr);
	if (hdrsz < TUNITDATAINDSZ ||
	    hdrsz < (pptr->unitdata_ind.OPT_offset +
		    pptr->unitdata_ind.OPT_length) ||
	    hdrsz < (pptr->unitdata_ind.SRC_offset +
		    pptr->unitdata_ind.SRC_length)) {
		goto bad;
	}

	/*
	 * Make sure that the transport provided a usable address.
	 */
	if (pptr->unitdata_ind.SRC_length <= 0) {
		goto bad;
	}
	/*
	 * Point the remote transport address in the service_transport
	 * handle at the address in the request.
	 */
	clone_xprt->xp_rtaddr.buf = (char *)mp->b_rptr +
	    pptr->unitdata_ind.SRC_offset;
	clone_xprt->xp_rtaddr.len = pptr->unitdata_ind.SRC_length;

	/*
	 * Save the first mblk which contains the T_unidata_ind in
	 * ud_resp.  It will be used to generate the T_unitdata_req
	 * during the reply.
	 */
	if (ud->ud_resp) {
		if (ud->ud_resp->b_cont != NULL) {
			cmn_err(CE_WARN, "svc_clts_krecv: ud_resp %p, "
			    "b_cont %p", (void *)ud->ud_resp,
			    (void *)ud->ud_resp->b_cont);
		}
		freeb(ud->ud_resp);
	}
	ud->ud_resp = mp;
	mp = mp->b_cont;
	ud->ud_resp->b_cont = NULL;

	xdrmblk_init(xdrs, mp, XDR_DECODE, 0);

	TRACE_0(TR_FAC_KRPC, TR_XDR_CALLMSG_START,
	    "xdr_callmsg_start:");
	if (! xdr_callmsg(xdrs, msg)) {
		TRACE_1(TR_FAC_KRPC, TR_XDR_CALLMSG_END,
		    "xdr_callmsg_end:(%S)", "bad");
		RSSTAT_INCR(stats, rsxdrcall);
		goto bad;
	}
	TRACE_1(TR_FAC_KRPC, TR_XDR_CALLMSG_END,
	    "xdr_callmsg_end:(%S)", "good");

	clone_xprt->xp_xid = msg->rm_xid;
	ud->ud_inmp = mp;

	TRACE_1(TR_FAC_KRPC, TR_SVC_CLTS_KRECV_END,
	    "svc_clts_krecv_end:(%S)", "good");
	return (TRUE);

bad:
	if (mp)
		freemsg(mp);
	if (ud->ud_resp) {
		/*
		 * There should not be any left over results buffer.
		 */
		ASSERT(ud->ud_resp->b_cont == NULL);
		freeb(ud->ud_resp);
		ud->ud_resp = NULL;
	}

	RSSTAT_INCR(stats, rsbadcalls);
	TRACE_1(TR_FAC_KRPC, TR_SVC_CLTS_KRECV_END,
	    "svc_clts_krecv_end:(%S)", "bad");
	return (FALSE);
}