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/slsi/sls_codec.h


File /code/strss7/drivers/slsi/sls_codec.h



#ifndef __SLS_CODEC_H__
#define __SLS_CODEC_H__

#ident "@(#) $RCSfile: sls_codec.h,v $ $Name:  $($Revision: 0.8.2.1 $) $Date: 2002/10/18 02:40:37 $"

#include "sls_parse.h"

int lk_build_msu(lk_t * lk, mblk_t * mp);
int lk_parse_msu(lk_t * lk, mblk_t * mp);

/*
 *  This is a decoder (parser) and encoder (builder) for SS7 MTP messages.  It
 *  is used to abstract the actual line coding of the SS7 message by placing
 *  it into a common internal representation in a message buffer.
 */

static int lk_itut_build_msu(mblk_t * mp)
{
	mblk_t *md = mp->b_cont;
	ls_prim_t *p = (ls_prim_t *) mp->b_rptr;
	mtp_msg_t *m = (mtp_msg_t *) md->b_rptr;
	m->itut.mh.ni = p->sig.mh.ni;
	m->itut.mh.mp = p->sig.mh.mp;
	m->itut.mh.si = p->sig.mh.si;
	m->itut.mh.rl.dpc = p->sig.mh.rl.dpc;
	m->itut.mh.rl.opc = p->sig.mh.rl.opc;
	m->itut.mh.rl.sls = p->sig.mh.rl.sls;
	/* FIXME: rearrange these case statements for speed */
	switch (p->sig.signal & LS_SIGNALS_MASK_H0) {
	case LS_SIGNAL_CHM:
		m->itut.mh.rl.sls = p->slm.slc;	/* relates to link */
		switch (p->sig.signal) {
		case LS_SIGNAL_COO:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x1;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x1;
			m->itut.msg.coo.fsnc = p->coo.fsnc;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.coo);
			break;
		case LS_SIGNAL_COA:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x1;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x2;
			m->itut.msg.coa.fsnc = p->coa.fsnc;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.coa);
			break;
		case LS_SIGNAL_CBD:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x1;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x5;
			m->itut.msg.cbd.cbc = p->cbd.cbc;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.cbd);
			break;
		case LS_SIGNAL_CBA:
			m->itut.mh.rl.sls = p->sig.mh.rl.sls;
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x1;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x6;
			m->itut.msg.cba.cbc = p->cba.cbc;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.cba);
			break;
		default:
			return -EINVAL;
		}
		break;
	case LS_SIGNAL_ECM:
		m->itut.mh.rl.sls = p->slm.slc;	/* relates to link */
		switch (p->sig.signal) {
		case LS_SIGNAL_ECO:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x2;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x1;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.eco);
			break;
		case LS_SIGNAL_ECA:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x2;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x2;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.eca);
			break;
		default:
			return -EINVAL;
		}
		break;
	case LS_SIGNAL_FCM:
		switch (p->sig.signal) {
		case LS_SIGNAL_RCT:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x3;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x1;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.rct);
			break;
		case LS_SIGNAL_TFC:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x3;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x2;
			m->itut.msg.tfc.dest = p->tfc.dest;
			m->itut.msg.tfc.stat = p->tfc.stat;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.tfc);
			break;
		default:
			return -EINVAL;
		}
		break;
	case LS_SIGNAL_TFM:
		switch (p->sig.signal) {
		case LS_SIGNAL_TFP:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x4;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x1;
			m->itut.msg.tfp.dest = p->tfp.dest;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.tfp);
			break;
		case LS_SIGNAL_TFR:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x4;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x3;
			m->itut.msg.tfr.dest = p->tfr.dest;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.tfr);
			break;
		case LS_SIGNAL_TFA:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x4;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x5;
			m->itut.msg.tfa.dest = p->tfa.dest;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.tfa);
			break;
		default:
			return -EINVAL;
		}
		break;
	case LS_SIGNAL_RSM:
		switch (p->sig.signal) {
		case LS_SIGNAL_RSP:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x5;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x1;
			m->itut.msg.rsp.dest = p->rsp.dest;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.rsp);
			break;
		case LS_SIGNAL_RSR:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x5;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x2;
			m->itut.msg.rsr.dest = p->rsr.dest;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.rsr);
			break;
		default:
			return -EINVAL;
		}
		break;
	case LS_SIGNAL_MIM:
		m->itut.mh.rl.sls = p->slm.slc;	/* relates to link */
		switch (p->sig.signal) {
		case LS_SIGNAL_LIN:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x6;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x1;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.lin);
			break;
		case LS_SIGNAL_LUN:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x6;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x2;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.lun);
			break;
		case LS_SIGNAL_LIA:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x6;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x3;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.lia);
			break;
		case LS_SIGNAL_LUA:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x6;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x4;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.lua);
			break;
		case LS_SIGNAL_LID:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x6;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x5;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.lid);
			break;
		case LS_SIGNAL_LFU:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x6;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x6;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.lfu);
			break;
		case LS_SIGNAL_LLI:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x6;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x7;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.lli);
			break;
		case LS_SIGNAL_LRI:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x6;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x8;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.lri);
			break;
		default:
			return -EINVAL;
		}
		break;
	case LS_SIGNAL_TRM:
		switch (p->sig.signal) {
		case LS_SIGNAL_TRA:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x7;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x1;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.tra);
			break;
		default:
			return -EINVAL;
		}
		break;
	case LS_SIGNAL_DLM:
		m->itut.mh.rl.sls = p->slm.slc;	/* relates to link */
		switch (p->sig.signal) {
		case LS_SIGNAL_DLC:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x8;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x1;
			m->itut.msg.dlc.sdli = p->dlc.sdli;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.dlc);
			break;
		case LS_SIGNAL_CSS:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x8;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x2;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.css);
			break;
		case LS_SIGNAL_CNS:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x8;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x3;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.cns);
			break;
		case LS_SIGNAL_CNP:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x8;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x4;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.cnp);
			break;
		default:
			return -EINVAL;
		}
		break;
	case LS_SIGNAL_UFC:
		switch (p->sig.signal) {
		case LS_SIGNAL_UPU:
			m->itut.mh.si = p->sig.mh.si = 0x0;
			m->itut.mh.h0 = p->sig.mh.h0 = 0xa;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x1;
			m->itut.msg.upu.dest = p->upu.dest;
			m->itut.msg.upu.upi = p->upu.upi;
			md->b_wptr = md->b_rptr + sizeof(m->itut.msg.upu);
			break;
		default:
			return -EINVAL;
		}
		break;
	case LS_SIGNAL_SLTC:
		m->itut.mh.rl.sls = p->slm.slc;	/* relates to link */
		switch (p->sig.signal) {
		case LS_SIGNAL_SLTM:
			m->itut.mh.si = p->sig.mh.si = 0x1;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x1;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x1;
			m->itut.msg.sltm.tli = p->sltm.tli;
			bcopy(p->sltm.tmsx, m->itut.msg.sltm.tmsx, p->sltm.tli & 0xf);
			md->b_wptr =
			    md->b_rptr + sizeof(m->itut.msg.sltm) - 15 + (p->sltm.tli & 0xf);
			break;
		case LS_SIGNAL_SLTA:
			m->itut.mh.si = p->sig.mh.si = 0x1;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x1;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x2;
			m->itut.msg.slta.tli = p->slta.tli;
			bcopy(p->slta.tmsx, m->itut.msg.slta.tmsx, p->slta.tli & 0xf);
			md->b_wptr =
			    md->b_rptr + sizeof(m->itut.msg.slta) - 15 + (p->slta.tli & 0xf);
			break;
		default:
			return -EINVAL;
		}
		break;
	case LS_SIGNAL_SSLTC:
		m->itut.mh.rl.sls = p->slm.slc;	/* relates to link */
		switch (p->sig.signal) {
		case LS_SIGNAL_SSLTM:
			m->itut.mh.si = p->sig.mh.si = 0x2;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x1;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x1;
			m->itut.msg.ssltm.tli = p->ssltm.tli;
			bcopy(p->ssltm.tmsx, m->itut.msg.ssltm.tmsx, p->ssltm.tli & 0xf);
			md->b_wptr =
			    md->b_rptr + sizeof(m->itut.msg.ssltm) - 15 + (p->ssltm.tli & 0xf);
			break;
		case LS_SIGNAL_SSLTA:
			m->itut.mh.si = p->sig.mh.si = 0x2;
			m->itut.mh.h0 = p->sig.mh.h0 = 0x1;
			m->itut.mh.h1 = p->sig.mh.h1 = 0x2;
			m->itut.msg.sslta.tli = p->sslta.tli;
			bcopy(p->sslta.tmsx, m->itut.msg.sslta.tmsx, p->sslta.tli & 0xf);
			md->b_wptr =
			    md->b_rptr + sizeof(m->itut.msg.sslta) - 15 + (p->sslta.tli & 0xf);
			break;
		default:
			return -EINVAL;
		}
		break;
	case LS_SIGNAL_USER:
		switch (p->sig.signal) {
		case LS_SIGNAL_USER:
			md->b_wptr = md->b_rptr + sizeof(m->itut.mh) - 1;
			return (0);
		default:
			return -EINVAL;
		}
		break;
	default:
		return -EINVAL;
	}
	m->itut.mh.mp = p->sig.mh.mp = 0x3;
	mp->b_wptr = mp->b_rptr + sizeof(p->primitive);
	p->primitive = SL_PDU_REQ;
	return (0);
}

