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/ua/ua_upper.c


File /code/strss7/drivers/ua/ua_upper.c



#ident "@(#) $RCSfile: ua_upper.c,v $ $Name:  $($Revision: 0.8.2.2 $) $Date: 2003/04/03 19:51:46 $"

static char const ident[] =
    "$RCSfile: ua_upper.c,v $ $Name:  $($Revision: 0.8.2.2 $) $Date: 2003/04/03 19:51:46 $";

#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 "ua.h"
#include "ua_data.h"
//#include "ua_msgs.h"
#include "ua_ctrl.h"
//#include "ua_prov.h"
//#include "ua_pdu.h"
#include "../sl/sl_user.h"
#include "../mtp/mtp_user.h"
#include "../sccpi/sccp_user.h"
#include "../tcap/tcap_user.h"

/*
 *  =========================================================================
 *
 *  Message Processing
 *
 *  =========================================================================
 */
/*
 *  M_DATA Processing
 *  -------------------------------------------------------------------------
 */
static inline int ua_data(queue_t * q, mblk_t * mp)
{
	dp_t *dp = (dp_t *) q->q_ptr;
	ensure(dp, return -EFAULT);
	ensure(dp->w_data, return -EFAULT);
	return (*dp->w_data) (q, mp);
}

/*
 *  M_PROTO Processing
 *  -------------------------------------------------------------------------
 */
static inline int ua_proto(queue_t * q, mblk_t * mp)
{
	dp_t *dp = (dp_t *) q->q_ptr;
	ensure(dp, return -EFAULT);
	ensure(dp->w_proto, return -EFAULT);
	return (*dp->w_proto) (q, mp);
}

/*
 *  M_PCPROTO Processing
 *  -------------------------------------------------------------------------
 */
static inline int ua_pcproto(queue_t * q, mblk_t * mp)
{
	dp_t *dp = (dp_t *) q->q_ptr;
	ensure(dp, return -EFAULT);
	ensure(dp->w_pcproto, return -EFAULT);
	return (*dp->w_pcproto) (q, mp);
}

/*
 *  M_ERROR Processing
 *  -------------------------------------------------------------------------
 *  We don't accept M_ERRORs from above.
 */
/*
 *  M_HANGUP Processing
 *  -------------------------------------------------------------------------
 *  We don't accept M_HANGUPs from above.
 */
/*
 *  M_FLUSH Processing
 *  -------------------------------------------------------------------------
 *  Take flushes from above and turn them back around back up to the SS7 User.
 *  Perhaps we should push a FLUSH downwards and make a BEAT out of it,
 *  waiting for the BEAT Ack before returning the flush back upstream.
 */
static int ua_w_flush(queue_t * q, mblk_t * mp)
{
	if (*mp->b_rptr & FLUSHW) {
		if (*mp->b_rptr & FLUSHBAND)
			flushband(q, mp->b_rptr[1], FLUSHALL);
		else
			flushq(q, FLUSHALL);
		*mp->b_rptr &= ~FLUSHW;
	}
	if (*mp->b_rptr & FLUSHR && !(mp->b_flag & MSGNOLOOP)) {
		if (*mp->b_rptr & FLUSHBAND)
			flushband(RD(q), mp->b_rptr[1], FLUSHALL);
		else
			flushq(RD(q), FLUSHALL);
		mp->b_flag |= MSGNOLOOP;
		qreply(q, mp);	/* flush all the way back up */
		return (0);
	}
	freemsg(mp);
	return (0);
}

/*
 *  =========================================================================
 *
 *  M_IOCTL Processing
 *
 *  =========================================================================
 */
/*
 *  I_LINK, I_PLINK Handling
 *  -------------------------------------------------------------------------
 *  SS7 or SGP Provider or ASP User streams can be linked under the UA
 *  multiplexing driver.  We permit normal SS7 streams to perform an I_LINK of
 *  SS7 or SGP provider or ASP user streams under the UA driver, but we only
 *  permit the SS7 control stream to perform an I_PLINK of SS7 or SGP provider
 *  or ASP user streams.  This is so that if the configuration daemon crashes
 *  it can come back and the configuration has not been destroyed.
 *
 *  When linked, we generate the appropriate information request downstream to
 *  the newly linked SS7 or SGP provider or ASP user stream.  The purpose of
 *  this is to discover the response from the stream as to which state the
 *  stream is currently in and which addresses might be currently bound.  This
 *  permits the caller to bind the SS7 or SGP provider or ASP user streams.
 */
static inline int ua_i_link(queue_t * q, mblk_t * pdu, struct linkblk *lb)
{
	mblk_t *mp;
	lp_t *lp;
	queue_t *lq;
	ensure(lb, return (-EFAULT));
	lq = RD(lb->l_qbot);
	if (!(lp = kmalloc(sizeof(*lp), GFP_KERNEL)))
		return (-ENOMEM);
	bzero(lp, sizeof(*lp));
	lp->q = RD(lq);
	lp->lmp = RD(q);
	lp->muxid = lb->l_index;
	lp->state = 0;
	RD(lq)->q_ptr = WR(lq)->q_ptr = lp;
	if ((lp->next = ua_links))
		lp->next->prev = &lp->next;
	lp->prev = &ua_links;
	qdisable(lq);		/* disable queue till configured */
	return (lb->l_index);
}

/*
 *  I_UNLINK, I_PUNLINK Handling
 *  -------------------------------------------------------------------------
 *  When we unlink, if we still have referencing upper SS7-user streams, we
 *  send each of them a M_HANGUP message indicating the loss of the
 *  connection.  This might result in a SIG_PIPE signal being sent to the
 *  process if the SS7-user is a stream head.
 */
static inline int ua_i_unlink(queue_t * q, struct linkblk *lb)
{
	int err;
	lp_t *lp;
	uint muxid;
	ensure(lb, return (-EFAULT));
	muxid = lb->l_lindex;
	for (lp = ua_links; lp && lp->muxid != muxid; lp = lp->next);
	if (!lp)
		return (-EINVAL);
	if ((err = m_flush_all(q, NULL, FLUSHW, 0)))
		return (err);
	if ((err = m_hanup_all(q, NULL)))
		return (err);
	if ((*(lp->prev) = lp->next))
		lp->next->prev = lp->prev;
	lp->q->q_ptr = WR(lp->q)->q_ptr = NULL;
	kfree(lp);
	return (0);
}
static int ua_w_ioctl(queue_t * q, mblk_t * pdu)
{
	int ret = -EINVAL;
	void *arg = pdu->b_cont ? pdu->b_cont->b_rptr : NULL;
	struct iocblk = *iocp = (struct iocblk *) pdu->b_wptr;
	int cmd = iocp->ioc_cmd;
	switch (_IOC_TYPE(cmd)) {
	case __SID:
		switch (cmd) {
		case I_PLINK:
			if (RD(q) != ua_lmq) {
				ret = -EPERM;
				break;
			}
		case I_LINK:
			ret = ua_i_link(q, pdu, arg);
			break;
		case I_PUNLINK:
			if (RD(q) != ua_lmq) {
				ret = -EPERM;
				break;
			}
		case I_UNLINK:
			ret - ua_i_unlink(q, arg);
			break;
		}
		break;
	case UA_IOC_MAGIC:
	default:
		ret = -EOPNOTSUPP;
		break;
	}
	pdu->b_datap->db_type = ret < 0 ? M_IOCNAK : M_IOCACK;
	iocp->ioc_error = ret < 0 ? -ret : 0;
	iocp->ioc_rva = ret > 0 ? ret : -1;
	qreply(q, pdu);
	return (0);
}

/*
 *  =========================================================================
 *
 *  QUEUE PUT and SERVICE routines
 *
 *  =========================================================================
 */
static inline int ua_recover(queue_t * q, mblk_t * mp, int err)
{
	switch (err) {
	case -EBUSY:
	case -EAGAIN:
	case -ENOMEM:
	case -ENOBUFS:
		putq(q, mp);
		return (0);
	}
	freemsg(mp);
	return (err);
}
static inline int ua_reservice(queue_t * q, mblk_t * mp, int err)
{
	if (mp->b_datap->db_type < QPCTL)
		switch (err) {
		case -EBUSY:
		case -EAGAIN:
		case -ENOMEM:
		case -ENOBUFS:
			putbq(q, mp);
			return (0);
		}
	freemsg(mp);
	return (err);
}

/*
 *  WRITE PUT and SERVICE (Message from above SS7-User --> UA)
 *  -------------------------------------------------------------------------
 */
static inline int ua_wr(queue_t * q, mblk_t * mp)
{
	switch (mp->b_datap->db_type) {
	case M_DATA:
		return ua_w_data(q, mp);
	case M_PROTO:
		return ua_w_proto(q, mp);
	case M_PCPROTO:
		return ua_w_pcproto(q, mp);
	case M_CTL:
		return ua_w_ctl(q, mp);
	case M_FLUSH:
		return ua_w_flush(q, mp);
	case M_IOCTL:
		return ua_w_ioctl(q, mp);
	}
}
INT ua_u_wput(queue_t * q, mblk_t * mp)
{
	int err;
	dp_t *dp = (dp_t *) q->q_ptr;
	if (mp->b_datap->db_type < QPCTL && q->q_count) {
		putq(q, mp);
		return (INT) (0);
	}
	if ((err = (*dp->rd) (q, mp)))
		return (INT) (ua_recover(q, mp, err));
	return (INT) (0);
}

INT ua_u_wsrv(queue_t * q)
{
	mblk_t *mp;
	dp_t *dp = (dp_t *) q->q_ptr;
	while ((mp = getq(q))) {
		int err;
		if ((err = (*dp->rd) (q, mp)))
			return (INT) (ua_reservice(q, mp, err));
	}
	return (INT) (0);
}


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

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

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