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/tcap/tcap_lower.c#ident "@(#) $RCSfile: tcap_lower.c,v $ $Name: $($Revision: 0.8.2.2 $) $Date: 2003/04/03 19:51:40 $" static char const ident[] = "$RCSfile: tcap_lower.c,v $ $Name: $($Revision: 0.8.2.2 $) $Date: 2003/04/03 19:51:40 $"; #define __NO_VERSION__ #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 "../debug.h" #include "../bufq.h" #include "tcap.h" #include "tcap_data.h" #include "tcap_msgs.h" #include "tcap_ctrl.h" #include "tcap_prov.h" #include "../sccpi/sccp_user.h" /* * ========================================================================= * * TCAP INPUT EVENT State Machines * * ========================================================================= * These functions take an input msg at the TCAP stream and run the state * machine associated with the TCAP stream. These are the Transaction (TR) * Sub-Layer services. */ static int tcap_i_uni(queue_t * q, mblk_t * msg) { mblk_t *mp; TC_uni_ind_t *p; N_unitdata_ind_t *s = (N_unitdata_ind_t *) msg->b_cont->b_rptr; tcap_t *tcap = (tcap_t *) q->q_ptr; tr_msg_t *m = (tr_msg_t *) msg->b_rptr; (void) m; (void) tcap; /* * TODO: process message... * * Provide a TC_UNI_IND and follow with any TC_XXX_IND component * indications. */ if (!(mp = allocb(sizeof(*p), BPRI_MED))) return (-ENOBUFS); p = (TC_uni_ind_t *) mp->b_wptr; mp->b_datap->db_type = M_PROTO; p->PRIM_type = TC_UNI_IND; p->SRC_length = s->SRC_length; p->SRC_offset = s->SRC_length ? sizeof(*p) : 0; p->DEST_length = s->DEST_length; p->DEST_offset = s->DEST_length ? sizeof(*p) + s->SRC_length : 0; p->QOS_length = 0; p->QOS_offset = 0; p->CONTEXT_length = FIXME; p->CONTEXT_offset = FIXME; p->DIALOG_id = 0; p->COMP_flags = (m->parms & TCAP_PTF_CSEQ) ? 1 : 0; mp->b_wptr += sizeof(*p); /* FIXME */ return (0); } /* * ========================================================================= * * SCCP --> TCAP (Upstream Primitives received from downstream) * * ========================================================================= */ /* * N_INFO_ACK 16 - Information Acknowledgement * ---------------------------------------------------------------- */ static int sccp_info_ack(queue_t * q, mblk_t * pdu) { sccp_t *sccp = (sccp_t *) q->q_ptr; N_info_ack_t *p = (N_info_ack_t *) pdu->b_rptr; if (pdu->b_wptr - pdu->b_rptr < sizeof(*p)) return m_error_all(q, pdu, EFAULT, EFAULT); sccp->flags = p->OPTIONS_flags; sccp->nsdu = p->NSDU_size; sccp->nidu = p->NIDU_size; sccp->nodu = p->NODU_size; if (p->ADDR_length >= sizeof(sccp_addr_t)) { sccp_addr_t *add = (sccp_addr_t *) (pdu->b_rptr + p->ADDR_offset); bcopy(add, &sccp->bnd, sizeof(*add) + add->alen); } if (p->PROTOID_length == 1) sccp->ssn = *((uint8_t *) (pdu->b_rptr + p->PROTOID_offset)); sccp->state = p->CURRENT_state; freemsg(pdu); return (0); } /* * N_BIND_ACK 17 - NS User bound to network address * ---------------------------------------------------------------- */ static int sccp_bind_ack(queue_t * q, mblk_t * pdu) { sccp_t *sccp = (sccp_t *) q->q_ptr; N_bind_ack_t *p = (N_bind_ack_t *) pdu->b_rptr; if (pdu->b_wptr - pdu->b_rptr < sizeof(*p)) return m_error_reply(q, pdu, EFAULT, EFAULT); if (sccp->state != NS_WACK_BREQ) return m_error_reply(q, pdu, EPROTO, EPROTO); if (p->ADDR_length >= sizeof(sccp_addr_t)) { sccp_addr_t *add = (sccp_addr_t *) (pdu->b_rptr + p->ADDR_offset); bcopy(add, &sccp->bnd, sizeof(*add) + add->alen); } if (p->PROTOID_length == 1) sccp->ssn = *((uint8_t *) (pdu->b_rptr + p->PROTOID_offset)); sccp->state = NS_IDLE; freemsg(pdu); return (0); } /* * N_ERROR_ACK 18 - Error Acknowledgement * ---------------------------------------------------------------- */ static int sccp_error_ack(queue_t * q, mblk_t * pdu) { sccp_t *sccp = (sccp_t *) q->q_ptr; N_error_ack_t *p = (N_error_ack_t *) pdu->b_rptr; if (pdu->b_wptr - pdu->b_rptr < sizeof(*p)) return m_error_reply(q, pdu, EFAULT, EFAULT); switch (sccp->state) { case NS_WACK_BREQ: if (p->ERROR_prim == N_BIND_REQ) sccp->state = NS_UNBND; break; case NS_WACK_UREQ: if (p->ERROR_prim == N_UNBIND_REQ) sccp->state = NS_IDLE; break; case NS_WACK_OPTREQ: if (p->ERROR_prim == N_OPTMGMT_REQ) sccp->state = sccp->state; break; case NS_WCON_CREQ: if (p->ERROR_prim == N_CONN_REQ) sccp->state = NS_IDLE; break; case NS_WRES_CIND: if (p->ERROR_prim == N_CONN_RES) sccp->state = sccp->state; break; case NS_WACK_CRES: case NS_DATA_XFER: case NS_WCON_RREQ: case NS_WRES_RIND: case NS_WACK_DREQ6: case NS_WACK_DREQ7: case NS_WACK_DREQ9: case NS_WACK_DREQ10: case NS_WACK_DREQ11: default: case NS_NOSTATES: } freemsg(pdu); return (0); } /* * N_OK_ACK 19 - Success Acknowledgement * ---------------------------------------------------------------- */ static int sccp_ok_ack(queue_t * q, mblk_t * pdu) { sccp_t *sccp = (sccp_t *) q->q_ptr; N_ok_ack_t *p = (N_ok_ack_t *) pdu->b_rptr; if (pdu->b_wptr - pdu->b_rptr < sizeof(*p)) return m_error_reply(q, pdu, EFAULT, EFAULT); switch (sccp->state) { case NS_WACK_BREQ: case NS_WACK_UREQ: case NS_WACK_OPTREQ: case NS_WCON_CREQ: case NS_WRES_CIND: case NS_WACK_CRES: case NS_DATA_XFER: case NS_WCON_RREQ: case NS_WRES_RIND: case NS_WACK_DREQ6: case NS_WACK_DREQ7: case NS_WACK_DREQ9: case NS_WACK_DREQ10: case NS_WACK_DREQ11: default: case NS_NOSTATES: } /* * TODO: more... */ freemsg(pdu); return (0); } /* * N_UNITDATA_IND 20 - Connection-less data receive indication * ---------------------------------------------------------------- */ static int sccp_unitdata_ind(queue_t * q, mblk_t * pdu) { sccp_t *sccp = (sccp_t *) q->q_ptr; N_unitdata_ind_t *p = (N_unitdata_ind_t *) pdu->b_rptr; (void) sccp; if (pdu->b_wptr - pdu->b_rptr < sizeof(*p)) return m_error_all(q, pdu, EFAULT, EFAULT); if (p->SRC_length < sizeof(sccp_addr_t)) return m_error_all(q, pdu, EFAULT, EFAULT); if (p->DEST_length < sizeof(sccp_addr_t)) return m_error_all(q, pdu, EFAULT, EFAULT); if (!pdu->b_cont) return (-EINVAL); return tcap_recv_msg(q, pdu); } /* * N_UDERROR_IND 21 - UNITDATA Error Indication * ---------------------------------------------------------------- */ static int sccp_uderror_ind(queue_t * q, mblk_t * pdu) { tcap_t *tcap; int ecode; sccp_t *sccp = (sccp_t *) q->q_ptr; N_uderror_ind_t *p = (N_uderror_ind_t *) pdu->b_rptr; (void) ecode; if (pdu->b_wptr - pdu->b_rptr < sizeof(*p)) return m_error_all(q, pdu, EFAULT, EFAULT); if (p->DEST_length < sizeof(sccp_addr_t)) return m_error_all(q, pdu, EFAULT, EFAULT); /* * TODO: have to propagate error to TCAP-Users. Most of these turn * into aborts (TR_ABORT_IND). We still have to generate a * TRE_ABT_RES msg. */ for (tcap = sccp->tcap; tcap; tcap = tcap->sccp_next) { if (tcap->outcnt > 0) { /* * Send TRE_ABT_RES msg to tcap user.... */ } } freemsg(pdu); return (0); } int (*sccp_dprim[]) (queue_t *, mblk_t *) = { #define SCCP_DSTR_FIRST N_CONN_REQ NULL, /* N_CONN_REQ 0 - NC request */ NULL, /* N_CONN_RES 1 - Accept prev NC indication */ NULL, /* N_DISOCN_REQ 2 - NC disconnect request */ NULL, /* N_DATA_REQ 3 - CO data transfer request */ NULL, /* N_EXDATA_REQ 4 - CO data transfer request */ NULL, /* N_INFO_REQ 5 - Information request */ NULL, /* N_BIND_REQ 6 - Bind an NS user */ NULL, /* N_UNBIND_REQ 7 - Unbind an NS user */ NULL, /* N_UNITDATA_REQ 8 - CL data transfer request */ NULL, /* N_OPTMGMT_REQ 9 - Options mgmt request */ NULL, /* (not used) 10 - (not used) */ NULL, /* N_CONN_IND 11 - Incoming NC indication */ NULL, /* N_CONN_CON 12 - NC established */ NULL, /* N_DISCON_IND 13 - NC disconnected */ NULL, /* N_DATA_IND 14 - CO data transfer indication */ NULL, /* N_EXDATA_IND 15 - CO data transfer indication */ sccp_info_ack, /* N_INFO_ACK 16 - Information Acknowledgement */ sccp_bind_ack, /* N_BIND_ACK 17 - NS User bound Ack */ sccp_error_ack, /* N_ERROR_ACK 18 - Error Acknowledgement */ sccp_ok_ack, /* N_OK_ACK 19 - Success Acknowledgement */ sccp_unitdata_ind, /* N_UNITDATA_IND 20 - CL data transfer indication */ sccp_uderror_ind, /* N_UDERROR_IND 21 - CL data error indication */ NULL, /* (not used) 22 - (not used) */ NULL, /* N_DATACK_REQ 23 - Data ack request */ NULL, /* N_DATACK_IND 24 - Data ack indication */ NULL, /* N_RESET_REQ 25 - NC reset request */ NULL, /* N_RESET_IND 26 - Incoming NC reset ind */ NULL, /* N_RESET_RES 27 - Reset processing accepted */ NULL /* N_RESET_CON 28 - Reset processing complete */ #define SCCP_DSTR_LAST N_RESET_CON }; static int tcap_r_proto(queue_t * q, mblk_t * mp) { /* FIXME */ freemsg(mp); return (0); } /* * ========================================================================= * * M_ERROR Processing * * ========================================================================= * We propagate any M_ERROR(s) received on the lower stream from the SCCP * Provider to every TCAP-User upper stream which is using the SCCP provider. * We also set states here to indicate the error. This is because if we run * out of mblks to propagate the M_ERROR, we will discard the priority * message (M_ERROR) if we are in the read service routine. Setting the * error ensures that we will respond with an M_ERROR later when resources * are available. */ static int tcap_r_error(queue_t * q, mblk_t * pdu) { /* * FIXME: Notify this SCCP-Provider's management stream that the * SCCP-Provider has errored out... */ return m_error_all(q, pdu, *(pdu->b_rptr + 4), *(pdu->b_wptr - 1)); } /* * ========================================================================= * * M_HANGUP Processing * * ========================================================================= * We propagate any M_HANGUP(s) received on the lower stream from the SCCP * Provider to every TCAP-User upper stream which is using the SCCP provider. * We also set states here to indicate the error. This is because if we run * out of mblks to propagate the M_HANGUP, we will discard the priority * message (M_HANGUP) if we are in the read service routine. Setting the * error ensures that we will respond with an M_HANGUP later when resources * are available. */ static int tcap_r_hangup(queue_t * q, mblk_t * pdu) { /* * FIXME: Notify this SCCP-Provider's management stream that the * SCCP-Provider has hung up... */ return m_hangup_all(q, pdu); } /* * ========================================================================= * * QUEUE PUT and SERVICE routines * * ========================================================================= */ /* * READ PUT and SERVICE (Message from below SCCP-Provider --> TCAP) * ------------------------------------------------------------------------- */ int tcap_l_r_prim(queue_t * q, mblk_t * mp) { switch (mp->b_datap->db_type) { case M_PROTO: case M_PCPROTO: return tcap_r_proto(q, mp); case M_FLUSH: return tcap_r_flush(q, mp); case M_ERROR: return tcap_r_error(q, mp); case M_HANGUP: return tcap_r_hangup(q, mp); } return (-EOPNOTSUPP); }
|
|||||||||||||||||||||||||||
OpenSS7 SS7 for the Common Man |
Home | Overview | Status | News | Documentation | Resources | About | ||||||||||||||||||||
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |