libsua/sualibrary/sua/sua_syntax.cpp

5727 lines
188 KiB
C++

/***************************************************************************
sua_syntax.cpp - description
-------------------
begin : Tue Jan 8 2002
copyright : (C) 2002 by Lode Coene
email : lode.coene@siemens.atea.be
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/*
* $Id: sua_syntax.cpp,v 1.10 2003/08/26 11:43:57 p82609 Exp $
*
* SUA implementation according to SUA draft issue 8.
*
* Author(s): Gery Verwimp
* Lode Coene
*
* Copyright (C) 2001 by Siemens Atea, Herentals, Belgium.
*
* Realized in co-operation between Siemens Atea and
* Siemens AG, Munich, Germany.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Contact: gery.verwimp@siemens.atea.be
* lode.coene@siemens.atea.be
*
* The alternative comment
* inspiration : Dorine
* "route some msg and get a hug from the Easter bunny."
* "question: which bunny, the right one , the left one or both "
* "(and don't forget to apply the KISS (ME *) methodology)"
*
* Purpose: This header-file defines the SUA syntax class for SUA
* primitives and messages, including the en/decoding routines.
*/
#include "sua_syntax.h"
#include <iostream>
#include <iomanip>
using namespace std;
/********************************************************************/
/* General error structure, returned by main en/decoder */
/********************************************************************/
Sua_syntax_error_struct SYNTAX_ERR;
/********************************************************************/
/* General purpose overlay structure, used everywhere */
/********************************************************************/
union Four_bytes_overlay {
uint32_t dq;
uint16_t dw[2];
uint8_t db[4];
};
Four_bytes_overlay OVERLAY;
/********************************************************************/
/* Sua_container method sua_init : Initialize SUA container element */
/********************************************************************/
void Sua_container::sua_init () {
/* Initialize primitive */
/* Initialize SUA header */
sua_prim.hdr_version = Sua_unknown;
sua_prim.hdr_msg_class = sua_mngt;
sua_prim.hdr_msg_type.mngt = mngt_error;
/* Initialize every boolean parameter to FALSE */
sua_prim.data_pres = FALSE;
sua_prim.info_pres = FALSE;
sua_prim.rout_con_pres = FALSE;
sua_prim.diag_info_pres = FALSE;
sua_prim.hb_data_pres = FALSE;
sua_prim.traf_mode_pres = FALSE;
sua_prim.err_code_pres = FALSE;
sua_prim.status_pres = FALSE;
sua_prim.ssnm_parm.cong_lvl_pres = FALSE;
sua_prim.ASP_id_pres = FALSE;
sua_prim.ssnm_parm.aff_pc_pres = FALSE;
sua_prim.ssnm_parm.SSN_pres = FALSE;
sua_prim.ssnm_parm.SMI_pres = FALSE;
sua_prim.hop_count_pres = FALSE;
sua_prim.source_addr_pres = FALSE;
sua_prim.dest_addr_pres = FALSE;
sua_prim.source_ref_pres = FALSE;
sua_prim.dest_ref_pres = FALSE;
sua_prim.SCCP_cause_pres = FALSE;
sua_prim.seq_nr_pres = FALSE;
sua_prim.rec_seq_nr_pres = FALSE;
sua_prim.asp_cap_pres = FALSE;
sua_prim.credit_pres = FALSE;
sua_prim.importance_pres = FALSE;
sua_prim.prot_class_pres = FALSE;
sua_prim.seq_control_pres = FALSE;
sua_prim.segm_pres = FALSE;
sua_prim.TID_label_pres = FALSE;
sua_prim.DRN_label_pres = FALSE;
sua_prim.dest_addr.ssn_incl = FALSE;
sua_prim.dest_addr.gt_incl = FALSE;
sua_prim.dest_addr.pc_incl = FALSE;
sua_prim.dest_addr.pc_pres = FALSE;
sua_prim.dest_addr.ip_addr_pres = FALSE;
sua_prim.dest_addr.gt_pres = FALSE;
sua_prim.dest_addr.hostname_pres = FALSE;
sua_prim.source_addr.ssn_incl = FALSE;
sua_prim.source_addr.gt_incl = FALSE;
sua_prim.source_addr.pc_incl = FALSE;
sua_prim.source_addr.pc_pres = FALSE;
sua_prim.source_addr.ip_addr_pres = FALSE;
sua_prim.source_addr.gt_pres = FALSE;
sua_prim.source_addr.hostname_pres = FALSE;
/* The message string is NOT explicitly initialized !! */
}
/********************************************************************/
/* Sua_container method sua_encode : Encode primitive */
/********************************************************************/
/* The encoder function expects a valid local syntax (sua_prim)
and returns the transfer syntax (message) in the sua_msg string field.
A number of plausibility checks are done :
- mandatory parameters (depending on msg type and class) must be present
- parameters which are not applicable are ignored, even when present
- parameters are checked on validity (range, compatibility with other parameters)
*/
/* 1. Definition of encoding procedures */
/* 1.1 Parameter encoding procedures */
/* 1.1.1 Common parameters */
boolean encode_netw_app (string& msg, uint32_t netw_app) {
/* Kept for RK syntax */
/* Reserve 8 bytes */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x010D);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
OVERLAY.dq = htonl(netw_app);
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
boolean encode_data (string& msg, string& data) {
/* Reserve 4 bytes for tag and length */
int pdu_index = msg.size();
msg.resize(pdu_index + 4);
/* Encode tag */
OVERLAY.dw[0] = htons(0x010b);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length */
OVERLAY.dw[1] = htons(data.size() + 4);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
/* Encode data */
if (data.size() > 0) {
msg += data;
/* Encode possible padding bytes */
if ((data.size() % 4) != 0) {
OVERLAY.db[0] = 0; // padding byte is zero
int nr_of_pad = 4 - (data.size() % 4);
for (int i = 0; i < nr_of_pad; i++)
msg += OVERLAY.db[0];
}
return TRUE;
}
else {
/* Signal error : empty parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Empty Data parameter";
return FALSE;
}
}
boolean encode_ASP_id (string& msg, uint32_t asp_id) {
/* Reserve 4 bytes for tag and length */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0011);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode data */
OVERLAY.dq = htonl(asp_id);
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
boolean encode_info (string& msg, string& info) {
/* Reserve 4 bytes for tag and length */
int pdu_index = msg.size();
msg.resize(pdu_index + 4);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0004);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length */
OVERLAY.dw[1] = htons(info.size() + 4);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
/* Encode data */
if (info.size() > 0) {
msg += info;
/* Encode possible padding bytes */
if ((info.size() % 4) != 0) {
OVERLAY.db[0] = 0; // padding byte is zero
int nr_of_pad = 4 - (info.size() % 4);
for (int i = 0; i < nr_of_pad; i++)
msg += OVERLAY.db[0];
}
return TRUE;
}
else {
/* Signal error : empty parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Empty Info parameter";
return FALSE;
}
}
boolean encode_rout_con (string& msg, uint32_t routing_ctxt) {
/* Reserve 8 bytes for routing context */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0006);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
OVERLAY.dq = htonl(routing_ctxt);
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
boolean encode_diag_info (string& msg, string& diag_info) {
/* Reserve 4 bytes for tag and length */
int pdu_index = msg.size();
msg.resize(pdu_index + 4);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0007);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length */
OVERLAY.dw[1] = htons(diag_info.size() + 4);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
/* Encode data */
if (diag_info.size() > 0) {
msg += diag_info;
/* Encode possible padding bytes */
if ((diag_info.size() % 4) != 0) {
OVERLAY.db[0] = 0; // padding byte is zero
int nr_of_pad = 4 - (diag_info.size() % 4);
for (int i = 0; i < nr_of_pad; i++)
msg += OVERLAY.db[0];
}
return TRUE;
}
else {
/* Signal error : empty parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Empty Diagnostics Info parameter";
return FALSE;
}
}
boolean encode_hb_data (string& msg, string& hb_data) {
/* Reserve 4 bytes for tag and length */
int pdu_index = msg.size();
msg.resize(pdu_index + 4);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0009);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length */
OVERLAY.dw[1] = htons(hb_data.size() + 4);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
/* Encode data */
if (hb_data.size() > 0) {
msg += hb_data;
/* Encode possible padding bytes */
if ((hb_data.size() % 4) != 0) {
OVERLAY.db[0] = 0; // padding byte is zero
int nr_of_pad = 4 - (hb_data.size() % 4);
for (int i = 0; i < nr_of_pad; i++)
msg += OVERLAY.db[0];
}
return TRUE;
}
else {
/* Signal error : empty parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Empty Heartbeat data parameter";
return FALSE;
}
}
boolean encode_traf_mode (string& msg, Sua_traffic_mode_type traffic_mt) {
/* Reserve 8 bytes for traffic mode type */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x000B);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
/* Check traffic mode type */
if (traffic_mt < tmt_max) {
OVERLAY.dq = htonl(uint32_t(traffic_mt));
for (int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
else {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Invalid Traffic Mode";
return FALSE;
}
}
boolean encode_error_code (string& msg, Sua_error_code_type err_code) {
/* Reserve 8 bytes for error code type */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x000C);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
/* Check error code type */
if (err_code < ect_max) {
OVERLAY.dq = htonl(uint32_t(err_code));
for (int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
else {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Invalid Error Code";
return FALSE;
}
}
boolean encode_aff_pc (string& msg, Sua_affected_pc_struct& affected_pc) {
/* Reserve 8 bytes for affected pointcode type */
int pdu_index = msg.size();
if ((affected_pc.num_aff_pc <= 0) ||
(affected_pc.num_aff_pc > 10))
{
/* Signal error : parameter out of range */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : num_aff_pc out of range( <> 1..10) ";
return FALSE;
}
msg.resize(pdu_index + 4 + (affected_pc.num_aff_pc * 4));
/* Encode tag */
OVERLAY.dw[0] = htons(0x0012);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length */
OVERLAY.dw[1] = htons(4 + (affected_pc.num_aff_pc * 4));
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
for (int k = 0; k < affected_pc.num_aff_pc; k++)
{
/* Encode value pointcode */
OVERLAY.dq = htonl(uint32_t(affected_pc.pc[k]));
for (int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
}
return TRUE;
}
/* 1.1.2 SUA specific parameters */
boolean encode_hop_count (string& msg, uint8_t hop_count) {
/* Reserve 8 bytes for hop count */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0101);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
for(int i = 0; i < 3; i++)
msg[pdu_index + i] = 0; // spare bytes
pdu_index += 3; // value
if (hop_count < 16)
msg[pdu_index] = hop_count;
else {
/* Signal error : parameter out of range */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Hop counter too high";
return FALSE;
}
return TRUE;
}
boolean encode_addr (string& msg, Sua_address_struct& address) {
/* Encode address parameters */
/* Reserve 4 bytes for routing and address indicator */
int pdu_index = msg.size();
msg.resize(pdu_index + 4);
/* Routing indicator : in this version only route on IP, hostname and SSN is allowed */
if ((address.rout_ind != ri_route_IP_SSN) &&
(address.rout_ind != ri_route_PC_SSN) &&
(address.rout_ind != ri_route_hostname) &&
(address.rout_ind != ri_route_GT)) {
/* Signal error : invalid routing indicator used */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Invalid routing indicator";
return FALSE;
}
OVERLAY.dw[0] = htons(address.rout_ind);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Address indicator : depending on routing indicator, we set the appropriate flags */
OVERLAY.dw[0] = 0; // Include nothing
if ((address.rout_ind == ri_route_PC_SSN) || (address.rout_ind == ri_route_IP_SSN) || (address.ssn_incl))
OVERLAY.db[0] |= 0x01;
if (address.pc_incl)
OVERLAY.db[0] |= 0x02;
if ((address.rout_ind == ri_route_GT) || (address.gt_incl))
OVERLAY.db[0] |= 0x04;
OVERLAY.dw[0] = htons(OVERLAY.dw[0]);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Address element checks : when routing on
- GT, a GT must be present
- SSN, either an IP address or PC must be present; these may never appear together
- hostname, a hostname must be present
Currently, we only allow SSN + IP address or hostname
*/
/* Reserve 8 bytes for SSN address parameter */
msg.resize(pdu_index + 8);
/* Encode SSN tag */
OVERLAY.dw[0] = htons(0x8003);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode SSN length : always 8 bytes, no padding */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode SSN value */
for(int i = 0; i < 3; i++)
msg[pdu_index + i] = 0; // spare bytes
pdu_index += 3; // value
msg[pdu_index] = address.ssn;
pdu_index++; // next tag
/* Encode IP address or hostname */
char* pdu_c;
if (address.ip_addr_pres) {
/* Check type */
switch (address.ip_addr_type) {
case short(ip_v4) :
/* An IPv4 address is 4 bytes long (NBO), so reserve 8 bytes */
msg.resize(pdu_index + 8);
OVERLAY.dw[0] = htons(0x8004);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
OVERLAY.dq = address.ip_addr.ipv4.sin_addr.s_addr;
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
break;
case short(ip_v6) :
/* An IPv6 address is 16 bytes long (NBO), so reserve 20 bytes */
msg.resize(pdu_index + 20);
OVERLAY.dw[0] = htons(0x8006);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
OVERLAY.dw[1] = htons(20);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
pdu_c = (char*) &address.ip_addr.ipv6.sin6_addr.s6_addr;
for(int i = 0; i < 16; i++) {
msg[pdu_index + i] = *pdu_c;
pdu_c++;
}
pdu_index += 16; // next tag
break;
default : {
/* Signal error : invalid IP address type */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Invalid IP address type";
return FALSE;
}
} // End switch IP type
} // Endif
else if (address.pc_pres) {
/* An point code address is 4 bytes long (NBO), so reserve 8 bytes */
msg.resize(pdu_index + 8);
OVERLAY.dw[0] = htons(0x8002);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
OVERLAY.dq = address.pc;
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[3-i];
} // Endif
else if (address.hostname_pres){
short padding = (4 - ((pdu_index + address.hostname.length() + 6 ) % 4)) % 4;
msg.resize(pdu_index + address.hostname.length() + 2 + 4 + padding);
OVERLAY.dw[0] = htons(0x8005);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
OVERLAY.dw[1] = htons(address.hostname.length() + 6);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
string name_str;
int numchar = 0;
int i,first= 0; /* start of name array */
int last= address.hostname.size();
unsigned int current = address.hostname.find('.');
while(current != string::npos)
{
/* determine the length of each label(except the last)*/
numchar = current - first;
/* copy length of label into PDU */
OVERLAY.dw[0] = numchar;
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
/* copy the label in the PDU */
for (i=0; i < numchar; i++) {
OVERLAY.dw[0] = address.hostname[first + i];
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
}
first= current + 1;
current = address.hostname.find('.', first);
}
/* determine lenght of last label */
numchar = last - first;
OVERLAY.dw[0] = numchar;
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
for (i=0; i < numchar; i++) {
OVERLAY.dw[0] = address.hostname[first + i];
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
}
/* end of hostname */
msg[pdu_index] = htons(0x00);
pdu_index++;
/* padding out up a 32 bit boundary */
int mod_nr = 0;
if ((mod_nr = pdu_index % 4) != 0)
{
OVERLAY.dw[0] = htons(0x0000);;
for (i=0; i < (4 - mod_nr); i++) {
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
}
}
}
// Endif
else if (address.gt_pres){
short gt_length = ((address.gt.nr_of_digits/2) + (address.gt.nr_of_digits % 2) + 4 + 4 + 4);
short padding = (4 - ((pdu_index + gt_length) % 4)) % 4;
msg.resize(pdu_index + gt_length + padding);
OVERLAY.dw[0] = htons(0x8001);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
OVERLAY.dw[1] = htons(gt_length);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* GTI */
OVERLAY.dw[0] = htons(0x0000);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
OVERLAY.dw[1] = htons(0x0004);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* nr of digits , TT, NP and NA */
OVERLAY.dw[0] = address.gt.nr_of_digits;
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
OVERLAY.dw[0] = address.gt.translation_type;
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
OVERLAY.dw[0] = address.gt.num_plan;
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
OVERLAY.dw[0] = address.gt.nat_addr;
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
/* put digits in msg */
int i;
int last= (address.gt.nr_of_digits/2) + (address.gt.nr_of_digits%2);
for (i= 0; i < last; i++)
{
/* put in digit N + 1 and digit N */
if (((2*i)+1) >= address.gt.nr_of_digits)
OVERLAY.dw[0] = htons(0x0000);
else
OVERLAY.dw[0] = 16 * (address.gt.digits[(2*i)+1] % 16);
OVERLAY.dw[0] = OVERLAY.dw[0] + (address.gt.digits[(2*i)] % 16);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
}
/* end of Global Title */
/* padding out up a 32 bit boundary */
int mod_nr = 0;
if ((mod_nr = pdu_index % 4) != 0)
{
OVERLAY.dw[0] = htons(0x0000);
for (i=0; i < (4 - mod_nr); i++) {
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
}
}
}
else {
/* Signal error : IP address missing */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Address parameter missing";
return FALSE;
}
return TRUE;
}
boolean encode_src_addr (string& msg, Sua_address_struct& address) {
boolean no_error = TRUE;
/* Reserve extra 4 bytes for tag, length */
int pdu_index = msg.size();
msg.resize(pdu_index + 4);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0102);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Lenght is encoded when known, at the end */
/* Encode value */
no_error = encode_addr (msg, address);
if (no_error) {
/* Encode length : calculate as current size - pdu_index + 2 (tag) */
OVERLAY.dw[1] = htons(msg.size() - pdu_index + 2);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
}
return no_error;
}
boolean encode_dest_addr (string& msg, Sua_address_struct& address) {
boolean no_error = TRUE;
/* Reserve extra 4 bytes for tag, length */
int pdu_index = msg.size();
msg.resize(pdu_index + 4);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0103);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Lenght is encoded when known, at the end */
/* Encode value */
no_error = encode_addr (msg, address);
if (no_error) {
/* Encode length : calculate as current size - pdu_index + 2 (tag) */
OVERLAY.dw[1] = htons(msg.size() - pdu_index + 2);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
}
return no_error;
}
boolean encode_source_ref (string& msg, uint32_t src_ref) {
/* Reserve 8 bytes for source reference */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0104);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
OVERLAY.dq = htonl(src_ref);
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
boolean encode_dest_ref (string& msg, uint32_t dest_ref) {
/* Reserve 8 bytes for destination reference */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0105);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
OVERLAY.dq = htonl(dest_ref);
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
boolean encode_SCCP_cause (string& msg, SCCP_cause_struct cause) {
/* Reserve 8 bytes */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0106);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value : 2 spare bytes, then cause type and value */
OVERLAY.dw[0] = 0;
OVERLAY.db[2] = uint8_t(cause.cause_type);
OVERLAY.db[3] = cause.cause_value;
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
boolean encode_credit (string& msg, uint32_t credit) {
/* Reserve 8 bytes for credit number */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x010A);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value : 2 spare bytes, then received seq nr, more data flag and sent seq nr */
OVERLAY.dq = htonl(credit); // fill in credit value
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
boolean encode_seq_nr (string& msg, Sua_seq_nr_struct seq_nr) {
/* Reserve 8 bytes for sequence number */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0107);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value : 2 spare bytes, then received seq nr, more data flag and sent seq nr */
OVERLAY.dw[0] = 0;
OVERLAY.db[2] = 0; // No rcvd seq nr, only more data flag will be set
OVERLAY.db[3] = 0; // No sent seq nr for protocol class 2
if (seq_nr.more_data)
OVERLAY.db[2] |= 0x01;
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
boolean encode_asp_cap (string& msg, Sua_asp_cap_struct asp_cap) {
/* Reserve 8 bytes for ASP capabilities */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0109);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
msg[pdu_index] = 0; // spare byte
pdu_index++;
msg[pdu_index] = 0; // spare byte
pdu_index++;
OVERLAY.db[0] = 0; // clear byte
/* Protocol class 0 is always supported */
OVERLAY.db[0] |= 0x01;
if (asp_cap.cl1_supp)
OVERLAY.db[0] |= 0x02;
if (asp_cap.cl2_supp)
OVERLAY.db[0] |= 0x04;
if (asp_cap.cl3_supp)
OVERLAY.db[0] |= 0x08;
msg[pdu_index] = OVERLAY.db[0]; // Supported protocol classes
pdu_index++;
/* Check interworking type */
if (asp_cap.interworking < iw_max) {
msg[pdu_index] = uint8_t(asp_cap.interworking);
return TRUE;
}
else {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Invalid Interworking type";
return FALSE;
}
}
boolean encode_seq_ctrl (string& msg, uint32_t seq_ctrl) {
/* Reserve 8 bytes for sequence control */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0116);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
OVERLAY.dq = htonl(seq_ctrl);
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
boolean encode_importance (string& msg, uint8_t importance) {
/* Reserve 8 bytes for importance */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0113);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
for(int i = 0; i < 3; i++)
msg[pdu_index + i] = 0; // spare bytes
pdu_index += 3; // value
if (importance < 8)
msg[pdu_index] = importance;
else {
/* Signal error : parameter out of range */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Importance too high";
return FALSE;
}
return TRUE;
}
boolean encode_prot_class (string& msg, Sua_protocol_class_struct pr_cl) {
/* Reserve 8 bytes for protocol class */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0115);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
for(int i = 0; i < 3; i++)
msg[pdu_index + i] = 0; // spare bytes
pdu_index += 3; // value
/* Encode protocol class and special options */
if (pr_cl.pcl < prot_max) {
OVERLAY.db[0] = uint8_t(pr_cl.pcl);
if ((pr_cl.return_option) && ((pr_cl.pcl == prot_class_0) || (pr_cl.pcl == prot_class_1)))
OVERLAY.db[0] |= 0x80; // Set return on error flag
}
else {
/* Signal error : invalid parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Invalid Protocol Class";
return FALSE;
}
msg[pdu_index] = OVERLAY.db[0];
return TRUE;
}
boolean encode_segmentation (string& msg, Sua_segm_struct segments) {
/* Reserve 8 bytes for segmentation parameter */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0117);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
OVERLAY.dq = htonl(segments.segm_ref);
if (OVERLAY.db[0] == 0) {
if (segments.remain < 16) {
OVERLAY.db[0] = segments.remain;
if (segments.first)
OVERLAY.db[0] |= 0x80; // Set first segment flag
}
else {
/* Signal error : parameter out of range */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Remaining segments too high";
return FALSE;
}
}
else {
/* Signal error : parameter out of range */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Segmentation reference out of range";
return FALSE;
}
/* Copy into message */
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
boolean encode_TID_label (string& msg, Sua_label_struct TID_label) {
/* Reserve 8 bytes for TID label */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x0119);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
int max_label = 2;
if ((TID_label.start < 32) && (TID_label.start >= TID_label.end) && ((TID_label.start - TID_label.end) < 16)) {
for (int i = 0; i < (TID_label.start - TID_label.end); i++)
max_label = max_label * 2;
if (TID_label.label_value < max_label) {
OVERLAY.db[0] = TID_label.start;
OVERLAY.db[1] = TID_label.end;
OVERLAY.dw[1] = htons(TID_label.label_value);
}
else {
/* Signal error : paramater syntax error */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Invalid TID label";
return FALSE;
}
}
else {
/* Signal error : parameter syntax error */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Invalid TID label position or length";
return FALSE;
}
/* Copy into message */
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
boolean encode_DRN_label (string& msg, Sua_label_struct DRN_label) {
/* Reserve 8 bytes for DRN label */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x011A);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value */
int max_label = 2;
if ((DRN_label.start < 32) && (DRN_label.start >= DRN_label.end) && ((DRN_label.start - DRN_label.end) < 16)) {
for (int i = 0; i < (DRN_label.start - DRN_label.end); i++)
max_label = max_label * 2;
if (DRN_label.label_value < max_label) {
OVERLAY.db[0] = DRN_label.start;
OVERLAY.db[1] = DRN_label.end;
OVERLAY.dw[1] = htons(DRN_label.label_value);
}
else {
/* Signal error : paramater syntax error */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Invalid DRN label";
return FALSE;
}
}
else {
/* Signal error : parameter syntax error */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Encoding : Invalid DRN label position or length";
return FALSE;
}
/* Copy into message */
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = OVERLAY.db[i];
return TRUE;
}
/* 1.2 Message encoding procedures */
/* 1.2.3 Signalling network management messages */
boolean encode_ssnm_duna_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are mandatory :
- affected pointcode(single) (list of aff. PC's is not supported yet)
Following parameters are optional :
- routing context
- subsystem number (SSN)
- (SMI)
- cause / user
- Info string
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.ssnm_parm.aff_pc_pres && no_error)
no_error = encode_aff_pc (msg, prim.ssnm_parm.aff_pc);
else {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : DUNA :affected pointcode missing";
return FALSE;
}
/* no support yet for SSN in msg */
/*if (prim.ssnm_parm.ssn_pres && no_error)
no_error = encode_ssn (msg, prim.ssnm_parm.ssn);*/
/* no support yet for Cause/user */
/*if (prim.ssnm_parm._pres && no_error)
no_error = encode_affected_pc (msg, prim.aff_pc);*/
if (prim.info_pres && no_error)
no_error = encode_info (msg, prim.info_string);
return no_error;
}
boolean encode_ssnm_dava_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are mandatory :
- affected pointcode(single) (list of aff. PC's is not supported yet)
Following parameters are optional :
- routing context
- subsystem number (SSN)
- (SMI)
- cause / user
- Info string
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.ssnm_parm.aff_pc_pres && no_error)
no_error = encode_aff_pc (msg, prim.ssnm_parm.aff_pc);
else {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : DAVA :affected pointcode missing";
return FALSE;
}
/* no support yet for SSN in msg */
/*if (prim.ssnm_parm.ssn_pres && no_error)
no_error = encode_ssn (msg, prim.ssnm_parm.ssn);*/
/* no support yet for Cause/user */
if (prim.info_pres && no_error)
no_error = encode_info (msg, prim.info_string);
return no_error;
}
boolean encode_ssnm_daud_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are mandatory :
- affected pointcode(single) (list of aff. PC's is not supported yet)
Following parameters are optional :
- routing context
- subsystem number (SSN)
- cause / user
- Info string
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.ssnm_parm.aff_pc_pres && no_error)
no_error = encode_aff_pc (msg, prim.ssnm_parm.aff_pc);
else {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : DAUD :affected pointcode missing";
return FALSE;
}
/* no support yet for SSN in msg */
/*if (prim.ssnm_parm.ssn_pres && no_error)
no_error = encode_ssn (msg, prim.ssnm_parm.ssn);*/
/* no support yet for Cause/user */
/*if (prim.ssnm_parm._pres && no_error)
no_error = encode_affected_pc (msg, prim.aff_pc);*/
if (prim.info_pres && no_error)
no_error = encode_info (msg, prim.info_string);
return no_error;
}
/* 1.2.3 ASP Server Management messages */
boolean encode_ASP_up_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are optional :
- ASP Identifier (dynamic assignment not supported)
- Info string
*/
boolean no_error = TRUE;
if (prim.ASP_id_pres)
no_error = encode_ASP_id (msg, prim.ASP_id);
if (prim.info_pres && no_error)
no_error = encode_info (msg, prim.info_string);
return no_error;
}
boolean encode_ASP_down_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are optional :
- Info string
*/
boolean no_error = TRUE;
if (prim.info_pres)
no_error = encode_info (msg, prim.info_string);
return no_error;
}
boolean encode_ASP_beat_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are optional :
- Heartbeat data
*/
boolean no_error = TRUE;
if (prim.hb_data_pres)
no_error = encode_hb_data (msg, prim.hb_data);
return no_error;
}
boolean encode_ASP_up_ack_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are optional :
- ASP Identifier (dynamic assignment not supported)
- Info string
*/
boolean no_error = TRUE;
if (prim.info_pres)
no_error = encode_info (msg, prim.info_string);
return no_error;
}
boolean encode_ASP_down_ack_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are optional :
- Info string
*/
boolean no_error = TRUE;
if (prim.info_pres)
no_error = encode_info (msg, prim.info_string);
return no_error;
}
boolean encode_ASP_beat_ack_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are optional :
- Heartbeat data
*/
boolean no_error = TRUE;
if (prim.hb_data_pres)
no_error = encode_hb_data (msg, prim.hb_data);
return no_error;
}
/* 1.2.4 ASP Traffic Management messages */
boolean encode_ASP_act_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are optional :
- Traffic mode type
- Routing context
- TID label
- DRN label
- Info string
*/
boolean no_error = TRUE;
if (prim.traf_mode_pres)
no_error = encode_traf_mode (msg, prim.traf_mode);
if (prim.rout_con_pres && no_error)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.TID_label_pres && no_error)
no_error = encode_TID_label (msg, prim.TID_label);
if (prim.DRN_label_pres && no_error)
no_error = encode_DRN_label (msg, prim.DRN_label);
if (prim.info_pres && no_error)
no_error = encode_info (msg, prim.info_string);
return no_error;
}
boolean encode_ASP_inact_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are optional :
- Routing context
- Info string
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.info_pres && no_error)
no_error = encode_info (msg, prim.info_string);
return no_error;
}
boolean encode_ASP_act_ack_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are optional :
- Traffic mode type
- Routing context
- Info string
*/
boolean no_error = TRUE;
if (prim.traf_mode_pres)
no_error = encode_traf_mode (msg, prim.traf_mode);
if (prim.rout_con_pres && no_error)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.info_pres && no_error)
no_error = encode_info (msg, prim.info_string);
return no_error;
}
boolean encode_ASP_inact_ack_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters are optional :
- Routing context
- Info string
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.info_pres && no_error)
no_error = encode_info (msg, prim.info_string);
return no_error;
}
/* 1.2.7 Connectionless messages */
boolean encode_cl_data_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters MUST be present :
- Protocol class
- Source address
- Destination address
- Sequence control
- Data
Following parameters are optional :
- Routing context
- Hop count
- Importance
- Message priority (we don't use it)
- Correlation ID (we don't use Broadcast mode)
- Segmentation
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.prot_class_pres && no_error) {
/* Protocol class must be 0 or 1 */
if ((prim.prot_class.pcl == prot_class_0) || (prim.prot_class.pcl == prot_class_1))
no_error = encode_prot_class (msg, prim.prot_class);
else {
/* Signal error : invalid parameter */
SYNTAX_ERR.msg_index = msg.size();
SYNTAX_ERR.error_text = "Encoding : Invalid protocol class for connectionless msg";
return FALSE;
}
}
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Protocol class parameter missing";
return FALSE;
}
}
if (prim.source_addr_pres && no_error)
no_error = encode_src_addr (msg, prim.source_addr);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Source address parameter missing";
return FALSE;
}
}
if (prim.dest_addr_pres && no_error)
no_error = encode_dest_addr (msg, prim.dest_addr);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Destination address parameter missing";
return FALSE;
}
}
if (prim.seq_control_pres && no_error)
no_error = encode_seq_ctrl (msg, prim.seq_control);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Sequence control parameter missing";
return FALSE;
}
}
if (prim.hop_count_pres && no_error)
no_error = encode_hop_count (msg, prim.hop_count);
if (prim.importance_pres && no_error)
no_error = encode_importance (msg, prim.importance);
if (prim.segm_pres && no_error)
no_error = encode_segmentation (msg, prim.segm);
if (prim.data_pres && no_error)
no_error = encode_data (msg, prim.data_string);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Data parameter missing";
return FALSE;
}
}
return no_error;
}
boolean encode_cl_data_resp_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters MUST be present :
- SCCP Cause
- Source address
- Destination address
Following parameters are optional :
- Routing context
- Hop count
- Importance
- Message priority (we don't use it)
- Correlation ID (we don't use Broadcast mode)
- Data
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.SCCP_cause_pres && no_error) {
/* Cause type must be return cause */
prim.SCCP_cause.cause_type = ctp_return_cause;
no_error = encode_SCCP_cause (msg, prim.SCCP_cause);
}
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : SCCP cause parameter missing";
return FALSE;
}
}
if (prim.source_addr_pres && no_error)
no_error = encode_src_addr (msg, prim.source_addr);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Source address parameter missing";
return FALSE;
}
}
if (prim.dest_addr_pres && no_error)
no_error = encode_dest_addr (msg, prim.dest_addr);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Destination address parameter missing";
return FALSE;
}
}
if (prim.hop_count_pres && no_error)
no_error = encode_hop_count (msg, prim.hop_count);
if (prim.importance_pres && no_error)
no_error = encode_importance (msg, prim.importance);
if (prim.data_pres && no_error)
no_error = encode_data (msg, prim.data_string);
return no_error;
}
/* 1.2.8 Connection-oriented messages */
/* Only protocol class 2 messages are supported */
boolean encode_co_conn_req_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters MUST be present :
- Protocol class
- Source reference
- Destination address
- Sequence control
Following parameters are optional :
- Routing context
- Source address
- Hop count
- Importance
- Message priority (we don't use it)
- Credit (no support for protocol class 3)
- Data
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.prot_class_pres && no_error) {
/* Return option not applicable */
prim.prot_class.return_option = FALSE;
/* Protocol class must be 2 or 3 */
if ((prim.prot_class.pcl == prot_class_2) || (prim.prot_class.pcl == prot_class_3))
no_error = encode_prot_class (msg, prim.prot_class);
else {
/* Signal error : invalid parameter */
SYNTAX_ERR.msg_index = msg.size();
SYNTAX_ERR.error_text = "Encoding : Invalid protocol class for connection-oriented msg";
return FALSE;
}
}
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Protocol class parameter missing";
return FALSE;
}
}
if (prim.source_ref_pres && no_error)
no_error = encode_source_ref (msg, prim.source_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Source Reference parameter missing";
return FALSE;
}
}
if (prim.dest_addr_pres && no_error)
no_error = encode_dest_addr (msg, prim.dest_addr);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Destination address parameter missing";
return FALSE;
}
}
if (prim.seq_control_pres && no_error)
no_error = encode_seq_ctrl (msg, prim.seq_control);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Sequence control parameter missing";
return FALSE;
}
}
if (prim.source_addr_pres && no_error)
no_error = encode_src_addr (msg, prim.source_addr);
if (prim.hop_count_pres && no_error)
no_error = encode_hop_count (msg, prim.hop_count);
if (prim.importance_pres && no_error)
no_error = encode_importance (msg, prim.importance);
if (prim.data_pres && no_error)
no_error = encode_data (msg, prim.data_string);
return no_error;
}
boolean encode_co_conn_ack_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters MUST be present :
- Protocol class
- Destination reference
- Source reference
- sequence control
Following parameters are optional :
- Routing context
- Destination address
- Importance
- Message priority (we don't use it)
- Credit (no support for protocol class 3)
- Data
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.prot_class_pres && no_error) {
/* Return option not applicable */
prim.prot_class.return_option = FALSE;
/* Protocol class must be 2 or 3 */
if ((prim.prot_class.pcl == prot_class_2) || (prim.prot_class.pcl == prot_class_3))
no_error = encode_prot_class (msg, prim.prot_class);
else {
/* Signal error : invalid parameter */
SYNTAX_ERR.msg_index = msg.size();
SYNTAX_ERR.error_text = "Encoding : Invalid protocol class for connection-oriented msg";
return FALSE;
}
}
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Protocol class parameter missing";
return FALSE;
}
}
if (prim.dest_ref_pres && no_error)
no_error = encode_dest_ref (msg, prim.dest_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing";
return FALSE;
}
}
if (prim.source_ref_pres && no_error)
no_error = encode_source_ref (msg, prim.source_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Source Reference parameter missing";
return FALSE;
}
}
if (prim.seq_control_pres && no_error)
no_error = encode_seq_ctrl (msg, prim.seq_control);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Sequence Control parameter missing";
return FALSE;
}
}
if (prim.dest_addr_pres && no_error)
no_error = encode_dest_addr (msg, prim.dest_addr);
if (prim.importance_pres && no_error)
no_error = encode_importance (msg, prim.importance);
if (prim.data_pres && no_error)
no_error = encode_data (msg, prim.data_string);
return no_error;
}
boolean encode_co_conn_ref_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters MUST be present :
- Destination reference
- SCCP cause
Following parameters are optional :
- Routing context
- Destination address
- Importance
- Data
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.dest_ref_pres && no_error)
no_error = encode_dest_ref (msg, prim.dest_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing";
return FALSE;
}
}
if (prim.SCCP_cause_pres && no_error) {
/* Cause type must be refusal cause */
prim.SCCP_cause.cause_type = ctp_refusal_cause;
no_error = encode_SCCP_cause (msg, prim.SCCP_cause);
}
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : SCCP Cause parameter missing";
return FALSE;
}
}
if (prim.dest_addr_pres && no_error)
no_error = encode_dest_addr (msg, prim.dest_addr);
if (prim.importance_pres && no_error)
no_error = encode_importance (msg, prim.importance);
if (prim.data_pres && no_error)
no_error = encode_data (msg, prim.data_string);
return no_error;
}
boolean encode_co_rel_req_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters MUST be present :
- Destination reference
- Source reference
- SCCP cause
Following parameters are optional :
- Routing context
- Importance
- Data
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.dest_ref_pres && no_error)
no_error = encode_dest_ref (msg, prim.dest_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing";
return FALSE;
}
}
if (prim.source_ref_pres && no_error)
no_error = encode_source_ref (msg, prim.source_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Source Reference parameter missing";
return FALSE;
}
}
if (prim.SCCP_cause_pres && no_error) {
/* Cause type must be release cause */
prim.SCCP_cause.cause_type = ctp_release_cause;
no_error = encode_SCCP_cause (msg, prim.SCCP_cause);
}
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : SCCP Cause parameter missing";
return FALSE;
}
}
if (prim.importance_pres && no_error)
no_error = encode_importance (msg, prim.importance);
if (prim.data_pres && no_error)
no_error = encode_data (msg, prim.data_string);
return no_error;
}
boolean encode_co_rel_conf_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters MUST be present :
- Destination reference
- Source reference
Following parameters are optional :
- Routing context
- Importance
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.dest_ref_pres && no_error)
no_error = encode_dest_ref (msg, prim.dest_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing";
return FALSE;
}
}
if (prim.source_ref_pres && no_error)
no_error = encode_source_ref (msg, prim.source_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Source Reference parameter missing";
return FALSE;
}
}
if (prim.importance_pres && no_error)
no_error = encode_importance (msg, prim.importance);
return no_error;
}
boolean encode_co_data_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters MUST be present :
- Sequence number
- Destination reference
- Data
Following parameters are optional :
- Routing context
- Message priority (we don't use it)
- Correlation ID (we don't support Broadcast mode)
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.seq_nr_pres && no_error) {
/* Sent and received sequence number don't apply */
prim.seq_nr.sent_seq_nr = 0;
prim.seq_nr.rcvd_seq_nr = 0;
no_error = encode_seq_nr (msg, prim.seq_nr);
}
else {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Sequence number parameter missing";
return FALSE;
}
if (prim.dest_ref_pres && no_error)
no_error = encode_dest_ref (msg, prim.dest_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing";
return FALSE;
}
}
if (prim.data_pres && no_error)
no_error = encode_data (msg, prim.data_string);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Data parameter missing";
return FALSE;
}
}
return no_error;
}
boolean encode_co_err_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters MUST be present :
- Destination reference
- SCCP cause
Following parameters are optional :
- Routing context
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.dest_ref_pres && no_error)
no_error = encode_dest_ref (msg, prim.dest_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing";
return FALSE;
}
}
if (prim.SCCP_cause_pres && no_error) {
/* Cause type must be error cause */
prim.SCCP_cause.cause_type = ctp_error_cause;
no_error = encode_SCCP_cause (msg, prim.SCCP_cause);
}
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : SCCP Cause parameter missing";
return FALSE;
}
}
return no_error;
}
boolean encode_co_it_msg (Sua_primitive_struct& prim, string& msg) {
/* Following parameters MUST be present :
- Protocol class
- Destination reference
- Source reference
- Sequence number (coded zero for protocol class 2)
- Credit (coded zero for protocol class 2)
Following parameters are optional :
- Routing context
*/
boolean no_error = TRUE;
if (prim.rout_con_pres)
no_error = encode_rout_con (msg, prim.rout_con);
if (prim.prot_class_pres && no_error) {
/* Return option not applicable */
prim.prot_class.return_option = FALSE;
/* Protocol class is set to 2 */
prim.prot_class.pcl = prot_class_2;
no_error = encode_prot_class (msg, prim.prot_class);
}
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Protocol class parameter missing";
return FALSE;
}
}
if (prim.dest_ref_pres)
no_error = encode_dest_ref (msg, prim.dest_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing";
return FALSE;
}
}
if (prim.source_ref_pres && no_error)
no_error = encode_source_ref (msg, prim.source_ref);
else {
if (no_error) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Encoding : Source Reference parameter missing";
return FALSE;
}
}
if (no_error) {
prim.seq_nr.sent_seq_nr = 0;
prim.seq_nr.rcvd_seq_nr = 0;
prim.seq_nr.more_data = FALSE;
no_error = encode_seq_nr (msg, prim.seq_nr);
}
if (no_error) {
prim.credit = 0;
/* Reserve 8 bytes */
int pdu_index = msg.size();
msg.resize(pdu_index + 8);
/* Encode tag */
OVERLAY.dw[0] = htons(0x010A);
msg[pdu_index] = OVERLAY.db[0];
pdu_index++;
msg[pdu_index] = OVERLAY.db[1];
pdu_index++;
/* Encode length, always 8 bytes */
OVERLAY.dw[1] = htons(8);
msg[pdu_index] = OVERLAY.db[2];
pdu_index++;
msg[pdu_index] = OVERLAY.db[3];
pdu_index++;
/* Encode value : completely zero */
for(int i = 0; i < 4; i++)
msg[pdu_index + i] = 0;
}
return no_error;
}
/* 1.3 Sua encoding method */
Sua_syntax_error_struct Sua_container::sua_encode () {
/* Syntax Error struct initialization */
SYNTAX_ERR.msg_index = 0;
SYNTAX_ERR.no_error = TRUE;
SYNTAX_ERR.error_text = "Encoding : no error";
/* Encoding variables */
int pdu_index = 0;
boolean no_error = TRUE;
string strBlank;
/* Initialize message string to clean up old mess */
sua_msg = strBlank;
/* Reserve 8 bytes for msg header */
sua_msg.resize(8);
/* Only version 1 is supported */
sua_prim.hdr_version = Sua_version1;
sua_msg[pdu_index] = uint8_t(Sua_version1);
pdu_index++;
/* Reserved byte coded 0 */
sua_msg[pdu_index] = 0;
pdu_index++;
/* Encode message class */
sua_msg[pdu_index] = uint8_t(sua_prim.hdr_msg_class);
pdu_index++;
/* Encode message type according to class */
switch (sua_prim.hdr_msg_class) {
case sua_ssnm :
sua_msg[pdu_index] = uint8_t(sua_prim.hdr_msg_type.ssnm);
pdu_index++;
break;
case sua_aspsm :
sua_msg[pdu_index] = uint8_t(sua_prim.hdr_msg_type.aspsm);
pdu_index++;
break;
case sua_asptm :
sua_msg[pdu_index] = uint8_t(sua_prim.hdr_msg_type.asptm);
pdu_index++;
break;
case sua_cl :
sua_msg[pdu_index] = uint8_t(sua_prim.hdr_msg_type.cl);
pdu_index++;
break;
case sua_co :
sua_msg[pdu_index] = uint8_t(sua_prim.hdr_msg_type.co);
pdu_index++;
break;
default : {
/* Signal error : invalid message class */
SYNTAX_ERR.msg_index = 2;
SYNTAX_ERR.error_text = "Encoding : Invalid message class";
no_error = FALSE;
}
} // End switch message class
if (no_error) {
/* The message length field is encoded at the end, pdu_index is kept at this position */
/* Start encoding of message parameters : double switch ! */
switch (sua_prim.hdr_msg_class) {
case sua_ssnm :
switch (sua_prim.hdr_msg_type.ssnm) {
case ssnm_duna :
no_error = encode_ssnm_duna_msg (sua_prim, sua_msg);
break;
case ssnm_dava :
no_error = encode_ssnm_dava_msg (sua_prim, sua_msg);
break;
case ssnm_daud :
no_error = encode_ssnm_daud_msg (sua_prim, sua_msg);
break;
case ssnm_scon :
;
break;
case ssnm_dupu :
;
break;
case ssnm_drst :
;
break;
default : {
/* Signal error : invalid message type */
SYNTAX_ERR.msg_index = 3;
SYNTAX_ERR.error_text = "Encoding : Invalid sua_ssnm message type";
no_error = FALSE;
}
} // End switch ssnm msg type
break;
case sua_aspsm :
switch (sua_prim.hdr_msg_type.aspsm) {
case aspsm_up :
no_error = encode_ASP_up_msg (sua_prim, sua_msg);
break;
case aspsm_down :
no_error = encode_ASP_down_msg (sua_prim, sua_msg);
break;
case aspsm_beat :
no_error = encode_ASP_beat_msg (sua_prim, sua_msg);
break;
case aspsm_up_ack :
no_error = encode_ASP_up_ack_msg (sua_prim, sua_msg);
break;
case aspsm_down_ack :
no_error = encode_ASP_down_ack_msg (sua_prim, sua_msg);
break;
case aspsm_beat_ack :
no_error = encode_ASP_beat_ack_msg (sua_prim, sua_msg);
break;
default : {
/* Signal error : invalid message type */
SYNTAX_ERR.msg_index = 3;
SYNTAX_ERR.error_text = "Encoding : Invalid sua_aspsm message type";
no_error = FALSE;
}
} // End switch aspsm msg type
break;
case sua_asptm :
switch (sua_prim.hdr_msg_type.asptm) {
case asptm_act :
no_error = encode_ASP_act_msg (sua_prim, sua_msg);
break;
case asptm_inact :
no_error = encode_ASP_inact_msg (sua_prim, sua_msg);
break;
case asptm_act_ack :
no_error = encode_ASP_act_ack_msg (sua_prim, sua_msg);
break;
case asptm_inact_ack :
no_error = encode_ASP_inact_ack_msg (sua_prim, sua_msg);
break;
default : {
/* Signal error : invalid message type */
SYNTAX_ERR.msg_index = 3;
SYNTAX_ERR.error_text = "Encoding : Invalid sua_asptm message type";
no_error = FALSE;
}
} // End switch asptm msg type
break;
case sua_cl :
switch (sua_prim.hdr_msg_type.cl) {
case cl_data_transfer :
no_error = encode_cl_data_msg (sua_prim, sua_msg);
break;
case cl_data_response :
no_error = encode_cl_data_resp_msg (sua_prim, sua_msg);
break;
default : {
/* Signal error : invalid message type */
SYNTAX_ERR.msg_index = 3;
SYNTAX_ERR.error_text = "Encoding : Invalid sua_cl message type";
no_error = FALSE;
}
} // End switch cl msg type
break;
case sua_co :
switch (sua_prim.hdr_msg_type.co) {
case co_core :
no_error = encode_co_conn_req_msg (sua_prim, sua_msg);
break;
case co_coak :
no_error = encode_co_conn_ack_msg (sua_prim, sua_msg);
break;
case co_coref :
no_error = encode_co_conn_ref_msg (sua_prim, sua_msg);
break;
case co_relre :
no_error = encode_co_rel_req_msg (sua_prim, sua_msg);
break;
case co_relco :
no_error = encode_co_rel_conf_msg (sua_prim, sua_msg);
break;
case co_data :
no_error = encode_co_data_msg (sua_prim, sua_msg);
break;
case co_err :
no_error = encode_co_err_msg (sua_prim, sua_msg);
break;
case co_it :
no_error = encode_co_it_msg (sua_prim, sua_msg);
break;
default : {
/* Signal error : invalid message type */
SYNTAX_ERR.msg_index = 3;
SYNTAX_ERR.error_text = "Encoding : Invalid sua_co message type";
no_error = FALSE;
}
} // End switch co msg type
break;
default : {
/* Signal error : invalid message class */
SYNTAX_ERR.msg_index = 2;
SYNTAX_ERR.error_text = "Encoding : Invalid message class";
no_error = FALSE;
}
} // End switch message class
} // End message encoding
if (no_error) {
// Also padding bytes of final parameter are included in the total message length
OVERLAY.dq = htonl(sua_msg.size());
for (int i = 0; i < 4; i++)
sua_msg[pdu_index + i] = OVERLAY.db[i];
pdu_index += 4; // next tag
}
else {
/* Printout error text */
SYNTAX_ERR.no_error = FALSE;
cout << "Error position = " << SYNTAX_ERR.msg_index << endl;
cout << SYNTAX_ERR.error_text << endl;
}
return SYNTAX_ERR;
}
/********************************************************************/
/* Sua_container method sua_decode : Decode SUA container element */
/********************************************************************/
/* The decoder function expects a valid transfer syntax (sua_msg)
and returns the local syntax (primitive) in the sua_prim field.
A number of plausibility checks are done :
- the message and parameter length fields must be consistent
- mandatory parameters (depending on msg type and class) must be present
- unrecognized parameters or parameters that are not applicable, are ignored
- parameters are checked on validity (range, compatibility with other parameters)
- duplicate parameters are not allowed
*/
/* 2. Definition of decoding procedures */
/* 2.1 Parameter decoding procedures */
/* Input pdu_index always points to the tag field of the parameter in the message */
/* Output pdu_index always points to the tag field of the next parameter in the message */
/* 2.1.1 Common parameters */
boolean decode_netw_app (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* Kept for RK syntax */
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode network appearance */
prim.netw_app_pres = TRUE;
pdu_index += 4;
for (int i = 0; i < 4; i++) {
OVERLAY.db[i] = msg[pdu_index + i];
}
prim.netw_app = ntohl(OVERLAY.dq);
pdu_index += 4; // Next tag
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Network Appearance length";
return FALSE;
}
}
boolean decode_data (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* Get the parameter length */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
/* There should be at least 1 byte of data */
if (par_len > 4) {
/* Copy to the data string */
prim.data_pres = TRUE;
prim.data_string = msg.substr(pdu_index + 4, par_len - 4);
/* Set pdu_index to next tag */
pdu_index += par_len;
pdu_index += (4 - (par_len % 4)) % 4; // don't forget padding bytes
return TRUE;
}
else {
/* Signal error : empty parameter */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Empty Data parameter";
return FALSE;
}
}
boolean decode_info (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* Get the parameter length */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
/* There should be at least 1 byte of info */
if (par_len > 4) {
/* Copy to the info string */
prim.info_pres = TRUE;
prim.info_string = msg.substr(pdu_index + 4, par_len - 4);
/* Set pdu_index to next tag */
pdu_index += par_len;
pdu_index += (4 - (par_len % 4)) % 4; // don't forget padding bytes
return TRUE;
}
else {
/* Signal error : empty parameter */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Empty Info parameter";
return FALSE;
}
}
boolean decode_rout_con (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode routing context */
prim.rout_con_pres = TRUE;
pdu_index += 4;
for (int i = 0; i < 4; i++) {
OVERLAY.db[i] = msg[pdu_index + i];
}
prim.rout_con = ntohl(OVERLAY.dq);
pdu_index += 4; // Next tag
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Routing Context length";
return FALSE;
}
}
boolean decode_hb_data (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* Get the parameter length */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
/* There should be at least 1 byte of data */
if (par_len > 4) {
/* Copy to the hb_data string */
prim.hb_data_pres = TRUE;
prim.hb_data = msg.substr(pdu_index + 4, par_len - 4);
/* Set pdu_index to next tag */
pdu_index += par_len;
pdu_index += (4 - (par_len % 4)) % 4; // don't forget padding bytes
return TRUE;
}
else {
/* Signal error : empty parameter */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Empty Heartbeat data parameter";
return FALSE;
}
}
boolean decode_traf_mode (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode traffic mode type */
pdu_index += 4;
for (int i = 0; i < 4; i++) {
OVERLAY.db[i] = msg[pdu_index + i];
}
OVERLAY.dq = ntohl(OVERLAY.dq);
/* Check traffic mode type value */
if (OVERLAY.dq < tmt_max) {
pdu_index += 4; // Next tag
prim.traf_mode_pres = TRUE;
prim.traf_mode = Sua_traffic_mode_type(OVERLAY.dq);
return TRUE;
}
else {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Invalid Traffic Mode Type value";
return FALSE;
}
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Traffic Mode Type length";
return FALSE;
}
}
boolean decode_error_code (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode error code */
pdu_index += 4;
for (int i = 0; i < 4; i++) {
OVERLAY.db[i] = msg[pdu_index + i];
}
OVERLAY.dq = ntohl(OVERLAY.dq);
/* Check error code value */
if (OVERLAY.dq < ect_max) {
pdu_index += 4; // Next tag
prim.err_code_pres = TRUE;
prim.err_code = Sua_error_code_type(OVERLAY.dq);
return TRUE;
}
else {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Invalid Error Code value";
return FALSE;
}
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Error Code length";
return FALSE;
}
}
boolean decode_aff_pc (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if ((par_len > 4)|| (par_len <= 44)) {
/* Decode affected pointcode */
prim.ssnm_parm.aff_pc_pres = TRUE;
prim.ssnm_parm.aff_pc.num_aff_pc = ((par_len - 4) / 4);
pdu_index += 4;
for ( int k = 0; k < prim.ssnm_parm.aff_pc.num_aff_pc; k++)
{
for (int i = 0; i < 4; i++) {
OVERLAY.db[i] = msg[pdu_index + i];
}
prim.ssnm_parm.aff_pc.pc[k] = ntohl(OVERLAY.dq);
pdu_index += 4; // Next aff_pc value(if more than 1) or next tag
}
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid affected pointcode length";
return FALSE;
}
}
/* 2.1.2 SUA specific parameters */
boolean decode_hop_count (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode hop counter */
prim.hop_count = uint8_t(msg[pdu_index + 7]);
/* Check whether hop counter within range */
if (prim.hop_count > 15) {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index + 7;
SYNTAX_ERR.error_text = "Decoding : Invalid Hop Counter value";
return FALSE;
}
pdu_index += 8; // next tag
prim.hop_count_pres = TRUE;
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Hop Counter length";
return FALSE;
}
}
boolean decode_addr (Sua_address_struct& addr, string& msg, unsigned int& pdu_index) {
unsigned int next_tag_pdu_idx = 0;
int j = 0, last = 0;
unsigned int numchar = 0;
bool look_for_next_label = FALSE;
/* Get the parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[1]);
/* There must be at least a routing and address indicator, plus 1 parameter */
if (par_len > 12) {
/* Evaluate address parameters, the address structure has been cleaned up */
/* Routing indicator */
pdu_index += 4;
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
uint16_t pdu_word = ntohs(OVERLAY.dw[0]);
/* Check validity of routing indicator, only route on IP and SSN is supported */
if ((pdu_word != uint16_t(ri_route_IP_SSN)) &&
(pdu_word != uint16_t(ri_route_PC_SSN)) &&
(pdu_word != uint16_t(ri_route_hostname)) &&
(pdu_word != uint16_t(ri_route_GT))){
/* Signal error : routing indicator not supported */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Routing Indicator not supported";
return FALSE;
}
addr.rout_ind = Sua_rout_ind(pdu_word);
/* Address indicator */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
pdu_word = ntohs(OVERLAY.dw[1]);
if ((pdu_word & 0x01) != 0)
addr.ssn_incl = TRUE;
if ((pdu_word & 0x02) != 0)
addr.pc_incl = TRUE;
if ((pdu_word & 0x04) != 0)
addr.gt_incl = TRUE;
/* Address parameters */
pdu_index += 4; // pdu_index points to first address parameter tag
par_len -= 8; // remaining address length
uint16_t addr_par_len, addr_par_tag;
uint32_t addr_par_val;
char* pdu_c;
while (par_len > 4) {
/* Evaluate address parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
addr_par_len = ntohs(OVERLAY.dw[1]);
/* Check for length overflow */
if (addr_par_len <= par_len) {
/* Evaluate address parameter tag and decode or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
addr_par_tag = ntohs(OVERLAY.dw[0]);
switch (addr_par_tag) {
case 0x8001 :
/* Global Title */
addr_par_len += (4 - (addr_par_len % 4)) % 4; // don't forget padding bytes
addr.gt_pres = TRUE;
next_tag_pdu_idx = pdu_index + addr_par_len; // next tag
pdu_index += 4;
/* get GTI format */
OVERLAY.dq = 0;
OVERLAY.db[3] = msg[pdu_index + 3];
pdu_index += 4;
/* get nr-of-digits, translation type, */
/* numbering plan and nature-of-address */
OVERLAY.dq = 0;
OVERLAY.db[0] = msg[pdu_index + 0];
OVERLAY.db[1] = msg[pdu_index + 1];
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
addr.gt.nr_of_digits = OVERLAY.db[0];
addr.gt.translation_type = OVERLAY.db[1];
addr.gt.num_plan = OVERLAY.db[2];
addr.gt.nat_addr = OVERLAY.db[3];
pdu_index += 4;
/* put digits in msg */
OVERLAY.dq = 0;
last = (addr.gt.nr_of_digits/2) + (addr.gt.nr_of_digits%2);
for (int i= 0; i < last; i++)
{
OVERLAY.db[0] = msg[pdu_index];
/* get digit N + 1 and digit N out from msg */
addr.gt.digits[(2*i)+1] = (uint8_t) OVERLAY.db[0] / 16;
addr.gt.digits[(2*i)] = (uint8_t) OVERLAY.db[0] % 16;
pdu_index++;
}
/* end of Global Title */
/* set pdu_index onto next following tag of sua msg */
pdu_index = next_tag_pdu_idx;
if (par_len >= addr_par_len)
par_len -= addr_par_len; // adjust remaining parameter length
else
par_len = 0;
break;
case 0x8002 :
/* SS7 Point code , length 8 bytes */
if (addr_par_len == 8) {
/* Fill in point code address parameters */
addr.pc_pres = TRUE;
pdu_index += 4;
for (int i = 0; i < 4; i++)
OVERLAY.db[3-i] = msg[pdu_index + i];
addr.pc = OVERLAY.dq;
pdu_index += 4; // next tag
par_len -= 8; // adjust remaining parameter length
}
else {
/* Signal error : invalid point code parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid point code length";
return FALSE;
}
break;
case 0x8003 :
/* SSN parameter, length 8 bytes */
if (addr_par_len == 8) {
pdu_index += 4;
for (int i = 0; i < 4; i++)
OVERLAY.db[i] = msg[pdu_index + i];
addr_par_val = ntohl(OVERLAY.dq);
if (addr_par_val <= 255)
addr.ssn = addr_par_val;
else
addr.ssn = 0;
pdu_index += 4; // next tag
par_len -= 8; // adjust remaining parameter length
}
else {
/* Signal error : invalid address parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid SSN length";
return FALSE;
}
break;
case 0x8004 :
/* IPv4 address, length 8 bytes */
if (addr_par_len == 8) {
/* Fill in IP address parameters */
addr.ip_addr_pres = TRUE;
addr.ip_addr_type = ip_v4;
pdu_index += 4;
for (int i = 0; i < 4; i++)
OVERLAY.db[i] = msg[pdu_index + i];
addr.ip_addr.ipv4.sin_addr.s_addr = OVERLAY.dq;
pdu_index += 4; // next tag
par_len -= 8; // adjust remaining parameter length
}
else {
/* Signal error : invalid address parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid IPv4 address length";
return FALSE;
}
break;
case 0x8005 :
/* Hostname, variable length */
addr_par_len += (4 - (addr_par_len % 4)) % 4; // don't forget padding bytes
addr.hostname_pres = TRUE;
next_tag_pdu_idx = pdu_index + addr_par_len; // next tag
j = 0;
numchar = 0;
// resize the string to receive the hostname in
addr.hostname.resize(addr_par_len - 6);
// get length of first label
pdu_index += 4;
OVERLAY.dq = 0;
OVERLAY.db[0] = msg[pdu_index];
numchar = uint8_t(OVERLAY.db[0]);
//cout << "numchar = " << numchar << ", " << msg[pdu_index] << "\n";
pdu_index++; // go to first char of label
look_for_next_label = (numchar != 0) &&
( pdu_index < next_tag_pdu_idx);
while (look_for_next_label) {
// copy contents of label into the string
for (unsigned int i = 0; i < numchar; i++){
OVERLAY.db[0] = msg[pdu_index + i];
addr.hostname[j] = OVERLAY.db[0];
j++;
}
pdu_index += (numchar); // next label length field ?
// get length of next label
OVERLAY.db[0] = msg[pdu_index];
numchar = uint8_t(OVERLAY.db[0]);
//cout << "numchar = " << numchar << ", j = " << j <<"\n";
if (numchar != 0){
addr.hostname[j]= '.';
pdu_index++; // go to first char of label
j++;
}
/* else end of name */
look_for_next_label = (numchar != 0) &&
( pdu_index < next_tag_pdu_idx);
}
if (par_len >= addr_par_len)
par_len -= addr_par_len; // adjust remaining parameter length
else
par_len = 0;
/* set pdu_index onto next following tag of sua msg */
pdu_index = next_tag_pdu_idx;
break;
case 0x8006 :
/* IPv6 address, length 20 bytes */
if (addr_par_len == 20) {
/* Fill in IP address parameters */
addr.ip_addr_pres = TRUE;
addr.ip_addr_type = ip_v6;
pdu_index += 4;
pdu_c = (char*) &addr.ip_addr.ipv6.sin6_addr.s6_addr;
for (int i = 0; i < 16; i++) {
*pdu_c = msg[pdu_index + i];
pdu_c++;
}
pdu_index += 16; // next tag
par_len -= 20; // adjust remaining parameter length
}
else {
/* Signal error : invalid address parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid IPv6 address length";
return FALSE;
}
break;
default : {
/* Jump over this unknown address parameter */
addr_par_len += (4 - (addr_par_len % 4)) % 4; // don't forget padding bytes
pdu_index += addr_par_len; // next tag
if (par_len >= addr_par_len)
par_len -= addr_par_len; // adjust remaining parameter length
else
par_len = 0;
}
} // End switch address parameter tag
}
else {
/* Signal error : invalid address parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Address parameter length overflow";
return FALSE;
} // End check valid address parameter length
} //End while address parameters present
}
else {
/* Signal error : address parameters missing */
SYNTAX_ERR.msg_index = pdu_index + 4;
SYNTAX_ERR.error_text = "Decoding : Mandatory address parameters missing";
return FALSE;
}
/* Address parameter check */
/* An SSN different from "unknown" (0) and an IP address must be present */
if (addr.ssn == 0) {
/* Signal error : unknown SSN */
SYNTAX_ERR.error_text = "Decoding : SSN missing or unknown";
return FALSE;
}
if (!addr.ip_addr_pres) {
/* Signal error : missing IP address */
//SYNTAX_ERR.error_text = "Decoding : IP address missing";
//return FALSE;
}
return TRUE;
}
boolean decode_src_addr (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
boolean no_error = TRUE;
/* Clear source address */
prim.source_addr.rout_ind = ri_reserved0;
prim.source_addr.ssn_incl = FALSE;
prim.source_addr.gt_incl = FALSE;
prim.source_addr.pc_incl = FALSE;
prim.source_addr.pc_pres = FALSE;
prim.source_addr.ip_addr_pres = FALSE;
prim.source_addr.gt_pres = FALSE;
prim.source_addr.hostname_pres = FALSE;
/* Decode source address */
no_error = decode_addr (prim.source_addr, msg, pdu_index);
if (no_error)
prim.source_addr_pres = TRUE;
return no_error;
}
boolean decode_dest_addr (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
boolean no_error = TRUE;
/* Clear destination address */
prim.dest_addr.rout_ind = ri_reserved0;
prim.dest_addr.ssn_incl = FALSE;
prim.dest_addr.gt_incl = FALSE;
prim.dest_addr.pc_incl = FALSE;
prim.dest_addr.pc_pres = FALSE;
prim.dest_addr.ip_addr_pres = FALSE;
prim.dest_addr.gt_pres = FALSE;
prim.dest_addr.hostname_pres = FALSE;
/* Decode destination address */
no_error = decode_addr (prim.dest_addr, msg, pdu_index);
if (no_error)
prim.dest_addr_pres = TRUE;
return no_error;
}
boolean decode_source_ref (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode source reference */
prim.source_ref_pres = TRUE;
pdu_index += 4;
for (int i = 0; i < 4; i++) {
OVERLAY.db[i] = msg[pdu_index + i];
}
prim.source_ref = ntohl(OVERLAY.dq);
pdu_index += 4; // Next tag
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Source Reference length";
return FALSE;
}
}
boolean decode_dest_ref (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode destination reference */
prim.dest_ref_pres = TRUE;
pdu_index += 4;
for (int i = 0; i < 4; i++) {
OVERLAY.db[i] = msg[pdu_index + i];
}
prim.dest_ref = ntohl(OVERLAY.dq);
pdu_index += 4; // Next tag
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Destination Reference length";
return FALSE;
}
}
boolean decode_SCCP_cause (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode SCCP cause */
pdu_index += 6;
/* Check cause type within range */
OVERLAY.db[2] = msg[pdu_index];
if ((OVERLAY.db[2] > uint8_t(ctp_reserved0)) && (OVERLAY.db[2] < uint8_t(ctp_max))) {
prim.SCCP_cause.cause_type = SCCP_cause_type(OVERLAY.db[2]);
prim.SCCP_cause.cause_value = msg[pdu_index + 1];
pdu_index += 2; // Next tag
prim.SCCP_cause_pres = TRUE;
return TRUE;
}
else {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause type";
return FALSE;
}
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause length";
return FALSE;
}
}
boolean decode_seq_nr (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode sequence number */
pdu_index += 6;
/* Clear sequence number, only interpret more data flag */
prim.seq_nr.sent_seq_nr = 0;
prim.seq_nr.rcvd_seq_nr = 0;
prim.seq_nr.more_data = ((msg[pdu_index] & 0x01) != 0);
pdu_index += 2; // Next tag
prim.seq_nr_pres = TRUE;
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Sequence Number length";
return FALSE;
}
}
boolean decode_asp_cap (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode ASP capabilities */
pdu_index += 6;
/* Get supported protocol classes, at least protocol class 0 must be supported */
prim.asp_cap.cl0_supp = (msg[pdu_index] && 0x01);
prim.asp_cap.cl1_supp = (msg[pdu_index] && 0x02);
prim.asp_cap.cl2_supp = (msg[pdu_index] && 0x04);
prim.asp_cap.cl3_supp = (msg[pdu_index] && 0x08);
if (!prim.asp_cap.cl0_supp) {
/* Signal error : basic protocol class not supported */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : No support of protocol class 0";
return FALSE;
}
pdu_index++;
/* Check whether interworking type allowed */
if (uint8_t(msg[pdu_index]) < uint8_t(iw_max)) {
prim.asp_cap.interworking = Sua_interworking_type(msg[pdu_index]);
}
else {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Invalid Interworking type";
return FALSE;
}
pdu_index++; // next tag
prim.asp_cap_pres = TRUE;
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid ASP capabilities length";
return FALSE;
}
}
boolean decode_seq_ctrl (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode sequence control */
prim.seq_control_pres = TRUE;
pdu_index += 4;
for (int i = 0; i < 4; i++) {
OVERLAY.db[i] = msg[pdu_index + i];
}
prim.seq_control = ntohl(OVERLAY.dq);
pdu_index += 4; // Next tag
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Sequence Control length";
return FALSE;
}
}
boolean decode_importance (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode importance */
prim.importance = uint8_t(msg[pdu_index + 7]);
/* Check whether importance within range */
if (prim.importance > 7) {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index + 7;
SYNTAX_ERR.error_text = "Decoding : Invalid Importance value";
return FALSE;
}
pdu_index += 8; // next tag
prim.importance_pres = TRUE;
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Importance length";
return FALSE;
}
}
boolean decode_prot_class (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode protocol class */
uint8_t prot_cl = uint8_t(msg[pdu_index + 7]);
prim.prot_class.return_option = ((prot_cl & 0x80) != 0);
prot_cl &= 0x03;
prim.prot_class.pcl = Sua_protocol_class(prot_cl);
pdu_index += 8; // next tag
prim.prot_class_pres = TRUE;
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Protocol Class length";
return FALSE;
}
}
boolean decode_segmentation (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode segmentation */
uint8_t first_rem = uint8_t(msg[pdu_index + 4]);
prim.segm.first = ((first_rem & 0x80) != 0);
first_rem &= 0x0F;
prim.segm.remain = first_rem;
OVERLAY.db[0] = 0;
OVERLAY.db[1] = uint8_t(msg[pdu_index + 5]);
OVERLAY.db[2] = uint8_t(msg[pdu_index + 6]);
OVERLAY.db[3] = uint8_t(msg[pdu_index + 7]);
prim.segm.segm_ref = ntohl(OVERLAY.dq);
pdu_index += 8; // next tag
prim.segm_pres = TRUE;
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid Segmentation length";
return FALSE;
}
}
boolean decode_TID_label (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
uint16_t max_label = 2;
if (par_len == 8) {
/* Decode TID label */
prim.TID_label.start = uint8_t(msg[pdu_index + 4]);
prim.TID_label.end = uint8_t(msg[pdu_index + 5]);
OVERLAY.db[2] = uint8_t(msg[pdu_index + 6]);
OVERLAY.db[3] = uint8_t(msg[pdu_index + 7]);
prim.TID_label.label_value = ntohs(OVERLAY.dw[1]);
/* Check values */
if ((prim.TID_label.start < 32) && (prim.TID_label.start >= prim.TID_label.end)
&& ((prim.TID_label.start - prim.TID_label.end) < 16)) {
for (int i = 0; i < (prim.TID_label.start - prim.TID_label.end); i++)
max_label = max_label * 2;
if (prim.TID_label.label_value >= max_label) {
/* Signal error : paramater syntax error */
SYNTAX_ERR.msg_index = pdu_index + 6;
SYNTAX_ERR.error_text = "Decoding : Invalid TID label";
return FALSE;
}
}
else {
/* Signal error : parameter syntax error */
SYNTAX_ERR.msg_index = pdu_index + 4;
SYNTAX_ERR.error_text = "Decoding : Invalid TID label position or length";
return FALSE;
}
pdu_index += 8; // next tag
prim.TID_label_pres = TRUE;
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid TID label length";
return FALSE;
}
}
boolean decode_DRN_label (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
uint16_t max_label = 2;
if (par_len == 8) {
/* Decode DRN label */
prim.DRN_label.start = uint8_t(msg[pdu_index + 4]);
prim.DRN_label.end = uint8_t(msg[pdu_index + 5]);
OVERLAY.db[2] = uint8_t(msg[pdu_index + 6]);
OVERLAY.db[3] = uint8_t(msg[pdu_index + 7]);
prim.DRN_label.label_value = ntohs(OVERLAY.dw[1]);
/* Check values */
if ((prim.DRN_label.start < 32) && (prim.DRN_label.start >= prim.DRN_label.end)
&& ((prim.DRN_label.start - prim.DRN_label.end) < 16)) {
for (int i = 0; i < (prim.DRN_label.start - prim.DRN_label.end); i++)
max_label = max_label * 2;
if (prim.DRN_label.label_value >= max_label) {
/* Signal error : paramater syntax error */
SYNTAX_ERR.msg_index = pdu_index + 6;
SYNTAX_ERR.error_text = "Decoding : Invalid DRN label";
return FALSE;
}
}
else {
/* Signal error : parameter syntax error */
SYNTAX_ERR.msg_index = pdu_index + 4;
SYNTAX_ERR.error_text = "Decoding : Invalid DRN label position or length";
return FALSE;
}
pdu_index += 8; // next tag
prim.DRN_label_pres = TRUE;
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid DRN label length";
return FALSE;
}
}
boolean decode_SSN (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode SSN */
prim.ssnm_parm.SSN_pres = TRUE;
pdu_index += 4;
for (int i = 0; i < 4; i++) {
OVERLAY.db[i] = msg[pdu_index + i];
}
prim.ssnm_parm.SSN = ntohl(OVERLAY.db[3]);
pdu_index += 4; // Next tag
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid SSN length";
return FALSE;
}
}
boolean decode_SMI (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode SMI */
prim.ssnm_parm.SMI_pres = TRUE;
pdu_index += 4;
for (int i = 0; i < 4; i++) {
OVERLAY.db[i] = msg[pdu_index + i];
}
prim.ssnm_parm.SMI = ntohl(OVERLAY.db[3]);
pdu_index += 4; // Next tag
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid SMI length";
return FALSE;
}
}
boolean decode_cong_lvl (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) {
/* The parameter length should be 8 bytes */
OVERLAY.db[0] = msg[pdu_index + 2];
OVERLAY.db[1] = msg[pdu_index + 3];
uint16_t par_len = ntohs(OVERLAY.dw[0]);
if (par_len == 8) {
/* Decode congestion level */
prim.ssnm_parm.cong_lvl_pres = TRUE;
pdu_index += 4;
for (int i = 0; i < 4; i++) {
OVERLAY.db[i] = msg[pdu_index + i];
}
prim.ssnm_parm.cong_lvl = ntohl(OVERLAY.db[3]);
pdu_index += 4; // Next tag
return TRUE;
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Invalid congestion level length";
return FALSE;
}
}
/* 2.2 Message decoding procedures */
/* 2.2.2 Signalling Network Management messages */
boolean decode_ssnm_duna_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing context parameter";
return FALSE;
}
break;
case 0x0012 :
if (!prim.ssnm_parm.aff_pc_pres)
no_error = decode_aff_pc (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate affected pointcode parameter";
return FALSE;
}
break;
case 0x8003:
if (!prim.ssnm_parm.SSN_pres)
no_error = decode_SSN (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SSN parameter";
return FALSE;
}
break;
case 0x010c:
if (!prim.SCCP_cause_pres)
no_error = decode_SCCP_cause (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP cause parameter";
return FALSE;
}
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ssnm_dava_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing context parameter";
return FALSE;
}
break;
case 0x0012 :
if (!prim.ssnm_parm.aff_pc_pres)
no_error = decode_aff_pc (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate affected pointcode parameter";
return FALSE;
}
break;
case 0x8003:
if (!prim.ssnm_parm.SSN_pres)
no_error = decode_SSN (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SSN parameter";
return FALSE;
}
break;
case 0x010c:
if (!prim.SCCP_cause_pres)
no_error = decode_SCCP_cause (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP cause parameter";
return FALSE;
}
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ssnm_daud_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing context parameter";
return FALSE;
}
break;
case 0x0012 :
if (!prim.ssnm_parm.aff_pc_pres)
no_error = decode_aff_pc (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate affected pointcode parameter";
return FALSE;
}
break;
case 0x8003:
if (!prim.ssnm_parm.SSN_pres)
no_error = decode_SSN (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SSN parameter";
return FALSE;
}
break;
case 0x010c:
if (!prim.SCCP_cause_pres)
no_error = decode_SCCP_cause (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP cause parameter";
return FALSE;
}
break;
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ssnm_scon_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing context parameter";
return FALSE;
}
break;
case 0x0012 :
if (!prim.ssnm_parm.aff_pc_pres)
no_error = decode_aff_pc (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate affected pointcode parameter";
return FALSE;
}
break;
case 0x8003:
if (!prim.ssnm_parm.SSN_pres)
no_error = decode_SSN (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SSN parameter";
return FALSE;
}
break;
case 0x0118:
if (!prim.ssnm_parm.cong_lvl_pres)
no_error = decode_cong_lvl (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP cause parameter";
return FALSE;
}
break;
case 0x0112:
if (!prim.ssnm_parm.SMI_pres)
no_error = decode_SMI (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP cause parameter";
return FALSE;
}
break;
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ssnm_dupu_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing context parameter";
return FALSE;
}
break;
case 0x0012 :
if (!prim.ssnm_parm.aff_pc_pres)
no_error = decode_aff_pc (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate affected pointcode parameter";
return FALSE;
}
break;
case 0x010c:
if (!prim.SCCP_cause_pres)
no_error = decode_SCCP_cause (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP cause parameter";
return FALSE;
}
break;
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ssnm_drst_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing context parameter";
return FALSE;
}
break;
case 0x0012 :
if (!prim.ssnm_parm.aff_pc_pres)
no_error = decode_aff_pc (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate affected pointcode parameter";
return FALSE;
}
break;
case 0x8003:
if (!prim.ssnm_parm.SSN_pres)
no_error = decode_SSN (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SSN parameter";
return FALSE;
}
break;
case 0x0112:
if (!prim.ssnm_parm.SMI_pres)
no_error = decode_SMI (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SMI parameter";
return FALSE;
}
break;
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
/* 2.2.3 ASP Server Management messages */
boolean decode_ASP_up_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ASP_down_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ASP_beat_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0009 :
if (!prim.hb_data_pres)
no_error = decode_hb_data (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Heartbeat data parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ASP_up_ack_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ASP_down_ack_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ASP_beat_ack_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0009 :
if (!prim.hb_data_pres)
no_error = decode_hb_data (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Heartbeat data parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
/* 2.2.4 ASP Traffic Management messages */
boolean decode_ASP_act_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x000B :
if (!prim.traf_mode_pres)
no_error = decode_traf_mode (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Traffic Mode type parameter";
return FALSE;
}
break;
case 0x0119 :
if (!prim.TID_label_pres)
no_error = decode_TID_label (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate TID label parameter";
return FALSE;
}
break;
case 0x011A :
if (!prim.DRN_label_pres)
no_error = decode_DRN_label (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate DRN label parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ASP_inact_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ASP_act_ack_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x000B :
if (!prim.traf_mode_pres)
no_error = decode_traf_mode (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Traffic Mode type parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
boolean decode_ASP_inact_ack_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8;
/* Check whether further parameters are present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0004 :
if (!prim.info_pres)
no_error = decode_info (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter";
return FALSE;
}
break;
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End parameter length check
} // End while parameters present
/* No checks for mandatory parameters are needed */
return no_error;
}
/* 2.2.7 Connectionless messages */
boolean decode_cl_data_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8; // Start with first tag
/* Check whether a further parameter is present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x010b :
if (!prim.data_pres)
no_error = decode_data (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter";
return FALSE;
}
break;
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x0101 :
if (!prim.hop_count_pres)
no_error = decode_hop_count (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Hop Counter parameter";
return FALSE;
}
break;
case 0x0102 :
if (!prim.source_addr_pres)
no_error = decode_src_addr (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Source Address parameter";
return FALSE;
}
break;
case 0x0103 :
if (!prim.dest_addr_pres)
no_error = decode_dest_addr (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Address parameter";
return FALSE;
}
break;
case 0x0116 :
if (!prim.seq_control_pres)
no_error = decode_seq_ctrl (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Sequence Control parameter";
return FALSE;
}
break;
case 0x0113 :
if (!prim.importance_pres)
no_error = decode_importance (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter";
return FALSE;
}
break;
case 0x0115 :
if (!prim.prot_class_pres)
no_error = decode_prot_class (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Protocol Class parameter";
return FALSE;
}
if (no_error && (prim.prot_class.pcl != prot_class_0) && (prim.prot_class.pcl != prot_class_1)) {
/* Signal error : invalid protocol class */
SYNTAX_ERR.msg_index = pdu_index - 1;
SYNTAX_ERR.error_text = "Decoding : Invalid protocol class for connectionless msg";
return FALSE;
}
break;
case 0x0117 :
if (!prim.segm_pres)
no_error = decode_segmentation (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Segmentation parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End check valid parameter length
} // End while parameters present
/* Start checks for mandatory parameters :
- Protocol class
- Source address
- Destination address
- Sequence control
- Data
The local syntax is filled out unless an error has occurred.
*/
if (no_error && !prim.prot_class_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Protocol Class missing";
return FALSE;
}
if (no_error && !prim.source_addr_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Source Address missing";
return FALSE;
}
if (no_error && !prim.dest_addr_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Destination Address missing";
return FALSE;
}
if (no_error && !prim.seq_control_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Sequence Control missing";
return FALSE;
}
if (no_error && !prim.data_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Data missing";
return FALSE;
}
return no_error;
}
boolean decode_cl_data_resp_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8; // Start with first tag
/* Check whether a further parameter is present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x010b :
if (!prim.data_pres)
no_error = decode_data (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter";
return FALSE;
}
break;
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x0101 :
if (!prim.hop_count_pres)
no_error = decode_hop_count (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Hop Counter parameter";
return FALSE;
}
break;
case 0x0102 :
if (!prim.source_addr_pres)
no_error = decode_src_addr(prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Source Address parameter";
return FALSE;
}
break;
case 0x0103 :
if (!prim.dest_addr_pres)
no_error = decode_dest_addr (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Address parameter";
return FALSE;
}
break;
case 0x0106 :
if (!prim.SCCP_cause_pres)
no_error = decode_SCCP_cause (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP Cause parameter";
return FALSE;
}
if (no_error && (prim.SCCP_cause.cause_type != ctp_return_cause)) {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index - 2;
SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause type for connectionless msg";
return FALSE;
}
break;
case 0x0113 :
if (!prim.importance_pres)
no_error = decode_importance (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End check valid parameter length
} // End while parameters present
/* Start checks for mandatory parameters :
- SCCP Cause
- Source address
- Destination address
The local syntax is filled out unless an error has occurred.
*/
if (no_error && !prim.SCCP_cause_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter SCCP Cause missing";
return FALSE;
}
if (no_error && !prim.source_addr_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Source Address missing";
return FALSE;
}
if (no_error && !prim.dest_addr_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Destination Address missing";
return FALSE;
}
return no_error;
}
/* 2.2.8 Connection-oriented messages */
/* Only protocol class 2 messages are supported */
boolean decode_co_conn_req_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8; // Start with first tag
/* Check whether a further parameter is present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x010b :
if (!prim.data_pres)
no_error = decode_data (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter";
return FALSE;
}
break;
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x0101 :
if (!prim.hop_count_pres)
no_error = decode_hop_count (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Hop Counter parameter";
return FALSE;
}
break;
case 0x0102 :
if (!prim.source_addr_pres)
no_error = decode_src_addr (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Source Address parameter";
return FALSE;
}
break;
case 0x0103 :
if (!prim.dest_addr_pres)
no_error = decode_dest_addr (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Address parameter";
return FALSE;
}
break;
case 0x0104 :
if (!prim.source_ref_pres)
no_error = decode_source_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Source Reference parameter";
return FALSE;
}
break;
case 0x0113 :
if (!prim.importance_pres)
no_error = decode_importance (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter";
return FALSE;
}
break;
case 0x0115 :
if (!prim.prot_class_pres)
no_error = decode_prot_class (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Protocol Class parameter";
return FALSE;
}
prim.prot_class.return_option = FALSE;
if (no_error && (prim.prot_class.pcl != prot_class_2) && (prim.prot_class.pcl != prot_class_3)) {
/* Signal error : invalid protocol class */
SYNTAX_ERR.msg_index = pdu_index - 1;
SYNTAX_ERR.error_text = "Decoding : Invalid protocol class for connection-oriented msg";
return FALSE;
}
break;
case 0x0116 :
if (!prim.seq_control_pres)
no_error = decode_seq_ctrl (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Sequence ccontrol parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End check valid parameter length
} // End while parameters present
/* Start checks for mandatory parameters :
- Protocol class
- Source reference
- Destination address
The local syntax is filled out unless an error has occurred.
*/
if (no_error && !prim.prot_class_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Protocol Class missing";
return FALSE;
}
if (no_error && !prim.source_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Source Reference missing";
return FALSE;
}
if (no_error && !prim.dest_addr_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Destination Address missing";
return FALSE;
}
return no_error;
}
boolean decode_co_conn_ack_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8; // Start with first tag
/* Check whether a further parameter is present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x010b :
if (!prim.data_pres)
no_error = decode_data (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter";
return FALSE;
}
break;
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x0103 :
if (!prim.dest_addr_pres)
no_error = decode_dest_addr (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Address parameter";
return FALSE;
}
break;
case 0x0104 :
if (!prim.source_ref_pres)
no_error = decode_source_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Source Reference parameter";
return FALSE;
}
break;
case 0x0105 :
if (!prim.dest_ref_pres)
no_error = decode_dest_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter";
return FALSE;
}
break;
case 0x0113 :
if (!prim.importance_pres)
no_error = decode_importance (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter";
return FALSE;
}
break;
case 0x0115 :
if (!prim.prot_class_pres)
no_error = decode_prot_class (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Protocol Class parameter";
return FALSE;
}
prim.prot_class.return_option = FALSE;
if (no_error && (prim.prot_class.pcl != prot_class_2) && (prim.prot_class.pcl != prot_class_3)) {
/* Signal error : invalid protocol class */
SYNTAX_ERR.msg_index = pdu_index - 1;
SYNTAX_ERR.error_text = "Decoding : Invalid protocol class for connection-oriented msg";
return FALSE;
}
break;
case 0x0116 :
if (!prim.seq_control_pres)
no_error = decode_seq_ctrl (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Sequence ccontrol parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End check valid parameter length
} // End while parameters present
/* Start checks for mandatory parameters :
- Protocol class
- Destination reference
- Source reference
The local syntax is filled out unless an error has occurred.
*/
if (no_error && !prim.prot_class_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Protocol Class missing";
return FALSE;
}
if (no_error && !prim.dest_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing";
return FALSE;
}
if (no_error && !prim.source_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Source Reference missing";
return FALSE;
}
return no_error;
}
boolean decode_co_conn_ref_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8; // Start with first tag
/* Check whether a further parameter is present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x010b :
if (!prim.data_pres)
no_error = decode_data (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter";
return FALSE;
}
break;
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x0103 :
if (!prim.dest_addr_pres)
no_error = decode_dest_addr (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Address parameter";
return FALSE;
}
break;
case 0x0105 :
if (!prim.dest_ref_pres)
no_error = decode_dest_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter";
return FALSE;
}
break;
case 0x0106 :
if (!prim.SCCP_cause_pres)
no_error = decode_SCCP_cause (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP Cause parameter";
return FALSE;
}
if (no_error && (prim.SCCP_cause.cause_type != ctp_refusal_cause)) {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index - 2;
SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause type for connection refused msg";
return FALSE;
}
break;
case 0x0113 :
if (!prim.importance_pres)
no_error = decode_importance (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End check valid parameter length
} // End while parameters present
/* Start checks for mandatory parameters :
- Destination reference
- SCCP cause
The local syntax is filled out unless an error has occurred.
*/
if (no_error && !prim.dest_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing";
return FALSE;
}
if (no_error && !prim.SCCP_cause_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter SCCP Cause missing";
return FALSE;
}
return no_error;
}
boolean decode_co_rel_req_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8; // Start with first tag
/* Check whether a further parameter is present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x010b :
if (!prim.data_pres)
no_error = decode_data (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter";
return FALSE;
}
break;
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x0104 :
if (!prim.source_ref_pres)
no_error = decode_source_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Source Reference parameter";
return FALSE;
}
break;
case 0x0105 :
if (!prim.dest_ref_pres)
no_error = decode_dest_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter";
return FALSE;
}
break;
case 0x0106 :
if (!prim.SCCP_cause_pres)
no_error = decode_SCCP_cause (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP Cause parameter";
return FALSE;
}
if (no_error && (prim.SCCP_cause.cause_type != ctp_release_cause)) {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index - 2;
SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause type for release req msg";
return FALSE;
}
break;
case 0x0113 :
if (!prim.importance_pres)
no_error = decode_importance (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End check valid parameter length
} // End while parameters present
/* Start checks for mandatory parameters :
- Destination reference
- Source reference
- SCCP cause
The local syntax is filled out unless an error has occurred.
*/
if (no_error && !prim.dest_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing";
return FALSE;
}
if (no_error && !prim.source_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Source Reference missing";
return FALSE;
}
if (no_error && !prim.SCCP_cause_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter SCCP Cause missing";
return FALSE;
}
return no_error;
}
boolean decode_co_rel_conf_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8; // Start with first tag
/* Check whether a further parameter is present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x0104 :
if (!prim.source_ref_pres)
no_error = decode_source_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Source Reference parameter";
return FALSE;
}
break;
case 0x0105 :
if (!prim.dest_ref_pres)
no_error = decode_dest_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter";
return FALSE;
}
break;
case 0x0113 :
if (!prim.importance_pres)
no_error = decode_importance (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End check valid parameter length
} // End while parameters present
/* Start checks for mandatory parameters :
- Destination reference
- Source reference
The local syntax is filled out unless an error has occurred.
*/
if (no_error && !prim.dest_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing";
return FALSE;
}
if (no_error && !prim.source_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Source Reference missing";
return FALSE;
}
return no_error;
}
boolean decode_co_data_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8; // Start with first tag
/* Check whether a further parameter is present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x010b :
if (!prim.data_pres)
no_error = decode_data (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter";
return FALSE;
}
break;
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x0105 :
if (!prim.dest_ref_pres)
no_error = decode_dest_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter";
return FALSE;
}
break;
case 0x0107 :
if (!prim.seq_nr_pres)
no_error = decode_seq_nr (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Sequence Number parameter";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End check valid parameter length
} // End while parameters present
/* Start checks for mandatory parameters :
- Sequence number
- Destination reference
- Data
The local syntax is filled out unless an error has occurred.
*/
if (no_error && !prim.seq_nr_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Sequence Number missing";
return FALSE;
}
if (no_error && !prim.dest_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing";
return FALSE;
}
if (no_error && !prim.data_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Data missing";
return FALSE;
}
return no_error;
}
boolean decode_co_err_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8; // Start with first tag
/* Check whether a further parameter is present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x0105 :
if (!prim.dest_ref_pres)
no_error = decode_dest_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter";
return FALSE;
}
break;
case 0x0106 :
if (!prim.SCCP_cause_pres)
no_error = decode_SCCP_cause (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP Cause parameter";
return FALSE;
}
if (no_error && (prim.SCCP_cause.cause_type != ctp_error_cause)) {
/* Signal error : invalid parameter value */
SYNTAX_ERR.msg_index = pdu_index - 2;
SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause type for error msg";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End check valid parameter length
} // End while parameters present
/* Start checks for mandatory parameters :
- Destination reference
- SCCP cause
The local syntax is filled out unless an error has occurred.
*/
if (no_error && !prim.dest_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing";
return FALSE;
}
if (no_error && !prim.SCCP_cause_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter SCCP Cause missing";
return FALSE;
}
return no_error;
}
boolean decode_co_it_msg (Sua_primitive_struct& prim, string& msg) {
boolean no_error = TRUE;
uint32_t msg_len = ntohl(OVERLAY.dq);
unsigned int pdu_index = 8; // Start with first tag
/* Check whether a further parameter is present, at least tag & length fields must be there */
uint16_t par_tag, par_len;
while ((msg_len >= (pdu_index + 3)) && no_error) {
/* Evaluate parameter length */
OVERLAY.db[2] = msg[pdu_index + 2];
OVERLAY.db[3] = msg[pdu_index + 3];
par_len = ntohs(OVERLAY.dw[1]);
if ((pdu_index + par_len) <= msg_len) {
/* Evaluate parameter tag and call corresponding decoding routine or jump over it */
OVERLAY.db[0] = msg[pdu_index];
OVERLAY.db[1] = msg[pdu_index + 1];
par_tag = ntohs(OVERLAY.dw[0]);
switch (par_tag) {
case 0x0006 :
if (!prim.rout_con_pres)
no_error = decode_rout_con (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter";
return FALSE;
}
break;
case 0x0104 :
if (!prim.source_ref_pres)
no_error = decode_source_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Source Reference parameter";
return FALSE;
}
break;
case 0x0105 :
if (!prim.dest_ref_pres)
no_error = decode_dest_ref (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter";
return FALSE;
}
break;
case 0x0115 :
if (!prim.prot_class_pres)
no_error = decode_prot_class (prim, msg, pdu_index);
else {
/* Signal error : duplicate parameter */
SYNTAX_ERR.msg_index = pdu_index;
SYNTAX_ERR.error_text = "Decoding : Duplicate Protocol Class parameter";
return FALSE;
}
prim.prot_class.return_option = FALSE;
if (no_error && (prim.prot_class.pcl != prot_class_2) && (prim.prot_class.pcl != prot_class_3)) {
/* Signal error : invalid protocol class */
SYNTAX_ERR.msg_index = pdu_index - 1;
SYNTAX_ERR.error_text = "Decoding : Invalid protocol class for connection-oriented msg";
return FALSE;
}
break;
default : {
/* Jump over this totally uninteresting parameter to next double word position */
par_len += (4 - (par_len % 4)) % 4;
pdu_index += par_len;
}
} // End switch parameter tag
}
else {
/* Signal error : invalid parameter length */
SYNTAX_ERR.msg_index = pdu_index + 2;
SYNTAX_ERR.error_text = "Decoding : Parameter length overflow";
return FALSE;
} // End check valid parameter length
} // End while parameters present
/* Start checks for mandatory parameters :
- Protocol class
- Destination reference
- Source reference
The local syntax is filled out unless an error has occurred.
*/
if (no_error && !prim.prot_class_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Protocol Class missing";
return FALSE;
}
if (no_error && !prim.dest_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing";
return FALSE;
}
if (no_error && !prim.source_ref_pres) {
/* Signal error : mandatory parameter missing */
SYNTAX_ERR.error_text = "Decoding : Parameter Source Reference missing";
return FALSE;
}
return no_error;
}
/* 2.3 Sua decoding method */
Sua_syntax_error_struct Sua_container::sua_decode () {
/* Syntax Error struct initialization */
SYNTAX_ERR.msg_index = 0;
SYNTAX_ERR.no_error = TRUE;
SYNTAX_ERR.error_text = "Decoding no error";
/* Decoding variables */
uint8_t pdu_byte;
boolean no_error = TRUE;
/* Initialize primitive container to clean up old mess */
this->sua_init ();
/* Start decoding message header, at least 8 bytes must be present */
uint32_t msg_len;
if (sua_msg.size() >= 8) {
for (int i = 0; i < 4; i++)
OVERLAY.db[i] = sua_msg[i + 4];
msg_len = ntohl(OVERLAY.dq);
}
else
msg_len = 0;
if ((msg_len >= 8) && (msg_len <= sua_msg.size())) {
/* Check Sua version, only version 1 is supported */
pdu_byte = uint8_t(sua_msg[0]);
if (pdu_byte == uint8_t(Sua_version1)) {
sua_prim.hdr_version = Sua_version1;
/* Check message class and type, with call to corresponding msg decoding procedure */
pdu_byte = uint8_t(sua_msg[2]);
switch (pdu_byte) {
case uint8_t(sua_ssnm) :
sua_prim.hdr_msg_class = sua_ssnm;
/* Check signalling network management msg type */
pdu_byte = uint8_t(sua_msg[3]);
switch (pdu_byte) {
case uint8_t(ssnm_duna) :
sua_prim.hdr_msg_type.ssnm = ssnm_duna;
no_error = decode_ssnm_duna_msg (sua_prim, sua_msg);
break;
case uint8_t(ssnm_dava) :
sua_prim.hdr_msg_type.ssnm = ssnm_dava;
no_error = decode_ssnm_dava_msg (sua_prim, sua_msg);
break;
case uint8_t(ssnm_daud) :
sua_prim.hdr_msg_type.ssnm = ssnm_daud;
no_error = decode_ssnm_daud_msg (sua_prim, sua_msg);
break;
case uint8_t(ssnm_scon) :
sua_prim.hdr_msg_type.ssnm = ssnm_scon;
no_error = decode_ssnm_scon_msg (sua_prim, sua_msg);
break;
case uint8_t(ssnm_dupu) :
sua_prim.hdr_msg_type.ssnm = ssnm_dupu;
no_error = decode_ssnm_dupu_msg (sua_prim, sua_msg);
break;
case uint8_t(ssnm_drst) :
sua_prim.hdr_msg_type.ssnm = ssnm_drst;
no_error = decode_ssnm_drst_msg (sua_prim, sua_msg);
break;
default : {
sua_prim.hdr_msg_type.ssnm = ssnm_reserved0;
/* Signal error : invalid message type */
SYNTAX_ERR.msg_index = 3;
SYNTAX_ERR.error_text = "Decoding : Invalid Signalling Network Management message type";
no_error = FALSE;
}
} // End switch ssnm msg
break;
case uint8_t(sua_aspsm) :
sua_prim.hdr_msg_class = sua_aspsm;
/* Check ASP server management msg type */
pdu_byte = uint8_t(sua_msg[3]);
switch (pdu_byte) {
case uint8_t(aspsm_up) :
sua_prim.hdr_msg_type.aspsm = aspsm_up;
no_error = decode_ASP_up_msg (sua_prim, sua_msg);
break;
case uint8_t(aspsm_down) :
sua_prim.hdr_msg_type.aspsm = aspsm_down;
no_error = decode_ASP_down_msg (sua_prim, sua_msg);
break;
case uint8_t(aspsm_beat) :
sua_prim.hdr_msg_type.aspsm = aspsm_beat;
no_error = decode_ASP_beat_msg (sua_prim, sua_msg);
break;
case uint8_t(aspsm_up_ack) :
sua_prim.hdr_msg_type.aspsm = aspsm_up_ack;
no_error = decode_ASP_up_ack_msg (sua_prim, sua_msg);
break;
case uint8_t(aspsm_down_ack) :
sua_prim.hdr_msg_type.aspsm = aspsm_down_ack;
no_error = decode_ASP_down_ack_msg (sua_prim, sua_msg);
break;
case uint8_t(aspsm_beat_ack) :
sua_prim.hdr_msg_type.aspsm = aspsm_beat_ack;
no_error = decode_ASP_beat_ack_msg (sua_prim, sua_msg);
break;
default : {
sua_prim.hdr_msg_type.aspsm = aspsm_reserved0;
/* Signal error : invalid message type */
SYNTAX_ERR.msg_index = 3;
SYNTAX_ERR.error_text = "Decoding : Invalid ASP server management message type";
no_error = FALSE;
}
} // End switch aspsm msg
break;
case uint8_t(sua_asptm) :
sua_prim.hdr_msg_class = sua_asptm;
/* Check ASP traffic management msg type */
pdu_byte = uint8_t(sua_msg[3]);
switch (pdu_byte) {
case uint8_t(asptm_act) :
sua_prim.hdr_msg_type.asptm = asptm_act;
no_error = decode_ASP_act_msg (sua_prim, sua_msg);
break;
case uint8_t(asptm_inact) :
sua_prim.hdr_msg_type.asptm = asptm_inact;
no_error = decode_ASP_inact_msg (sua_prim, sua_msg);
break;
case uint8_t(asptm_act_ack) :
sua_prim.hdr_msg_type.asptm = asptm_act_ack;
no_error = decode_ASP_act_ack_msg (sua_prim, sua_msg);
break;
case uint8_t(asptm_inact_ack) :
sua_prim.hdr_msg_type.asptm = asptm_inact_ack;
no_error = decode_ASP_inact_ack_msg (sua_prim, sua_msg);
break;
default : {
sua_prim.hdr_msg_type.asptm = asptm_reserved0;
/* Signal error : invalid message type */
SYNTAX_ERR.msg_index = 3;
SYNTAX_ERR.error_text = "Decoding : Invalid connectionless message type";
no_error = FALSE;
}
} // End switch asptm msg
break;
case uint8_t(sua_cl):
sua_prim.hdr_msg_class = sua_cl;
/* Check connectionless msg type */
pdu_byte = uint8_t(sua_msg[3]);
switch (pdu_byte) {
case uint8_t(cl_data_transfer) :
sua_prim.hdr_msg_type.cl = cl_data_transfer;
no_error = decode_cl_data_msg (sua_prim, sua_msg);
break;
case uint8_t(cl_data_response) :
sua_prim.hdr_msg_type.cl = cl_data_response;
no_error = decode_cl_data_resp_msg (sua_prim, sua_msg);
break;
default : {
sua_prim.hdr_msg_type.cl = cl_reserved0;
/* Signal error : invalid message type */
SYNTAX_ERR.msg_index = 3;
SYNTAX_ERR.error_text = "Decoding : Invalid connectionless message type";
no_error = FALSE;
}
} // End switch cl msg
break;
case uint8_t(sua_co) :
sua_prim.hdr_msg_class = sua_co;
/* Check connection-oriented msg type */
pdu_byte = uint8_t(sua_msg[3]);
switch (pdu_byte) {
case uint8_t(co_core) :
sua_prim.hdr_msg_type.co = co_core;
no_error = decode_co_conn_req_msg (sua_prim, sua_msg);
break;
case uint8_t(co_coak) :
sua_prim.hdr_msg_type.co = co_coak;
no_error = decode_co_conn_ack_msg (sua_prim, sua_msg);
break;
case uint8_t(co_coref) :
sua_prim.hdr_msg_type.co = co_coref;
no_error = decode_co_conn_ref_msg (sua_prim, sua_msg);
break;
case uint8_t(co_relre) :
sua_prim.hdr_msg_type.co = co_relre;
no_error = decode_co_rel_req_msg (sua_prim, sua_msg);
break;
case uint8_t(co_relco) :
sua_prim.hdr_msg_type.co = co_relco;
no_error = decode_co_rel_conf_msg (sua_prim, sua_msg);
break;
case uint8_t(co_data) :
sua_prim.hdr_msg_type.co = co_data;
no_error = decode_co_data_msg (sua_prim, sua_msg);
break;
case uint8_t(co_err) :
sua_prim.hdr_msg_type.co = co_err;
no_error = decode_co_err_msg (sua_prim, sua_msg);
break;
case uint8_t(co_it) :
sua_prim.hdr_msg_type.co = co_it;
no_error = decode_co_it_msg (sua_prim, sua_msg);
break;
default : {
sua_prim.hdr_msg_type.co = co_reserved0;
/* Signal error : invalid message type */
SYNTAX_ERR.msg_index = 3;
SYNTAX_ERR.error_text = "Decoding : Invalid connection-oriented message type";
no_error = FALSE;
}
} // End switch co msg
break;
default : {
/* Signal error : invalid message class */
SYNTAX_ERR.msg_index = 2;
SYNTAX_ERR.error_text = "Decoding : Unknown message class";
no_error = FALSE;
}
} // End msg class switch
}
else {
sua_prim.hdr_version = Sua_unknown;
/* Signal error : invalid Sua version */
SYNTAX_ERR.msg_index = 0;
SYNTAX_ERR.error_text = "Decoding : Invalid Sua version";
no_error = FALSE;
} // Endif version
}
else {
/* Signal error : invalid message length */
SYNTAX_ERR.msg_index = 4;
SYNTAX_ERR.error_text = "Decoding : Invalid message length";
no_error = FALSE;
} // Endif msg length
if (!no_error) {
/* Printout error text */
SYNTAX_ERR.no_error = FALSE;
cout << "Error position = " << SYNTAX_ERR.msg_index << endl;
cout << SYNTAX_ERR.error_text << endl;
}
return SYNTAX_ERR;
}
///:~