OpenSS7 SS7 for the Common Man |
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |
||||||||||||||||||||||||||
Home | Overview | Status | News | Documentation | Resources | About | |||||||||||||||||||||
File /code/strss7/modules/timod/timod.c#ident "@(#) $RCSfile: timod.c,v $ $Name: $($Revision: 0.8.2.1 $) $Date: 2003/06/16 09:04:09 $" static char const ident[] = "$RCSfile: timod.c,v $ $Name: $($Revision: 0.8.2.1 $) $Date: 2003/06/16 09:04:09 $"; #include <linux/config.h> #include <linux/version.h> #ifdef MODVERSIONS #include <linux/modversions.h> #endif #include <linux/module.h> #include <sys/stream.h> #include <sys/stropts.h> #include <sys/cmn_err.h> #include <sys/ddi.h> #include <sys/dki.h> #include <sys/tpi.h> #include <sys/xti.h> #include "../../drivers/debug.h" #include "../../drivers/priv.h" #include "../../drivers/lock.h" #include "../../drivers/queue.h" #include "../../drivers/allocb.h" #include "../../drivers/bufq.h" #define TMOD_DESCRIP "X/OPEN XNS 5.2 (TIMOD) XTI SOCKETS MODULE" "\n" \ "Part of the OpenSS7 Stack for LiS STREAMS." #define TMOD_COPYRIGHT "Copyright (c) 1997-2003 OpenSS7 Corporation. All Rights Reserved." #define TMOD_DEVICE "Supports LiS STREAMS TPI Drivers." #define TMOD_CONTACT "Brian Bidulock <bidulock@openss7.org>" #define TMOD_LICENSE "GPL" #define TMOD_BANNER TMOD_DESCRIP "\n" \ TMOD_COPYRIGHT "\n" \ TMOD_DEVICE "\n" \ TMOD_CONTACT "\n" MODULE_AUTHOR(TMOD_CONTACT); MODULE_DESCRIPTION(TMOD_DESCRIP); MODULE_SUPPORTED_DEVICE(TMOD_DEVICE); #ifdef MODULE_LICENSE MODULE_LICENSE(TMOD_LICENSE); #endif #ifdef LINUX_2_4 #define INT int #else #define INT void #endif /* * ========================================================================= * * STREAMS Definitions * * ========================================================================= */ #define TMOD_MOD_NAME "timod" #define TMOD_MOD_ID (TMOD_IOC_MAGIC<<8) static struct module_info tmod_info = { mi_idnum:TMOD_MOD_ID, /* Module ID number */ mi_idname:TMOD_MOD_NAME, /* Module name */ mi_minpsz:0, /* Min packet size accepted */ mi_maxpsz:INFPSZ, /* Max packet size accepted */ mi_hiwat:(1 << 15), /* Hi water mark */ mi_lowat:(1 << 10), /* Lo water mark */ }; static int tmod_open(queue_t *, dev_t *, int, int, cred_t *); static int tmod_close(queue_t *, int, cred_t *); static struct qinit tmod_rinit = { qi_putp:ss7_oput, /* Read put (msg from below) */ qi_qopen:tmod_open, /* Each open */ qi_qclose:tmod_close, /* Last close */ qi_minfo:&tmod_minfo, /* Information */ }; static struct qinit tmod_winit = { qi_putp:ss7_iput, /* Write put (msg from above) */ qi_minfo:&tmod_minfo, /* Information */ }; static struct streamtab tmod_info = { st_rdinit:&tmod_rinit, /* Upper read queue */ st_wrinit:&tmod_winit, /* Upper write queue */ }; /* * ========================================================================= * * Private Structure * * ========================================================================= */ typedef struct tmod { STR_DECLARATION (struct tmod); /* stream declarations */ tmod_addr_t src; /* src address */ tmod_size_t src_len; /* src address length */ tmod_addr_t dst; /* dst address */ tmod_size_t dst_len; /* dst address length */ bufq_t conq; /* connection indication queue */ uint conind; /* number of connection indications */ } tmod_t; #define TMOD_PRIV(q) ((struct tmod *)((__q)->q_ptr) /* * ------------------------------------------------------------------------- * * Private structure allocation, deallocation and cache * * ------------------------------------------------------------------------- */ STATIC kmem_cache_t *tmod_priv_cachep = NULL; STATIC int tmod_init_caches(void) { if (!tmod_priv_cachep && !(tmod_priv_cachep = kmem_cache_create ("tmod_priv_cachep", sizeof(struct tmod), 0, SLAB_HWCACHE_ALIGN, NULL, NULL))) { cmn_err(CE_PANIC, "%s: ERROR: could not allocate tmod_priv_cachep", __FUNCTION__); return (-ENOMEM); } else printd(("%s: intialized tmod private cache\n", TMOD_MOD_NAME)); return (0); } STATIC void tmod_term_caches(void) { if (tmod_priv_cachep) { if (kmem_cache_destroy(tmod_priv_cachep)) cmn_err(CE_WARN, "%s: ERROR: could not destroy tmod_priv_cachep", __FUNCTION__); else printd(("%s: destroyed tmod_priv_cachep\n", TMOD_MOD_NAME)); } return; } /* * TIMOD allocation and deallocation * ------------------------------------------------------------------------- */ STATIC struct tmod *tmod_alloc_priv(queue_t *q, struct tmod **tmodp, dev_t *devp, cred_t *crp) { struct tmod *tmod; if ((tmod = kmem_cache_alloc(tmod_priv_cachep, SLAB_ATOMIC))) { printd(("%s: %p: allocated tmod private structure\n", TMOD_MOD_NAME, tmod)); bzero(tmod, sizeof(*tmod)); tmod->u.dev.cmajor = getmajor(*devp); tmod->u.dev.cminor = getminor(*devp); tmod->cred = *crp; lis_spin_lock_init(&tmod->qlock, "tmod-queue-lock"); (tmod->oq = RD(q))->q_ptr = tmod_get(tmod); (tmod->iq = WR(q))->q_ptr = tmod_get(tmod); tmod->o_prim = &tmod_r_prim; tmod->i_prim = &tmod_w_prim; tmod->o_wakeup = NULL; tmod->i_wakeup = NULL; tmod->state = 0; /* unintialized */ lis_spin_lock_init(&tmod->lock, "tmod-lock"); if ((tmod->next = *tmodp)) tmod->next->prev = &tmod->next; tmod->prev = tmodp; *tmodp = tmod_get(tmod); printd(("%s: %p: linked tmod private structure\n", TMOD_MOD_NAME)); } else ptrace(("%s: ERROR: could not allocate tmod private structure\n", TMOD_MOD_NAME)); return (tmod); } STATIC void tmod_free_priv(queue_t *q) { struct tmod *tmod = TMOD_PRIV(q); int flags = 0; ensure(tmod, return); lis_spin_lock_irqsave(&tmod->lock, &flags); { ss7_unbufcall((str_t *) tmod); if ((*tmod->prev = tmod->next)) tmod->next->prev = tmod->prev; tmod->next = NULL; tmod->prev = &tmod->next; tmod_put(tmod); tmod->oq->q_ptr = NULL; flushq(tmod->oq, FLUSHALL); tmod->oq = NULL; tmod_put(tmod); tmod->iq->q_ptr = NULL; flushq(tmod->iq, FLUSHALL); tmod->iq = NULL; } lis_spin_lock_irqrestore(&tmod->lock, &flags); tmod_put(tmod); /* final put */ return; } STATIC struct tmod *tmod_get(struct tmod *tmod) { atomic_inc(&tmod->refcnt); return (tmod); } STATIC void tmod_put(struct tmod *tmod) { if (atomic_dec_and_test(&tmod->refcnt)) { kmem_cache_free(tmod_priv_cachep); printd(("%s: %p: freed tmod private structure\n", TMOD_MOD_NAME, tmod)); } } /* * ========================================================================= * * PROTOCOL PRIMITIVES * * ========================================================================= */ /* * ------------------------------------------------------------------------- * * Primitives from above * * ------------------------------------------------------------------------- */ /* * T_CONN_REQ * ----------------------------------- */ STATIC int t_conn_req(queue_t *q, mblk_t *mp) { } /* * T_CONN_RES * ----------------------------------- */ STATIC int t_conn_res(queue_t *q, mblk_t *mp) { } /* * T_DISCON_REQ * ----------------------------------- */ STATIC int t_discon_req(queue_t *q, mblk_t *mp) { } /* * T_DATA_REQ * ----------------------------------- */ STATIC int t_data_req(queue_t *q, mblk_t *mp) { } /* * T_EXDATA_REQ * ----------------------------------- */ STATIC int t_exdata_req(queue_t *q, mblk_t *mp) { } /* * T_INFO_REQ * ----------------------------------- */ STATIC int t_info_req(queue_t *q, mblk_t *mp) { } /* * T_BIND_REQ * ----------------------------------- */ STATIC int t_bind_req(queue_t *q, mblk_t *mp) { } /* * T_UNBIND_REQ * ----------------------------------- */ STATIC int t_unbind_req(queue_t *q, mblk_t *mp) { } /* * T_UNITDATA_REQ * ----------------------------------- */ STATIC int t_unitdata_req(queue_t *q, mblk_t *mp) { } /* * T_OPTMGMT_REQ * ----------------------------------- */ STATIC int t_optmgmt_req(queue_t *q, mblk_t *mp) { } /* * T_ORDREL_REQ * ----------------------------------- */ STATIC int t_ordrel_req(queue_t *q, mblk_t *mp) { } /* * T_OPTDATA_REQ * ----------------------------------- */ STATIC int t_optdata_req(queue_t *q, mblk_t *mp) { } /* * T_ADDR_REQ * ----------------------------------- */ STATIC int t_addr_req(queue_t *q, mblk_t *mp) { } /* * ------------------------------------------------------------------------- * * Primitives from below * * ------------------------------------------------------------------------- */ /* * T_CONN_IND * ----------------------------------- */ STATIC int t_conn_ind(queue_t *q, mblk_t *mp) { } /* * T_CONN_CON * ----------------------------------- */ STATIC int t_conn_con(queue_t *q, mblk_t *mp) { } /* * T_DISCON_IND * ----------------------------------- */ STATIC int t_discon_ind(queue_t *q, mblk_t *mp) { } /* * T_DATA_IND * ----------------------------------- */ STATIC int t_data_ind(queue_t *q, mblk_t *mp) { } /* * T_EXDATA_IND * ----------------------------------- */ STATIC int t_exdata_ind(queue_t *q, mblk_t *mp) { } /* * T_INFO_ACK * ----------------------------------- */ STATIC int t_info_ack(queue_t *q, mblk_t *mp) { } /* * T_BIND_ACK * ----------------------------------- */ STATIC int t_bind_ack(queue_t *q, mblk_t *mp) { } /* * T_ERROR_ACK * ----------------------------------- */ STATIC int t_error_ack(queue_t *q, mblk_t *mp) { } /* * T_OK_ACK * ----------------------------------- */ STATIC int t_ok_ack(queue_t *q, mblk_t *mp) { } /* * T_UNITDATA_IND * ----------------------------------- */ STATIC int t_unitdata_ind(queue_t *q, mblk_t *mp) { } /* * T_UDERROR_IND * ----------------------------------- */ STATIC int t_uderror_ind(queue_t *q, mblk_t *mp) { } /* * T_OPTMGMT_ACK * ----------------------------------- */ STATIC int t_optmgmt_ack(queue_t *q, mblk_t *mp) { } /* * T_ORDREL_IND * ----------------------------------- */ STATIC int t_ordrel_ind(queue_t *q, mblk_t *mp) { } /* * T_OPTDATA_IND * ----------------------------------- */ STATIC int t_optdata_ind(queue_t *q, mblk_t *mp) { } /* * T_ADDR_ACK * ----------------------------------- */ STATIC int t_addr_ack(queue_t *q, mblk_t *mp) { } /* * ========================================================================= * * I/O Controls * * ========================================================================= */ /* * TI_GETINFO * ----------------------------------- */ STATIC int tmod_ti_getinfo(queue_t *q, mblk_t *mp, int *rvp) { struct tmod *tmod = TMOD_PRIV(q); struct iocblk *iocp = (typeof(iocp)) mp->b_rptr; struct copyresp *resp = (typeof(resp)) mp->b_rptr; switch (mp->b_datap->db_type) { case M_IOCTL: break; case M_IOCDATA: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * TI_OPTMGMT * ----------------------------------- */ STATIC int tmod_ti_optmgmt(queue_t *q, mblk_t *mp, int *rvp) { struct tmod *tmod = TMOD_PRIV(q); struct iocblk *iocp = (typeof(iocp)) mp->b_rptr; struct copyresp *resp = (typeof(resp)) mp->b_rptr; switch (mp->b_datap->db_type) { case M_IOCTL: break; case M_IOCDATA: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * TI_BIND * ----------------------------------- */ STATIC int tmod_ti_bind(queue_t *q, mblk_t *mp, int *rvp) { struct tmod *tmod = TMOD_PRIV(q); struct iocblk *iocp = (typeof(iocp)) mp->b_rptr; struct copyresp *resp = (typeof(resp)) mp->b_rptr; switch (mp->b_datap->db_type) { case M_IOCTL: break; case M_IOCDATA: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * TI_UNBIND * ----------------------------------- */ STATIC int tmod_ti_unbind(queue_t *q, mblk_t *mp, int *rvp) { struct tmod *tmod = TMOD_PRIV(q); struct iocblk *iocp = (typeof(iocp)) mp->b_rptr; struct copyresp *resp = (typeof(resp)) mp->b_rptr; switch (mp->b_datap->db_type) { case M_IOCTL: break; case M_IOCDATA: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * TI_GETMYNAME * ----------------------------------- */ STATIC int tmod_ti_getmyname(queue_t *q, mblk_t *mp, int *rvp) { struct tmod *tmod = TMOD_PRIV(q); struct iocblk *iocp = (typeof(iocp)) mp->b_rptr; struct copyresp *resp = (typeof(resp)) mp->b_rptr; switch (mp->b_datap->db_type) { case M_IOCTL: break; case M_IOCDATA: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * TI_GETPEERNAME * ----------------------------------- */ STATIC int tmod_ti_getpeername(queue_t *q, mblk_t *mp, int *rvp) { struct tmod *tmod = TMOD_PRIV(q); struct iocblk *iocp = (typeof(iocp)) mp->b_rptr; struct copyresp *resp = (typeof(resp)) mp->b_rptr; switch (mp->b_datap->db_type) { case M_IOCTL: break; case M_IOCDATA: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * TI_SETMYNAME * ----------------------------------- */ STATIC int tmod_ti_setmyname(queue_t *q, mblk_t *mp, int *rvp) { struct tmod *tmod = TMOD_PRIV(q); struct iocblk *iocp = (typeof(iocp)) mp->b_rptr; struct copyresp *resp = (typeof(resp)) mp->b_rptr; switch (mp->b_datap->db_type) { case M_IOCTL: break; case M_IOCDATA: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * TI_SETPEERNAME * ----------------------------------- */ STATIC int tmod_ti_setpeername(queue_t *q, mblk_t *mp, int *rvp) { struct tmod *tmod = TMOD_PRIV(q); struct iocblk *iocp = (typeof(iocp)) mp->b_rptr; struct copyresp *resp = (typeof(resp)) mp->b_rptr; switch (mp->b_datap->db_type) { case M_IOCTL: break; case M_IOCDATA: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (tmod->ioc_state) { case TMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * ========================================================================= * * STREAMS Message Handling * * ========================================================================= * * M_IOCTL Handling * * ------------------------------------------------------------------------- */ STATIC int tmod_w_ioctl(queue_t *q, mblk_t *mp) { struct tmod *tmod = TMOD_PRIV(q); struct iocblk *iocp = (typeof(iocp)) 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 err = -EOPNOTSUPP, ret = -1; switch (type) { case TMOD_IOC_MAGIC: { /* These are TIMOD IOCTLs */ switch (nr) { case _IOC_NR(TI_GETINFO): printd(("%s: %p: -> TI_GETINFO\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_getinfo(q, mp, &ret); break; case _IOC_NR(TI_OPTMGMT): printd(("%s: %p: -> TI_OPTMGMT\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_optmgmt(q, mp, &ret); break; case _IOC_NR(TI_BIND): printd(("%s: %p: -> TI_BIND\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_bind(q, mp, &ret); break; case _IOC_NR(TI_UNBIND): printd(("%s: %p: -> TI_UNBIND\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_unbind(q, mp, &ret); break; case _IOC_NR(TI_GETMYNAME): printd(("%s: %p: -> TI_GETMYNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_getmyname(q, mp, &ret); break; case _IOC_NR(TI_GETPEERNAME): printd(("%s: %p: -> TI_GETPEERNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_getpeername(q, mp, &ret); break; case _IOC_NR(TI_SETMYNAME): printd(("%s: %p: -> TI_SETMYNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_setmyname(q, mp, &ret); break; case _IOC_NR(TI_SETPEERNAME): printd(("%s: %p: -> TI_SETPEERNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_setpeername(q, mp, &ret); break; default: ptrace(("%s: %p: ERROR: Unsupported TIMOD ioctl %c, %d\n", SOCK_MOD_NAME, tmod(char) type, nr)); break; } break; } default: ptrace(("%s: %p: ERROR: Unsupported ioctl %c, %d\n", SOCK_MOD_NAME, tmod, (char) type, nr)); break; } if (err > 0) return (err); else if (err == 0) mp->b_datap->db_type = M_IOCACK; else mp->b_datap->db_type = M_IOCNAK; iocp->ioc_error = -err; iocp->ioc_rval = ret; qreply(q, mp); return (QR_ABSORBED); } /* * ------------------------------------------------------------------------- * * M_IOCDATA Handling * * ------------------------------------------------------------------------- */ STATIC int tmod_w_iocdata(queue_t *q, mblk_t *mp) { struct tmod *tmod = TMOD_PRIV(q); struct copyresp *resp = (typeof(resp)) mp->b_rptr; mblk_t *dp = mp->b_cont; void *arg = dp ? dp->b_rptr : NULL; int cmd = resp->cp_cmd, count = dp ? dp->b_wptr - dp->b_rptr : 0; int type = _IOC_TYPE(cmd), nr = _IOC_NR(cmd), size = _IOC_SIZE(cmd); int err = -EOPNOTSUPP, ret = -1; if (resp->cp_rval != 0) goto efault; if (tmod->ioc_state == IOC_STATE_NULL) goto einval; switch (type) { case TMOD_IOC_MAGIC: { /* These are TIMOD IOCTLs */ switch (nr) { case _IOC_NR(TI_GETINFO): printd(("%s: %p: -> TI_GETINFO\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_getinfo(q, mp, &ret); break; case _IOC_NR(TI_OPTMGMT): printd(("%s: %p: -> TI_OPTMGMT\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_optmgmt(q, mp, &ret); break; case _IOC_NR(TI_BIND): printd(("%s: %p: -> TI_BIND\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_bind(q, mp, &ret); break; case _IOC_NR(TI_UNBIND): printd(("%s: %p: -> TI_UNBIND\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_unbind(q, mp, &ret); break; case _IOC_NR(TI_GETMYNAME): printd(("%s: %p: -> TI_GETMYNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_getmyname(q, mp, &ret); break; case _IOC_NR(TI_GETPEERNAME): printd(("%s: %p: -> TI_GETPEERNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_getpeername(q, mp, &ret); break; case _IOC_NR(TI_SETMYNAME): printd(("%s: %p: -> TI_SETMYNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_setmyname(q, mp, &ret); break; case _IOC_NR(TI_SETPEERNAME): printd(("%s: %p: -> TI_SETPEERNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_setpeername(q, mp, &ret); break; default: ptrace(("%s: %p: ERROR: Unsupported TIMOD ioctl %c, %d\n", SOCK_MOD_NAME, tmod(char) type, nr)); break; } break; } default: ptrace(("%s: %p: ERROR: Unsupported ioctl %c, %d\n", SOCK_MOD_NAME, tmod, (char) type, nr)); break; } done: if (err > 0) return (err); else if (err == 0) mp->b_datap->db_type = M_IOCACK; else mp->b_datap->db_type = M_IOCNAK; iocp->ioc_error = -err; iocp->ioc_rval = ret; qreply(q, mp); return (QR_ABSORBED); efault: err = -EFAULT; ret = -1; goto done; einval: err = -EINVAL; ret = -1; goto done; } /* * ------------------------------------------------------------------------- * * M_IOCACK, M_IOCNAK Handling * * ------------------------------------------------------------------------- */ STATIC int tmod_r_iocack(queue_t *q, mblk_t *mp) { struct tmod *tmod = TMOD_PRIV(q); struct iocblk *iocp = (typeof(iocp)) mp->b_rptr; mblk_t *bp = mp->b_cont; void *arg = bp ? bp->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 err = QR_PASSALONG, ret = -1; if (iocp->ioc_id != ss->ioc_id) goto passalong; switch (type) { case TMOD_IOC_MAGIC: { /* These are TIMOD IOCTLs */ switch (nr) { case _IOC_NR(TI_GETINFO): printd(("%s: %p: -> TI_GETINFO\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_getinfo(q, mp, &ret); break; case _IOC_NR(TI_OPTMGMT): printd(("%s: %p: -> TI_OPTMGMT\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_optmgmt(q, mp, &ret); break; case _IOC_NR(TI_BIND): printd(("%s: %p: -> TI_BIND\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_bind(q, mp, &ret); break; case _IOC_NR(TI_UNBIND): printd(("%s: %p: -> TI_UNBIND\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_unbind(q, mp, &ret); break; case _IOC_NR(TI_GETMYNAME): printd(("%s: %p: -> TI_GETMYNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_getmyname(q, mp, &ret); break; case _IOC_NR(TI_GETPEERNAME): printd(("%s: %p: -> TI_GETPEERNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_getpeername(q, mp, &ret); break; case _IOC_NR(TI_SETMYNAME): printd(("%s: %p: -> TI_SETMYNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_setmyname(q, mp, &ret); break; case _IOC_NR(TI_SETPEERNAME): printd(("%s: %p: -> TI_SETPEERNAME\n", TMOD_MOD_NAME, tmod)); err = tmod_ti_setpeername(q, mp, &ret); break; default: ptrace(("%s: %p: ERROR: Unsupported TIMOD ioctl %c, %d\n", SOCK_MOD_NAME, tmod(char) type, nr)); break; } break; } } done: if (err > 0) return (err); else if (err == 0) mp->b_datap->db_type = M_IOCACK; else mp->b_datap->db_type = M_IOCNAK; iocp->ioc_error = -err; iocp->ioc_rval = ret; putnext(q, mp); return (QR_ABSORBED); efault: err = -EFAULT; ret = -1; goto done; passalong: err = QR_PASSALONG; ret = 0; goto done; } /* * ------------------------------------------------------------------------- * * M_PROTO, M_PCPROTO Handling * * ------------------------------------------------------------------------- */ /* * Primitives from TIMOD user to TIMOD * ----------------------------------------------------------- */ STATIC int tmod_w_proto(queue_t *q, mblk_t *mp) { struct tmod *tmod = TMOD_PRIV(q); int rtn; ulong prim; (void) tmod; switch ((prim = *(ulong *) mp->b_rptr)) { case T_CONN_REQ: printd(("%s: %p: -> T_CONN_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_conn_req(q, mp); break; case T_CONN_RES: printd(("%s: %p: -> T_CONN_RES\n", TMOD_MOD_NAME, tmod)); rtn = t_conn_res(q, mp); break; case T_DISCON_REQ: printd(("%s: %p: -> T_DISCON_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_discon_req(q, mp); break; case T_DATA_REQ: printd(("%s: %p: -> T_DATA_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_data_req(q, mp); break; case T_EXDATA_REQ: printd(("%s: %p: -> T_EXDATA_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_exdata_req(q, mp); break; case T_INFO_REQ: printd(("%s: %p: -> T_INFO_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_info_req(q, mp); break; case T_BIND_REQ: printd(("%s: %p: -> T_BIND_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_bind_req(q, mp); break; case T_UNBIND_REQ: printd(("%s: %p: -> T_UNBIND_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_unbind_req(q, mp); break; case T_UNITDATA_REQ: printd(("%s: %p: -> T_UNITDATA_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_unitdata_req(q, mp); break; case T_OPTMGMT_REQ: printd(("%s: %p: -> T_OPTMGMT_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_optmgmt_req(q, mp); break; case T_ORDREL_REQ: printd(("%s: %p: -> T_ORDREL_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_ordrel_req(q, mp); break; case T_OPTDATA_REQ: printd(("%s: %p: -> T_OPTDATA_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_optdata_req(q, mp); break; case T_ADDR_REQ: printd(("%s: %p: -> T_ADDR_REQ\n", TMOD_MOD_NAME, tmod)); rtn = t_addr_req(q, mp); break; default: printd(("%s: %p: -> T_????\n", TMOD_MOD_NAME, tmod)); rtn = QR_PASSALONG; break; } return (rtn); } /* * Primitives from TPI provider to TIMOD * ----------------------------------------------------------- */ STATIC int tmod_r_proto(queue_t *q, mblk_t *mp) { struct tmod *tmod = TMOD_PRIV(q); int rtn; ulong prim; (void) tmod; switch ((prim = *(ulong *) mp->b_rptr)) { case T_CONN_IND: printd(("%s: %p: T_CONN_IND <-\n", TMOD_MOD_NAME, tmod)); rtn = t_conn_ind(q, mp); break; case T_CONN_CON: printd(("%s: %p: T_CONN_CON <-\n", TMOD_MOD_NAME, tmod)); rtn = t_conn_con(q, mp); break; case T_DISCON_IND: printd(("%s: %p: T_DISCON_IND <-\n", TMOD_MOD_NAME, tmod)); rtn = t_discon_ind(q, mp); break; case T_DATA_IND: printd(("%s: %p: T_DATA_IND <-\n", TMOD_MOD_NAME, tmod)); rtn = t_data_ind(q, mp); break; case T_EXDATA_IND: printd(("%s: %p: T_EXDATA_IND <-\n", TMOD_MOD_NAME, tmod)); rtn = t_exdata_ind(q, mp); break; case T_INFO_ACK: printd(("%s: %p: T_INFO_ACK <-\n", TMOD_MOD_NAME, tmod)); rtn = t_info_ack(q, mp); break; case T_BIND_ACK: printd(("%s: %p: T_BIND_ACK <-\n", TMOD_MOD_NAME, tmod)); rtn = t_bind_ack(q, mp); break; case T_ERROR_ACK: printd(("%s: %p: T_ERROR_ACK <-\n", TMOD_MOD_NAME, tmod)); rtn = t_error_ack(q, mp); break; case T_OK_ACK: printd(("%s: %p: T_OK_ACK <-\n", TMOD_MOD_NAME, tmod)); rtn = t_ok_ack(q, mp); break; case T_UNITDATA_IND: printd(("%s: %p: T_UNITDATA_IND <-\n", TMOD_MOD_NAME, tmod)); rtn = t_unitdata_ind(q, mp); break; case T_UDERROR_IND: printd(("%s: %p: T_UDERROR_IND <-\n", TMOD_MOD_NAME, tmod)); rtn = t_uderror_ind(q, mp); break; case T_OPTMGMT_ACK: printd(("%s: %p: T_OPTMGMT_ACK <-\n", TMOD_MOD_NAME, tmod)); rtn = t_optmgmt_ack(q, mp); break; case T_ORDREL_IND: printd(("%s: %p: T_ORDREL_IND <-\n", TMOD_MOD_NAME, tmod)); rtn = t_ordrel_ind(q, mp); break; case T_OPTDATA_IND: printd(("%s: %p: T_OPTDATA_IND <-\n", TMOD_MOD_NAME, tmod)); rtn = t_optdata_ind(q, mp); break; case T_ADDR_ACK: printd(("%s: %p: T_ADDR_ACK <-\n", TMOD_MOD_NAME, tmod)); rtn = t_addr_ack(q, mp); break; default: printd(("%s: %p: T_???? <-\n", TMOD_MOD_NAME, tmod)); rtn = QR_PASSALONG; break; } return (rtn); } /* * ------------------------------------------------------------------------- * * M_DATA Handling * * ------------------------------------------------------------------------- */ STATIC INLINE int tmod_w_data(queue_t *q, mblk_t *mp) { /* data from above */ printd(("%s: %p: -> M_DATA\n", TMOD_MOD_NAME, TMOD_PRIV(q))); return (QR_PASSFLOW); } STATIC INLINE int tmod_r_data(queue_t *q, mblk_t *mp) { /* data from below */ printd(("%s: %p: M_DATA <-\n", TMOD_MOD_NAME, TMOD_PRIV(q))); return (QR_PASSFLOW); } /* * ------------------------------------------------------------------------- * * M_ERROR, M_HANGUP Handling * * ------------------------------------------------------------------------- */ STATIC int tmod_r_error(queue_t *q, mblk_t *mp) { printd(("%s: %p: M_ERROR <-\n", TMOD_MOD_NAME, TMOD_PRIV(q))); tmod->state = TMODS_UNUSABLE; return (QR_PASSALONG); } STATIC int tmod_r_hangup(queue_t *q, mblk_t *mp) { printd(("%s: %p: M_HANGUP <-\n", TMOD_MOD_NAME, TMOD_PRIV(q))); tmod->state = TMODS_UNUSABLE; return (QR_PASSALONG); } /* * ========================================================================= * * PUT and SRV * * ========================================================================= */ STATIC INLINE int tmod_w_prim(queue_t *q, mblk_t *mp) { ulong type; /* Fast Path */ if ((type = mp->b_datap->db_type) == M_DATA) return tmod_w_data(q, mp); switch (type) { case M_DATA: return tmod_w_data(q, mp); case M_PROTO: case M_PCPROTO: return tmod_w_proto(q, mp); case M_FLUSH: return ss7_w_flush(q, mp); case M_IOCTL: return tmod_w_ioctl(q, mp); case M_IOCDATA: return tmod_w_iocdata(q, mp); } return (QR_PASSALONG); } STATIC INLINE int tmod_r_prim(queue_t *q, mblk_t *mp) { ulong type; /* Fast Path */ if ((type = mp->b_datap->db_type) == M_DATA) return tmod_r_data(q, mp); switch (type) { case M_DATA: return tmod_r_data(q, mp); case M_PROTO: case M_PCPROTO: return tmod_r_proto(q, mp); case M_FLUSH: return ss7_r_flush(q, mp); case M_IOCACK: case M_IOCNAK: return tmod_r_iocack(q, mp); case M_ERROR: return tmod_r_error(q, mp); case M_HANGUP: return tmod_r_hangup(q, mp); } return (QR_PASSALONG); } /* * ========================================================================= * * OPEN and CLOSE * * ========================================================================= */ STATIC int tmod_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp) { int err; MOD_INC_USE_COUNT; /* keep module from unloading */ if (q->q_ptr != NULL) { MOD_DEC_USE_COUNT; return (0); /* already open */ } if (sflag == MODOPEN || WR(q)->q_next != NULL) { int cmajor = getmajor(*devp); int cminor = getminor(*devp); struct tmod *tmod; for (tmod = tmod_opens; tmod; tmod = tmod->next) { if (tmod->u.dev.cmajor == cmajor && tmod->u.dev.cminor == cminor) { MOD_DEC_USE_COUNT; return (ENXIO); /* double push */ } } if (!tmod_alloc_priv(q, &tmod_opens, devp, crp)) { MOD_DEC_USE_COUNT; return (ENOMEM); } /* generate immediate information request */ if ((err = t_info_req(q)) < 0) { tmod_free_priv(q); MOD_DEC_USE_COUNT; return (-err); } return (0); } MOD_DEC_USE_COUNT; return (EIO); /* can't be opened as driver */ } STATIC int tmod_close(queue_t *q, int flag, cred_t *crp) { (void) flag; (void) crp; tmod_free_priv(q); MOD_DEC_USE_COUNT; return (0); } /* * ========================================================================= * * LiS Module Initialization * * ========================================================================= */ STAIC int tmod_initialized = 0; void tmod_init(void) { unless(tmod_initialized > 0, return); cmn_err(CE_NOTE, TMOD_BANNER); /* console splash */ if ((tmod_initialized = tmod_init_caches())) { cmn_err(CE_PANIC, "%s: ERROR: could not allocate caches", TMOD_MOD_NAME); } else if ((tmod_initialized = lis_register_strmod(&tmod_info, TMOD_NOD_NAME)) < 0) { cmn_err(CE_WARN, "%s: ERROR: could not register module", TMOD_MOD_NAME); tmod_term_caches(); } return; } void tmod_term(void) { ensure(tmod_initialized > 0, return); if ((tmod_initialized = lis_unregister_strmod(&tmod_info)) < 0) { cmn_err(CE_PANIC, "%s: ERROR: could not unregister module", TMOD_MOD_NAME); } else { tmod_term_caches(); } return; } /* * ========================================================================= * * Kernel Module Initialization * * ========================================================================= */ int init_module(void) { tmod_init(); if (tmod_initialized < 0) return tmod_initialized; return (0); } void cleanup_module(void) { tmod_terminate(); return; }
|
|||||||||||||||||||||||||||
OpenSS7 SS7 for the Common Man |
Home | Overview | Status | News | Documentation | Resources | About | ||||||||||||||||||||
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |