📄 timod.c
字号:
break; } putnext(q, mp); return (0);}static inttimod_wput(queue_t *q, mblk_t *mp){ struct timod *priv = q->q_ptr;#if defined _LIS_SOURCE if (q->q_next == NULL || OTHER(q)->q_next == NULL) { cmn_err(CE_WARN, "%s: %s: LiS pipe bug: called with NULL q->q_next pointer", TIMOD_MOD_NAME, __FUNCTION__); freemsg(mp); return (0); }#endif /* defined _LIS_SOURCE */ switch (mp->b_datap->db_type) { union T_primitives *p; struct iocblk *ioc; mblk_t *dp; int err; case M_IOCTL: /* Most of the ioctls provided here are to acheive atomic and thread-safe operations on the stream for use by the XTI/TLI library. Each ioctl takes a TPI message in the buffer and results in sending the TPI message downstream. We strip off and keep the io control block for latter response correlation. We also track the state of the stream and the number of outstanding connection indications. */ ioc = (typeof(ioc)) mp->b_rptr; err = -EFAULT; if (!(dp = unlinkb(mp))) goto error; dp->b_datap->db_type = (ioc->ioc_cmd == TI_GETINFO) ? M_PCPROTO : M_PROTO; p = (typeof(p)) dp->b_rptr; err = -EINVAL; if (ioc->ioc_count == TRANSPARENT) goto error; switch (ioc->ioc_cmd) { case O_TI_OPTMGMT: err = TNOTSUPPORT; goto error; case TI_OPTMGMT: if (p->type == T_OPTMGMT_REQ && ioc->ioc_count >= sizeof(p->optmgmt_ack)) { dp->b_datap->db_type = M_PROTO; priv->oldstate = priv->state;#ifdef TS_WACK_OPTREQ priv->state = TS_WACK_OPTREQ;#endif break; } goto error; case O_TI_BIND: err = TNOTSUPPORT; goto error; case TI_BIND: if (p->type == T_BIND_REQ && ioc->ioc_count >= sizeof(p->bind_ack)) { dp->b_datap->db_type = M_PROTO; priv->oldstate = priv->state; priv->state = TS_WACK_BREQ; break; } goto error; case O_TI_GETINFO: err = TNOTSUPPORT; goto error; case TI_GETINFO: if (p->type == T_INFO_REQ && ioc->ioc_count >= sizeof(p->info_ack)) { dp->b_datap->db_type = M_PROTO; priv->oldstate = priv->state; break; } goto error; case O_TI_UNBIND: err = TNOTSUPPORT; goto error; case TI_UNBIND: if (p->type == T_UNBIND_REQ && ioc->ioc_count >= sizeof(p->ok_ack)) { dp->b_datap->db_type = M_PROTO; priv->oldstate = priv->state; priv->state = TS_WACK_UREQ; break; } goto error;#if defined TI_ACCEPT case TI_ACCEPT:#endif case TI_SETMYNAME: if (p->type == T_CONN_RES && ioc->ioc_count >= sizeof(p->conn_res)) { int doff = sizeof(p->conn_res); if (p->conn_res.OPT_length && doff < p->conn_res.OPT_offset + p->conn_res.OPT_length) doff = p->conn_res.OPT_offset + p->conn_res.OPT_length; if ((err = split_buffer(dp, doff)) < 0) goto error; dp->b_datap->db_type = M_PROTO; priv->oldstate = priv->state; priv->state = TS_WACK_CRES; break; } if (p->type == T_DISCON_REQ && ioc->ioc_count >= sizeof(p->discon_req)) { if ((err = split_buffer(dp, sizeof(p->discon_req))) < 0) goto error; dp->b_datap->db_type = M_PROTO; priv->oldstate = priv->state; priv->state = TS_WACK_DREQ7; break; } goto error;#if defined TI_CONNECT case TI_CONNECT:#endif case TI_SETPEERNAME: if (p->type == T_CONN_REQ && ioc->ioc_count >= sizeof(p->conn_req)) { int doff = sizeof(p->conn_req); if (p->conn_req.OPT_length && doff < p->conn_req.OPT_offset + p->conn_req.OPT_length) doff = p->conn_req.OPT_offset + p->conn_req.OPT_length; if (p->conn_req.DEST_length && doff < p->conn_req.DEST_offset + p->conn_req.DEST_length) doff = p->conn_req.DEST_offset + p->conn_req.DEST_length; if ((err = split_buffer(dp, doff)) < 0) goto error; dp->b_datap->db_type = M_PROTO; priv->oldstate = priv->state; priv->state = TS_WACK_CREQ; break; } if (p->type == T_DISCON_REQ && ioc->ioc_count >= sizeof(p->discon_req)) { if ((err = split_buffer(dp, sizeof(p->discon_req))) < 0) goto error; dp->b_datap->db_type = M_PROTO; switch ((priv->oldstate = priv->state)) { case TS_WCON_CREQ: priv->state = TS_WACK_DREQ6; break; case TS_DATA_XFER: priv->state = TS_WACK_DREQ9; break; case TS_WIND_ORDREL: priv->state = TS_WACK_DREQ10; break; case TS_WREQ_ORDREL: priv->state = TS_WACK_DREQ11; break; } break; } goto error; case TI_GETMYNAME: if (ioc->ioc_count >= sizeof(p->addr_ack)) { dp->b_datap->db_type = M_PCPROTO; p->type = T_ADDR_REQ; dp->b_wptr = dp->b_rptr + sizeof(p->addr_req); break; } goto error; case TI_GETPEERNAME: if (ioc->ioc_count >= sizeof(p->addr_ack)) { dp->b_datap->db_type = M_PCPROTO; p->type = T_ADDR_REQ; dp->b_wptr = dp->b_rptr + sizeof(p->addr_req); break; } goto error; case TI_GETADDRS: if (ioc->ioc_count >= sizeof(p->addr_ack) && p->type == T_ADDR_REQ) { dp->b_datap->db_type = M_PCPROTO; priv->oldstate = priv->state; break; } goto error; case TI_SYNC: if (ioc->ioc_count >= sizeof(struct ti_sync_ack)) { int flags = ((struct ti_sync_req *) p)->tsr_flags; if (flags & TSRF_INFO_REQ) { dp->b_datap->db_type = M_PCPROTO; p->type = T_INFO_REQ; dp->b_wptr = dp->b_rptr + sizeof(p->info_req); break; } else { } if (flags & TSRF_IS_EXP_IN_RCVBUF) { } if (flags & TSRF_QLEN_REQ) { } break; } goto error;#if 0 case TI_GETPROTADDR: err = -EOPNOTSUPP; goto error; case TI_DISCONNECT: if (p->type == T_DISCON_REQ && ioc->ioc_count >= sizeof(p->discon_req)) { if ((err = split_buffer(dp, sizeof(p->discon_req))) < 0) goto error; dp->b_datap->db_type = M_PROTO; priv->oldstate = priv->state; switch (priv->state) { case TS_WCON_CREQ: priv->state = TS_WACK_DREQ6; break; case TS_WRES_CIND: priv->state = TS_WACK_DREQ7; break; case TS_DATA_XFER: priv->state = TS_WACK_DREQ9; break; case TS_WIND_ORDREL: priv->state = TS_WACK_DREQ10; break; case TS_WREQ_ORDREL: priv->state = TS_WACK_DREQ11; break; default: priv->state = -1; goto error; } break; } goto error;#endif case TI_CAPABILITY:#ifdef T_CAPABILITY_REQ if (ioc->ioc_count >= sizeof(p->capability_req) && p->type == T_CAPABILITY_REQ) { dp->b_datap->db_type = M_PCPROTO; priv->oldstate = priv->state; break; } goto error;#endif default: putnext(q, mp); return (0); } if ((mp = xchg(&priv->iocblk, mp))) freemsg(mp); putnext(q, dp); return (0); error: mp->b_datap->db_type = M_IOCNAK; linkb(mp, dp); ioc->ioc_error = -err; ioc->ioc_rval = -1; qreply(q, mp); return (0); case M_PROTO: case M_PCPROTO: /* this is just to do state tracking */ if (mp->b_wptr < mp->b_rptr + sizeof(p->type)) break; p = (typeof(p)) mp->b_rptr; switch (p->type) { case T_CONN_REQ: priv->oldstate = priv->state; priv->state = TS_WACK_CREQ; break; case T_CONN_RES: priv->oldstate = priv->state; priv->state = TS_WACK_CRES; break; case T_DISCON_REQ: switch ((priv->oldstate = priv->state)) { case TS_WCON_CREQ: priv->state = TS_WACK_DREQ6; break; case TS_WRES_CIND: priv->state = TS_WACK_DREQ7; break; case TS_DATA_XFER: priv->state = TS_WACK_DREQ9; break; case TS_WIND_ORDREL: priv->state = TS_WACK_DREQ10; break; case TS_WREQ_ORDREL: priv->state = TS_WACK_DREQ11; break; } break; case T_DATA_REQ: priv->oldstate = priv->state; priv->state = TS_DATA_XFER; break; case T_EXDATA_REQ: priv->oldstate = priv->state; priv->state = TS_DATA_XFER; break; case T_INFO_REQ: priv->oldstate = priv->state; priv->state = priv->oldstate; break; case T_BIND_REQ: priv->oldstate = priv->state; priv->state = TS_WACK_BREQ; break; case T_UNBIND_REQ: priv->oldstate = priv->state; priv->state = TS_WACK_UREQ; break; case T_UNITDATA_REQ: priv->oldstate = priv->state; priv->state = TS_IDLE; break; case T_OPTMGMT_REQ: priv->oldstate = priv->state;#ifdef TS_WACK_OPTREQ priv->state = TS_WACK_OPTREQ;#endif break; case T_ORDREL_REQ: switch ((priv->oldstate = priv->state)) { case TS_WREQ_ORDREL: priv->state = TS_IDLE; break; case TS_DATA_XFER: priv->state = TS_WIND_ORDREL; break; } break; case T_ADDR_REQ: priv->oldstate = priv->state; priv->state = priv->oldstate; break;#ifdef T_CAPABILITY_REQ case T_CAPABILITY_REQ: priv->oldstate = priv->state; priv->state = priv->oldstate; break;#endif default: break; } } putnext(q, mp); return (0);}#define TIMOD_HANGUP 01#define TIMOD_EPROTO 02/* * ------------------------------------------------------------------------- * * OPEN and CLOSE * * ------------------------------------------------------------------------- *//* LiS does not offer us a way to wait for an allocation. Solaris, OSF and Linux Fast-STREAMS do. */#if !defined BPRI_WAITOK# if defined BPRI_FT# define BPRI_WAITOK BPRI_FT# else# define BPRI_WAITOK BPRI_HI# endif#endifstatic voidtimod_pop(queue_t *q){ struct timod *priv = (typeof(priv)) q->q_ptr; mblk_t *mp; switch (priv->state) { case TS_WREQ_ORDREL: if (!(priv->flags & TIMOD_EPROTO)) { if ((mp = allocb(sizeof(struct T_discon_req), BPRI_WAITOK))) { struct T_discon_req *prim = ((typeof(prim)) mp->b_wptr)++; mp->b_datap->db_type = M_PROTO; prim->PRIM_type = T_ORDREL_REQ; qreply(q, mp); } } /* fall through */ case TS_DATA_XFER: if ((mp = allocb(sizeof(struct T_discon_req), BPRI_WAITOK))) { struct T_discon_req *prim = ((typeof(prim)) mp->b_wptr)++; mp->b_datap->db_type = M_PROTO; prim->PRIM_type = T_DISCON_REQ; prim->SEQ_number = 0; qreply(q, mp); } break; break; case TS_IDLE: default: break; } if ((priv->flags & TIMOD_EPROTO)) { if ((mp = allocb(2, BPRI_WAITOK))) { mp->b_datap->db_type = M_ERROR; *(mp->b_wptr)++ = 0; *(mp->b_wptr)++ = 0; qreply(q, mp); }# if defined M_ERROR_UNDOES_M_HANGUP priv->flags &= ~(TIMOD_EPROTO | TIMOD_HANGUP);# else /* defined M_ERROR_UNDOES_M_HANGUP */ priv->flags &= ~TIMOD_EPROTO;# endif /* defined M_ERROR_UNDOES_M_HANGUP */ }# if defined M_UNHANGUP if ((priv->flags & TIMOD_HANGUP)) { if ((mp = allocb(0, BRPI_WAITOK))) { mp->b_datap->db_type = M_UNHANGUP; qreply(q, mp); } priv->flags &= ~TIMOD_HANGUP; }# endif /* defined M_UNHANGUP */}static inttimod_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp){ int err; MOD_INC_USE_COUNT; /* keep module from unloading */ err = 0; if (q->q_ptr != NULL) goto quit; /* already open */ err = ENXIO; if (sflag != MODOPEN || WR(q)->q_next == NULL) goto quit; err = ENOMEM; if (!(timod_alloc_priv(q))) goto quit; qprocson(q); return (0); quit: MOD_DEC_USE_COUNT; return (ENXIO);}static inttimod_close(queue_t *q, int oflag, cred_t *crp){ (void) oflag; (void) crp;#if defined _LIS_SOURCE /* protect against LiS bugs */ if (q->q_ptr == NULL) { cmn_err(CE_WARN, "%s: %s: LiS double-close bug detected.", TIMOD_MOD_NAME, __FUNCTION__); goto quit; } if (q->q_next == NULL || OTHER(q)->q_next == NULL) { cmn_err(CE_WARN, "%s: %s: LiS pipe bug: called with NULL q->q_next pointer", TIMOD_MOD_NAME, __FUNCTION__); goto skip_pop; }#endif /* defined _LIS_SOURCE */ timod_pop(q); goto skip_pop; skip_pop: qprocsoff(q); timod_free_priv(q); MOD_DEC_USE_COUNT; goto quit; quit: return (0);}/* * ------------------------------------------------------------------------- * * Registration and initialization * * ------------------------------------------------------------------------- */#if defined _LFS_SOURCEstatic struct fmodsw timod_fmod = { f_name:TIMOD_MOD_NAME, f_str:&timod_info, f_flag:0, f_kmod:THIS_MODULE,};static inttimod_register_module(void){ int err; if ((err = register_strmod(&timod_fmod)) < 0) return (err); if (modid == 0 && err > 0) modid = err; return (0);}static voidtimod_unregister_module(void){ return (void) unregister_strmod(&timod_fmod);}#elif defined _LIS_SOURCEstatic inttimod_register_module(void){ int ret; if ((ret = lis_register_strmod(&timod_info, TIMOD_MOD_NAME)) != LIS_NULL_MID) { if (modid == 0) modid = ret; return (0); } /* LiS is not too good on giving informative errors here. */ return (EIO);}static voidtimod_unregister_module(void){ /* LiS provides detailed errors here when they are discarded. */ return (void) lis_unregister_strmod(&timod_info);}#endifstatic int __inittimod_init(void){ int err;#ifdef MODULE printk(KERN_INFO TIMOD_BANNER); /* banner message */#else printk(KERN_INFO TIMOD_SPLASH); /* console splash */#endif if ((err = timod_init_caches())) { cmn_err(CE_WARN, "%s: could not init caches, err = %d", TIMOD_MOD_NAME, -err); return (err); } if ((err = timod_register_module())) { timod_term_caches(); cmn_err(CE_WARN, "%s: could not register module, err = %d", TIMOD_MOD_NAME, -err); return (err); } return (0);};static void __exittimod_exit(void){ timod_unregister_module(); timod_term_caches(); return;};module_init(timod_init);module_exit(timod_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -