示例#1
0
文件: xdr_mblk.c 项目: ryao/openzfs
static bool_t
xdrmblk_getint32(XDR *xdrs, int32_t *int32p)
{
	mblk_t *m;
	struct xdrmblk_params *p;

	xdrmblk_skip_fully_read_mblks(xdrs);

	/* LINTED pointer alignment */
	m = (mblk_t *)xdrs->x_base;
	if (m == NULL)
		return (FALSE);

	p = (struct xdrmblk_params *)xdrs->x_private;

	/*
	 * If the pointer is not aligned or there is not
	 * enough bytes, pullupmsg to get enough bytes and
	 * align the mblk.
	 */
	if (!IS_P2ALIGNED(m->b_rptr, sizeof (int32_t)) ||
	    xdrs->x_handy < sizeof (int32_t)) {
		while (!pullupmsg(m, sizeof (int32_t))) {
			/*
			 * Could have failed due to not
			 * enough data or an allocb failure.
			 */
			if (xmsgsize(m) < sizeof (int32_t))
				return (FALSE);
			delay(hz);
		}
		p->apos += p->rpos;
		p->rpos = 0;
		xdrs->x_handy = (int)MBLKL(m);
	}

	/* LINTED pointer alignment */
	*int32p = ntohl(*((int32_t *)(m->b_rptr)));
	m->b_rptr += sizeof (int32_t);
	xdrs->x_handy -= sizeof (int32_t);
	p->rpos += sizeof (int32_t);

	return (TRUE);
}
示例#2
0
static bool_t
xdrmblk_getint32(XDR *xdrs, int32_t *int32p)
{
	mblk_t *m;

	/* LINTED pointer alignment */
	m = (mblk_t *)xdrs->x_base;
	if (m == NULL)
		return (FALSE);
	/*
	 * If the pointer is not aligned or there is not
	 * enough bytes, pullupmsg to get enough bytes and
	 * align the mblk.
	 */
	if (!IS_P2ALIGNED(m->b_rptr, sizeof (int32_t)) ||
	    xdrs->x_handy < sizeof (int32_t)) {
		while (!pullupmsg(m, sizeof (int32_t))) {
			/*
			 * Could have failed due to not
			 * enough data or an allocb failure.
			 */
			if (xmsgsize(m) < sizeof (int32_t))
				return (FALSE);
			delay(hz);
		}
		xdrs->x_handy = (int)(m->b_wptr - m->b_rptr);
	}

	/* LINTED pointer alignment */
	*int32p = ntohl(*((int32_t *)(m->b_rptr)));
	m->b_rptr += sizeof (int32_t);

	/*
	 * Instead of leaving handy as 0 causing more pullupmsg's
	 * simply move to the next mblk.
	 */
	if ((xdrs->x_handy -= sizeof (int32_t)) == 0) {
		m = m->b_cont;
		xdrs->x_base = (caddr_t)m;
		if (m != NULL)
			xdrs->x_handy = (int)(m->b_wptr - m->b_rptr);
	}
	return (TRUE);
}
示例#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);
}