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); }
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); }
/* * 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); }