static int lk_ansi_build_msu(mblk_t * mp)
{
	/* 
	 *  For ANSI we must do SLS rotation on some messages before transmission
	 *  to the link.  Buffered messages are not SLS rotated to permit easier
	 *  rerouting on changeover.
	 */
	mblk_t *md = mp->b_cont;
	ls_prim_t *p = (ls_prim_t *) mp->b_rptr;
	mtp_msg_t *m = (mtp_msg_t *) md->b_rptr;
	int sls = p->sig.mh.rl.sls & 0x1f;
	int slsr = (sls << 1) | ((sls >> 4) & 0x1);
	m->ansi.mh.ni = p->sig.mh.ni;
	m->ansi.mh.mp = p->sig.mh.mp;
	m->ansi.mh.si = p->sig.mh.si;
	m->ansi.mh.rl.dpc = p->sig.mh.rl.dpc;
	m->ansi.mh.rl.opc = p->sig.mh.rl.opc;
	m->ansi.mh.rl.sls = slsr;	/* rotate sls */
	/* FIXME: rearrange these case statements for speed */
	switch (p->sig.signal & LS_SIGNALS_MASK_H0) {
	case LS_SIGNAL_CHM:
		switch (p->sig.signal) {
		case LS_SIGNAL_COO:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x1;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			m->ansi.msg.coo.slc = p->coo.slc;
			m->ansi.msg.coo.fsnc = p->coo.fsnc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.coo);
			break;
		case LS_SIGNAL_COA:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x1;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x2;
			m->ansi.msg.coa.slc = p->coa.slc;
			m->ansi.msg.coa.fsnc = p->coa.fsnc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.coa);
			break;
		case LS_SIGNAL_CBD:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x1;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x5;
			m->ansi.msg.cbd.slc = p->cbd.slc;
			m->ansi.msg.cbd.cbc = p->cbd.cbc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.cbd);
			break;
		case LS_SIGNAL_CBA:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x1;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x6;
			m->ansi.msg.cba.slc = p->cba.slc;
			m->ansi.msg.cba.cbc = p->cba.cbc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.cba);
			break;
		default:
			return -EINVAL;
		}
	case LS_SIGNAL_ECM:
		switch (p->sig.signal) {
		case LS_SIGNAL_ECO:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x2;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			m->ansi.msg.eco.slc = p->eco.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.eco);
			break;
		case LS_SIGNAL_ECA:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x2;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x2;
			m->ansi.msg.eca.slc = p->eca.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.eca);
			break;
		default:
			return -EINVAL;
		}
	case LS_SIGNAL_FCM:
		switch (p->sig.signal) {
		case LS_SIGNAL_RCT:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x3;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.rct);
			break;
		case LS_SIGNAL_TFC:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x3;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x2;
			m->ansi.msg.tfc.dest = p->tfc.dest;
			m->ansi.msg.tfc.stat = p->tfc.stat;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.tfc);
			break;
		default:
			return -EINVAL;
		}
	case LS_SIGNAL_TFM:
		switch (p->sig.signal) {
		case LS_SIGNAL_TFP:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x4;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			m->ansi.msg.tfp.dest = p->tfp.dest;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.tfp);
			break;
		case LS_SIGNAL_TCP:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x4;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x2;
			m->ansi.msg.tcp.dest = p->tcp.dest;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.tcp);
			break;
		case LS_SIGNAL_TFR:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x4;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x3;
			m->ansi.msg.tfr.dest = p->tfr.dest;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.tfr);
			break;
		case LS_SIGNAL_TCR:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x4;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x4;
			m->ansi.msg.tcr.dest = p->tcr.dest;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.tcr);
			break;
		case LS_SIGNAL_TFA:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x4;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x5;
			m->ansi.msg.tfa.dest = p->tfa.dest;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.tfa);
			break;
		case LS_SIGNAL_TCA:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x4;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x6;
			m->ansi.msg.tca.dest = p->tca.dest;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.tca);
			break;
		default:
			return -EINVAL;
		}
	case LS_SIGNAL_RSM:
		switch (p->sig.signal) {
		case LS_SIGNAL_RSP:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x5;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			m->ansi.msg.rsp.dest = p->rsp.dest;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.rsp);
			break;
		case LS_SIGNAL_RSR:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x5;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x2;
			m->ansi.msg.rsr.dest = p->rsr.dest;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.rsr);
			break;
		case LS_SIGNAL_RCP:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x5;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			m->ansi.msg.rcp.dest = p->rcp.dest;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.rcp);
			break;
		case LS_SIGNAL_RCR:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x5;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x2;
			m->ansi.msg.rcr.dest = p->rcr.dest;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.rcr);
			break;
		default:
			return -EINVAL;
		}
	case LS_SIGNAL_MIM:
		switch (p->sig.signal) {
		case LS_SIGNAL_LIN:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x6;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			m->ansi.msg.lin.slc = p->lin.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.lin);
			break;
		case LS_SIGNAL_LUN:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x6;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x2;
			m->ansi.msg.lun.slc = p->lun.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.lun);
			break;
		case LS_SIGNAL_LIA:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x6;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x3;
			m->ansi.msg.lia.slc = p->lia.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.lia);
			break;
		case LS_SIGNAL_LUA:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x6;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x4;
			m->ansi.msg.lua.slc = p->lua.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.lua);
			break;
		case LS_SIGNAL_LID:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x6;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x5;
			m->ansi.msg.lid.slc = p->lid.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.lid);
			break;
		case LS_SIGNAL_LFU:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x6;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x6;
			m->ansi.msg.lfu.slc = p->lfu.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.lfu);
			break;
		case LS_SIGNAL_LLI:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x6;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x7;
			m->ansi.msg.lli.slc = p->lli.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.lli);
			break;
		case LS_SIGNAL_LRI:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x6;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x8;
			m->ansi.msg.lri.slc = p->lri.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.lri);
			break;
		default:
			return -EINVAL;
		}
	case LS_SIGNAL_TRM:
		switch (p->sig.signal) {
		case LS_SIGNAL_TRA:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x7;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.tra);
			break;
		case LS_SIGNAL_TRW:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x7;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x2;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.trw);
			break;
		default:
			return -EINVAL;
		}
	case LS_SIGNAL_DLM:
		switch (p->sig.signal) {
		case LS_SIGNAL_DLC:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x8;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			m->ansi.msg.dlc.sdli = p->dlc.sdli;
			m->ansi.msg.dlc.slc = p->dlc.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.dlc);
			break;
		case LS_SIGNAL_CSS:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x8;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x2;
			m->ansi.msg.css.slc = p->css.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.css);
			break;
		case LS_SIGNAL_CNS:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x8;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x3;
			m->ansi.msg.cns.slc = p->cns.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.cns);
			break;
		case LS_SIGNAL_CNP:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x8;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x4;
			m->ansi.msg.cnp.slc = p->cnp.slc;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.cnp);
			break;
		default:
			return -EINVAL;
		}
	case LS_SIGNAL_UFC:
		switch (p->sig.signal) {
		case LS_SIGNAL_UPU:
			m->ansi.mh.si = p->sig.mh.si = 0x0;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0xa;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			m->ansi.msg.upu.dest = p->upu.dest;
			m->ansi.msg.upu.upi = p->upu.upi;
			md->b_wptr = md->b_rptr + sizeof(m->ansi.msg.upu);
			break;
			/* FIXME: some more here I don't have */
		default:
			return -EINVAL;
		}
	case LS_SIGNAL_SLTC:
		switch (p->sig.signal) {
		case LS_SIGNAL_SLTM:
			m->ansi.mh.si = p->sig.mh.si = 0x1;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x1;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			m->ansi.msg.sltm.slc = p->sltm.slc;
			m->ansi.msg.sltm.tli = p->sltm.tli;
			bcopy(p->sltm.tmsx, m->ansi.msg.sltm.tmsx, p->sltm.tli & 0xf);
			md->b_wptr =
			    md->b_rptr + sizeof(m->ansi.msg.sltm) - 15 + (p->sltm.tli & 0xf);
			break;
		case LS_SIGNAL_SLTA:
			m->ansi.mh.si = p->sig.mh.si = 0x1;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x1;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x2;
			m->ansi.msg.slta.slc = p->slta.slc;
			m->ansi.msg.slta.tli = p->slta.tli;
			bcopy(p->slta.tmsx, m->ansi.msg.slta.tmsx, p->slta.tli & 0xf);
			md->b_wptr =
			    md->b_rptr + sizeof(m->ansi.msg.slta) - 15 + (p->slta.tli & 0xf);
			break;
		default:
			return -EINVAL;
		}
	case LS_SIGNAL_SSLTC:
		switch (p->sig.signal) {
		case LS_SIGNAL_SSLTM:
			m->ansi.mh.si = p->sig.mh.si = 0x2;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x1;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x1;
			m->ansi.msg.ssltm.slc = p->ssltm.slc;
			m->ansi.msg.ssltm.tli = p->ssltm.tli;
			bcopy(p->ssltm.tmsx, m->ansi.msg.ssltm.tmsx, p->ssltm.tli & 0xf);
			md->b_wptr =
			    md->b_rptr + sizeof(m->ansi.msg.ssltm) - 15 + (p->ssltm.tli & 0xf);
			break;
		case LS_SIGNAL_SSLTA:
			m->ansi.mh.si = p->sig.mh.si = 0x2;
			m->ansi.mh.h0 = p->sig.mh.h0 = 0x1;
			m->ansi.mh.h1 = p->sig.mh.h1 = 0x2;
			m->ansi.msg.sslta.slc = p->sslta.slc;
			m->ansi.msg.sslta.tli = p->sslta.tli;
			bcopy(p->sslta.tmsx, m->ansi.msg.sslta.tmsx, p->sslta.tli & 0xf);
			md->b_wptr =
			    md->b_rptr + sizeof(m->ansi.msg.sslta) - 15 + (p->sslta.tli & 0xf);
			break;
		default:
			return -EINVAL;
		}
	case LS_SIGNAL_USER:
		switch (p->sig.signal) {
		case LS_SIGNAL_USER:
			md->b_wptr = md->b_rptr + sizeof(m->ansi.mh) - 1;
			return (0);
		default:
			return -EINVAL;
		}
	default:
		return -EINVAL;
	}
	m->ansi.mh.mp = p->sig.mh.mp = 0x3;
	mp->b_wptr = mp->b_rptr + sizeof(p->primitive);
	p->primitive = SL_PDU_REQ;
	return (0);
}

int lk_build_msu(lk_t * lk, mblk_t * mp)
{
	/* 
	 *  Takes the message (M_PROTO) as provided for in the message block in mp
	 *  and encodes it into an MSU frame in attached (M_DATA).  Attached
	 *  M_DATA must be large enough to hold the resulting frame.  The M_PROTO
	 *  message block is converted to a generic MSU primitive block.
	 *
	 *  Get it right: send a M_PROTO block followed by an M_DATA block.  I do
	 *  very little error checking here for speed.
	 *
	 *  FIXME: Encode by network indicator....
	 *  FIXME: Allocate an M_DATA correctly...
	 */
	int var = lk->module->option.pvar;
	mblk_t *md = mp->b_cont;

	if (!md)
		return -EINVAL;

	switch (var) {
	case SS7_PVAR_ITUT_88:
	case SS7_PVAR_ITUT_93:
	case SS7_PVAR_ITUT_96:
	case SS7_PVAR_ITUT_00:
	case SS7_PVAR_ETSI_88:
	case SS7_PVAR_ETSI_93:
	case SS7_PVAR_ETSI_96:
	case SS7_PVAR_ETSI_00:
		return lk_itut_build_msu(mp);
	case SS7_PVAR_ANSI_88:
	case SS7_PVAR_ANSI_92:
	case SS7_PVAR_ANSI_96:
	case SS7_PVAR_ANSI_00:
	case SS7_PVAR_JTTC_94:
		return lk_ansi_build_msu(mp);
	}
	return -EINVAL;
}

static int lk_itut_parse_msu(mblk_t * mp)
{
	mblk_t *md = mp->b_cont;
	ls_prim_t *p = (ls_prim_t *) mp->b_rptr;
	mtp_msg_t *m = (mtp_msg_t *) md->b_rptr;
	p->sig.mh.ni = m->itut.mh.ni;
	p->sig.mh.mp = m->itut.mh.mp;
	p->sig.mh.si = m->itut.mh.si;
	p->sig.mh.rl.dpc = m->itut.mh.rl.dpc;
	p->sig.mh.rl.opc = m->itut.mh.rl.opc;
	p->sig.mh.rl.sls = m->itut.mh.rl.sls;
	switch (p->sig.mh.si) {
	case 0x0:		/* snmm */
		p->sig.mh.h0 = m->itut.mh.h0;
		p->sig.mh.h1 = m->itut.mh.h1;
		switch (p->sig.mh.h0) {
		case 0x1:	/* chm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* coo - changeover-order */
				p->coo.slc = m->itut.mh.rl.sls;
				p->coo.fsnc = m->itut.msg.coo.fsnc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_COO_SIZE;
				p->primitive = LS_SIGNAL_COO;
				break;
			case 0x2:	/* coa - changeover-ack */
				p->coa.slc = m->itut.mh.rl.sls;
				p->coa.fsnc = m->itut.msg.coa.fsnc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_COA_SIZE;
				p->primitive = LS_SIGNAL_COA;
				break;
			case 0x5:	/* cbd - changeback-declaration */
				p->cbd.slc = m->itut.mh.rl.sls;
				p->cbd.cbc = m->itut.msg.cbd.cbc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_CBD_SIZE;
				p->primitive = LS_SIGNAL_CBD;
				break;
			case 0x6:	/* cba - changeback-ack */
				p->cba.slc = m->itut.mh.rl.sls;
				p->cba.cbc = m->itut.msg.cba.cbc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_CBA_SIZE;
				p->primitive = LS_SIGNAL_CBA;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x2:	/* ecm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* eco - emergency-changeover-order */
				p->eco.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_ECO_SIZE;
				p->primitive = LS_SIGNAL_ECO;
				break;
			case 0x2:	/* eca - emergency-changeover-ack */
				p->eca.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_ECA_SIZE;
				p->primitive = LS_SIGNAL_ECA;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x3:	/* fcm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* rct - signalling-route-set-congestion-test */
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_RCT_SIZE;
				p->primitive = LS_SIGNAL_RCT;
				break;
			case 0x2:	/* tfc - transfer-controlled */
				p->tfc.dest = m->itut.msg.tfc.dest;
				p->tfc.stat = m->itut.msg.tfc.stat;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TFC_SIZE;
				p->primitive = LS_SIGNAL_TFC;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x4:	/* tfm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* tfp - transfer prohibited */
				p->tfp.dest = m->itut.msg.tfp.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TFP_SIZE;
				p->primitive = LS_SIGNAL_TFP;
				break;
			case 0x3:	/* tfr - transfer-restricted */
				p->tfr.dest = m->itut.msg.tfr.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TFR_SIZE;
				p->primitive = LS_SIGNAL_TFR;
				break;
			case 0x5:	/* tfa - transfer-allowed */
				p->tfa.dest = m->itut.msg.tfa.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TFA_SIZE;
				p->primitive = LS_SIGNAL_TFA;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x5:	/* rsm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* rsp - signalling-route-set-test-prohibited */
				p->rsp.dest = m->itut.msg.rsp.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_RSP_SIZE;
				p->primitive = LS_SIGNAL_TFA;
				break;
			case 0x2:	/* rsr - signalling-route-set-test-restricted */
				p->rsr.dest = m->itut.msg.rsr.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_RSR_SIZE;
				p->primitive = LS_SIGNAL_RSR;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x6:	/* mim */
			switch (p->sig.mh.h1) {
			case 0x1:	/* lin - link-inhibit */
				p->lin.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LIN_SIZE;
				p->primitive = LS_SIGNAL_LIN;
				break;
			case 0x2:	/* lun - link-uninhibit */
				p->lun.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LUN_SIZE;
				p->primitive = LS_SIGNAL_LUN;
				break;
			case 0x3:	/* lia - link-inhibit-ack */
				p->lia.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LIA_SIZE;
				p->primitive = LS_SIGNAL_LIA;
				break;
			case 0x4:	/* lua - link-uninhibit-ack */
				p->lua.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LUA_SIZE;
				p->primitive = LS_SIGNAL_LUA;
				break;
			case 0x5:	/* lid - link-inhibit-denied */
				p->lid.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LID_SIZE;
				p->primitive = LS_SIGNAL_LID;
				break;
			case 0x6:	/* lfu - force-uninhibit */
				p->lfu.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LFU_SIZE;
				p->primitive = LS_SIGNAL_LFU;
				break;
			case 0x7:	/* llt - local-inhibit-test */
				p->lli.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LLI_SIZE;
				p->primitive = LS_SIGNAL_LLI;
				break;
			case 0x8:	/* lrt - remote-inhibit-test */
				p->lri.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LRI_SIZE;
				p->primitive = LS_SIGNAL_LRI;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x7:	/* trm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* tra - traffic-restart-allowed */
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TRA_SIZE;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x8:	/* dlm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* dlc - signalling-data-link-connection-order */
				p->dlc.sdli = m->itut.msg.dlc.sdli;
				p->dlc.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_DLC_SIZE;
				p->primitive = LS_SIGNAL_DLC;
				break;
			case 0x2:	/* css - connection-successful */
				p->css.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_CSS_SIZE;
				p->primitive = LS_SIGNAL_CSS;
				break;
			case 0x3:	/* cns - connection-not-successful */
				p->cns.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_CNS_SIZE;
				p->primitive = LS_SIGNAL_CNS;
				break;
			case 0x4:	/* cnp - connection-not-possible */
				p->cnp.slc = m->itut.mh.rl.sls;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_CNP_SIZE;
				p->primitive = LS_SIGNAL_CNP;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0xa:	/* ufc */
			switch (p->sig.mh.h1) {
			case 0x1:	/* upu - user part unavailable */
				p->upu.dest = m->itut.msg.upu.dest;
				p->upu.upi = m->itut.msg.upu.upi;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_UPU_SIZE;
				p->primitive = LS_SIGNAL_UPU;
				break;
			default:
				return -EINVAL;
			}
			break;
		default:
			return -EINVAL;
		}
		break;
	case 0x1:		/* sltc */
		p->sig.mh.h0 = m->itut.mh.h0;
		p->sig.mh.h1 = m->itut.mh.h1;
		switch (p->sig.mh.h0) {
		case 0x1:
			switch (p->sig.mh.h1) {
			case 0x1:	/* sltm */
				p->sltm.slc = m->itut.mh.rl.sls;
				p->sltm.tli = m->itut.msg.sltm.tli;
				bcopy(m->itut.msg.sltm.tmsx, p->sltm.tmsx, p->sltm.tli);
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_SLTM_SIZE - 15 + p->sltm.tli;
				p->primitive = LS_SIGNAL_SLTM;
				break;
			case 0x2:	/* slta */
				p->slta.slc = m->itut.mh.rl.sls;
				p->slta.tli = m->itut.msg.slta.tli;
				bcopy(m->itut.msg.slta.tmsx, p->slta.tmsx, p->slta.tli);
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_SLTM_SIZE - 15 + p->slta.tli;
				p->primitive = LS_SIGNAL_SLTA;
				break;
			default:
				return -EINVAL;
			}
			break;
		default:
			return -EINVAL;
		}
		break;
	case 0x2:		/* ssltc */
		p->sig.mh.h0 = m->itut.mh.h0;
		p->sig.mh.h1 = m->itut.mh.h1;
		switch (p->sig.mh.h0) {
		case 0x1:
			switch (p->sig.mh.h1) {
			case 0x1:	/* ssltm */
				p->ssltm.slc = m->itut.mh.rl.sls;
				p->ssltm.tli = m->itut.msg.ssltm.tli;
				bcopy(m->itut.msg.ssltm.tmsx, p->ssltm.tmsx, p->ssltm.tli);
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_SLTM_SIZE - 15 + p->ssltm.tli;
				p->primitive = LS_SIGNAL_SSLTM;
				break;
			case 0x2:	/* sslta */
				p->sslta.slc = m->itut.mh.rl.sls;
				p->sslta.tli = m->itut.msg.sslta.tli;
				bcopy(m->itut.msg.sslta.tmsx, p->sslta.tmsx, p->sslta.tli);
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_SLTM_SIZE - 15 + p->sslta.tli;
				p->primitive = LS_SIGNAL_SSLTA;
				break;
			default:
				return -EINVAL;
			}
			break;
		default:
			return -EINVAL;
		}
		break;
	default:
		mp->b_wptr = mp->b_rptr + LS_SIGNAL_USER_SIZE;
		md->b_rptr += sizeof(m->itut.mh) - 1;	/* strip MTP header */
		p->primitive = LS_SIGNAL_USER;
		return (0);
	}
	mp->b_datap->db_type = M_PROTO;
	md = unlinkb(mp);
	freemsg(md);
	return (0);
}

static int lk_ansi_parse_msu(mblk_t * mp)
{
	mblk_t *md = mp->b_cont;
	ls_prim_t *p = (ls_prim_t *) mp->b_rptr;
	mtp_msg_t *m = (mtp_msg_t *) md->b_rptr;
	p->sig.mh.ni = m->ansi.mh.ni;
	p->sig.mh.mp = m->ansi.mh.mp;
	p->sig.mh.si = m->ansi.mh.si;
	p->sig.mh.rl.dpc = m->ansi.mh.rl.dpc;
	p->sig.mh.rl.opc = m->ansi.mh.rl.opc;
	p->sig.mh.rl.sls = m->ansi.mh.rl.sls;
	switch (p->sig.mh.si) {
	case 0x0:		/* snmm */
		p->sig.mh.h0 = m->ansi.mh.h0;
		p->sig.mh.h1 = m->ansi.mh.h1;
		switch (p->sig.mh.h0) {
		case 0x1:	/* chm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* coo - changeover-order */
				p->coo.slc = m->ansi.msg.coo.slc;
				p->coo.fsnc = m->ansi.msg.coo.fsnc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_COO_SIZE;
				p->primitive = LS_SIGNAL_COO;
				break;
			case 0x2:	/* coa - changeover-ack */
				p->coa.slc = m->ansi.msg.coa.slc;
				p->coa.fsnc = m->ansi.msg.coa.fsnc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_COA_SIZE;
				p->primitive = LS_SIGNAL_COA;
				break;
			case 0x5:	/* cbd - changeback-declaration */
				p->cbd.slc = m->ansi.msg.cbd.slc;
				p->cbd.cbc = m->ansi.msg.cbd.cbc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_CBD_SIZE;
				p->primitive = LS_SIGNAL_CBD;
				break;
			case 0x6:	/* cba - changeback-ack */
				p->cba.slc = m->ansi.msg.cba.slc;
				p->cba.cbc = m->ansi.msg.cba.cbc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_CBA_SIZE;
				p->primitive = LS_SIGNAL_CBA;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x2:	/* ecm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* eco - emergency-changeover-order */
				p->eco.slc = m->ansi.msg.eco.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_ECO_SIZE;
				p->primitive = LS_SIGNAL_ECO;
				break;
			case 0x2:	/* eca - emergency-changeover-ack */
				p->eca.slc = m->ansi.msg.eca.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_ECA_SIZE;
				p->primitive = LS_SIGNAL_ECA;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x3:	/* fcm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* rct - signalling-route-set-congestion-test */
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_RCT_SIZE;
				p->primitive = LS_SIGNAL_RCT;
				break;
			case 0x2:	/* tfc - transfer-controlled */
				p->tfc.dest = m->ansi.msg.tfc.dest;
				p->tfc.stat = m->ansi.msg.tfc.stat;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TFC_SIZE;
				p->primitive = LS_SIGNAL_TFC;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x4:	/* tfm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* tfp - transfer-prohibited */
				p->tfp.dest = m->ansi.msg.tfp.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TFP_SIZE;
				p->primitive = LS_SIGNAL_TFP;
				break;
			case 0x2:	/* tcp - transfer-cluster-prohibited */
				p->tcp.dest = m->ansi.msg.tcp.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TCP_SIZE;
				p->primitive = LS_SIGNAL_TCP;
				break;
			case 0x3:	/* tfr - transfer-restricted */
				p->tfr.dest = m->ansi.msg.tfr.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TFR_SIZE;
				p->primitive = LS_SIGNAL_TFR;
				break;
			case 0x4:	/* tcr - transfer-cluster-restricted */
				p->tcr.dest = m->ansi.msg.tcr.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TCR_SIZE;
				p->primitive = LS_SIGNAL_TCR;
				break;
			case 0x5:	/* tfa - transfer-allowed */
				p->tfa.dest = m->ansi.msg.tfa.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TFA_SIZE;
				p->primitive = LS_SIGNAL_TFA;
				break;
			case 0x6:	/* tca - transfer-cluster-allowed */
				p->tca.dest = m->ansi.msg.tca.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TCA_SIZE;
				p->primitive = LS_SIGNAL_TCA;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x5:	/* rsm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* rsp - signalling-route-set-test-prohibited */
				p->rsp.dest = m->ansi.msg.rsp.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_RSP_SIZE;
				p->primitive = LS_SIGNAL_RSP;
				break;
			case 0x2:	/* rsr - signalling-route-set-test-restricted */
				p->rsr.dest = m->ansi.msg.rsr.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_RSR_SIZE;
				p->primitive = LS_SIGNAL_RSR;
				break;
			case 0x3:	/* rcp - signalling-route-set-test-cluster-prohibited */
				p->rcp.dest = m->ansi.msg.rcp.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_RCP_SIZE;
				p->primitive = LS_SIGNAL_RCP;
				break;
			case 0x4:	/* rcr - signalling-route-set-test-cluster-restricted */
				p->rcr.dest = m->ansi.msg.rcr.dest;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_RCR_SIZE;
				p->primitive = LS_SIGNAL_RCR;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x6:	/* mim */
			switch (p->sig.mh.h1) {
			case 0x1:	/* lin - link-inhibit */
				p->lin.slc = m->ansi.msg.lin.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LIN_SIZE;
				p->primitive = LS_SIGNAL_LIN;
				break;
			case 0x2:	/* lun - link-uninhibit */
				p->lun.slc = m->ansi.msg.lun.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LUN_SIZE;
				p->primitive = LS_SIGNAL_LUN;
				break;
			case 0x3:	/* lia - link-inhibit-ack */
				p->lia.slc = m->ansi.msg.lia.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LIA_SIZE;
				p->primitive = LS_SIGNAL_LIA;
				break;
			case 0x4:	/* lua - link-uninhibit-ack */
				p->lua.slc = m->ansi.msg.lua.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LUA_SIZE;
				p->primitive = LS_SIGNAL_LUA;
				break;
			case 0x5:	/* lid - link-inhibit-denied */
				p->lid.slc = m->ansi.msg.lid.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LID_SIZE;
				p->primitive = LS_SIGNAL_LID;
				break;
			case 0x6:	/* lfu - force-uninhibit */
				p->lfu.slc = m->ansi.msg.lfu.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LFU_SIZE;
				p->primitive = LS_SIGNAL_LFU;
				break;
			case 0x7:	/* lli - local-inhibit-test */
				p->lli.slc = m->ansi.msg.lli.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LLI_SIZE;
				p->primitive = LS_SIGNAL_LLI;
				break;
			case 0x8:	/* lri - remote-inhibit-test */
				p->lri.slc = m->ansi.msg.lri.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_LRI_SIZE;
				p->primitive = LS_SIGNAL_LRI;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x7:	/* trm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* tra - traffic-restart-allowed */
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TRA_SIZE;
				break;
			case 0x2:	/* trw - traffic-restart-waiting */
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_TRW_SIZE;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0x8:	/* dlm */
			switch (p->sig.mh.h1) {
			case 0x1:	/* dlc - signalling-data-link-connection-order */
				p->dlc.sdli = m->ansi.msg.dlc.sdli;
				p->dlc.slc = m->ansi.msg.dlc.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_DLC_SIZE;
				p->primitive = LS_SIGNAL_DLC;
				break;
			case 0x2:	/* css - connection-successful */
				p->css.slc = m->ansi.msg.css.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_CSS_SIZE;
				p->primitive = LS_SIGNAL_CSS;
				break;
			case 0x3:	/* cns - connection-not-successful */
				p->cns.slc = m->ansi.msg.cns.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_CNS_SIZE;
				p->primitive = LS_SIGNAL_CNS;
				break;
			case 0x4:	/* cnp - connection-not-possible */
				p->cnp.slc = m->ansi.msg.cnp.slc;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_CNP_SIZE;
				p->primitive = LS_SIGNAL_CNP;
				break;
			default:
				return -EINVAL;
			}
			break;
		case 0xa:	/* ufc */
			switch (p->sig.mh.h1) {
			case 0x1:	/* upu - user part unavailable */
				p->upu.dest = m->ansi.msg.upu.dest;
				p->upu.upi = m->ansi.msg.upu.upi;
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_UPU_SIZE;
				p->primitive = LS_SIGNAL_UPU;
				break;
				/* FIXME: some more here I don't have */
			default:
				return -EINVAL;
			}
			break;
		default:
			return -EINVAL;
		}
		break;
	case 0x1:		/* sltc */
		p->sig.mh.h0 = m->ansi.mh.h0;
		p->sig.mh.h1 = m->ansi.mh.h1;
		switch (p->sig.mh.h0) {
		case 0x1:
			switch (p->sig.mh.h1) {
			case 0x1:	/* sltm */
				p->sltm.slc = m->ansi.msg.sltm.slc;
				p->sltm.tli = m->ansi.msg.sltm.tli;
				bcopy(m->ansi.msg.sltm.tmsx, p->sltm.tmsx, p->sltm.tli);
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_SLTM_SIZE - 15 + p->sltm.tli;
				p->primitive = LS_SIGNAL_SLTM;
				break;
			case 0x2:	/* slta */
				p->slta.slc = m->ansi.msg.slta.slc;
				p->slta.tli = m->ansi.msg.slta.tli;
				bcopy(m->ansi.msg.slta.tmsx, p->slta.tmsx, p->slta.tli);
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_SLTM_SIZE - 15 + p->slta.tli;
				p->primitive = LS_SIGNAL_SLTA;
				break;
			default:
				return -EINVAL;
			}
			break;
		default:
			return -EINVAL;
		}
		break;
	case 0x2:		/* ssltc */
		p->sig.mh.h0 = m->ansi.mh.h0;
		p->sig.mh.h1 = m->ansi.mh.h1;
		switch (p->sig.mh.h0) {
		case 0x1:
			switch (p->sig.mh.h1) {
			case 0x1:	/* ssltm */
				p->ssltm.slc = m->ansi.msg.ssltm.slc;
				p->ssltm.tli = m->ansi.msg.ssltm.tli;
				bcopy(m->ansi.msg.ssltm.tmsx, p->ssltm.tmsx, p->ssltm.tli);
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_SLTM_SIZE - 15 + p->ssltm.tli;
				p->primitive = LS_SIGNAL_SSLTM;
				break;
			case 0x2:	/* sslta */
				p->sslta.slc = m->ansi.msg.sslta.slc;
				p->sslta.tli = m->ansi.msg.sslta.tli;
				bcopy(m->ansi.msg.sslta.tmsx, p->sslta.tmsx, p->sslta.tli);
				mp->b_wptr = mp->b_rptr + LS_SIGNAL_SLTM_SIZE - 15 + p->sslta.tli;
				p->primitive = LS_SIGNAL_SSLTA;
				break;
			default:
				return -EINVAL;
			}
			break;
		default:
			return -EINVAL;
		}
		break;
	default:
		mp->b_wptr = mp->b_rptr + LS_SIGNAL_USER_SIZE;
		md->b_rptr += sizeof(m->ansi.mh) - 1;	/* strip MTP header */
		p->primitive = LS_SIGNAL_USER;
		return (0);
	}
	mp->b_datap->db_type = M_PROTO;
	md = unlinkb(mp);
	freemsg(md);
	return (0);
}

int lk_parse_msu(lk_t * lk, mblk_t * mp)
{
	/* 
	 *  Takes the MSU (M_DATA) as provided for in the message block (M_DATA)
	 *  and decodes it into a message block in mp (M_PROTO).
	 *
	 *  FIXME: Make this decode by network indicator...
	 */
	int var = lk->module->option.pvar;

	if (!mp->b_cont)
		mp->b_cont = allocb(LS_PRIMITIVE_MAX_SIZE, BPRI_HI);
	if (!mp->b_cont)
		return -ENOMEM;

	switch (var) {
	case SS7_PVAR_ITUT_88:
	case SS7_PVAR_ITUT_93:
	case SS7_PVAR_ITUT_96:
	case SS7_PVAR_ITUT_00:
	case SS7_PVAR_ETSI_88:
	case SS7_PVAR_ETSI_93:
	case SS7_PVAR_ETSI_96:
	case SS7_PVAR_ETSI_00:
		return lk_itut_parse_msu(mp);
	case SS7_PVAR_ANSI_88:
	case SS7_PVAR_ANSI_92:
	case SS7_PVAR_ANSI_96:
	case SS7_PVAR_ANSI_00:
	case SS7_PVAR_JTTC_94:
		return lk_ansi_parse_msu(mp);
	}
	return -EINVAL;
}

#endif				/* __SLS_CODEC_H__ */


Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/drivers/slsi/sls_codec.h

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

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