t_look.c revision 61961e0f20c7637a3846bb39786bb9dffa91dfb9
253N/A/*
253N/A * CDDL HEADER START
253N/A *
470N/A * The contents of this file are subject to the terms of the
253N/A * Common Development and Distribution License, Version 1.0 only
253N/A * (the "License"). You may not use this file except in compliance
253N/A * with the License.
253N/A *
292N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
292N/A * or http://www.opensolaris.org/os/licensing.
292N/A * See the License for the specific language governing permissions
292N/A * and limitations under the License.
253N/A *
253N/A * When distributing Covered Code, include this CDDL HEADER in each
253N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
292N/A * If applicable, add the following below this CDDL HEADER, with the
292N/A * fields enclosed by brackets "[]" replaced with your own identifying
292N/A * information: Portions Copyright [yyyy] [name of copyright owner]
292N/A *
292N/A * CDDL HEADER END
292N/A */
292N/A
292N/A/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
292N/A/* All Rights Reserved */
292N/A
292N/A/*
253N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
253N/A * Use is subject to license terms.
253N/A */
253N/A
253N/A#pragma ident "%Z%%M% %I% %E% SMI"
253N/A
253N/A#include "mt.h"
253N/A#include <errno.h>
253N/A#include <unistd.h>
253N/A#include <sys/stream.h>
253N/A#include <stropts.h>
253N/A#define _SUN_TPI_VERSION 2
253N/A#include <sys/tihdr.h>
253N/A#include <sys/timod.h>
253N/A#include <xti.h>
253N/A#include <assert.h>
253N/A#include "tx.h"
253N/A
470N/Aint
253N/A_tx_look(int fd, int api_semantics)
253N/A{
253N/A int state;
253N/A int sv_errno;
253N/A int do_expinline_peek; /* unusual XTI specific processing */
253N/A struct _ti_user *tiptr;
253N/A
253N/A if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL)
253N/A return (-1);
253N/A sig_mutex_lock(&tiptr->ti_lock);
253N/A
253N/A if (_T_IS_XTI(api_semantics))
253N/A do_expinline_peek = 1;
253N/A else
253N/A do_expinline_peek = 0;
253N/A state = _t_look_locked(fd, tiptr, do_expinline_peek, api_semantics);
253N/A
470N/A sv_errno = errno;
253N/A
253N/A sig_mutex_unlock(&tiptr->ti_lock);
253N/A errno = sv_errno;
470N/A return (state);
253N/A}
253N/A
253N/A/*
470N/A * _t_look_locked() assumes tiptr->ti_lock lock is already held and signals
253N/A * already blocked in MT case.
253N/A * Intended for use by other TLI routines only.
253N/A */
253N/Aint
253N/A_t_look_locked(
253N/A int fd,
253N/A struct _ti_user *tiptr,
253N/A int do_expinline_peek,
470N/A int api_semantics
470N/A)
253N/A{
470N/A struct strpeek strpeek;
470N/A int retval;
253N/A union T_primitives *pptr;
253N/A t_scalar_t type;
253N/A t_scalar_t ctltype;
253N/A
253N/A assert(MUTEX_HELD(&tiptr->ti_lock));
470N/A
470N/A#ifdef notyet
253N/A if (_T_IS_XTI(api_semantics)) {
470N/A /*
470N/A * XTI requires the strange T_GODATA and T_GOEXDATA
253N/A * events which are almost brain-damaged but thankfully
253N/A * not tested. Anyone feeling the need for those should
253N/A * consider the need for using non-blocking endpoint.
253N/A * Probably introduced at the behest of some weird-os
253N/A * vendor which did not understand the non-blocking endpoint
253N/A * option.
253N/A * We choose not to implment these mis-features.
253N/A * Here is the plan-of-action (POA)if we are ever forced
253N/A * to implement these.
253N/A * - When returning TFLOW set state to indicate if it was
253N/A * a normal or expedited data send attempt.
253N/A * - In routines that set TFLOW, clear the above set state
253N/A * on each entry/reentry
253N/A * - In this routine, if that state flag is set,
253N/A * do a I_CANPUT on appropriate band to to see if it
253N/A * is writeable. If that indicates that the band is
253N/A * writeable, return T_GODATA or T_GOEXDATA event.
253N/A *
253N/A * Actions are also influenced by whether T_EXDATA_REQ stays
253N/A * band 1 or goes to band 0 if EXPINLINE is set
253N/A *
253N/A * We will also need to sort out if "write side" events
253N/A * (such as T_GODATA/T_GOEXDATA) take precedence over
253N/A * all other events (all read side) or not.
253N/A */
253N/A }
253N/A#endif /* notyet */
253N/A
253N/A strpeek.ctlbuf.maxlen = (int)sizeof (ctltype);
253N/A strpeek.ctlbuf.len = 0;
253N/A strpeek.ctlbuf.buf = (char *)&ctltype;
253N/A strpeek.databuf.maxlen = 0;
253N/A strpeek.databuf.len = 0;
253N/A strpeek.databuf.buf = NULL;
470N/A strpeek.flags = 0;
253N/A
253N/A do {
253N/A retval = _ioctl(fd, I_PEEK, &strpeek);
470N/A } while (retval < 0 && errno == EINTR);
253N/A
253N/A if (retval < 0) {
470N/A if (_T_IS_TLI(api_semantics)) {
470N/A /*
253N/A * This return of T_ERROR event is ancient
253N/A * SVR3 TLI semantics and not documented for
253N/A * current SVR4 TLI interface.
253N/A * Fixing this will impact some apps
253N/A * (e.g. nfsd,lockd) in ON consolidation
253N/A * so they need to be fixed first before TLI
253N/A * can be fixed.
253N/A * XXX Should we never fix this because it might
253N/A * break apps in field ?
253N/A */
253N/A return (T_ERROR);
253N/A }
253N/A /*
253N/A * XTI semantics (also identical to documented,
253N/A * but not implemented TLI semantics).
253N/A */
253N/A t_errno = TSYSERR;
253N/A return (-1);
253N/A }
253N/A
253N/A /*
253N/A * if something there and cntl part also there
253N/A */
253N/A if ((tiptr->ti_lookcnt > 0) ||
253N/A ((retval > 0) && (strpeek.ctlbuf.len >= (int)sizeof (t_scalar_t)))) {
253N/A /* LINTED pointer cast */
253N/A pptr = (union T_primitives *)strpeek.ctlbuf.buf;
253N/A if (tiptr->ti_lookcnt > 0) {
253N/A /* LINTED pointer cast */
253N/A type = *((t_scalar_t *)tiptr->ti_lookbufs.tl_lookcbuf);
253N/A /*
253N/A * If message on stream head is a T_DISCON_IND, that
253N/A * has priority over a T_ORDREL_IND in the look
470N/A * buffer.
253N/A * (This assumes that T_ORDREL_IND can only be in the
253N/A * first look buffer in the list)
253N/A */
253N/A if ((type == T_ORDREL_IND) && retval &&
253N/A (pptr->type == T_DISCON_IND)) {
253N/A type = pptr->type;
253N/A /*
253N/A * Blow away T_ORDREL_IND
253N/A */
253N/A _t_free_looklist_head(tiptr);
253N/A }
470N/A } else
470N/A type = pptr->type;
253N/A
253N/A switch (type) {
253N/A
253N/A case T_CONN_IND:
470N/A return (T_LISTEN);
253N/A
253N/A case T_CONN_CON:
470N/A return (T_CONNECT);
470N/A
253N/A case T_DISCON_IND:
253N/A return (T_DISCONNECT);
253N/A
253N/A case T_DATA_IND: {
253N/A int event = T_DATA;
253N/A int retval, exp_on_q;
253N/A
470N/A if (do_expinline_peek &&
253N/A (tiptr->ti_prov_flag & EXPINLINE)) {
253N/A assert(_T_IS_XTI(api_semantics));
253N/A retval = _t_expinline_queued(fd, &exp_on_q);
253N/A if (retval < 0) {
622N/A t_errno = TSYSERR;
622N/A return (-1);
253N/A }
253N/A if (exp_on_q)
253N/A event = T_EXDATA;
253N/A }
253N/A return (event);
253N/A }
470N/A
470N/A case T_UNITDATA_IND:
253N/A return (T_DATA);
253N/A
253N/A case T_EXDATA_IND:
253N/A return (T_EXDATA);
253N/A
253N/A case T_UDERROR_IND:
253N/A return (T_UDERR);
253N/A
253N/A case T_ORDREL_IND:
253N/A return (T_ORDREL);
253N/A
253N/A default:
253N/A t_errno = TSYSERR;
253N/A errno = EPROTO;
253N/A return (-1);
}
}
/*
* if something there put no control part
* it must be data on the stream head.
*/
if ((retval > 0) && (strpeek.ctlbuf.len <= 0)) {
int event = T_DATA;
int retval, exp_on_q;
if (do_expinline_peek &&
(tiptr->ti_prov_flag & EXPINLINE)) {
assert(_T_IS_XTI(api_semantics));
retval = _t_expinline_queued(fd, &exp_on_q);
if (retval < 0)
return (-1);
if (exp_on_q)
event = T_EXDATA;
}
return (event);
}
/*
* if msg there and control
* part not large enough to determine type?
* it must be illegal TLI message
*/
if ((retval > 0) && (strpeek.ctlbuf.len > 0)) {
t_errno = TSYSERR;
errno = EPROTO;
return (-1);
}
return (0);
}