OpenSS7 SS7 for the Common Man |
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |
||||||||||||||||||||||||||
Home | Overview | Status | News | Documentation | Resources | About | |||||||||||||||||||||
File /code/strss7/drivers/sigtran/lm.c#ident "@(#) $RCSfile: lm.c,v $ $Name: $($Revision: 0.8.2.2 $) $Date: 2002/10/18 03:09:20 $" static char const ident[] = "$RCSfile: lm.c,v $ $Name: $($Revision: 0.8.2.2 $) $Date: 2002/10/18 03:09:20 $"; /* * ========================================================================= */ extern ua_t *ua_opens_list; extern ua_t *ua_links_list; static xp_t *ua_xp_find(uint type, uint aspid) { xp_t *xp = NULL; if (aspid) for (xp = (type & UA_MODE_SGP) ? ua_sgp_list : ua_asp_list; xp && xp->aspid != aspid; xp = xp->type.next); return (xp); } static int ua_xp_create(lp_t * lp, uint aspid, uint type) { xp_t *xp, **xpp, **cpp; if ((xp = ua_xp_find(type, aspid))) { if (xp->pp) return (-EBUSY); xp->use_count++; xp->pp = lp; if (lp) lp->xp = xp; return (0); } if ((xp = kmem_cache_alloc(ua_xp_cachep, SLAB_ATOMIC))) { xp->pp = lp; xp->id = aspid; xp->state = ASP_DOWN; xp->type = type; xp->version = 1; xp->use_count = 1; switch (type & UA_MODE_MASK) { case UA_MODE_SGP: switch (type & UA_PROT_MASK) { case UA_PROT_SL: xp->recv = &m2ua_sgp_recv; xp->send = &m2ua_sgp_send; xpp = &m2ua_sgp_list; break; case UA_PROT_MTP: xp->recv = &m3ua_sgp_recv; xp->send = &m3ua_sgp_send; xpp = &m3ua_sgp_list; break; case UA_PROT_ISUP: xp->recv = &isua_sgp_recv; xp->send = &isua_sgp_send; xpp = &isua_sgp_list; break; case UA_PROT_SCCP: xp->recv = &sua_sgp_recv; xp->send = &sua_sgp_send; xpp = &sua_sgp_list; break; case UA_PROT_TCAP: xp->recv = &tua_sgp_recv; xp->send = &tua_sgp_send; xpp = &tua_sgp_list; break; default: kmem_cache_free(ua_xp_cachep, xp); return (-EINVAL); } cpp = &ua_sgp_list; break; case UA_MODE_ASP: switch (type & UA_PROT_MASK) { case UA_PROT_SL: xp->recv = &m2ua_asp_recv; xp->send = &m2ua_asp_send; xpp = &m2ua_asp_list; break; case UA_PROT_MTP: xp->recv = &m3ua_asp_recv; xp->send = &m3ua_asp_send; xpp = &m3ua_asp_list; break; case UA_PROT_ISUP: xp->recv = &isua_asp_recv; xp->send = &isua_asp_send; xpp = &isua_asp_list; break; case UA_PROT_SCCP: xp->recv = &sua_asp_recv; xp->send = &sua_asp_send; xpp = &sua_asp_list; break; case UA_PROT_TCAP: xp->recv = &tua_asp_recv; xp->send = &tua_asp_send; xpp = &tua_asp_list; break; default: kmem_cache_free(ua_xp_cachep, xp); return (-EINVAL); } cpp = &ua_asp_list; break; default: kmem_cache_free(ua_xp_cachep, xp); return (-EINVAL); } if ((xp->prot.next = *xpp)) xp->prot.next->prot.prev = &xp->prot.next; xp->prot.prev = xpp; *xpp = xp; if ((xp->clas.next = *cpp)) xp->clas.next->clas.prev = &xp->clas.next; xp->clas.prev = cpp; *cpp = xp; if (lp) lp->xp = xp; return (0); } return (-ENOMEM); } /* * ========================================================================= */ /* * LM_AS_ADD_REQ * ----------------------------------- * Requests that the driver add or augment the application server for the * protocol on whose user or control queue the request was issued. The AS * identifier si for further reference. The RC or IID identifier will be * added to the AS if the AS already exists with the specified AS Id. * * The lower or local management queue normally uses this primitive to add an * application server which does not yet exist at boot time or in response to * an LM_REG_REQ before issuing and LM_REG_RES. * * The optional routing (link) key is only required for statically allocated * Application Servers. This key is used to bind/connect SS7 provider * streams which support the AS or to generate REG REQ to SGP/SPP IPC and UA * proxies. I don't really intend to use this function, but it is there to * support all SIGTRAN UA allocation modes. */ static int lm_as_add_req(queue_t * q, mblk_t * mp) { int err; as_t *as; size_t mlen = mp->b_wptr - mp->b_rptr; do { if (mlen < sizeof(*p)) { if (!(as = ua_as_find(p->asid, p->rc))) { if ((err = ua_as_create(NULL, p->asid, p->rc))) break; return lm_ok_ack(q, mp, LM_AS_ADD_REQ); } err = -EBUSY; break; } err = -EMSGSIZE; break; } while (0); return lm_error_ack(q, mp, LM_AS_ADD_REQ, err); } static int lm_as_del_req(queue_t * q, mblk_t * mp) { } /* * LM_PROC_ADD_REQ * ----------------------------------- * Requests that the driver add an ASP/SGP proxy process. This is for static * configuration of proxy processes only. Dynamic configuration will create * SGP proxy processes on demand. */ static int lm_proc_add_req(queue_t * q, mblk_t * mp) { int err; xp_t *xp; size_t mlen = mp->b_wptr - mp->b_rptr; do { if (mlen < sizeof(*p)) { if (!(xp = ua_xp_find(p->type, p->aspid))) { if ((err = ua_xp_create(NULL, p->aspid, p->type))) break; return lm_ok_ack(q, mp, LM_PROC_ADD_REQ); } err = -EBUSY:break; } err = -EMSGSIZE; break; } while (0); return lm_error_ack(q, mp, LM_PROC_ADD_REQ, err); } static int lm_proc_del_req(queue_t * q, mblk_t * mp) { } /* * LM_LINK_ADD_REQ * ----------------------------------- * Requests that the driver configures and associated the indicated linked * (muxid) stream as the indicated type of proxy and associate it with the * indicated local or remote ASP Identifier. Transport SGP proxies must have * aspids associated with them. Transport ASP proxies may either have fixed * aspids associated wtih them or may have aspid set to zero, the aspid to be * identified in subsequent ASPUP message from the ASP if the ASP requires * dynamic registration. */ static int lm_link_add_req(queue_t * q, mblk_t * mp) { int err; lp_t *lp; xp_t *xp; size_t mlen = mp->b_wptr - mp->b_rptr; lm_link_add_req_t *p = (typeof(p)) mp->b_rptr; do { if (mlen < sizeof(*p)) { if ((lp = ua_link_find(p->muxid))) { switch (p->type) { case LM_ASP: case LM_ASP | LM_IPC: case LM_ASP | LM_UAP: case LM_SGP: case LM_SGP | LM_IPC: case LM_SGP | LM_UAP: case LM_SPP: case LM_SPP | LM_IPC: case LM_SPP | LM_UAP: if (!(lp->u.xp)) { if ((err = ua_xp_create(lp, p->aspid, p->type))) break; return lm_ok_ack(q, mp, LM_LINK_ADD_REQ); } err = -EBUSY; break; default: case LM_SS7: case LM_SGP | LM_SS7: case LM_ASP | LM_SS7: case LM_SPP | LM_SS7: err = -EINVAL; break; } break; } err = -ENXIO; break; } err = -EMSGSIZE; break; } while (0); return lm_error_ack_reply(q, mp, LM_LINK_ADD_REQ, err); } static int lm_link_del_req(queue_t * q, mblk_t * mp) { } static int lm_route_add_req(queue_t * q, mblk_t * mp) { } static int lm_route_del_req(queue_t * q, mblk_t * mp) { } static int lm_reg_res(queue_t * q, mblk_t * mp) { } static int lm_reg_ref(queue_t * q, mblk_t * mp) { } static int lm_ioctl(queue_t * q, mblk_t * mp) { int err = EOPNOTSUPP; struct iocblk *iocp = (struct iocblk *) mp->b_rptr; switch (_IOC_TYPE(iocp->ioc_cmd)) { case __SID: { lp_t *lp; ua_t *ua = (ua_t *) q->q_ptr; struct linkblk *lb = (struct linkblk *) (mp->b_cont ? mp->b_cont->b_rptr : NULL); switch (iocp->ioc_cmd) { case I_PLINK: err = EPERM; if (iocp->ioc_cr->cr_uid != 0) { ptrace(("Non-root attempt to I_PLINK\n")); break; } case I_LINK: err = 0; if (lb->l_qbot->q_ptr != NULL) { ptrace(("Stream already linked\n")); break; } if ((lp = kmem_cache_alloc(ua_pp_cachep, SLAB_ATOMIC))) { bzero(lp, sizeof(lp_t)); if ((lp->next = ua_links_list)) lp->next->prev = &lp->next; lp->prev = &ua_links_list; ua_links_list = lp; lp->id.nux = lp->l_index; lp->rq = RD(lb->l_qbot); lp->wq = WR(lb->l_qbot); lp->mq = RD(q); lp->rq->q_ptr = lp; lp->wq->q_ptr = lp; } err = ENOMEM; break; case I_PUNLINK: err = EPERM; if (iocp->ioc_cr->cr_uid != 0) { ptrace(("Non-root attempt to I_PUNLINK\n")); break; } case I_UNLINK: err = 0; if (!(lp = (lp_t *) lb->l_qbot->q_ptr)) { ptrace(("Stream already unlinked\n")); break; } fixme(("Make sure we are not linked to xp\n")); if ((*(lp->prev) = lp->next)) lp->next->prev = lp->prev; lp->prev = NULL; lp->next = NULL; if (lp->bid) unbufcall(lp->bid); lp->rq->q_ptr = NULL; lp->wq->q_ptr = NULL; kmem_cache_free(ua_pp_cachep, lp); qenable(lp->rq); qenable(lp->wq); break; } } } if (err) { mp->b_datap->db_type = M_IOCNAK; iocp->ioc_error = err; iocp->ioc_rval = -1; } else { mp->b_datap->db_type = M_IOCACK; iocp->ioc_error = 0; iocp->ioc_rval = 0; } qreply(q, mp); return (1); } static int ua_u_w_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_PROTO: case M_PCPROTO: switch (*((long *) mp->b_rptr)) { case LM_AS_ADD_REQ: return lm_as_add_req(q, mp); case LM_AS_DEL_REQ: return lm_as_del_req(q, mp); case LM_PROC_ADD_REQ: return lm_proc_add_req(q, mp); case LM_PROC_DEL_REQ: return lm_proc_del_req(q, mp); case LM_LINK_ADD_REQ: return lm_link_add_req(q, mp); case LM_LINK_DEL_REQ: return lm_link_del_req(q, mp); case LM_ROUTE_ADD_REQ: return lm_route_add_req(q, mp); case LM_ROUTE_DEL_REQ: return lm_route_del_req(q, mp); case LM_REG_RES: return lm_reg_res(q, mp); case LM_REG_REF: return lm_reg_ref(q, mp); } break; case M_IOCTL: return lm_ioctl(q, mp); case M_FLUSH: return ua_w_flush(q, mp); } return (-EOPNOTSUPP); } static INT ua_u_wput(queue_t * q, mblk_t * mp) { return ua_putq(q, mp, &ua_u_w_prim); } static INT ua_u_wsrv(queue_t * q) { return ua_srvq(q, &ua_u_w_prim); } static int n_data(queue_t * q, mblk_t * mp) { ua_t *ua = (ua_t *) q->q_ptr; if (ua->xp) return ((*ua->xp->recv) (q, mp)); noenable(q); return (-EAGAIN); } static int n_data_ind(queue_t * q, mblk_t * mp) { ua_t *ua = (ua_t *) q->q_ptr; if (ua->xp) return ((*ua->xp->recv) (q, mp)); noenable(q); return (-EAGAIN); } static int n_exdata_ind(queue_t * q, mblk_t * mp) { ua_t *ua = (ua_t *) q->q_ptr; if (ua->xp) return ((*ua->xp->recv) (q, mp)); noenable(q); return (-EAGAIN); } static int n_datack_ind(queue_t * q, mblk_t * mp) { ua_t *ua = (ua_t *) q->q_ptr; if (ua->xp) return ((*ua->xp->recv) (q, mp)); noenable(q); return (-EAGAIN); } static int n_discon_ind(queue_t * q, mblk_t * mp) { ua_t *ua = (ua_t *) q->q_ptr; if (ua->xp) return ((*ua->xp->recv) (q, mp)); noenable(q); return (-EAGAIN); } static int n_reset_ind(queue_t * q, mblk_t * mp) { ua_t *ua = (ua_t *) q->q_ptr; if (ua->xp) return ((*ua->xp->recv) (q, mp)); noenable(q); return (-EAGAIN); } static int n_other_ind(queue_t * q, mblk_t * mp) { ua_t *ua = (ua_t *) q->q_ptr; if (ua->xp) return ((*ua->xp->recv) (q, mp)); noenable(q); return (-EAGAIN); } static int n_ctl(queue_t * q, mblk_t * mp) { } static int n_error(queue_t * q, mblk_t * mp) { ua_t *ua = (ua_t *) q->q_ptr; if (ua->xp) return ((*ua->xp->recv) (q, mp)); noenable(q); return (-EAGAIN); } static int n_hangup(queue_t * q, mblk_t * mp) { ua_t *ua = (ua_t *) q->q_ptr; if (ua->xp) return ((*ua->xp->recv) (q, mp)); noenable(q); return (-EAGAIN); } static int ua_l_r_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_DATA: return n_data(q, mp); case M_PROTO: case M_PCPROTO: switch (*((long *) mp->b_rptr)) { case N_DATA_IND: return n_data_ind(q, mp); case N_EXDATA_IND: return n_exdata_ind(q, mp); case N_DATACK_IND: return n_datack_ind(q, mp); case N_DISCON_IND: return n_discon_ind(q, mp); case N_RESET_IND: return n_reset_ind(q, mp); default: return n_other_ind(q, mp); } break; case M_CTL: return n_ctl(q, mp); case M_ERROR: return n_error(q, mp); case M_HANGUP: return n_hangup(q, mp); case M_FLUSH: return ua_r_flush(q, mp); } return (-EPROTO); } static INT ua_l_rput(queue_t * q, mblk_t * mp) { return ua_putq(q, mp, &ua_l_r_prim); } static INT ua_l_rsrv(queue_t * q) { return ua_srvq(q, &ua_l_r_prim); } static int ua_u_r_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_CTL: return ua_u_r_ctl(q, mp); case M_FLUSH: return ua_r_flush(q, mp); default: return (5); } } static INT ua_u_rput(queue_t * q, mblk_t * mp) { return ua_putq(q, mp, &ua_u_r_prim); } static INT ua_u_rsrv(queue_t * q) { return ua_srvq(q, &ua_u_r_prim); } static int ua_l_w_prim(queue_t * q, mblk_t * mp) { int rtn; switch (mp->b_datap->db_type) { case M_FLUSH: return ua_w_flush(q, mp); default: return (5); } } static INT ua_l_wput(queue_t * q, mblk_t * mp) { return ua_putq(q, mp, &ua_l_w_prim); } static INT ua_l_wsrv(queue_t * q) { return ua_srvq(q, &ua_l_w_prim); } /* * ========================================================================= * * OPEN and CLOSE * * ========================================================================= */ static int ua_open(queue_t * q, dev_t * devp, int flag, int sflag, cred_t * crp) { int cmajor = getmajor(*devp); int cminor = getminor(*devp); dp_t *dp, **dpp; if (sflag == MODOPEN || WR(q)->q_next) { ptrace(("Can't open as module\n")); return (EIO); } if (cmajor == UA_CMAJOR && cminor == 1 && crp->cr_uid != 0) { ptrace(("Non-root priviledge user attempting to open control stream\n")); return (PERM); } if (q->q_ptr != NULL) { ptrace(("Device already open\n")); return (0); } if (cmajor == UA_CMAJOR && cminor == 0) { ptrace(("Clone minor opened\n")); sflag = CLONEOPEN; } for (dpp = &ua_opens_list; *dpp; dpp = &(*dpp)->next) { ushort dmajor = getmajor(*devp); if (cmajor < dmajor) break; if (cmajor == dmajor) { if (sflag == CLONEOPEN) { if (++cminor > UA_NMINOR) { if (++cmajor > UA_CMAJOR + (UA_NMAJOR - 1)) break; cminor = 0; } continue; } ptrace(("Requested device in use\n")); return (EIO); } } if (cmajor > UA_CMAJOR + (UA_NMAJOR - 1)) { ptrace(("No devices available\n")); return (ENXIO); } *devp = makedevice(cmajor, cminor); if (!(dp = kmem_cache_alloc(ua_pp_cachep, SLAB_ATOMIC))) { ptrace(("Cannot allocate cache entry for device\n")); return (ENOMEM); } bzero(dp, sizeof(dp_t)); if ((dp->next = *dpp)) dp->next->prev = &dp->next; dp->prev = dpp; *dpp = dp; dp->id.dev = *devp; dp->rq = RD(q); dp->wq = WR(q); dp->mq = RD(q); dp->rq->q_ptr = dp; dp->wq->q_ptr = dp; return (0); } static int ua_close(queue_t * q, int flag, cred_t * crp) { dp_t *dp = (dp_t *) q->q_ptr; if ((*(dp->prev) = dp->next)) dp->next->prev = dp->next; dp->prev = NULL; dp->next = NULL; if (dp->bid) unbufcall(dp->bid); dp->rq->q_ptr = NULL; dp->wq->q_ptr = NULL; fixme(("Make sure that we are not referenced...\n")); kmem_cache_free(ua_pp_cachep, dp); return (0); } /* * ========================================================================= * * Lis Driver Initialization * * ========================================================================= */ static int ua_init(void) { int rtn; if (!ua_u_minfo.mi_idnum) { if ((rtn = ua_init_caches())) return (-rtn); if ((rtn = lis_register_strdev(UA_CMAJOR, &ua_info, UA_NMINOR, ua_u_minfo.mi_idname)) < 0) { ua_u_minfo.mi_idnum = 0; rare(); cmn_err(CE_NOTE, "ua: couldn't register driver\n"); return (-rtn); ua_u_minfo.mi_idnum = rtn; } } return (0); } static void ua_terminate(void) { if (ua_u_minfo.mi_idnum) { if ((ua_u_minfo.mi_idnum = lis_unregister_strdev(ua_u_minfo.mi_idnum))) { ua_u_minfo.mi_idnum = 0; rare(); cmn_err(CE_WARN, "ua: couldn't unregsiter driver\n"); } } } /* * ========================================================================= * * Kernel Module Initialization * * ========================================================================= */ int init_module(void) { int err; ua_init(); return (0); } void cleanup_module(void) { ua_terminate(); return; }
|
|||||||||||||||||||||||||||
OpenSS7 SS7 for the Common Man |
Home | Overview | Status | News | Documentation | Resources | About | ||||||||||||||||||||
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |