summaryrefslogtreecommitdiff
path: root/usr/src/lib/libnsl/nsl/t_rcvvudata.c
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libnsl/nsl/t_rcvvudata.c
downloadillumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libnsl/nsl/t_rcvvudata.c')
-rw-r--r--usr/src/lib/libnsl/nsl/t_rcvvudata.c282
1 files changed, 282 insertions, 0 deletions
diff --git a/usr/src/lib/libnsl/nsl/t_rcvvudata.c b/usr/src/lib/libnsl/nsl/t_rcvvudata.c
new file mode 100644
index 0000000000..b3662271f4
--- /dev/null
+++ b/usr/src/lib/libnsl/nsl/t_rcvvudata.c
@@ -0,0 +1,282 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 1998-2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * t_rcvudata.c and t_rcvvudata.c are very similar and contain common code.
+ * Any changes to either of them should be reviewed to see whether they
+ * are applicable to the other file.
+ */
+#include "mt.h"
+#include <rpc/trace.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stropts.h>
+#include <sys/stream.h>
+#define _SUN_TPI_VERSION 2
+#include <sys/tihdr.h>
+#include <sys/timod.h>
+#include <xti.h>
+#include <syslog.h>
+#include <assert.h>
+#include "tx.h"
+
+
+int
+_tx_rcvvudata(
+ int fd,
+ struct t_unitdata *unitdata,
+ struct t_iovec *tiov,
+ unsigned int tiovcount,
+ int *flags,
+ int api_semantics
+)
+{
+ struct strbuf ctlbuf;
+ struct strbuf databuf;
+ char *dataptr;
+ int retval;
+ union T_primitives *pptr;
+ struct _ti_user *tiptr;
+ int sv_errno;
+ int didalloc;
+ int flg = 0;
+ unsigned int nbytes;
+
+ trace2(TR_t_rcvvudata, 0, fd);
+ assert(api_semantics == TX_XTI_XNS5_API);
+
+ if (tiovcount == 0 || tiovcount > T_IOV_MAX) {
+ t_errno = TBADDATA;
+ return (-1);
+ }
+
+ if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL) {
+ sv_errno = errno;
+ trace2(TR_t_rcvvudata, 1, fd);
+ errno = sv_errno;
+ return (-1);
+ }
+ sig_mutex_lock(&tiptr->ti_lock);
+
+ if (tiptr->ti_servtype != T_CLTS) {
+ t_errno = TNOTSUPPORT;
+ sig_mutex_unlock(&tiptr->ti_lock);
+ trace2(TR_t_rcvvudata, 1, fd);
+ return (-1);
+ }
+
+ if (tiptr->ti_state != T_IDLE) {
+ t_errno = TOUTSTATE;
+ sig_mutex_unlock(&tiptr->ti_lock);
+ trace2(TR_t_rcvvudata, 1, fd);
+ return (-1);
+ }
+
+ /*
+ * check if there is something in look buffer
+ */
+ if (tiptr->ti_lookcnt > 0) {
+ sig_mutex_unlock(&tiptr->ti_lock);
+ trace2(TR_t_rcvvudata, 1, fd);
+ t_errno = TLOOK;
+ return (-1);
+ }
+
+ /*
+ * Acquire ctlbuf for use in sending/receiving control part
+ * of the message.
+ */
+ if (_t_acquire_ctlbuf(tiptr, &ctlbuf, &didalloc) < 0) {
+ sv_errno = errno;
+ sig_mutex_unlock(&tiptr->ti_lock);
+ trace2(TR_t_rcvvudata, 1, fd);
+ errno = sv_errno;
+ return (-1);
+ }
+
+ *flags = 0;
+
+ nbytes = _t_bytecount_upto_intmax(tiov, tiovcount);
+ dataptr = NULL;
+ if (nbytes != 0 && ((dataptr = malloc(nbytes)) == NULL)) {
+ t_errno = TSYSERR;
+ goto err_out;
+ }
+
+ databuf.maxlen = nbytes;
+ databuf.len = 0;
+ databuf.buf = dataptr;
+
+ /*
+ * This is a call that may block indefinitely so we drop the
+ * lock and allow signals in MT case here and reacquire it.
+ * Error case should roll back state changes done above
+ * (happens to be no state change here)
+ */
+ sig_mutex_unlock(&tiptr->ti_lock);
+ if ((retval = getmsg(fd, &ctlbuf, &databuf, &flg)) < 0) {
+ if (errno == EAGAIN)
+ t_errno = TNODATA;
+ else
+ t_errno = TSYSERR;
+ sv_errno = errno;
+ sig_mutex_lock(&tiptr->ti_lock);
+ errno = sv_errno;
+ goto err_out;
+ }
+ sig_mutex_lock(&tiptr->ti_lock);
+
+ /*
+ * is there control piece with data?
+ */
+ if (ctlbuf.len > 0) {
+ if (ctlbuf.len < (int)sizeof (t_scalar_t)) {
+ t_errno = TSYSERR;
+ errno = EPROTO;
+ goto err_out;
+ }
+
+ pptr = (union T_primitives *)ctlbuf.buf;
+
+ switch (pptr->type) {
+
+ case T_UNITDATA_IND:
+ if ((ctlbuf.len <
+ (int)sizeof (struct T_unitdata_ind)) ||
+ (pptr->unitdata_ind.OPT_length &&
+ (ctlbuf.len < (int)(pptr->unitdata_ind.OPT_length
+ + pptr->unitdata_ind.OPT_offset)))) {
+ t_errno = TSYSERR;
+ errno = EPROTO;
+ goto err_out;
+ }
+
+ if (unitdata->addr.maxlen > 0) {
+ if (TLEN_GT_NLEN(pptr->unitdata_ind.SRC_length,
+ unitdata->addr.maxlen)) {
+ t_errno = TBUFOVFLW;
+ goto err_out;
+ }
+ (void) memcpy(unitdata->addr.buf,
+ ctlbuf.buf + pptr->unitdata_ind.SRC_offset,
+ (size_t)pptr->unitdata_ind.SRC_length);
+ unitdata->addr.len =
+ pptr->unitdata_ind.SRC_length;
+ }
+ if (unitdata->opt.maxlen > 0) {
+ if (TLEN_GT_NLEN(pptr->unitdata_ind.OPT_length,
+ unitdata->opt.maxlen)) {
+ t_errno = TBUFOVFLW;
+ goto err_out;
+ }
+ (void) memcpy(unitdata->opt.buf, ctlbuf.buf +
+ pptr->unitdata_ind.OPT_offset,
+ (size_t)pptr->unitdata_ind.OPT_length);
+ unitdata->opt.len =
+ pptr->unitdata_ind.OPT_length;
+ }
+ if (retval & MOREDATA)
+ *flags |= T_MORE;
+ /*
+ * No state changes happens on T_RCVUDATA
+ * event (NOOP). We do it only to log errors.
+ */
+ _T_TX_NEXTSTATE(T_RCVUDATA, tiptr,
+ "t_rcvvudata: invalid state event T_RCVUDATA");
+
+ if (didalloc)
+ free(ctlbuf.buf);
+ else
+ tiptr->ti_ctlbuf = ctlbuf.buf;
+ _t_scatter(&databuf, tiov, tiovcount);
+ if (dataptr != NULL)
+ free(dataptr);
+ sig_mutex_unlock(&tiptr->ti_lock);
+ trace2(TR_t_rcvvudata, 1, fd);
+ return (databuf.len);
+
+ case T_UDERROR_IND:
+ if (_t_register_lookevent(tiptr, 0, 0, ctlbuf.buf,
+ ctlbuf.len) < 0) {
+ t_errno = TSYSERR;
+ errno = ENOMEM;
+ goto err_out;
+ }
+ t_errno = TLOOK;
+ goto err_out;
+
+ default:
+ break;
+ }
+
+ t_errno = TSYSERR;
+ errno = EPROTO;
+ goto err_out;
+
+ } else { /* else part of "if (ctlbuf.len > 0)" */
+ unitdata->addr.len = 0;
+ unitdata->opt.len = 0;
+ /*
+ * only data in message no control piece
+ */
+ if (retval & MOREDATA)
+ *flags = T_MORE;
+ /*
+ * No state transition occurs on
+ * event T_RCVUDATA. We do it only to
+ * log errors.
+ */
+ _T_TX_NEXTSTATE(T_RCVUDATA, tiptr,
+ "t_rcvvudata: invalid state event T_RCVUDATA");
+ if (didalloc)
+ free(ctlbuf.buf);
+ else
+ tiptr->ti_ctlbuf = ctlbuf.buf;
+ _t_scatter(&databuf, tiov, tiovcount);
+ if (dataptr != NULL)
+ free(dataptr);
+ sig_mutex_unlock(&tiptr->ti_lock);
+ trace2(TR_t_rcvvudata, 0, fd);
+ return (databuf.len);
+ }
+ /* NOTREACHED */
+err_out:
+ sv_errno = errno;
+ if (didalloc)
+ free(ctlbuf.buf);
+ else
+ tiptr->ti_ctlbuf = ctlbuf.buf;
+ if (dataptr != NULL)
+ free(dataptr);
+ sig_mutex_unlock(&tiptr->ti_lock);
+ trace2(TR_t_rcvvudata, 1, fd);
+ errno = sv_errno;
+ return (-1);
+}