⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tirdwr.c

📁 7号信令功能代码,为开源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			if ((bp = unlinkb(mp)) && bp->b_datap->db_type == M_DATA && bp->b_band == 0) {				if (msgdsize(bp) > 0) {					tirdwr_restore_delim(p->data_ind.MORE_flag, bp);					freeb(mp);					putnext(q, bp);				} else {					/*					   Silently discard zero length normal data. 					 */					freeb(mp);					freemsg(bp);				}			} else				tirdwr_eproto(priv, mp, bp);			break;#	    if defined T_OPTDATA_IND		case T_OPTDATA_IND:			/*			   T_OPTDATA is not always provided by the tihdr and is a more recent TPI			   (Version 5 Release 2) addition.  The purpose of T_OPTDATA is to support			   sockmod rather than timod or bare TI streams.  If we are pedantic about			   the TPI spec, we should not accept them even if we have them. 			 */#		    if !defined TIRDWR_TPI_PEDANTIC			if ((bp = unlinkb(mp)) && bp->b_datap->db_type == M_DATA && bp->b_band == 0			    && !(p->optdata_ind.DATA_flag & T_ODF_EX)) {				if (msgdsize(bp) > 0) {					tirdwr_restore_delim(p->optdata_ind.DATA_flag & T_ODF_MORE,							     bp);					freeb(mp);					putnext(q, bp);				} else {					/*					   Silently discard zero length normal data. 					 */					freeb(mp);					freemsg(bp);				}			} else#		    endif	/* !defined TIRDWR_TPI_PEDANTIC */				tirdwr_eproto(priv, mp, bp);			break;#	    endif		/* defined T_OPTDATA_IND */		case T_DISCON_IND:			tirdwr_hangup(priv, mp, bp);			priv->state = TS_IDLE;			break;		case T_ORDREL_IND:			switch (priv->state) {			case TS_DATA_XFER:				tirdwr_rdzero(priv, mp, bp);				priv->state = TS_WREQ_ORDREL;				break;			default:				tirdwr_eproto(priv, mp, bp);				break;			}			break;		case T_EXDATA_IND:		default:			tirdwr_eproto(priv, mp, bp);			break;		}		break;	}	case M_FLUSH:	case M_SIG:		putnext(q, mp);		break;	case M_HANGUP:		priv->flags |= TIRDWR_HANGUP;		priv->state = TS_IDLE;		putnext(q, mp);		break;	case M_ERROR:		priv->flags |= TIRDWR_EPROTO;		priv->state = TS_IDLE;		putnext(q, mp);		break;	default:		/*		   If we are pedantic about the TPI spec and TIRDWR operation, we should not permit 		   any other STREAMS messages from being transported upstream.  To be a little more 		   forgiving we could just pass what we don't recognize. 		 */#	    if defined TIRDWR_TPI_PEDANTIC || defined TIRDWR_PEDANTIC		tirdwr_eproto(priv, mp, bp);#	    else		/* defined TIRDWR_TPI_PEDANTIC || defined TIRDWR_PEDANTIC */		putnext(q, mp);#	    endif		/* defined TIRDWR_TPI_PEDANTIC || defined TIRDWR_PEDANTIC */		break;	}	return (0);}static inttirdwr_wput(queue_t *q, mblk_t *mp){	tirdwr_t *priv = (typeof(priv)) q->q_ptr;	struct iocblk *iocp = (struct iocblk *) mp->b_rptr;#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.",			TIRDWR_MOD_NAME, __FUNCTION__);		freemsg(mp);		return (0);	}#endif				/* defined _LIS_SOURCE */	switch (mp->b_datap->db_type) {	case M_DATA:		if (!(priv->flags & (TIRDWR_EPROTO | TIRDWR_HANGUP))) {			if (mp->b_band == 0) {				if (msgdsize(mp) > 0) {					putnext(q, mp);				} else {					/*					   Silently discard zero-length data 					 */					freemsg(mp);				}			} else {				/*				   error on banded (expedited) data 				 */				tirdwr_eproto(priv, mp, NULL);			}		} else			freemsg(mp);		break;	case M_PROTO:	case M_PCPROTO:		/*		   The major reason for denying these messages is that the normal use of tirdwr is		   to dup2 standard in or standard out or both with a connected XTI device with		   tirdwr pushed. Because the parent can still access the stream with XTI commands, 		   these need to generate EPROTO to signal both parent and child that something is		   wrong. 		 */		tirdwr_eproto(priv, mp, NULL);		break;#   if !defined TIRDWR_PEDANTIC	case M_READ:		if (!(priv->flags & (TIRDWR_EPROTO | TIRDWR_HANGUP))) {			switch (priv->state) {			case TS_IDLE:				freemsg(mp);				break;			case TS_DATA_XFER:				putnext(q, mp);				break;			case TS_WREQ_ORDREL:				tirdwr_rdzero(priv, mp, NULL);				break;			default:				freemsg(mp);				break;			}		} else			freemsg(mp);		break;	case M_FLUSH:		putnext(q, mp);		break;#   endif			/* !defined TIRDWR_PEDANTIC */	case M_IOCTL:#	    if !defined TIRDWR_PEDANTIC		if (_IOC_TYPE(iocp->ioc_cmd) != 'T') {			putnext(q, mp);			break;		}#	    endif		/* !defined TIRDWR_PEDANTIC */		/*		   Documentation states that XTI/TLI library commands should fail with EPROTO.		   Also, there is never any reason why the user should be accessing lower layer		   IOCTLs with tirdwr installed.  This acheives that effect. 		 */		tirdwr_eproto(priv, NULL, NULL);		mp->b_datap->db_type = M_IOCNAK;		iocp->ioc_error = EPROTO;		iocp->ioc_rval = -1;		qreply(q, mp);		break;	default:		tirdwr_eproto(priv, mp, NULL);		break;	}	return (0);}/* *  ========================================================================= * *  OPEN and CLOSE * *  ========================================================================= *  Note that LiS does not do module counting, therefore we have to do it. */static inttirdwr_push(queue_t *q){	queue_t *hq;	int err = 0;	/*	   Need to check for bad messages on stream head read queue. LiS does not have a freezestr	   or much of a qprocsoff, but the stream should be effectively frozen, so we can	   dereference the q->q_next pointer.  If anything, the q->q_next pointer should remain	   valid until we return from the open procedure. 	 */	if ((hq = q->q_next) == NULL)		err = EFAULT;	else if (qsize(hq) > 0) {		mblk_t *mp;		lis_flags_t psw;		/*		   Under LiS we can't freeze the stream but we can lock the queue.  This is not a		   completely satisfactory solution for SMP because another processor could be in		   the middle of performing putq to the queue from before the push while we lock		   the queue.  Unless LiS provides assurances that the qopen procedure of the		   module will not be called while lower level modules are putting to the stream		   head, this will never work. Missing an M_PROTO or M_PCPROTO message on the		   stream head read queue will result in read(2) returning EBADMSG for default		   stream head read ops. tirdwr should return EPROTO and refuse to push the module		   instead. 		 */		LIS_QISRLOCK(hq, &psw);		for (mp = hq->q_first; mp && !err; mp = mp->b_next)			switch (mp->b_datap->db_type) {			case M_PROTO:			case M_PCPROTO:				err = EPROTO;			}		LIS_QISRUNLOCK(hq, &psw);	}	return (err);}/*   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 voidtirdwr_pop(queue_t *q){	tirdwr_t *priv = (typeof(priv)) q->q_ptr;	mblk_t *mp;	switch (priv->state) {	case TS_WREQ_ORDREL:		if (!(priv->flags & TIRDWR_EPROTO)) {			if ((mp = allocb(sizeof(struct T_ordrel_req), BPRI_WAITOK))) {				struct T_ordrel_req *prim = ((typeof(prim)) mp->b_wptr)++;				mp->b_datap->db_type = M_PROTO;				prim->PRIM_type = T_ORDREL_REQ;				putnext(priv->wq, mp);			}			break;		}		/*		   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;			putnext(priv->wq, mp);		}		break;	case TS_IDLE:	default:		break;	}	if ((priv->flags & TIRDWR_EPROTO)) {		if ((mp = allocb(2, BPRI_WAITOK))) {			mp->b_datap->db_type = M_ERROR;			*(mp->b_wptr)++ = 0;			*(mp->b_wptr)++ = 0;			putnext(priv->rq, mp);		}#	    if defined M_ERROR_UNDOES_M_HANGUP		priv->flags &= ~(TIRDWR_EPROTO | TIRDWR_HANGUP);#	    else		/* defined M_ERROR_UNDOES_M_HANGUP */		priv->flags &= ~TIRDWR_EPROTO;#	    endif		/* defined M_ERROR_UNDOES_M_HANGUP */	}#   if defined M_UNHANGUP	if ((priv->flags & TIRDWR_HANGUP)) {		if ((mp = allocb(0, BRPI_WAITOK))) {			mp->b_datap->db_type = M_UNHANGUP;			putnext(priv->rq, mp);		}		priv->flags &= ~TIRDWR_HANGUP;	}#   endif			/* defined M_UNHANGUP */}static inttirdwr_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;	if ((err = tirdwr_push(q)))		goto quit;	err = ENOMEM;	if (!(tirdwr_alloc_priv(q)))		goto quit;	qprocson(q);	return (0);      quit:	MOD_DEC_USE_COUNT;	return (ENXIO);}static inttirdwr_close(queue_t *q, int oflag, cred_t *crp){	(void) oflag;	(void) crp;#if defined _LIS_SOURCE	/*	   protect against some LiS bugs 	 */	if (q->q_ptr == NULL) {		cmn_err(CE_WARN, "%s: %s: LiS double-close bug detected.", TIRDWR_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.",			TIRDWR_MOD_NAME, __FUNCTION__);		goto skip_pop;	}#endif				/* defined _LIS_SOURCE */	tirdwr_pop(q);	goto skip_pop;      skip_pop:	qprocsoff(q);	tirdwr_free_priv(q);	MOD_DEC_USE_COUNT;	goto quit;      quit:	return (0);}/* *  ========================================================================= * *  Registration and intialization * *  ========================================================================= */#if defined _LFS_SOURCEstatic struct fmodsw tirdwr_fmod = {	f_name:TIRDWR_MOD_NAME,	f_str:&tirdwr_info,	f_flag:0,	f_kmod:THIS_MODULE,};static inttirdwr_register_module(void){	int err;	if ((err = register_strmod(modid, &tirdwr_fmod)) < 0)		return (err);	if (modid == 0 && err > 0)		modid = err;	return (0);}static voidtirdwr_unregister_module(void){	return (void) unregister_strmod(modid, &tirdwr_fmod);}#elif defined _LIS_SOURCEstatic inttirdwr_register_module(void){	int ret;	if ((ret = lis_register_strmod(&tirdwr_info, TIRDWR_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 voidtirdwr_unregister_module(void){	/*	   LiS provides detailed errors here when they are discarded. 	 */	return (void) lis_unregister_strmod(&tirdwr_info);}#else#   error ****#   error ****  One of _LFS_SOURCE or _LIS_SOURCE must be defined#   error ****  to compile the tirdwr module.#   error ****#endifstatic int __inittirdwr_init(void){	int err;#ifdef MODULE	cmn_err(CE_NOTE, TIRDWR_BANNER);	/* banner message */#else	cmn_err(CE_NOTE, TIRDWR_SLPASH);	/* console splash */#endif	if ((err = tirdwr_init_caches())) {		cmn_err(CE_WARN, "%s: could not init caches, err = %d", TIRDWR_MOD_NAME, -err);		return (err);	}	if ((err = tirdwr_register_module())) {		tirdwr_term_caches();		cmn_err(CE_WARN, "%s: could not register module, err = %d", TIRDWR_MOD_NAME, -err);		return (err);	}	return (0);}static void __exittirdwr_exit(void){	tirdwr_unregister_module();	tirdwr_term_caches();	return;}module_init(tirdwr_init);module_exit(tirdwr_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -