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_pdu.c


File /code/strss7/drivers/tcap/tcap_pdu.c



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

static char const ident[] =
    "$RCSfile: tcap_pdu.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 "tcap.h"
#include "tcap_data.h"
#include "tcap_msgs.h"
#include "tcap_ctrl.h"
#include "tcap_prov.h"
#include "../sccpi/sccp_user.h"

/*
 *  =========================================================================
 *
 *  TCAP RECV Peer Messages (Component (TC) Sub-Layer)
 *
 *  =========================================================================
 *
 *  ANSI PRIVATE-TCAP version of Components.
 *
 *  -------------------------------------------------------------------------
 *
 *  UNPACK ANSI Correlation Ids.
 */
static inline int unpack_priv_corids(unsigned char **p, unsigned char *e, tc_msg_t * m,
				     const uint ctype)
{
	int err;
	uint tag;
	if ((err = unpack_priv_prim(p, &e, &tag)))
		return (err);
	if (tag != TCAP_TAG_PRIV_CORID)
		return (-EINVAL);
	switch (e - *p) {
	case 0:		/* no ids */
		switch (ctype) {
		case TCAP_CT_INVOKE_L:
		case TCAP_CT_INVOKE_NL:
		case TCAP_CT_REJECT:
			return (0);
		}
		return (-EPROTO);
	case 1:		/* invoke id */
		switch (ctype) {
		default:
		case TCAP_CT_INVOKE_L:
		case TCAP_CT_INVOKE_NL:
		case TCAP_CT_RESULT_L:
		case TCAP_CT_RESULT_NL:
		case TCAP_CT_REJECT:
		case TCAP_CT_ERROR:
			if (*p >= e)
				return (-EMSGSIZE);
			m->iid = *(*p)++;
			m->parms |= TCAP_PTF_IID;
			break;
		}
		return (-EPROTO);
	case 2:		/* invoke id and correlation id */
		switch (ctype) {
		case TCAP_CT_INVOKE_L:
		case TCAP_CT_INVOKE_NL:
			if (*p >= e)
				return (-EMSGSIZE);
			m->iid = *(*p)++;
			m->parms |= TCAP_PTF_IID;
			if (*p >= e)
				return (-EMSGSIZE);
			m->lid = *(*p)++;
			m->parms |= TCAP_PTF_LID;
			return (0);
		}
		return (-EPROTO);
	}
	return (-EINVAL);
}

/*
 *  UNPACK ANSI Opcodes
 */
static inline int unpack_priv_opcode(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	uint tag;
	if ((err = unpack_priv_prim(p, &e, &tag)))
		return (err);
	if (e - *p != 2)
		return (-EMSGSIZE);
	switch (tag) {
	case TCAP_TAG_PRIV_NOPCO:
		if ((err = unpack_implicit_int(p, e, &m->opcode)))
			return (err);
		m->parms |= TCAP_PTF_NOPCO;
		return (0);
	case TCAP_TAG_PRIV_POPCO:
		if ((err = unpack_implicit_int(p, e, &m->opcode)))
			return (err);
		m->parms |= TCAP_PTF_POPCO;
		return (0);
	}
	return (-EPROTO);
}

/*
 *  UNPACK ANSI Error Codes
 */
static inline int unpack_priv_ecode(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	uint tag;
	if ((err = unpack_priv_prim(p, &e, &tag)))
		return (err);
	switch (tag) {
	case TCAP_TAG_PRIV_NECODE:
		if ((err = unpack_explicit_int(p, e, &m->ecode)))
			return (err);
		m->parms |= TCAP_PTF_NECODE;
		return (0);
	case TCAP_TAG_PRIV_PECODE:
		if ((err = unpack_explicit_int(p, e, &m->ecode)))
			return (err);
		m->parms |= TCAP_PTF_PECODE;
		return (0);
	}
	return (-EPROTO);
}

/*
 *  UNPACK ANSI Problem Codes
 */
static inline int unpack_priv_pcode(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	uint tag;
	if ((err = unpack_priv_prim(p, &e, &tag)))
		return (err);
	if ((err = unpack_implicit_int(p, e, &m->pcode)))
		return (err);
	m->parms |= TCAP_PTF_PCODE;
	return (0);
}

/*
 *  UNPACK ANSI Component Parameter Sets
 */
static inline int unpack_priv_pset(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	uint tag;
	if ((err = unpack_priv_cons(p, &e, &tag)))
		return (err);
	if (tag != TCAP_TAG_PRIV_PSET && tag != TCAP_TAG_PRIV_PSEQ)
		return (-EINVAL);
	m->prm_beg = *p;
	m->prm_end = e;
	*p = e;
	m->parms |= TCAP_PTF_PSEQ;
	return (0);
}

/*
 *  ANSI INVOKE (LAST)
 *  ------------------------------------------------------------------------
 */
static int tcap_priv_dec_inkl(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	m->type = TCAP_CT_INVOKE_L;
	if ((err = unpack_priv_corids(p, e, m, TCAP_CT_INVOKE_L)))
		return (err);
	if ((err = unpack_priv_opcode(p, e, m)))
		return (err);
	if ((err = unpack_priv_pset(p, e, m)))
		return (err);
	if (*p != e)
		return (-EMSGSIZE);
	return (0);
}

/*
 *  ANSI INVOKE (NOT LAST)
 *  ------------------------------------------------------------------------
 */
static int tcap_priv_dec_ink(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	m->type = TCAP_CT_INVOKE_NL;
	if ((err = unpack_priv_corids(p, e, m, TCAP_CT_INVOKE_NL)))
		return (err);
	if ((err = unpack_priv_opcode(p, e, m)))
		return (err);
	if ((err = unpack_priv_pset(p, e, m)))
		return (err);
	if (*p != e)
		return (-EMSGSIZE);
	return (0);
}

/*
 *  ANSI RETURN RESULT (LAST)
 *  ------------------------------------------------------------------------
 */
static int tcap_priv_dec_rrl(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	m->type = TCAP_CT_RESULT_L;
	if ((err = unpack_priv_corids(p, e, m, TCAP_CT_RESULT_L)))
		return (err);
	if ((err = unpack_priv_pset(p, e, m)))
		return (err);
	if (*p != e)
		return (-EMSGSIZE);
	return (0);
}

/*
 *  ANSI RETURN RESULT (NOT LAST)
 *  ------------------------------------------------------------------------
 */
static int tcap_priv_dec_rr(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	m->type = TCAP_CT_RESULT_NL;
	if ((err = unpack_priv_corids(p, e, m, TCAP_CT_RESULT_NL)))
		return (err);
	if ((err = unpack_priv_pset(p, e, m)))
		return (err);
	if (*p != e)
		return (-EMSGSIZE);
	return (0);
}

/*
 *  ANSI RETURN ERROR
 *  ------------------------------------------------------------------------
 */
static int tcap_priv_dec_rer(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	m->type = TCAP_CT_ERROR;
	if ((err = unpack_priv_corids(p, e, m, TCAP_CT_ERROR)))
		return (err);
	if ((err = unpack_priv_ecode(p, e, m)))
		return (err);
	if ((err = unpack_priv_pset(p, e, m)))
		return (err);
	if (*p != e)
		return (-EMSGSIZE);
	return (0);
}

/*
 *  ANSI REJECT
 *  ------------------------------------------------------------------------
 */
static int tcap_priv_dec_rej(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	m->type = TCAP_CT_REJECT;
	if ((err = unpack_priv_corids(p, e, m, TCAP_CT_REJECT)))
		return (err);
	if ((err = unpack_priv_pcode(p, e, m)))
		return (err);
	if ((err = unpack_priv_pset(p, e, m)))
		return (err);
	if (*p != e)
		return (-EMSGSIZE);
	return (0);
}

/*
 *  ANSI Component Decoder
 *  ------------------------------------------------------------------------
 */
int tcap_priv_dec_comp(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	uint tag;
	if (!(err = unpack_appl_cons(p, &e, &tag)))
		switch (tag) {
		case TCAP_TAG_PRIV_INKL:	/* Invoke (Last) */
			if (!(err = tcap_priv_dec_inkl(p, e, m)))
				return (0);
			break;
		case TCAP_TAG_PRIV_INK:	/* Invoke (Not Last) */
			if (!(err = tcap_priv_dec_ink(p, e, m)))
				return (0);
			break;
		case TCAP_TAG_PRIV_RRL:	/* Return Result (Last) */
			if (!(err = tcap_priv_dec_rrl(p, e, m)))
				return (0);
			break;
		case TCAP_TAG_PRIV_RR:	/* Return Result (Not Last) */
			if (!(err = tcap_priv_dec_rr(p, e, m)))
				return (0);
			break;
		case TCAP_TAG_PRIV_RER:	/* Return Error */
			if (!(err = tcap_priv_dec_rer(p, e, m)))
				return (0);
			break;
		case TCAP_TAG_PRIV_REJ:	/* Reject */
			if (!(err = tcap_priv_dec_rej(p, e, m)))
				return (0);
			break;
		default:
			err = -EINVAL;
			break;
		}
	return (err);
}

/*
 *  -------------------------------------------------------------------------
 *
 *  ITUT APPLICATION-TCAP version of Components.
 *
 *  -------------------------------------------------------------------------
 *
 *  UNPACK ITUT Correlation Ids.
 */
static inline int unpack_univ_iid(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	(void) p;
	(void) e;
	(void) m;
	/* FIXME */
	return (-EFAULT);
}
static inline int unpack_univ_lid(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	(void) p;
	(void) e;
	(void) m;
	/* FIXME */
	return (-EFAULT);
}
static inline int unpack_univ_corids(unsigned char **p, unsigned char *e, tc_msg_t * m,
				     const uint ctype)
{
	int err;
	switch (ctype) {
	case TCAP_CT_INVOKE_L:
		if ((err = unpack_univ_iid(p, e, m)))
			return (err);
		m->parms |= TCAP_PTF_IID;
		if ((err = unpack_univ_lid(p, e, m)))	/* optional */
			return (err);
		m->parms |= TCAP_PTF_LID;
		return (0);
	case TCAP_CT_RESULT_L:
	case TCAP_CT_RESULT_NL:
	case TCAP_CT_ERROR:
		if ((err = unpack_univ_iid(p, e, m)))
			return (err);
		m->parms |= TCAP_PTF_IID;
		return (0);
	case TCAP_CT_REJECT:
		/* could be NULL */
		if ((err = unpack_univ_iid(p, e, m)))
			return (err);
		m->parms |= TCAP_PTF_IID;
		return (0);
	}
	return (-EFAULT);
}

/*
 *  UNPACK ITUT Opcodes
 */
static inline int unpack_univ_opcode(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	uint tag;
	if ((err = unpack_univ_prim(p, &e, &tag)))
		return (err);
	if (tag == TCAP_TAG_UNIV_OID)	/* 6 */
		return (-EOPNOTSUPP);	/* we don't support OID opcodes */
	if (tag != TCAP_TAG_UNIV_INT)	/* 2 */
		return (-EPROTO);
	if ((err = unpack_implicit_int(p, e, &m->opcode)))
		return (err);
	m->parms |= TCAP_PTF_LOPCO;
	return (0);
}

/*
 *  UNPACK ITUT Parameter Sequences
 */
static inline int unpack_univ_pseq(unsigned char **p, unsigned char *e, tc_msg_t * m,
				   const uint opt)
{
	int err;
	uint tag;
	if (opt) {
		if (*p >= e)
			return (0);
		if (**p != (0x20 | TCAP_TAG_UNIV_SEQ))
			return (0);
	}
	if ((err = unpack_univ_cons(p, &e, &tag)))
		return (err);
	if (tag != TCAP_TAG_UNIV_SEQ)
		return (-EINVAL);
	m->prm_beg = *p;
	m->prm_end = e;
	*p = e;
	m->parms |= TCAP_PTF_PSEQ;
	return (0);
}

/*
 *  UNPACK ITUT Result Opcode and Parameter Sequences
 */
static inline int unpack_univ_rseq(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	uint tag;
	if (*p >= e)
		return (0);
	if (**p != (0x20 | TCAP_TAG_UNIV_SEQ))
		return (0);
	if ((err = unpack_univ_cons(p, &e, &tag)))
		return (err);
	if (tag != TCAP_TAG_UNIV_SEQ)
		return (-EINVAL);
	if ((err = unpack_univ_opcode(p, e, m)))
		return (err);
	if ((err = unpack_univ_pseq(p, e, m, 0)))
		return (err);
	return (0);
}

/*
 *  UNPACK ITUT Error Codes
 */
static inline int unpack_univ_ecode(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	uint tag;
	if ((err = unpack_univ_prim(p, &e, &tag)))
		return (err);
	switch (tag) {
	case TCAP_TAG_UNIV_INT:
		if ((err = unpack_implicit_int(p, e, &m->ecode)))
			return (err);
		m->parms |= TCAP_PTF_LECODE;
		return (0);
	case TCAP_TAG_UNIV_OID:
		return (-EOPNOTSUPP);	/* don't support global error codes */
	}
	return (-EPROTO);
}

/*
 *  UNPACK ITUT Problem Codes
 */
static inline int unpack_ctxt_pcode(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	uint tag;
	uint ptype;
	if ((err = unpack_ctxt_prim(p, &e, &tag)))
		return (err);
	ptype = tag;
	if ((err = unpack_implicit_int(p, e, &m->pcode)))
		return (err);
	m->pcode |= ptype << 16;
	m->parms |= TCAP_PTF_PCODE;
	return (0);
}

/*
 *  ITUT INVOKE (LAST)
 *  ------------------------------------------------------------------------
 */
static int tcap_ctxt_dec_inkl(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	m->type = TCAP_CT_INVOKE_L;
	if ((err = unpack_univ_corids(p, e, m, TCAP_CT_INVOKE_L)))
		return (err);
	if ((err = unpack_univ_opcode(p, e, m)))
		return (err);
	if ((err = unpack_univ_pseq(p, e, m, 1)))
		return (err);
	if (*p != e)
		return (-EMSGSIZE);
	return (0);
}

/*
 *  ITUT RETURN RESULT (LAST)
 *  ------------------------------------------------------------------------
 */
static int tcap_ctxt_dec_rrl(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	m->type = TCAP_CT_RESULT_L;
	if ((err = unpack_univ_corids(p, e, m, TCAP_CT_RESULT_L)))
		return (err);
	if ((err = unpack_univ_rseq(p, e, m)))
		return (err);
	if (*p != e)
		return (-EMSGSIZE);
	return (0);
}

/*
 *  ITUT RETURN RESULT (NOT LAST)
 *  ------------------------------------------------------------------------
 */
static int tcap_ctxt_dec_rr(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	m->type = TCAP_CT_RESULT_NL;
	if ((err = unpack_univ_corids(p, e, m, TCAP_CT_RESULT_NL)))
		return (err);
	if ((err = unpack_univ_rseq(p, e, m)))
		return (err);
	if (*p != e)
		return (-EMSGSIZE);
	return (0);
}

/*
 *  ITUT RETURN ERROR
 *  ------------------------------------------------------------------------
 */
static int tcap_ctxt_dec_rer(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	m->type = TCAP_CT_ERROR;
	if ((err = unpack_univ_corids(p, e, m, TCAP_CT_ERROR)))
		return (err);
	if ((err = unpack_univ_ecode(p, e, m)))
		return (err);
	if ((err = unpack_univ_pseq(p, e, m, 1)))
		return (err);
	if (*p != e)
		return (-EMSGSIZE);
	return (0);
}

/*
 *  ITUT REJECT
 *  ------------------------------------------------------------------------
 */
static int tcap_ctxt_dec_rej(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	m->type = TCAP_CT_REJECT;
	if ((err = unpack_univ_corids(p, e, m, TCAP_CT_REJECT)))
		return (err);
	if ((err = unpack_ctxt_pcode(p, e, m)))
		return (err);
	if (*p != e)
		return (-EMSGSIZE);
	return (0);
}

/*
 *  ITUT Component Decoder
 *  ------------------------------------------------------------------------
 */
int tcap_appl_dec_comp(unsigned char **p, unsigned char *e, tc_msg_t * m)
{
	int err;
	uint tag;
	if (!(err = unpack_ctxt_cons(p, &e, &tag)))
		switch (tag) {
		case TCAP_TAG_CNTX_INK:	/* Invoke */
			if (!(err = tcap_ctxt_dec_inkl(p, e, m)))
				return (0);
			break;
		case TCAP_TAG_CNTX_RRL:	/* Return Result (Last) */
			if (!(err = tcap_ctxt_dec_rrl(p, e, m)))
				return (0);
			break;
		case TCAP_TAG_CNTX_RER:	/* Return Error */
			if (!(err = tcap_ctxt_dec_rer(p, e, m)))
				return (0);
			break;
		case TCAP_TAG_CNTX_REJ:	/* Reject */
			if (!(err = tcap_ctxt_dec_rej(p, e, m)))
				return (0);
			break;
		case TCAP_TAG_CNTX_RR:	/* Return Result (Not Last) */
			if (!(err = tcap_ctxt_dec_rr(p, e, m)))
				return (0);
			break;
		default:
			err = -EINVAL;
			break;
		}
	return (err);
}

/*
 *  =========================================================================
 *
 *  TCAP RECV Peer Messages (Transaction (TR) Sub-Layer)
 *
 *  =========================================================================
 */
/*
 *  PRIVATE-TCAP version of Packages.  (Used by the TR sub-layer.)
 *  -------------------------------------------------------------------------
 */
static inline int unpack_priv_trsid(unsigned char **p, unsigned char *e, tr_msg_t * m,
				    const uint mtype)
{
	int err;
	uint tag;
	if ((err = unpack_priv_prim(p, &e, &tag)))
		return (err);
	if (tag != TCAP_TAG_PRIV_TRSID)
		return (-EINVAL);
	switch (e - *p) {
	case 0:		/* no transaction ids */
		switch (mtype) {
		case TCAP_MT_UNI:
			return (0);
		}
		return (-EPROTO);
	case 4:		/* orig or dest transaction id */
		switch (mtype) {
		case TCAP_MT_QWP:
		case TCAP_MT_QWOP:
		case TCAP_MT_RESP:
		case TCAP_MT_ABORT:
			unpack_implicit_int(p, e, &m->origid);
			m->parms |= TCAP_PTF_ORIGID;
			return (0);
		}
		return (-EPROTO);
	case 8:		/* orig and dest transaction id */
		switch (mtype) {
		case TCAP_MT_CWP:
		case TCAP_MT_CWOP:
			unpack_implicit_int(p, e - 4, &m->origid);
			m->parms |= TCAP_PTF_ORIGID;
			unpack_implicit_int(p, e, &m->destid);
			m->parms |= TCAP_PTF_DESTID;
			return (0);
		}
		return (-EPROTO);
	}
	return (-EMSGSIZE);
}

/* ANSI dialog portion */
static int unpack_priv_dialog_portion(unsigned char **p, unsigned char *e, tr_msg_t * m)
{
	uint err;
	uint tag;
	if (*p >= e)
		return (0);
	if (**p != (0xc0 | TCAP_TAG_PRIV_DIALOG))
		return (0);
	if ((err = unpack_priv_cons(p, &e, &tag)))
		return (err);
	if (tag != TCAP_TAG_PRIV_DIALOG)
		return (-EINVAL);
	m->dlg_beg = *p;
	m->dlg_end = e;
	*p = e;
	m->parms |= TCAP_PTF_DLGP;
	return (0);
}

/* ANSI component portion */
static int unpack_priv_component_portion(unsigned char **p, unsigned char *e, tr_msg_t * m,
					 uint opt)
{
	uint err;
	uint tag;
	if (opt) {
		if (*p >= e)
			return (0);
		if (**p != (0xc0 | TCAP_TAG_PRIV_CSEQ))
			return (0);
	}
	if ((err = unpack_priv_cons(p, &e, &tag)))
		return (err);
	if (tag != TCAP_TAG_PRIV_CSEQ)
		return (-EINVAL);
	m->cmp_beg = *p;
	m->cmp_end = e;
	*p = e;
	m->parms |= TCAP_PTF_CSEQ;
	return (0);
}

/* ANSI abort cause information */
static int unpack_priv_cause_info(unsigned char **p, unsigned char *e, tr_msg_t * m)
{
	(void) p;
	(void) e;
	(void) m;
	/* FIXME */
	return (-EFAULT);
}
static int tcap_priv_dec_uni(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	int err;
	m->type = TCAP_MT_UNI;
	if ((err = unpack_priv_trsid(&p, e, m, TCAP_MT_UNI)))
		return (err);
	if ((err = unpack_priv_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_priv_component_portion(&p, e, m, 0)))
		return (err);
	return (0);
}
static int tcap_priv_dec_qwp(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	int err;
	m->type = TCAP_MT_QWP;
	if ((err = unpack_priv_trsid(&p, e, m, TCAP_MT_QWP)))
		return (err);
	if ((err = unpack_priv_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_priv_component_portion(&p, e, m, 1)))
		return (err);
	return (0);
}
static int tcap_priv_dec_qwop(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	int err;
	m->type = TCAP_MT_QWOP;
	if ((err = unpack_priv_trsid(&p, e, m, TCAP_MT_QWOP)))
		return (err);
	if ((err = unpack_priv_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_priv_component_portion(&p, e, m, 1)))
		return (err);
	return (0);
}
static int tcap_priv_dec_cwp(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	int err;
	m->type = TCAP_MT_CWP;
	if ((err = unpack_priv_trsid(&p, e, m, TCAP_MT_CWP)))
		return (err);
	if ((err = unpack_priv_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_priv_component_portion(&p, e, m, 1)))
		return (err);
	return (0);
}
static int tcap_priv_dec_cwop(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	int err;
	m->type = TCAP_MT_CWOP;
	if ((err = unpack_priv_trsid(&p, e, m, TCAP_MT_CWOP)))
		return (err);
	if ((err = unpack_priv_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_priv_component_portion(&p, e, m, 1)))
		return (err);
	return (0);
}
static int tcap_priv_dec_resp(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	int err;
	m->type = TCAP_MT_RESP;
	if ((err = unpack_priv_trsid(&p, e, m, TCAP_MT_RESP)))
		return (err);
	if ((err = unpack_priv_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_priv_component_portion(&p, e, m, 1)))
		return (err);
	return (0);
}
static int tcap_priv_dec_abt(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	int err;
	m->type = TCAP_MT_ABORT;
	if ((err = unpack_priv_trsid(&p, e, m, TCAP_MT_ABORT)))
		return (err);
	if ((err = unpack_priv_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_priv_cause_info(&p, e, m)))
		return (err);
	return (0);
}

/*
 *  APPLICATION-TCAP version of Packages.  (Used by the TR sub-layer.)
 *  -------------------------------------------------------------------------
 */
static inline int unpack_appl_origid(unsigned char **p, unsigned char *e, tr_msg_t * m)
{
	uint err;
	uint tag;
	if ((err = unpack_appl_prim(p, &e, &tag)))
		return (err);
	if (tag != TCAP_TAG_APPL_ORIGID)
		return (-EPROTO);
	if (4 < e - *p || e - *p < 1)
		return (-EPROTO);
	unpack_implicit_int(p, e, &m->origid);
	m->parms |= TCAP_PTF_ORIGID;
	return (0);
}
static inline int unpack_appl_destid(unsigned char **p, unsigned char *e, tr_msg_t * m)
{
	uint err;
	uint tag;
	if ((err = unpack_appl_prim(p, &e, &tag)))
		return (err);
	if (tag != TCAP_TAG_APPL_DESTID)
		return (-EPROTO);
	if (4 < e - *p || e - *p < 1)
		return (-EPROTO);
	unpack_implicit_int(p, e, &m->destid);
	m->parms |= TCAP_PTF_DESTID;
	return (0);
}
static inline int unpack_appl_trsid(unsigned char **p, unsigned char *e, tr_msg_t * m,
				    const uint mtype)
{
	uint err;
	switch (mtype) {
	case TCAP_MT_UNI:
		return (0);
	case TCAP_MT_QWP:
		if ((err = unpack_appl_origid(p, e, m)))
			return (err);
		return (0);
	case TCAP_MT_CWP:
		if ((err = unpack_appl_origid(p, e, m)))
			return (err);
		if ((err = unpack_appl_destid(p, e, m)))
			return (err);
		return (0);
	case TCAP_MT_RESP:
	case TCAP_MT_ABORT:
		if ((err = unpack_appl_destid(p, e, m)))
			return (err);
		return (0);
	}
	return (-EFAULT);
}

/* ITU-T dialog portion */
static int unpack_appl_dialog_portion(unsigned char **p, unsigned char *e, tr_msg_t * m)
{
	uint err;
	uint tag;
	if (*p >= e)
		return (0);
	if (**p != (0x60 | TCAP_TAG_APPL_DIALOG))
		return (0);
	if ((err = unpack_appl_cons(p, &e, &tag)))
		return (err);
	if (tag != TCAP_TAG_APPL_DIALOG)
		return (-EINVAL);
	m->dlg_beg = *p;
	m->dlg_end = e;
	*p = e;
	m->parms |= TCAP_PTF_DLGP;
	return (0);
}

/* ITU-T component portion */
static int unpack_appl_component_portion(unsigned char **p, unsigned char *e, tr_msg_t * m,
					 uint opt)
{
	uint err;
	uint tag;
	if (opt) {
		if (*p >= e)
			return (0);
		if (**p != (0x60 | TCAP_TAG_APPL_CSEQ))
			return (0);
	}
	if ((err = unpack_appl_cons(p, &e, &tag)))
		return (err);
	if (tag != TCAP_TAG_APPL_CSEQ)
		return (-EINVAL);
	m->cmp_beg = *p;
	m->cmp_end = e;
	*p = e;
	m->parms |= TCAP_PTF_CSEQ;
	return (0);
}

/* ITU-T abort cause information */
static int unpack_appl_cause_info(unsigned char **p, unsigned char *e, tr_msg_t * m)
{
	(void) p;
	(void) e;
	(void) m;
	/* FIXME */
	return (-EFAULT);
}
static int tcap_appl_dec_uni(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	/* Application Context, Component Sequence */
	int err;
	m->type = TCAP_MT_UNI;
	if ((err = unpack_appl_trsid(&p, e, m, TCAP_MT_UNI)))
		return (err);
	if ((err = unpack_appl_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_appl_component_portion(&p, e, m, 0)))
		return (err);
	return (0);
}
static int tcap_appl_dec_beg(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	/* Originating Transaction Id, Application Context, Component Sequence */
	int err;
	m->type = TCAP_MT_QWP;	/* Query with permission to release */
	if ((err = unpack_appl_trsid(&p, e, m, TCAP_MT_QWP)))
		return (err);
	if ((err = unpack_appl_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_appl_component_portion(&p, e, m, 1)))
		return (err);
	return (0);
}
static int tcap_appl_dec_cnt(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	int err;
	m->type = TCAP_MT_CWP;	/* Conversation with permission to release */
	if ((err = unpack_appl_trsid(&p, e, m, TCAP_MT_CWP)))
		return (err);
	if ((err = unpack_appl_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_appl_component_portion(&p, e, m, 1)))
		return (err);
	return (0);
}
static int tcap_appl_dec_end(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	/* Dest Transaction Id, Application Context, Component Sequence */
	int err;
	m->type = TCAP_MT_RESP;	/* Response */
	if ((err = unpack_appl_trsid(&p, e, m, TCAP_MT_RESP)))
		return (err);
	if ((err = unpack_appl_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_appl_component_portion(&p, e, m, 1)))
		return (err);
	return (0);
}
static int tcap_appl_dec_abt(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	/* Dest Transaction Id, P-Abort-Cause prim or U-Abort-Info const */
	int err;
	if ((err = unpack_appl_trsid(&p, e, m, TCAP_MT_ABORT)))
		return (err);
	if ((err = unpack_appl_dialog_portion(&p, e, m)))
		return (err);
	if ((err = unpack_appl_cause_info(&p, e, m)))
		return (err);
	return (0);
}

/*
 *  TCAP Package decoder.  (Only decodes TR Sub-Layer.)
 *  -------------------------------------------------------------------------
 */
int tcap_dec_msg(unsigned char *p, unsigned char *e, tr_msg_t * m)
{
	int err;
	uint tag;
	uint cls;
	if ((err = unpack_taglen(&p, &e, &tag, &cls)))
		return (err);
	if ((cls & 0xe0) == 0xe0) {	/* private constructor */
		switch (tag) {
		case TCAP_TAG_PRIV_UNI:	/* Unidirectional */
			return tcap_priv_dec_uni(p, e, m);
		case TCAP_TAG_PRIV_QWP:	/* Begin or Query w/ permission */
			return tcap_priv_dec_qwp(p, e, m);
		case TCAP_TAG_PRIV_QWOP:	/* Query w/o permission */
			return tcap_priv_dec_qwop(p, e, m);
		case TCAP_TAG_PRIV_RESP:	/* End or Response */
			return tcap_priv_dec_resp(p, e, m);
		case TCAP_TAG_PRIV_CWP:	/* Continue or Conversation w/ permission */
			return tcap_priv_dec_cwp(p, e, m);
		case TCAP_TAG_PRIV_CWOP:	/* Conversation w/o permission */
			return tcap_priv_dec_cwop(p, e, m);
		case TCAP_TAG_PRIV_ABORT:	/* Abort */
			return tcap_priv_dec_abt(p, e, m);
		}
	}
	if ((cls & 0xe0) == 0xa0) {	/* application-wide constructor */
		switch (tag) {
		case TCAP_TAG_APPL_UNI:	/* Unidirectional */
			return tcap_appl_dec_uni(p, e, m);
		case TCAP_TAG_APPL_BEGIN:	/* Begin */
			return tcap_appl_dec_beg(p, e, m);
		case TCAP_TAG_APPL_END:	/* End */
			return tcap_appl_dec_end(p, e, m);
		case TCAP_TAG_APPL_CONT:	/* Continue */
			return tcap_appl_dec_cnt(p, e, m);
		case TCAP_TAG_APPL_ABORT:	/* Abort */
			return tcap_appl_dec_abt(p, e, m);
		}
	}
	return (-EINVAL);
}


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

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

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