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); } }
static int zap_m_ioctl(struct zt_chan *chan, queue_t *q, mblk_t *mp) { struct iocblk *ioc = (typeof(ioc)) mp->b_rptr; mblk_t *dp = mp->b_cont; switch (ioc->ioc_cmd) { case ZT_GET_BLOCKSIZE: case ZT_SET_BLOCKSIZE: case ZT_FLUSH: case ZT_SYNC: case ZT_GET_PARAMS: case ZT_SET_PARAMS: case ZT_HOOK: case ZT_SPANSTAT: case ZT_MAINT: case ZT_GETCONF: case ZT_SETCONF: case ZT_CONFLINK: case ZT_CONFDIAG: case ZT_GETGAINS: case ZT_SETGAINS: case ZT_SPANCONFIG: case ZT_CHANCONFIG: case ZT_CONFMUTE: case ZT_SENDTONE: case ZT_SETTONEZONE: case ZT_GETTONEZONE: case ZT_DEFAULTZONE: case ZT_LOADZONE: case ZT_FREEZONE: case ZT_SET_BUFINFO: case ZT_GET_BUFINFO: case ZT_GET_DIALPARAMS: case ZT_SET_DIALPARAMS: case ZT_DIAL: case ZT_AUDIOMODE: case ZT_ECHOCANCEL: case ZT_CHANNO: case ZT_DIALING: case ZT_HDLCRAWMODE: case ZT_HDLCFCSMODE: case ZT_SPECIFY: { int channo = *(int *) dp->b_rptr; if ((channo < 1) || (channo > ZT_MAX_CHANNELS)) miocnak(q, mp, 0, EINVAL); if ((err = zt_specchan_open(NULL, qstream(q)->sd_file, channo, 0)) == 0) { RD(q)->q_ptr = WR(q)->q_ptr = &chans[channo]; miocack(q, mp, 0, 0); } else { miocnak(q, mp, 0, (err < 0 ? -err : err)); } return (0); } case ZT_SETLAW: case ZT_SETLINEAR: case ZT_HDLCPPP: case ZT_SETCADENCE: case ZT_SETTXBITS: case ZT_CHANDIAG: case ZT_GETRXBITS: case ZT_SFCONFIG: case ZT_TIMERCONFIG: case ZT_TIMERACK: case ZT_GETCONFMUTE: case ZT_ECHOTRAIN: case ZT_ONHOOKTRANSFER: case ZT_TIMERPING: case ZT_TIMERPONG: case ZT_SIGFREEZE: case ZT_GETSIGFREEZE: mi_copyout(q, mp, NULL, sizeof(int)); return (0); case ZT_INDIRECT: case ZT_DYNAMIC_CREATE: case ZT_DYNAMIC_DESTROY: case ZT_TONEDETECT: case ZT_SETPOLARITY: case ZT_STARTUP: case ZT_SHUTDOWN: } }
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); }