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

📄 sdlm.c

📁 OpenSS7 This the fourth public release of the OpenSS7 Master Package. See README in the release for
💻 C
📖 第 1 页 / 共 2 页
字号:
{	int err;	size_t mlen = mp->b_wptr - mp->b_rptr;	lmi_attach_req_t *m = ((typeof(m)) mp->b_rptr);	if (mlen < sizeof(*m) || mlen < 2 * sizeof(ulong))		goto lprotoshort;	if (q->q_next)		goto loutstate;	{		struct dl *dl = DL_PRIV(q);		struct sd *sd;		ulong ppa = *((ulong *) &m->lmi_ppa);		for (sd = master.sd.list; sd && sd->ppa != ppa; sd = sd->next) ;		if (!sd || sd->iq->q_next)			goto lbadppa;		/* link queues together */#ifdef LFS		weldq(dl->iq, sd->oq, sd->iq, dl->oq, NULL, 0, dl->iq);#else		dl->iq->q_next = sd->oq;		sd->iq->q_next = dl->oq;#endif		return lmi_ok_ack_reply(q, mp, LMI_ATTACH_REQ, LMI_DISABLED);	}      lbadppa:	err = LMI_BADPPA;	ptrace(("ERROR: PPA in use\n"));	goto error;      loutstate:	err = LMI_OUTSTATE;	ptrace(("ERROR: would place i/f out of state\n"));	goto error;      lprotoshort:	err = LMI_PROTOSHORT;	ptrace(("ERROR: proto block to short\n"));	goto error;      error:	return lmi_error_ack_reply(q, mp, LMI_ATTACH_REQ, LMI_UNATTACHED, err);}/* *  LMI_DETACH_REQ: *  ----------------------------------- */STATIC INLINE intlmi_detach_req(queue_t *q, mblk_t *mp){	int err;	size_t mlen = mp->b_wptr - mp->b_rptr;	lmi_detach_req_t *m = ((typeof(m)) mp->b_rptr);	if (mlen < sizeof(*m))		goto lprotoshort;	if (!q->q_next)		goto loutstate;	{		lmi_ok_ack_t *p;		struct dl *dl = DL_PRIV(q);		struct sd *sd = SD_PRIV(q->q_next);		/* disconnect them */#ifdef LFS		unweldq(dl->iq, sd->oq, sd->iq, dl->oq, NULL, 0, dl->iq);#else		dl->iq->q_next = NULL;		sd->iq->q_next = NULL;#endif		mp->b_wptr = mp->b_rptr;		p = (typeof(p)) mp->b_wptr;		mp->b_wptr += sizeof(*p);		p->lmi_primitive = LMI_OK_ACK;		p->lmi_correct_primitive = LMI_DETACH_REQ;		p->lmi_state = LMI_UNATTACHED;		qreply(q, mp);		return (0);	}      loutstate:	err = LMI_OUTSTATE;	ptrace(("ERROR: would place i/f out of state\n"));	goto error;      lprotoshort:	err = LMI_PROTOSHORT;	ptrace(("ERROR: proto block too short\n"));	goto error;      error:	return lmi_error_ack_reply(q, mp, LMI_DETACH_REQ, LMI_UNATTACHED, err);}/* *  ========================================================================= * *  STREAMS Message Handling * *  ========================================================================= *//* *  ------------------------------------------------------------------------- * *  M_PROTO, M_PCPROTO Handling * *  ------------------------------------------------------------------------- */STATIC intdl_w_proto(queue_t *q, mblk_t *mp){	long prim = *((long *) mp->b_rptr);	switch (prim) {	case LMI_ATTACH_REQ:		return ((int) lmi_attach_req(q, mp));	case LMI_DETACH_REQ:		return ((int) lmi_detach_req(q, mp));	case LMI_INFO_REQ:	case LMI_ENABLE_REQ:	case LMI_DISABLE_REQ:	case LMI_OPTMGMT_REQ:		if (q->q_next) {			putnext(q, mp);			return ((int) (0));		}		ptrace(("ERROR: would place i/f out of state\n"));		return lmi_error_ack_reply(q, mp, prim, LMI_UNATTACHED, LMI_OUTSTATE);	case SDL_BITS_FOR_TRANSMISSION_REQ:	case SDL_CONNECT_REQ:	case SDL_DISCONNECT_REQ:		if (q->q_next) {			putnext(q, mp);			return ((int) (0));		}		return ((int) m_error_reply(q, mp, EPIPE));	default:		freemsg(mp);		return ((int) m_error_reply(q, mp, EPROTO));	}}/* *  ------------------------------------------------------------------------- * *  M_IOCTL Handling * *  ------------------------------------------------------------------------- */STATIC intdl_w_ioctl(queue_t *q, mblk_t *mp){	struct dl *dl = DL_PRIV(q);	struct iocblk *iocp = (struct iocblk *) mp->b_rptr;	void *arg = mp->b_cont ? mp->b_cont->b_rptr : NULL;	int cmd = iocp->ioc_cmd, count = iocp->ioc_count;	int type = _IOC_TYPE(cmd), nr = _IOC_NR(cmd), size = _IOC_SIZE(cmd);	int ret = 0;	(void) dl;	(void) size;	(void) count;	switch (type) {	case _IOC_TYPE(__SID):	{		psw_t flags;		struct sd *sd, **spp;		struct linkblk *lb = (struct linkblk *) arg;		if (!lb) {			swerr();			ret = -EINVAL;			break;		}		switch (nr) {		case _IOC_NR(I_PLINK):			ptrace(("%s: %p: I_PLINK\n", DRV_NAME, dl));			if (iocp->ioc_cr->cr_uid != 0) {				ptrace(("%s: %p: ERROR: Non-root attempt to I_PLINK\n", DRV_NAME,					dl));				ret = -EPERM;				break;			}		case _IOC_NR(I_LINK):			ptrace(("%s: %p: I_LINK\n", DRV_NAME, dl));			MOD_INC_USE_COUNT;	/* keep module from unloading */			spin_lock_irqsave(&master.lock, flags);			{				/* place in list in ascending index order */				for (spp = &master.sd.list;				     *spp && (*spp)->u.mux.index < lb->l_index;				     spp = &(*spp)->next) ;				if ((sd =				     sdlm_alloc_sd(lb->l_qbot, spp, lb->l_index, iocp->ioc_cr))) {					spin_unlock_irqrestore(&master.lock, flags);					break;				}				MOD_DEC_USE_COUNT;				ret = -ENOMEM;			}			spin_unlock_irqrestore(&master.lock, flags);			break;		case _IOC_NR(I_PUNLINK):			ptrace(("%s: %p: I_PUNLINK\n", DRV_NAME, dl));			if (iocp->ioc_cr->cr_uid != 0) {				ptrace(("%s: %p: ERROR: Non-root attempt to I_PUNLINK\n", DRV_NAME,					dl));				ret = -EPERM;				break;			}		case _IOC_NR(I_UNLINK):			ptrace(("%s: %p: I_UNLINK\n", DRV_NAME, dl));			spin_lock_irqsave(&master.lock, flags);			{				for (sd = master.sd.list; sd; sd = sd->next)					if (sd->u.mux.index == lb->l_index)						break;				if (!sd) {					ret = -EINVAL;					ptrace(("%s: %p: ERROR: Couldn't find I_UNLINK muxid\n",						DRV_NAME, dl));					spin_unlock_irqrestore(&master.lock, flags);					break;				}				sdlm_free_sd(sd->iq);				MOD_DEC_USE_COUNT;			}			spin_unlock_irqrestore(&master.lock, flags);			break;		default:		case _IOC_NR(I_STR):			ptrace(("%s: %p: ERROR: Unspported STREAMS ioctl %c, %d\n", DRV_NAME, dl,				(char) type, nr));			ret = -EOPNOTSUPP;			break;		}		break;	}	default:		ptrace(("%s: %p: ERROR: Unsupported ioctl %c, %d\n", DRV_NAME, dl, (char) type,			nr));		ret = -EOPNOTSUPP;		break;	}	if (ret > 0) {		return (ret);	} else if (ret == 0) {		mp->b_datap->db_type = M_IOCACK;		iocp->ioc_error = 0;		iocp->ioc_rval = 0;	} else {		mp->b_datap->db_type = M_IOCNAK;		iocp->ioc_error = -ret;		iocp->ioc_rval = -1;	}	qreply(q, mp);	return (QR_ABSORBED);}/* *  UPPER MUX Queues *  ----------------------------------- */STATIC streamscall intdl_r_prim(queue_t *q, mblk_t *mp){	switch (mp->b_datap->db_type) {	case M_FLUSH:		return ss7_r_flush(q, mp);	default:		return (QR_PASSFLOW);	}}STATIC streamscall intdl_w_prim(queue_t *q, mblk_t *mp){	switch (mp->b_datap->db_type) {	case M_FLUSH:		return ss7_w_flush(q, mp);	case M_PROTO:	case M_PCPROTO:		return dl_w_proto(q, mp);	case M_IOCTL:		return dl_w_ioctl(q, mp);	default:	case M_DATA:		return (QR_PASSFLOW);	}}/* *  LOWER MUX Queues *  ----------------------------------- */STATIC streamscall intsd_r_prim(queue_t *q, mblk_t *mp){	switch (mp->b_datap->db_type) {	case M_FLUSH:		return ss7_r_flush(q, mp);	default:		return (QR_PASSFLOW);	}}STATIC streamscall intsd_w_prim(queue_t *q, mblk_t *mp){	switch (mp->b_datap->db_type) {	case M_FLUSH:		return ss7_w_flush(q, mp);	default:		return (QR_PASSFLOW);	}}/* *  ========================================================================= * *  OPEN and CLOSE * *  ========================================================================= */STATIC major_t sdlm_majors[SDLM_CMAJORS] = { SDLM_CMAJOR_0, };/* *  OPEN *  ------------------------------------------------------------------------- */STATIC streamscall intsdlm_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp){	psw_t flags;	int mindex = 0;	major_t cmajor = getmajor(*devp);	minor_t cminor = getminor(*devp);	struct dl *dl, **dpp;	MOD_INC_USE_COUNT;	if (q->q_ptr != NULL) {		MOD_DEC_USE_COUNT;		return (0);	/* already open */	}	if (sflag == MODOPEN || WR(q)->q_next) {		ptrace(("%s: ERROR: cannot push as module\n", DRV_NAME));		MOD_DEC_USE_COUNT;		return (EIO);	}	if (cmajor != CMAJOR_0 || cminor > 0) {		MOD_DEC_USE_COUNT;		return (ENXIO);	}	/* allocate a new device */	cminor = 1;	spin_lock_irqsave(&master.lock, flags);	for (dpp = &master.dl.list; *dpp; dpp = &(*dpp)->next) {		major_t dmajor = (*dpp)->u.dev.cmajor;		if (cmajor != dmajor)			break;		if (cmajor == dmajor) {			minor_t dminor = (*dpp)->u.dev.cminor;			if (cminor < dminor)				break;			if (cminor > dminor)				continue;			if (cminor == dminor) {				if (++cminor >= NMINORS) {					if (++mindex >= CMAJORS || !(cmajor = sdlm_majors[mindex]))						break;					cminor = 0;				}				continue;			}		}	}	if (mindex >= CMAJORS || !cmajor) {		ptrace(("%s: ERROR: no device numbers available\n", DRV_NAME));		spin_unlock_irqrestore(&master.lock, flags);		MOD_DEC_USE_COUNT;		return (ENXIO);	}	printd(("%s: opened character device %d:%d\n", DRV_NAME, cmajor, cminor));	*devp = makedevice(cmajor, cminor);	if (!(dl = sdlm_alloc_dl(q, dpp, cmajor, cminor, crp))) {		ptrace(("%s: ERROR: no memory\n", DRV_NAME));		spin_unlock_irqrestore(&master.lock, flags);		MOD_DEC_USE_COUNT;		return (ENOMEM);	}	spin_unlock_irqrestore(&master.lock, flags);	return (0);}/* *  CLOSE *  ------------------------------------------------------------------------- */STATIC streamscall intsdlm_close(queue_t *q, int flag, cred_t *crp){	struct dl *dl = DL_PRIV(q);	psw_t flags;	(void) dl;	printd(("%s: %p: closing character device %hu:%hu\n", DRV_NAME, dl, dl->u.dev.cmajor,		dl->u.dev.cminor));	spin_lock_irqsave(&master.lock, flags);	{		sdlm_free_dl(q);	}	spin_unlock_irqrestore(&master.lock, flags);	MOD_DEC_USE_COUNT;	return (0);}/* *  ========================================================================= * *  Registration and initialization * *  ========================================================================= */#ifdef LINUX/* *  Linux Registration *  ------------------------------------------------------------------------- */unsigned short modid = DRV_ID;#ifndef module_paramMODULE_PARM(modid, "h");#elsemodule_param(modid, ushort, 0);#endifMODULE_PARM_DESC(modid, "Module ID for the SDL-MUX driver. (0 for allocation.)");major_t major = CMAJOR_0;#ifndef module_paramMODULE_PARM(major, "h");#elsemodule_param(major, uint, 0);#endifMODULE_PARM_DESC(major, "Device number for the SDL-MUX driver. (0 for allocation.)");/* *  Linux Fast-STREAMS Registration *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */#ifdef LFSSTATIC struct cdevsw sdlm_cdev = {	.d_name = DRV_NAME,	.d_str = &sdlminfo,	.d_flag = 0,	.d_fop = NULL,	.d_mode = S_IFCHR,	.d_kmod = THIS_MODULE,};STATIC intsdlm_register_strdev(major_t major){	int err;	if ((err = register_strdev(&sdlm_cdev, major)) < 0)		return (err);	return (0);}STATIC intsdlm_unregister_strdev(major_t major){	int err;	if ((err = unregister_strdev(&sdlm_cdev, major)) < 0)		return (err);	return (0);}#endif				/* LFS *//* *  Linux STREAMS Registration *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */#ifdef LISSTATIC intsdlm_register_strdev(major_t major){	int err;	if ((err = lis_register_strdev(major, &sdlminfo, UNITS, DRV_NAME)) < 0)		return (err);	return (0);}STATIC intsdlm_unregister_strdev(major_t major){	int err;	if ((err = lis_unregister_strdev(major)) < 0)		return (err);	return (0);}#endif				/* LIS */MODULE_STATIC void __exitsdlmterminate(void){	int err, mindex;	for (mindex = CMAJORS - 1; mindex >= 0; mindex--) {		if (sdlm_majors[mindex]) {			if ((err = sdlm_unregister_strdev(sdlm_majors[mindex])))				cmn_err(CE_PANIC, "%s: cannot unregister major %d", DRV_NAME,					sdlm_majors[mindex]);			if (mindex)				sdlm_majors[mindex] = 0;		}	}	if ((err = sdlm_term_caches()))		cmn_err(CE_WARN, "%s: could not terminate caches", DRV_NAME);	return;}MODULE_STATIC int __initsdlminit(void){	int err, mindex = 0;	cmn_err(CE_NOTE, DRV_BANNER);	/* console splash */	if ((err = sdlm_init_caches())) {		cmn_err(CE_WARN, "%s: could not init caches, err = %d", DRV_NAME, err);		sdlmterminate();		return (err);	}	for (mindex = 0; mindex < CMAJORS; mindex++) {		if ((err = sdlm_register_strdev(sdlm_majors[mindex])) < 0) {			if (mindex) {				cmn_err(CE_WARN, "%s: could not register major %d", DRV_NAME,					sdlm_majors[mindex]);				continue;			} else {				cmn_err(CE_WARN, "%s: could not register driver, err = %d",					DRV_NAME, err);				sdlmterminate();				return (err);			}		}		if (sdlm_majors[mindex] == 0)			sdlm_majors[mindex] = err;#if 0		LIS_DEVFLAGS(sdlm_majors[mindex]) |= LIS_MODFLG_CLONE;#endif		if (major == 0)			major = sdlm_majors[0];	}	return (0);}/* *  Linux Kernel Module Initialization *  ------------------------------------------------------------------------- */module_init(sdlminit);module_exit(sdlmterminate);#endif				/* LINUX */

⌨️ 快捷键说明

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