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/sockmod/sockmod.c#ident "@(#) $RCSfile: sockmod.c,v $ $Name: $($Revision: 0.8.2.1 $) $Date: 2003/05/27 09:52:34 $" static char const ident[] = "$RCSfile: sockmod.c,v $ $Name: $($Revision: 0.8.2.1 $) $Date: 2003/05/27 09:52:34 $"; #include <linux/config.h> #include <linux/version.h> #include <linux/modversions.h> #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 SMOD_DESCRIP "SVR3 STYLE (SOCKMOD) SOCKETS MODULE" "\n" \ "Part of the OpenSS7 Stack for LiS STREAMS." #define SMOD_COPYRIGHT "Copyright (c) 1997-2003 OpenSS7 Corporation. All Rights Reserved." #define SMOD_DEVICE "Supports LiS STREAMS TPI Drivers." #define SMOD_CONTACT "Brian Bidulock <bidulock@openss7.org>" #define SMOD_LICENSE "GPL" #define SMOD_BANNER SMOD_DESCRIP "\n" \ SMOD_COPYRIGHT "\n" \ SMOD_DEVICE "\n" \ SMOD_CONTACT "\n" MODULE_AUTHOR(SMOD_CONTACT); MODULE_DESCRIPTION(SMOD_DESCRIP); MODULE_SUPPORTED_DEVICE(SMOD_DEVICE); #ifdef MODULE_LICENSE MODULE_LICENSE(SMOD_LICENSE); #endif #ifdef LINUX_2_4 #define INT int #else #define INT void #endif /* * ========================================================================= * * STREAMS Definitions * * ========================================================================= */ #define SMOD_MOD_NAME "sockmod" #define SMOD_MOD_ID (SMOD_IOC_MAGIC<<8) static struct module_info smod_minfo = { mi_idnum:SMOD_MOD_ID, /* Module ID number */ mi_idname:SMOD_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 smod_open(queue_t *, dev_t *, int, int, cred_t *); static int smod_close(queue_t *, int, cred_t *); static struct qinit smod_rinit = { qi_putp:ss7_oput, /* Read put (msg from below) */ qi_qopen:smod_open, /* Each open */ qi_qclose:smod_close, /* Last close */ qi_minfo:&smod_minfo, /* Information */ }; static struct qinit smod_winit = { qi_putp:ss7_iput, /* Write put (msg from above) */ qi_minfo:&smod_minfo, /* Information */ }; static struct streamtab smod_info = { st_rdinit:&smod_rinit, /* Upper read queue */ st_wrinit:&smod_winit, /* Upper write queue */ }; /* * ========================================================================= * * Private Structure * * ========================================================================= */ typedef struct smod { STR_DECLARATION (struct smod); /* stream declarations */ smod_addr_t src; /* src address */ smod_size_t src_len; /* src address length */ smod_addr_t dst; /* src address */ smod_size_t dst_len; /* dst address length */ bufq_t conq; /* connection indication queue */ uint conind; /* number of connection indications */ } smod_t; #define SMOD_PRIV(q) ((struct smod *)((__q)->q_ptr)) /* * ------------------------------------------------------------------------- * * Private Structure allocation, deallocation and cache * * ------------------------------------------------------------------------- */ STATIC kmem_cache_t *smod_priv_cachep = NULL; STATIC int smod_init_caches(void) { if (!smod_priv_cachep && !(smod_priv_cachep = kmem_cache_create ("smod_priv_cachep", sizeof(struct smod), 0, SLAB_HWCACHE_ALIGN, NULL, NULL))) { cmn_err(CE_PANIC, "%s: ERROR: could not allocate smod_priv_cachep", __FUNCTION__); return (-ENOMEM); } else printd(("%s: initialized smod private cache\n", SMOD_MOD_NAME)); return (0); } STATIC void smod_term_caches(void) { if (smod_priv_cachep) { if (kmem_cache_destroy(smod_priv_cachep)) cmn_err(CE_WARN, "%s: ERROR: could not destroy smod_priv_cachep", __FUNCTION__); else printd(("%s: destroyed smod_priv_cachep\n", SMOD_MOD_NAME)); } return; } /* * SOCKMOD allocation and deallocation * ------------------------------------------------------------------------- */ STATIC struct smod *smod_alloc_priv(queue_t *q, struct smod **smodp, dev_t *devp, cred_t *crp) { struct smod *smod; if ((smod = kmem_cache_alloc(smod_priv_cachep, SLAB_ATOMIC))) { printd(("%s: %p: allocated smod private structure\n", SMOD_MOD_NAME, smod)); bzero(smod, sizeof(*smod)); smod->u.dev.cmajor = getmajor(*devp); smod->u.dev.cminor = getminor(*devp); smod->cred = *crp; lis_spin_lock_init(&smod->qlock, "smod-queue-lock"); (smod->oq = RD(q))->q_ptr = smod_get(smod); (smod->iq = WR(q))->q_ptr = smod_get(smod); smod->o_prim = &smod_r_prim; smod->i_prim = &smod_w_prim; smod->o_wakeup = NULL; smod->i_wakeup = NULL; smod->state = 0; /* unintialized */ lis_spin_lock_init(&smod->lock, "smod-lock"); if ((smod->next = *smodp)) smod->next->prev = &smod->next; smod->prev = smodp; *smodp = smod_get(smod); printd(("%s: %p: linked sockmod private structure\n", SMOD_MOD_NAME)); } else ptrace(("%s: ERROR: could not allocate smod private structure\n", SMOD_MOD_NAME)); return (smod); } STATIC void smod_free_priv(queue_t *q) { struct smod *smod = SMOD_PRIV(q); int flags = 0; ensure(smod, return); lis_spin_lock_irqsave(&smod->lock, &flags); { ss7_unbufcall((str_t *) smod); if ((*smod->prev = smod->next)) smod->next->prev = smod->prev; smod->next = NULL; smod->prev = &smod->next; smod_put(smod); smod->oq->q_ptr = NULL; flushq(smod->oq, FLUSHALL); smod->oq = NULL; smod_put(smod); smod->iq->q_ptr = NULL; flushq(smod->iq, FLUSHALL); smod->iq = NULL; } lis_spin_lock_irqrestore(&smod->lock, &flags); smod_put(smod); /* final put */ return; } STATIC struct smod *smod_get(struct smod *smod) { atomic_inc(&smod->refcnt); return (smod); } STATIC void smod_put(struct smod *smod) { if (atomic_dec_and_test(&smod->refcnt)) { kmem_cache_free(smod_priv_cachep); printd(("%s: %p: freed smod private structure\n", SMOD_MOD_NAME, smod)); } } /* * ========================================================================= * * 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 * * ========================================================================= */ /* * O_SI_GETUDATA * ----------------------------------- */ STATIC int smod_o_si_getudata(queue_t *q, mblk_t *mp, int *rvp) { struct smod *smod = SMOD_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 (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * SI_SHUTDOWN * ----------------------------------- */ STATIC int smod_si_shutdown(queue_t *q, mblk_t *mp, int *rvp) { struct smod *smod = SMOD_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 (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * SI_LISTEN * ----------------------------------- */ STATIC int smod_si_listen(queue_t *q, mblk_t *mp, int *rvp) { struct smod *smod = SMOD_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 (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * SI_SETMYNAME * ----------------------------------- */ STATIC int smod_si_setmyname(queue_t *q, mblk_t *mp, int *rvp) { struct smod *smod = SMOD_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 (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * SI_SETPEERNAME * ----------------------------------- */ STATIC int smod_si_setpeername(queue_t *q, mblk_t *mp, int *rvp) { struct smod *smod = SMOD_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 (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * SI_GETINTRANSIT * ----------------------------------- */ STATIC int smod_si_getintransit(queue_t *q, mblk_t *mp, int *rvp) { struct smod *smod = SMOD_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 (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * SI_TCL_LINK * ----------------------------------- */ STATIC int smod_si_tcl_link(queue_t *q, mblk_t *mp, int *rvp) { struct smod *smod = SMOD_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 (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * SI_TCL_UNLINK * ----------------------------------- */ STATIC int smod_si_tcl_unlink(queue_t *q, mblk_t *mp, int *rvp) { struct smod *smod = SMOD_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 (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * SI_SOCKPARAMS * ----------------------------------- */ STATIC int smod_si_sockparams(queue_t *q, mblk_t *mp, int *rvp) { struct smod *smod = SMOD_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 (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * SI_GETUDATA * ----------------------------------- */ STATIC int smod_si_getudata(queue_t *q, mblk_t *mp, int *rvp) { struct smod *smod = SMOD_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 (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCACK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; case M_IOCNAK: switch (smod->ioc_state) { case SMOD_IOCS_NULL: *rvp = -1; return (-EINVAL); } break; default: *rvp = -1; return (-EINVAL); } } /* * ========================================================================= * * STREAMS Message Handling * * ========================================================================= * * M_IOCTL Handling * * ------------------------------------------------------------------------- */ STATIC int smod_w_ioctl(queue_t *q, mblk_t *mp) { struct smod *smod = SMOD_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 SMOD_IOC_MAGIC: { /* These are SOCKMOD IOCTLs */ switch (nr) { case _IOC_NR(O_SI_GETUDATA): printd(("%s: %p: -> O_SI_GETUDATA\n", SMOD_MOD_NAME, smod)); err = smod_o_si_getudata(q, mp, &ret); break; case _IOC_NR(SI_SHUTDOWN): printd(("%s: %p: -> SI_SHUTDOWN\n", SMOD_MOD_NAME, smod)); err = smod_si_shutdown(q, mp, &ret); break; case _IOC_NR(SI_LISTEN): printd(("%s: %p: -> SI_LISTEN\n", SMOD_MOD_NAME, smod)); err = smod_si_listen(q, mp, &ret); break; case _IOC_NR(SI_SETMYNAME): printd(("%s: %p: -> SI_SETMYNAME\n", SMOD_MOD_NAME, smod)); err = smod_si_setmyname(q, mp, &ret); break; case _IOC_NR(SI_SETPEERNAME): printd(("%s: %p: -> SI_SETPEERNAME\n", SMOD_MOD_NAME, smod)); err = smod_si_setpeername(q, mp, &ret); break; case _IOC_NR(SI_GETINTRANSIT): printd(("%s: %p: -> SI_GETINTRANSIT\n", SMOD_MOD_NAME, smod)); err = smod_si_getintransit(q, mp, &ret); break; case _IOC_NR(SI_TCL_LINK): printd(("%s: %p: -> SI_TCL_LINK\n", SMOD_MOD_NAME, smod)); err = smod_si_tcl_link(q, mp, &ret); break; case _IOC_NR(SI_TCL_UNLINK): printd(("%s: %p: -> SI_TCL_UNLINK\n", SMOD_MOD_NAME, smod)); err = smod_si_tcl_unlink(q, mp, &ret); break; case _IOC_NR(SI_SOCKPARAMS): printd(("%s: %p: -> SI_SOCKPARAMS\n", SMOD_MOD_NAME, smod)); err = smod_si_sockparams(q, mp, &ret); break; case _IOC_NR(SI_GETUDATA): printd(("%s: %p: -> SI_GETUDATA\n", SMOD_MOD_NAME, smod)); err = smod_si_getudata(q, mp, &ret); break; default: ptrace(("%s: %p: ERROR: Unsupported SOCKMOD ioctl %c, %d\n", SOCK_MOD_NAME, smod(char) type, nr)); break; } break; } default: ptrace(("%s: %p: ERROR: Unsupported ioctl %c, %d\n", SOCK_MOD_NAME, smod, (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 smod_w_iocdata(queue_t *q, mblk_t *mp) { struct smod *smod = SMOD_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 (smod->ioc_state == IOC_STATE_NULL) goto einval; switch (type) { case SMOD_IOC_MAGIC: { /* These are SOCKMOD IOCTLs */ switch (nr) { case _IOC_NR(O_SI_GETUDATA): printd(("%s: %p: -> O_SI_GETUDATA\n", SMOD_MOD_NAME, smod)); err = smod_o_si_getudata(q, mp, &ret); break; case _IOC_NR(SI_SHUTDOWN): printd(("%s: %p: -> SI_SHUTDOWN\n", SMOD_MOD_NAME, smod)); err = smod_si_shutdown(q, mp, &ret); break; case _IOC_NR(SI_LISTEN): printd(("%s: %p: -> SI_LISTEN\n", SMOD_MOD_NAME, smod)); err = smod_si_listen(q, mp, &ret); break; case _IOC_NR(SI_SETMYNAME): printd(("%s: %p: -> SI_SETMYNAME\n", SMOD_MOD_NAME, smod)); err = smod_si_setmyname(q, mp, &ret); break; case _IOC_NR(SI_SETPEERNAME): printd(("%s: %p: -> SI_SETPEERNAME\n", SMOD_MOD_NAME, smod)); err = smod_si_setpeername(q, mp, &ret); break; case _IOC_NR(SI_GETINTRANSIT): printd(("%s: %p: -> SI_GETINTRANSIT\n", SMOD_MOD_NAME, smod)); err = smod_si_getintransit(q, mp, &ret); break; case _IOC_NR(SI_TCL_LINK): printd(("%s: %p: -> SI_TCL_LINK\n", SMOD_MOD_NAME, smod)); err = smod_si_tcl_link(q, mp, &ret); break; case _IOC_NR(SI_TCL_UNLINK): printd(("%s: %p: -> SI_TCL_UNLINK\n", SMOD_MOD_NAME, smod)); err = smod_si_tcl_unlink(q, mp, &ret); break; case _IOC_NR(SI_SOCKPARAMS): printd(("%s: %p: -> SI_SOCKPARAMS\n", SMOD_MOD_NAME, smod)); err = smod_si_sockparams(q, mp, &ret); break; case _IOC_NR(SI_GETUDATA): printd(("%s: %p: -> SI_GETUDATA\n", SMOD_MOD_NAME, smod)); err = smod_si_getudata(q, mp, &ret); break; default: ptrace(("%s: %p: ERROR: Unsupported SOCKMOD ioctl %c, %d\n", SOCK_MOD_NAME, smod(char) type, nr)); break; } break; } default: ptrace(("%s: %p: ERROR: Unsupported ioctl %c, %d\n", SOCK_MOD_NAME, smod, (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 smod_r_iocack(queue_t *q, mblk_t *mp) { struct smod *smod = SMOD_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 SMOD_IOC_MAGIC: { /* These are SOCKMOD IOCTLs */ switch (nr) { case _IOC_NR(O_SI_GETUDATA): printd(("%s: %p: -> O_SI_GETUDATA\n", SMOD_MOD_NAME, smod)); err = smod_o_si_getudata(q, mp, &ret); break; case _IOC_NR(SI_SHUTDOWN): printd(("%s: %p: -> SI_SHUTDOWN\n", SMOD_MOD_NAME, smod)); err = smod_si_shutdown(q, mp, &ret); break; case _IOC_NR(SI_LISTEN): printd(("%s: %p: -> SI_LISTEN\n", SMOD_MOD_NAME, smod)); err = smod_si_listen(q, mp, &ret); break; case _IOC_NR(SI_SETMYNAME): printd(("%s: %p: -> SI_SETMYNAME\n", SMOD_MOD_NAME, smod)); err = smod_si_setmyname(q, mp, &ret); break; case _IOC_NR(SI_SETPEERNAME): printd(("%s: %p: -> SI_SETPEERNAME\n", SMOD_MOD_NAME, smod)); err = smod_si_setpeername(q, mp, &ret); break; case _IOC_NR(SI_GETINTRANSIT): printd(("%s: %p: -> SI_GETINTRANSIT\n", SMOD_MOD_NAME, smod)); err = smod_si_getintransit(q, mp, &ret); break; case _IOC_NR(SI_TCL_LINK): printd(("%s: %p: -> SI_TCL_LINK\n", SMOD_MOD_NAME, smod)); err = smod_si_tcl_link(q, mp, &ret); break; case _IOC_NR(SI_TCL_UNLINK): printd(("%s: %p: -> SI_TCL_UNLINK\n", SMOD_MOD_NAME, smod)); err = smod_si_tcl_unlink(q, mp, &ret); break; case _IOC_NR(SI_SOCKPARAMS): printd(("%s: %p: -> SI_SOCKPARAMS\n", SMOD_MOD_NAME, smod)); err = smod_si_sockparams(q, mp, &ret); break; case _IOC_NR(SI_GETUDATA): printd(("%s: %p: -> SI_GETUDATA\n", SMOD_MOD_NAME, smod)); err = smod_si_getudata(q, mp, &ret); break; default: ptrace(("%s: %p: ERROR: Unsupported SOCKMOD ioctl %c, %d\n", SOCK_MOD_NAME, smod(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 SOCKMOD user to SOCKMOD * ----------------------------------------------------------- */ STATIC int smod_w_proto(queue_t *q, mblk_t *mp) { struct smod *smod = SMOD_PRIV(q); int rtn; ulong prim; (void) smod; switch ((prim = *(ulong *) mp->b_rptr)) { case T_CONN_REQ: printd(("%s: %p: -> T_CONN_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_conn_req(q, mp); break; case T_CONN_RES: printd(("%s: %p: -> T_CONN_RES\n", SMOD_MOD_NAME, smod)); rtn = t_conn_res(q, mp); break; case T_DISCON_REQ: printd(("%s: %p: -> T_DISCON_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_discon_req(q, mp); break; case T_DATA_REQ: printd(("%s: %p: -> T_DATA_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_data_req(q, mp); break; case T_EXDATA_REQ: printd(("%s: %p: -> T_EXDATA_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_exdata_req(q, mp); break; case T_INFO_REQ: printd(("%s: %p: -> T_INFO_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_info_req(q, mp); break; case T_BIND_REQ: printd(("%s: %p: -> T_BIND_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_bind_req(q, mp); break; case T_UNBIND_REQ: printd(("%s: %p: -> T_UNBIND_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_unbind_req(q, mp); break; case T_UNITDATA_REQ: printd(("%s: %p: -> T_UNITDATA_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_unitdata_req(q, mp); break; case T_OPTMGMT_REQ: printd(("%s: %p: -> T_OPTMGMT_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_optmgmt_req(q, mp); break; case T_ORDREL_REQ: printd(("%s: %p: -> T_ORDREL_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_ordrel_req(q, mp); break; case T_OPTDATA_REQ: printd(("%s: %p: -> T_OPTDATA_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_optdata_req(q, mp); break; case T_ADDR_REQ: printd(("%s: %p: -> T_ADDR_REQ\n", SMOD_MOD_NAME, smod)); rtn = t_addr_req(q, mp); break; default: printd(("%s: %p: -> T_????\n", SMOD_MOD_NAME, smod)); rtn = QR_PASSALONG; break; } return (rtn); } /* * Primitives from TPI provider to SOCKMOD * ----------------------------------------------------------- */ STATIC int smod_r_proto(queue_t *q, mblk_t *mp) { struct smod *smod = SMOD_PRIV(q); int rtn; ulong prim; (void) smod; switch ((prim = *(ulong *) mp->b_rptr)) { case T_CONN_IND: printd(("%s: %p: T_CONN_IND <-\n", SMOD_MOD_NAME, smod)); rtn = t_conn_ind(q, mp); break; case T_CONN_CON: printd(("%s: %p: T_CONN_CON <-\n", SMOD_MOD_NAME, smod)); rtn = t_conn_con(q, mp); break; case T_DISCON_IND: printd(("%s: %p: T_DISCON_IND <-\n", SMOD_MOD_NAME, smod)); rtn = t_discon_ind(q, mp); break; case T_DATA_IND: printd(("%s: %p: T_DATA_IND <-\n", SMOD_MOD_NAME, smod)); rtn = t_data_ind(q, mp); break; case T_EXDATA_IND: printd(("%s: %p: T_EXDATA_IND <-\n", SMOD_MOD_NAME, smod)); rtn = t_exdata_ind(q, mp); break; case T_INFO_ACK: printd(("%s: %p: T_INFO_ACK <-\n", SMOD_MOD_NAME, smod)); rtn = t_info_ack(q, mp); break; case T_BIND_ACK: printd(("%s: %p: T_BIND_ACK <-\n", SMOD_MOD_NAME, smod)); rtn = t_bind_ack(q, mp); break; case T_ERROR_ACK: printd(("%s: %p: T_ERROR_ACK <-\n", SMOD_MOD_NAME, smod)); rtn = t_error_ack(q, mp); break; case T_OK_ACK: printd(("%s: %p: T_OK_ACK <-\n", SMOD_MOD_NAME, smod)); rtn = t_ok_ack(q, mp); break; case T_UNITDATA_IND: printd(("%s: %p: T_UNITDATA_IND <-\n", SMOD_MOD_NAME, smod)); rtn = t_unitdata_ind(q, mp); break; case T_UDERROR_IND: printd(("%s: %p: T_UDERROR_IND <-\n", SMOD_MOD_NAME, smod)); rtn = t_uderror_ind(q, mp); break; case T_OPTMGMT_ACK: printd(("%s: %p: T_OPTMGMT_ACK <-\n", SMOD_MOD_NAME, smod)); rtn = t_optmgmt_ack(q, mp); break; case T_ORDREL_IND: printd(("%s: %p: T_ORDREL_IND <-\n", SMOD_MOD_NAME, smod)); rtn = t_ordrel_ind(q, mp); break; case T_OPTDATA_IND: printd(("%s: %p: T_OPTDATA_IND <-\n", SMOD_MOD_NAME, smod)); rtn = t_optdata_ind(q, mp); break; case T_ADDR_ACK: printd(("%s: %p: T_ADDR_ACK <-\n", SMOD_MOD_NAME, smod)); rtn = t_addr_ack(q, mp); break; default: printd(("%s: %p: T_???? <-\n", SMOD_MOD_NAME, smod)); rtn = QR_PASSALONG; break; } return (rtn); } /* * ------------------------------------------------------------------------- * * M_DATA Handling * * ------------------------------------------------------------------------- */ STATIC INLINE int smod_w_data(queue_t *q, mblk_t *mp) { /* data from above */ printd(("%s: %p: -> M_DATA\n", SMOD_MOD_NAME, SMOD_PRIV(q))); return (QR_PASSFLOW); } STATIC INLINE int smod_r_data(queue_t *q, mblk_t *mp) { /* data from below */ printd(("%s: %p: M_DATA <-\n", SMOD_MOD_NAME, SMOD_PRIV(q))); return (QR_PASSFLOW); } /* * ------------------------------------------------------------------------- * * M_ERROR, M_HANGUP Handling * * ------------------------------------------------------------------------- */ STATIC int smod_r_error(queue_t *q, mblk_t *mp) { printd(("%s: %p: M_ERROR <-\n", SMOD_MOD_NAME, SMOD_PRIV(q))); smod->state = SMODS_UNUSABLE; return (QR_PASSALONG); } STATIC int smod_r_hangup(queue_t *q, mblk_t *mp) { printd(("%s: %p: M_HANGUP <-\n", SMOD_MOD_NAME, SMOD_PRIV(q))); smod->state = SMODS_UNUSABLE; return (QR_PASSALONG); } /* * ========================================================================= * * PUT and SRV * * ========================================================================= */ STATIC INLINE int smod_w_prim(queue_t *q, mblk_t *mp) { ulong type; /* Fast Path */ if ((type = mp->b_datap->db_type) == M_DATA) return smod_w_data(q, mp); switch (type) { case M_DATA: return smod_w_data(q, mp); case M_PROTO: case M_PCPROTO: return smod_w_proto(q, mp); case M_FLUSH: return ss7_w_flush(q, mp); case M_IOCTL: return smod_w_ioctl(q, mp); case M_IOCDATA: return smod_w_iocdata(q, mp); } return (QR_PASSALONG); } STATIC INLINE int smod_r_prim(queue_t *q, mblk_t *mp) { ulong type; /* Fast Path */ if ((type = mp->b_datap->db_type) == M_DATA) return smod_r_data(q, mp); switch (type) { case M_DATA: return smod_r_data(q, mp); case M_PROTO: case M_PCPROTO: return smod_r_proto(q, mp); case M_FLUSH: return ss7_r_flush(q, mp); case M_IOCACK: case M_IOCNAK: return smod_r_iocack(q, mp); case M_ERROR: return smod_r_error(q, mp); case M_HANGUP: return smod_r_hangup(q, mp); } return (QR_PASSALONG); } /* * ========================================================================= * * OPEN and CLOSE * * ========================================================================= */ STATIC int smod_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 smod *smod; for (smod = smod_opens; smod; smod = smod->next) { if (smod->u.dev.cmajor == cmajor && smod->u.dev.cminor == cminor) { MOD_DEC_USE_COUNT; return (ENXIO); /* double push */ } } if (!smod_alloc_priv(q, &smod_opens, devp, crp)) { MOD_DEC_USE_COUNT; return (ENOMEM); } /* generate immediate information request */ if ((err = t_info_req(q)) < 0) { smod_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 smod_close(queue_t *q, int flag, cred_t *crp) { (void) flag; (void) crp; smod_free_priv(q); MOD_DEC_USE_COUNT; return (0); } /* * ========================================================================= * * LiS Module Initialization * * ========================================================================= */ STAIC int smod_initialized = 0; void smod_init(void) { unless(smod_initialized > 0, return); cmn_err(CE_NOTE, SMOD_BANNER); /* console splash */ if ((smod_initialized = smod_init_caches())) { cmn_err(CE_PANIC, "%s: ERROR: could not allocate caches", SMOD_MOD_NAME); } else if ((smod_initialized = lis_register_strmod(&smod_info, SMOD_NOD_NAME)) < 0) { cmn_err(CE_WARN, "%s: ERROR: could not register module", SMOD_MOD_NAME); smod_term_caches(); } return; } void smod_term(void) { ensure(smod_initialized > 0, return); if ((smod_initialized = lis_unregister_strmod(&smod_info)) < 0) { cmn_err(CE_PANIC, "%s: ERROR: could not unregister module", SMOD_MOD_NAME); } else { smod_term_caches(); } return; } /* * ========================================================================= * * Kernel Module Initialization * * ========================================================================= */ int init_module(void) { smod_init(); if (smod_initialized < 0) return smod_initialized; return (0); } void cleanup_module(void) { smod_terminate(); return; }
|
|||||||||||||||||||||||||||
OpenSS7 SS7 for the Common Man |
Home | Overview | Status | News | Documentation | Resources | About | ||||||||||||||||||||
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |