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/sua.c#ident "@(#) $RCSfile: sua.c,v $ $Name: $($Revision: 0.8.2.3 $) $Date: 2003/04/03 19:51:07 $" static char const ident[] = "$RCSfile: sua.c,v $ $Name: $($Revision: 0.8.2.3 $) $Date: 2003/04/03 19:51:07 $"; #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/dki.h> #include "../debug.h" #include "../bufq.h" #include "ua.h" #include "ua_data.h" #include "ua_msgs.h" #include "sua_msgs.h" /* * ========================================================================= * * STREAMS Message Handling * * ========================================================================= */ /* * ------------------------------------------------------------------------- * * Management Stream (LM) Message Handling * * ------------------------------------------------------------------------- */ /* * LM --> SUA Primitives * ----------------------------------- */ int lm_as_add_req(queue_t * q, mblk_t * mp) { } int lm_as_del_req(queue_t * q, mblk_t * mp) { } int lm_proc_add_req(queue_t * q, mblk_t * mp) { } int lm_proc_del_req(queue_t * q, mblk_t * mp) { } int lm_link_add_req(queue_t * q, mblk_t * mp) { } int lm_link_del_req(queue_t * q, mblk_t * mp) { } int lm_route_add_req(queue_t * q, mblk_t * mp) { } int lm_route_del_req(queue_t * q, mblk_t * mp) { } int lm_reg_res(queue_t * q, mblk_t * mp) { } int lm_reg_ref(queue_t * q, mblk_t * mp) { } static int sua_m_w_ioctl(queue_t * q, mblk_t * mp) { } static int sua_m_w_proto(queue_t * q, mblk_t * mp) { 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); } return (-EOPNOTSUPP); } static int sua_m_w_pcproto(queue_t * q, mblk_t * mp) { return sua_m_w_proto(q, mp); } static int sua_m_w_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_PROTO: return sua_m_w_proto(q, mp); case M_PCPROTO: return sua_m_w_pcproto(q, mp); case M_IOCTL: return sua_m_w_ioctl(q, mp); case M_FLUSH: return ua_w_flush(q, mp); } return (-EOPNOTSUPP); } /* * SUA --> LM Primitives * ----------------------------------- */ static int sua_m_r_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_FLUSH: return ua_r_flush(q, mp); } return (5); } /* * ========================================================================= * * STREAMS Message Handling * * ------------------------------------------------------------------------- * * SCCP User (SCCPU) Stream Message Handling * * ------------------------------------------------------------------------- * * SCCP User --> SUA Primitives * ----------------------------------- * This is the SCCPU upper write routines. This takes SCCP user primitives * and converts them to SCCP M_DATA and M_CTL messages, if required. If the * provider is a local SG, then the primitives are forwarded as is. * * These are primitives sent from a local SCCP user to the SUA layer on the * upper mux stream. This is part of the Adaptation Layer at an ASP * (Application Server Process). Each message is converted from an SCCP user * request or response primitive to an SUA message. These functions are pure * translation only. When they return zero, they return the SCCP primitive * translated in `mpp'. When they return non-zero, they return an error an * `mpp' is untouched. */ static int sccpu_info_req(queue_t * q, mblk_t * mp) { } static int sccpu_bind_req(queue_t * q, mblk_t * mp) { } static int sccpu_unbind_req(queue_t * q, mblk_t * mp) { } static int sccpu_unitdata_req(queue_t * q, mblk_t * mp) { } static int sccpu_optmgmt_req(queue_t * q, mblk_t * mp) { } static int sua_u_w_ioctl(queue_t * q, mblk_t * mp) { } static int sua_u_w_data(queue_t * q, mblk_t * dp) { /* * Need to convert data to SL_PDU_REQ. */ int rtn; mblk_t *mp; sl_pdu_req_t *p; if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((typeof(p)) mp->b_wptr)++; p->sl_primitive = SL_PDU_REQ; mp->b_cont = dp; switch ((rtn = slu_pdu_req(q, mp))) { } return (1); } return (-ENOBUFS); } static int sua_u_w_proto(queue_t * q, mblk_t * mp) { switch (*((long *) mp->b - rptr)) { case N_INFO_REQ: return sccpu_info_req(q, mp); case N_BIND_REQ: return sccpu_bind_req(q, mp); case N_UNBIND_REQ: return sccpu_unbind_req(q, mp); case N_UNITDATA_REQ: return sccpu_unitdata_req(q, mp); case N_OPTMGMT_REQ: return sccpu_optmgmt_req(q, mp); } return (-EOPNOTSUPP); } static int sua_u_w_pcproto(queue_t * q, mblk_t * mp) { return sua_u_w_proto(q, mp); } static int sua_u_w_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_DATA: return sua_u_w_data(q, mp); case M_PROTO: return sua_u_w_proto(q, mp); case M_PCPROTO: return sua_u_w_pcproto(q, mp); case M_IOCTL: return sua_u_w_ioctl(q, mp); case M_FLUSH: return ua_w_flush(q, mp); } return (-EOPNOTSUPP); } /* * SUA --> SCCP User Primitives * ----------------------------------- */ static int sua_u_r_data(queue_t * q, mblk_t * mp) { return sua_r_msg(q, mp); } static int sua_u_r_ctl(queue_t * q, mblk_t * mp) { return sua_r_msg(q, mp); } static int sua_u_r_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_DATA: return sua_u_r_data(q, mp); case M_CTL: return sua_u_r_ctl(q, mp); case M_FLUSH: return ua_r_flush(q, mp); } return (5); } /* * ------------------------------------------------------------------------- * * SCCP Provider (SCCPP) Stream Message Handling * * ------------------------------------------------------------------------- */ /* * SUA --> SCCP Provider Primitives * ----------------------------------- */ static int sua_l_w_data(queue_t * q, mblk_t * mp) { return sua_w_msg(q, mp); } static int sua_l_w_ctl(queue_t * q, mblk_t * mp) { return sua_w_msg(q, mp); } static int sua_l_w_error(queue_t * q, mblk_t * mp) { } static int sua_l_w_hangup(queue_t * q, mblk_t * mp) { } static int sua_l_w_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_DATA: return sua_l_w_data(q, mp); case M_CTL: return sua_l_w_ctl(q, mp); case M_ERROR: return sua_l_w_error(q, mp); case M_HANGUP: return sua_l_w_hangup(q, mp); case M_FLUSH: return ua_w_flush(q, mp); } return (5); } /* * SCCP Provider --> SUA Primitives * ------------------------------------------------------------------------- * This is the SCCPP lower read routine. This takes SCCP Primitives and * converts them to SUA M_DATA and M_CTL messages, if required. If the user * is a local AS, then the primitives are forwarded as is. */ static int sccpp_info_ack(queue_t * q, mblk_t * mp) { ptrace(("Aarrgh! Got unexpected N_INFO_ACK\n")); return (-EFAULT); } static int sccpp_bind_ack(queue_t * q, mblk_t * mp) { lp_t *lp = (lp_t *) q->q_ptr; as_t *as = lp->as; if (lp->l.state != NS_WACK_BREQ) { ptrace(("Aarrgh! Got unexpected N_BIND_ACK\n")); return (-EFAULT); } ensure(as, return (-EFAULT)); as->xpia_count--; as->xpac_count++; as->l.state = AS_ACTIVE; fixme(("Do some more...\n")); return (-EFAULT); } static int sccpp_error_ack(as_t * as, mblk_t ** mpp) { mblk_t *mp; N_error_ack_t *p = (typeof(p)) (*mpp)->b_rptr; switch (p->ERROR_primitive) { case N_CONN_REQ: { size_t mlen = *sizeof(uint32_t); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = SUA_CONS_COREF; *((uint32_t *) mp->b_wptr)++ = htonl(mlen); *((uint32_t *) mp->b_wptr)++ = UA_PARM_RC; *((uint32_t *) mp->b_wptr)++ = htonl(as->l.id.rc); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_DRN; *((uint32_t *) mp->b_wptr)++ = htonl(as->drn); fixme(("Get cause from ERROR_code\n")); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_CAUSE; *((uint32_t *) mp->b_wptr)++ = htonl(cause); (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } } return (-EPROTO); } static int sccpp_ok_ack(as_t * as, mblk_t ** mpp) { mblk_t *mp; N_ok_ack_t *p = (typeof(p)) (*mpp)->b_rptr; switch (p->CORRECT_primitive) { case N_DISCON_REQ: { size_t mlen = 8 * sizeof(uint32_t); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = SUA_CONS_RELCO; *((uint32_t *) mp->b_wptr)++ = htonl(mlen); *((uint32_t *) mp->b_wptr)++ = UA_PARM_RC; *((uint32_t *) mp->b_wptr)++ = htonl(as->l.id.rc); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_DRN; *((uint32_t *) mp->b_wptr)++ = htonl(as->drn); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_SRN; *((uint32_t *) mp->b_wptr)++ = htonl(as->srn); /* Note: se never send importance here */ (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } } return (-EPROTO); } static int sccpp_conn_ind(as_t * as, mblk_t ** mpp) { mblk_t *mp; N_conn_ind_t *p = (typeof(p)) (*mpp)->b_rptr; sccp_addr_t *src = (typeof(src)) ((*mpp)->b_rptr + p->SRC_offset); sccp_addr_t *dst = (typeof(src)) ((*mpp)->b_rptr + p->DEST_offset); N_qos_sel_conn_sctp_t *qos = (typeof(qos)) ((*mpp)->b_rptr + p->QOS_offset); uint pclass = qos->protocol_class; size_t mlen = *sizeof(uint32_t); size_t dlen = msgdsize((*mpp)->b_cont); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = SUA_CONS_CORE; *((uint32_t *) mp->b_wptr)++ = htonl(mlen + PAD4(dlen)); *((uint32_t *) mp->b_wptr)++ = UA_PARM_RC; *((uint32_t *) mp->b_wptr)++ = htonl(as->l.id.rc); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_PCLS; *((uint32_t *) mp->b_wptr)++ = htonl(qos->protocol_class); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_SRN; *((uint32_t *) mp->b_wptr)++ = htoml(srn); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_SEQ_CTL; *((uint32_t *) mp->b_wptr)++ = htonl(qos->sequence_control); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_HOP_CNT; *((uint32_t *) mp->b_wptr)++ =; *((uint32_t *) mp->b_wptr)++ = SUA_PARM_IMP; *((uint32_t *) mp->b_wptr)++ = htonl(qos->importance); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_MP; *((uint32_t *) mp->b_wptr)++ = htonl(qos->message_priority); if (p->DEST_length >= sizeof(*dst)) { fixme(("Place Dest address in message\n")); *((uint32_t *) mp->b_wptr)++ = UA_PARM(SUA_PARM_DEST_ADDR, dlen); } if (p->SRC_length >= sizeof(*src)) { fixme(("Place Srce address in message\n")); *((uint32_t *) mp->b_wptr)++ = UA_PARM(SUA_PARM_SRCE_ADDR, slen); /* * There are strange statements in the draft as to * when to place SRC address in the message. */ } if (pclass == 3) { *((uint32_t *) mp->b_wptr)++ = SUA_PARM_SEQ_NUM; *((uint32_t *) mp->b_wptr)++ =; *((uint32_t *) mp->b_wptr)++ = SUA_PARM_CREDIT; *((uint32_t *) mp->b_wptr)++ =; } if (dlen) { *((uint32_t *) mp->b_wptr)++ = UA_PARM(SUA_PARM_DATA, dlen); mp->b_cont = (*mpp)->b_cont; (*mpp)->b_cont = NULL; } (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } static int sccpp_conn_con(as_t * as, mblk_t ** mpp) { mblk_t *mp; N_conn_con_t *p = (typeof(p)) (*mpp)->b_rptr; sccp_addr_t *res = (typeof(src)) ((*mpp)->b_rptr + p->RES_offset); N_qos_sel_conn_sctp_t *qos = (typeof(qos)) ((*mpp)->b_rptr + p->QOS_offset); uint pclass = qos->protocol_class; size_t mlen = *sizeof(uint32_t); size_t dlen = msgdsize((*mpp)->b_cont); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = SUA_CONS_COAK; *((uint32_t *) mp->b_wptr)++ = htonl(mlen + PAD4(dlen)); *((uint32_t *) mp->b_wptr)++ = UA_PARM_RC; *((uint32_t *) mp->b_wptr)++ = htonl(as->l.id.rc); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_PCLS; *((uint32_t *) mp->b_wptr)++ = htonl(qos->protocol_class); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_DRN; *((uint32_t *) mp->b_wptr)++ = htoml(drn); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_SRN; *((uint32_t *) mp->b_wptr)++ = htoml(srn); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_SEQ_CTL; *((uint32_t *) mp->b_wptr)++ = htonl(qos->sequence_control); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_IMP; *((uint32_t *) mp->b_wptr)++ = htonl(qos->importance); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_MP; *((uint32_t *) mp->b_wptr)++ = htonl(qos->message_priority); if (p->RES_length >= sizeof(*res)) { fixme(("Place Dest address in message\n")); *((uint32_t *) mp->b_wptr)++ = UA_PARM(SUA_PARM_DEST_ADDR, dlen); /* * There are strange statements in the draft as to * when to place Dest address in the message. */ } if (pclass == 3) { *((uint32_t *) mp->b_wptr)++ = SUA_PARM_CREDIT; *((uint32_t *) mp->b_wptr)++ =; } if (dlen) { *((uint32_t *) mp->b_wptr)++ = UA_PARM(SUA_PARM_DATA, dlen); mp->b_cont = (*mpp)->b_cont; (*mpp)->b_cont = NULL; } (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } static int sccpp_discon_ind(as_t * as, mblk_t ** mpp) { switch (as->ss7->l.state) { case NS_WCON_CREQ: { mblk_t *mp; N_discon_ind_t *p = (typeof(p)) (*mpp)->b_rptr; sccp_addr_t *res = (typeof(src)) ((*mpp)->b_rptr + p->RES_offset); size_t mlen = *sizeof(uint32_t); size_t dlen = msgdsize((*mpp)->b_cont); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = SUA_CONS_COREF; *((uint32_t *) mp->b_wptr)++ = htonl(mlen); *((uint32_t *) mp->b_wptr)++ = UA_PARM_RC; *((uint32_t *) mp->b_wptr)++ = htonl(as->l.id.rc); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_DRN; *((uint32_t *) mp->b_wptr)++ = htonl(drn); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_IMP; *((uint32_t *) mp->b_wptr)++ = htonl(qos->importance); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_CAUSE; fixme(("Get cause from DISCON_orig and DISCON_reason\n")); *((uint32_t *) mp->b_wptr)++ = htonl(cause); if (p->RES_length >= sizeof(*res)) { fixme(("Place Dest address in message\n")); *((uint32_t *) mp->b_wptr)++ = UA_PARM(SUA_PARM_DEST_ADDR, dlen); /* * There are strange statements in the draft as to * when to place Dest address in the message. */ } if (dlen) { *((uint32_t *) mp->b_wptr)++ = UA_PARM(SUA_PARM_DATA, dlen); mp->b_cont = (*mpp)->b_cont; (*mpp)->b_cont = NULL; } (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } case NS_DATA_XFER: { mblk_t *mp; N_discon_ind_t *p = (typeof(p)) (*mpp)->b_rptr; size_t mlen = *sizeof(uint32_t); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = SUA_CONS_RELRE; *((uint32_t *) mp->b_wptr)++ = htonl(mlen); *((uint32_t *) mp->b_wptr)++ = UA_PARM_RC; *((uint32_t *) mp->b_wptr)++ = htonl(as->l.id.rc); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_DRN; *((uint32_t *) mp->b_wptr)++ = htoml(drn); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_SRN; *((uint32_t *) mp->b_wptr)++ = htoml(srn); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_IMP; *((uint32_t *) mp->b_wptr)++ = htonl(qos->importance); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_CAUSE; fixme(("Get cause from DISCON_orig and DISCON_reason\n")); *((uint32_t *) mp->b_wptr)++ = htonl(cause); if (dlen) { *((uint32_t *) mp->b_wptr)++ = UA_PARM(SUA_PARM_DATA, dlen); mp->b_cont = (*mpp)->b_cont; (*mpp)->b_cont = NULL; } (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } } ptrace(("Received N_DISCON_IND in unexpected state\n")); return (-EFAULT); } static int sccpp_data_ind(as_t * as, mblk_t ** mpp) { mblk_t *mp; N_data_ind_t *p = (typeof(p)) (*mpp)->b_rptr; sccp_addr_t *src = (typeof(src)) ((*mpp)->b_rptr + p->SRC_offset); sccp_addr_t *dst = (typeof(src)) ((*mpp)->b_rptr + p->DEST_offset); N_qos_sel_data_sctp_t *qos = (typeof(qos)) (dst + 1); size_t mlen = *sizeof(uint32_t); size_t dlen = msgdsize((*mpp)->b_cont); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } static int sccpp_exdata_ind(as_t * as, mblk_t ** mpp) { mblk_t *mp; N_exdata_ind_t *p = (typeof(p)) (*mpp)->b_rptr; sccp_addr_t *src = (typeof(src)) ((*mpp)->b_rptr + p->SRC_offset); sccp_addr_t *dst = (typeof(src)) ((*mpp)->b_rptr + p->DEST_offset); N_qos_sel_data_sctp_t *qos = (typeof(qos)) (dst + 1); size_t mlen = *sizeof(uint32_t); size_t dlen = msgdsize((*mpp)->b_cont); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } static int sccpp_unitdata_ind(as_t * as, mblk_t ** mpp) { mblk_t *mp; N_unitdata_ind_t *p = (typeof(p)) (*mpp)->b_rptr; sccp_addr_t *src = (typeof(src)) ((*mpp)->b_rptr + p->SRC_offset); sccp_addr_t *dst = (typeof(src)) ((*mpp)->b_rptr + p->DEST_offset); N_qos_sel_data_sctp_t *qos = (typeof(qos)) (dst + 1); size_t mlen = *sizeof(uint32_t); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } static int sccpp_uderror_ind(as_t * as, mblk_t ** mpp) { mblk_t *mp; N_uderror_ind_t *p = (typeof(p)) (*mpp)->b_rptr; sccp_addr_t *src = (typeof(src)) ((*mpp)->b_rptr + p->SRC_offset); sccp_addr_t *dst = (typeof(src)) ((*mpp)->b_rptr + p->DEST_offset); N_qos_sel_data_sctp_t *qos = (typeof(qos)) (dst + 1); size_t mlen = *sizeof(uint32_t); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } static int sccpp_datack_ind(as_t * as, mblk_t ** mpp) { mblk_t *mp; N_datack_ind_t *p = (typeof(p)) (*mpp)->b_rptr; size_t mlen = *sizeof(uint32_t); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } static int sccpp_reset_ind(as_t * as, mblk_t ** mpp) { mblk_t *mp; N_reset_ind_t *p = (typeof(p)) (*mpp)->b_rptr; size_t mlen = 10 * sizeof(uint32_t); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = SUA_CONS_RESRE; *((uint32_t *) mp->b_wptr)++ = htonl(mlen); *((uint32_t *) mp->b_wptr)++ = UA_PARM_RC; *((uint32_t *) mp->b_wptr)++ = htonl(as->l.id.rc); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_DRN; *((uint32_t *) mp->b_wptr)++ = htonl(as->drn); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_SRN; *((uint32_t *) mp->b_wptr)++ = htonl(as->srn); fixme(("Get cause from RESET_reason\n")); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_CAUSE; *((uint32_t *) mp->b_wptr)++ = hotnl(cause); (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } static int sccpp_reset_con(as_t * as, mblk_t ** mpp) { mblk_t *mp; N_reset_con_t *p = (typeof(p)) (*mpp)->b_rptr; size_t mlen = 8 * sizeof(uint32_t); if ((mp = allocb(mlen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = SUA_CONS_RESCO; *((uint32_t *) mp->b_wptr)++ = htonl(mlen); *((uint32_t *) mp->b_wptr)++ = UA_PARM_RC; *((uint32_t *) mp->b_wptr)++ = htonl(as->l.id.rc); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_DRN; *((uint32_t *) mp->b_wptr)++ = htonl(as->drn); *((uint32_t *) mp->b_wptr)++ = SUA_PARM_SRN; *((uint32_t *) mp->b_wptr)++ = htonl(as->srn); (*mpp) = mp; return (0); } return ua_bufcall(as->ss7->rq, mlen); } static int sccpp_xlat(as_t * as, mblk_t ** mpp) { switch (*((long *) (*mpp)->b_rptr)) { case N_ERROR_ACK: return sccpp_error_ack(as, mpp); case N_OK_ACK: return sccpp_ok_ack(as, mpp); case N_CONN_IND: return sccpp_conn_ind(as, mpp); case N_CONN_CON: return sccpp_conn_con(as, mpp); case N_DISCON_IND: return sccpp_discon_ind(as, mpp); case N_DATA_IND: return sccpp_data_ind(as, mpp); case N_EXDATA_IND: return sccpp_exdata_ind(as, mpp); case N_UNITDATA_IND: return sccpp_unitdata_ind(as, mpp); case N_UDERROR_IND: return sccpp_uderror_ind(as, mpp); case N_DATACK_IND: return sccpp_datack_ind(as, mpp); case N_RESET_IND: return sccpp_reset_ind(as, mpp); case N_RESET_CON: return sccpp_reset_con(as, mpp); } return (-ENOTSUPP); } static int sccpp_xlat_prim(queue_t * q, mblk_t * mp) { int err; xp_t *xp; pp_t *pp; as_t *as; lp_t *lp = (lp_t *) q->q_ptr; ensure(q, return (-EFAULT)); ensure(lp, return (-EFAULT)); if (!(as = ua_pp_route(lp))) return (0); /* * If we have a local SCCP User, then just pass the primitive on to * the local user. */ if ((pp = ua_as_route_loc(as))) { if (mp->b_datap->db_type < QPCTL && !canput(pp->rq)) return (-EBUSY); putq(pp->rq, mp); return (1); } /* * If we have a remote SCCP User (i.e, SUA AS), then translate the * primitive to an SUA message and pass it to the AS. */ if ((xp = ua_as_route_rem(as))) { if (!(pp = xp->pp.pp)) { ptrace(("Have route to XP but no LP\n")); return (-EFAULT); } if (mp->b_datap->db_type < QPCTL && !canput(pp->rq)) return (-EBUSY); if ((err = sccpp_xlat(as, &mp))) return (err); putq(pp->rq, mp); return (1); } ptrace(("AS-U marked active but no active AS-U\n")); return (-EFAULT); } static int sua_l_r_proto(queue_t * q, mblk_t * mp) { switch (*((long *) mp->b_rptr)) { case N_INFO_ACK: return sccpp_info_ack(q, mp); case N_BIND_ACK: return sccpp_bind_ack(q, mp); case N_ERROR_ACK: case N_OK_ACK: case N_CONN_IND: case N_CONN_CON: case N_DISCON_IND: case N_DATA_IND: case N_EXDATA_IND: case N_UNITDATA_IND: case N_UDERROR_IND: case N_DATACK_IND: case N_RESET_IND: case N_RESET_CON: return sccpp_xlat_prim(q, mp); } return (-EOPNOTSUPP); } static int sua_l_r_pcproto(queue_t * q, mblk_t * mp) { return sua_l_r_proto(q, mp); } static int sua_l_r_error(queue_t * q, mblk_t * mp) { fixme(("Deactivate and take down AS, notify LM\n")); return (-EFAULT); } static int sua_l_r_hangup(queue_t * q, mblk_t * mp) { fixme(("Deactivate and take down AS, notify LM\n")); return (-EFAULT); } static int sua_l_r_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_PROTO: return sua_l_r_proto(q, mp); case M_PCPROTO: return sua_l_r_pcproto(q, mp); case M_ERROR: return sua_l_r_error(q, mp); case M_HANGUP: return sua_l_r_hangup(q, mp); case M_FLUSH: return ua_r_flush(q, mp); } return (-EOPNOTSUPP); } /* * ------------------------------------------------------------------------- * * SCTP NPI Transport Message Handling * * ------------------------------------------------------------------------- * * SUA --> SCTP NPI Transport Primitives * ------------------------------------------------------------------------- */ static int sua_s_w_data(queue_t * q, mblk_t * dp) { mblk_t *mp; N_data_req_t *p; N_qos_sel_data_sctp_t *q; if ((mp = allocb(sizeof(*p) + sizeof(*q), BPRI_MED))) { uint32_t mhdr = ((uint32_t *) dp->b_rptr)[0]; mp->b_datap->db_type = M_PROTO; p = ((typeof(p)) mp->b_wptr)++; p->PRIM_type = N_DATA_REQ; p->DATA_xfer_flags = 0; q = ((typeof(q)) mp->b_wptr)++; q->n_qos_type = N_QOS_SEL_DATA_SCTP; q->ppi = SUA_PPI; q->tsn = 0; q->ssn = 0; mp->b_cont = dp; switch (UA_MSG_CLAS(mhdr)) { case UA_CLASS_MGMT: case UA_CLASS_ASPS: case UA_CLASS_RKMM: q->sid = 0; break; case UA_CLASS_ASPT: case UA_CLASS_XFER: case UA_CLASS_SNMM: { uint32_t rc = ((uint32_t *) dp->b_rptr)[3]; fixme(("Map RC onto a stream id\n")); q->sid = rc; break; } default: case UA_CLASS_MAUP: case UA_CLASS_Q921: case UA_CLASS_CNLS: case UA_CLASS_CONS: case UA_CLASS_TDHM: case UA_CLASS_TCHM: freeb(mp); return (-EPROTO); } putq(q, mp); return (1); } return (-ENOBUFS); } static int sua_s_w_ctl(queue_t * q, mblk_t * mp) { return sua_s_w_data(q, mp); } static int sua_s_w_error(queue_t * q, mblk_t * mp) { fixme(("Disconnect, deactivate and take down ASP and notify LM\n")); noenable(q); return (-EFAULT); } static int sua_s_w_hangup(queue_t * q, mblk_t * mp) { fixme(("Disconnect, deactivate and take down ASP and notify LM\n")); noenable(q); return (-EFAULT); } static int sua_x_w_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_DATA: return sua_s_w_data(q, mp); case M_CTL: return sua_s_w_ctl(q, mp); case M_ERROR: return sua_s_w_error(q, mp); case M_HANGUP: return sua_s_w_hangup(q, mp); case M_FLUSH: return ua_w_flush(q, mp); } return (-EOPNOTSUPP); } /* * SCTP NPI Transport --> SUA Primitives * ------------------------------------------------------------------------- */ static int sua_s_data_ind(queue_t * q, mblk_t * mp) { } static int sua_s_exdata_ind(queue_t * q, mblk_t * mp) { } static int sua_s_other_ind(queue_t * q, mblk_t * mp) { } static int sua_s_r_proto(queue_t * q, mblk_t * mp) { switch (*((long *) mp->b_rptr)) { case N_DATA_IND: return sua_s_data_ind(q, mp); case N_EXDATA_IND: return sua_s_exdata_ind(q, mp); default: return sua_s_other_ind(q, mp); } } static int sua_s_r_pcproto(queue_t * q, mblk_t * mp) { return sua_s_r_proto(q, mp); } static int sua_s_r_error(queue_t * q, mblk_t * mp) { fixme(("Deactivate and take down ASP and notify LM\n")); noenable(q); return (-EFAULT); } static int sua_s_r_hangup(queue_t * q, mblk_t * mp) { fixme(("Deactivate and take down ASP and notify LM\n")); noenable(q); return (-EFAULT); } static int sua_x_r_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_PROTO: return sua_s_r_proto(q, mp); case M_PCPROTO: return sua_s_r_pcproto(q, mp); case M_ERROR: return sua_s_r_error(q, mp); case M_HANGUP: return sua_s_r_hangup(q, mp); case M_FLUSH: return ua_r_flush(q, mp); } return (-EOPNOTSUPP); } extern struct drv sua_driver = { SUA_CMAJOR, SUA_NMAJOR, SUA_NMINOR, {&sua_u_r_prim, &sua_u_w_prim}, {&sua_l_r_prim, &sua_l_w_prim}, {&sua_x_r_prim, &sua_x_w_prim} };
|
|||||||||||||||||||||||||||
OpenSS7 SS7 for the Common Man |
Home | Overview | Status | News | Documentation | Resources | About | ||||||||||||||||||||
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |