static void
rds_wput_other(queue_t *q, mblk_t *mp)
{
	uchar_t *rptr = mp->b_rptr;
	struct datab *db;
	cred_t *cr;

	db = mp->b_datap;
	switch (db->db_type) {
	case M_DATA:
		/* Not connected */
		freemsg(mp);
		return;
	case M_PROTO:
	case M_PCPROTO:
		if ((uintptr_t)mp->b_wptr - (uintptr_t)rptr <
		    sizeof (t_scalar_t)) {
			freemsg(mp);
			return;
		}
		switch (((union T_primitives *)(uintptr_t)rptr)->type) {
		case T_CAPABILITY_REQ:
			rds_capability_req(q, mp);
			return;

		case T_INFO_REQ:
			rds_info_req(q, mp);
			return;
		case O_T_BIND_REQ:
		case T_BIND_REQ:
			rds_bind(q, mp);
			return;
		case T_SVR4_OPTMGMT_REQ:
		case T_OPTMGMT_REQ:
			/*
			 * All Solaris components should pass a db_credp
			 * for this TPI message, hence we ASSERT.
			 * But in case there is some other M_PROTO that looks
			 * like a TPI message sent by some other kernel
			 * component, we check and return an error.
			 */
			cr = msg_getcred(mp, NULL);
			ASSERT(cr != NULL);
			if (cr == NULL) {
				rds_err_ack(q, mp, TSYSERR, EINVAL);
				return;
			}
			if (((union T_primitives *)(uintptr_t)rptr)->type ==
			    T_SVR4_OPTMGMT_REQ) {
				svr4_optcom_req(q, mp, cr, &rds_opt_obj);
			} else {
				tpi_optcom_req(q, mp, cr, &rds_opt_obj);
			}
			return;
		case T_CONN_REQ:
			/*
			 * We should not receive T_CONN_REQ as sockfs only
			 * sends down T_CONN_REQ if family == AF_INET/AF_INET6
			 * and type == SOCK_DGRAM/SOCK_RAW. For all others
			 * it simply calls soisconnected. see sotpi_connect()
			 * for details.
			 */
		/* FALLTHRU */
		default:
			cmn_err(CE_PANIC, "type %d \n",
			    ((union T_primitives *)(uintptr_t)rptr)->type);
		}
		break;
	case M_FLUSH:
		if (*rptr & FLUSHW)
			flushq(q, FLUSHDATA);
		break;
	case M_IOCTL:
		rds_ioctl(q, mp);
		break;
	case M_IOCDATA:
		/* IOCTL continuation following copyin or copyout. */
		if (mi_copy_state(q, mp, NULL) == -1) {
			/*
			 * The copy operation failed.  mi_copy_state already
			 * cleaned up, so we're out of here.
			 */
			return;
		}
		/*
		 * If we just completed a copy in, continue processing
		 * in rds_ioctl_copyin_done. If it was a copy out, we call
		 * mi_copyout again.  If there is nothing more to copy out,
		 * it will complete the IOCTL.
		 */

		if (MI_COPY_DIRECTION(mp) == MI_COPY_IN)
			rds_ioctl_copyin_done(q, mp);
		else
			mi_copyout(q, mp);
		return;

	default:
		cmn_err(CE_PANIC, "types %d \n", db->db_type);
	}
}
Beispiel #2
0
static struct int
sl_w_iocdata(queue_t *q, mblk_t *mp)
{
	struct copyresp *cp = (struct copyresp *) mp->b_rptr;
	struct sl_mux_ppa sm;
	unsigned long flags;
	struct sl_mux *bot, *mux;
	mblk_t *dp, *bp;

	switch (cp->cp_cmd) {
	case SL_SETLINK:
		switch (mi_copy_state(q, mp, &dp)) {
		case MI_COPY_CASE(MI_COPY_IN, 1):
			/* This input-output control is used to set the global-PPA and CLEI
			   associated with a lower multiplex stream.  The argument is an sl_mux_ppa 
			   structure that contains the multiplex id, the 32-bit PPA, and a CLEI
			   string of up to 32 characters in length. */
			bcopy(dp->b_rptr, &sm, sizeof(sm));
			/* The assigned global PPA must be non-zero. */
			if (sm.sm_ppa == 0) {
				mi_copy_done(q, mp, EINVAL);
				return (0);
			}
			/* The assigned CLEI must be non-null. */
			if (sm.sm_clei[0] == '\0') {
				mi_copy_done(q, mp, EINVAL);
				return (0);
			}
			write_lock_str(&mux_lock, flags);
			/* Find the stream with the associated MUXID. */
			for (bot = mux_list; bot; bot = bot->next)
				if (bot->dev == sm.sm_index)
					break;
			if (!bot) {
				write_unlock_str(&mux_lock, flags);
				mi_copy_done(q, mp, EINVAL);
				return (0);
			}
			/* The global PPA to assign must be unique. */
			for (mux = mux_list; mux; mux = mux->next)
				if (mux != bot && mux->ppa == sm.sm_ppa)
					break;
			if (mux) {
				write_unlock_str(&mux_lock, flags);
				mi_copy_done(q, mp, EINVAL);
				return (0);
			}
			/* The CLEI to assign must also be unique. */
			for (mux = mux_list; mux; mux = mux->next)
				if (mux != bot && strncmp(mux->clei, sm.sm_clei, 32) == 0)
					break;
			if (mux) {
				write_unlock_str(&mux_lock, flags);
				mi_copy_done(q, mp, EINVAL);
				return (0);
			}
			bot->ppa = sm.sm_ppa;
			bcopy(bot->clei, sm.sm_clei, 32);
			write_unlock_str(&mux_lock, flags);
			mi_copy_done(q, mp, 0);
			return (0);
		case -1:
			return (0);
		}
		break;
	case SL_GETLINK:
		switch (mi_copy_state(q, mp, &dp)) {
		case MI_COPY_CASE(MI_COPY_IN, 1):
			/* This input-output control is used to obtain the multiplex-id assocated
			   with a lower multiplex stream.  The argument is an sl_mux_ppa structure
			   that contains a 32-bit PPA or CLEI string of up to 32 characters in
			   length.  It returns the multiplex id in the same structure. */
			bcopy(dp->b_rptr, &sm, sizeof(sm));
			if (sm.sm_ppa != 0) {
				/* If the supplied global PPA is non-zero, then search on PPA. */
				read_lock_str(&mux_lock, flags);
				for (bot = mux_list; bot; bot = bot->next)
					if (bot->ppa == sm.sm_ppa)
						break;
				if (!bot) {
					read_unlock_str(&mux_lock, flags);
					mi_copy_done(q, mp, EINVAL);
					return (0);
				}
				strncpy(sm.sm_clei, bot->clei, 32);
				sm.sm_index = bot->dev;
				read_unlock_str(&mux_lock, flags);
				if ((bp = mi_copyout_alloc(q, mp, NULL, sizeof(sm)))) {
					bcopy(&sm, bp->b_rptr, sizeof(sm));
					mi_copyout(q, mp);
				}
				return (0);
			} else if (sm.sm_clei[0] != '\0') {
				/* If the supplied CLEI is non-null, then search on CLEI. */
				read_lock_str(&mux_lock, flags);
				for (bot = mux_list; bot; bot = bot->next)
					if (strncmp(sm.sm_clei, bot->clei, 32) == 0)
						break;
				if (!bot) {
					read_unlock_str(&mux_lock, flags);
					mi_copy_done(q, mp, EINVAL);
					return (0);
				}
				sm.sm_ppa = bot->ppa;
				sm.sm_index = bot->dev;
				read_unlock_str(&mux_lock, flags);
				if ((bp = mi_copyout_alloc(q, mp, NULL, sizeof(sm)))) {
					bcopy(&sm, bp->b_rptr, sizeof(sm));
					mi_copyout(q, mp);
				}
				return (0);
			} else {
				/* If PPA is zero and CLEI is null, return the first item in the
				   list. */
				read_lock_str(&mux_lock, flags);
				bot = mux_list;
				if (!bot) {
					read_unlock_str(&mux_lock, flags);
					mi_copy_done(q, mp, EINVAL);
					return (0);
				}
				sm.sm_ppa = bot->ppa;
				strncpy(sm.sm_clei, bot->clei, 32);
				sm.sm_index = bot->dev;
				read_unlock_str(&mux_lock, flags);
				if ((bp = mi_copyout_alloc(q, mp, NULL, sizeof(sm)))) {
					bcopy(&sm, bp->b_rptr, sizeof(sm));
					mi_copyout(q, mp);
				}
				return (0);
			}
		case MI_COPY_CASE(MI_COPY_OUT, 1):
			mi_copy_done(q, mp, 0);
			return (0);
		case -1:
			return (0);
		}
		break;
	default:
		if (mux->other && mux->other->rq) {
			if (bcanputnext(mux->other->rq, mp->b_band)) {
				putnext(mux->other->rq, mp);
				return (0);
			}
			return (-EBUSY);
		}
		break;
	}
	mi_copy_done(q, mp, EINVAL);
	return (0);
}