5727 lines
188 KiB
C++
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;
|
|
}
|
|
|
|
|
|
|
|
///:~
|
|
|
|
|
|
|
|
|
|
|
|
|