OpenSS7
SS7 for the
Common Man

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified:

Home Overview Status News Documentation Resources About
   
 Overview
 Status
 News
 Documentation
 Resources
 About

   
Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/drivers/tcap/tcap_lower.c


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);
}


Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/drivers/tcap/tcap_lower.c

OpenSS7
SS7 for the
Common Man
Home Overview Status News Documentation Resources About

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified: