/*************************************************************************** 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.1.1.1 2002/02/04 14:30:41 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 #include 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.cong_lvl_pres = FALSE; sua_prim.ASP_id_pres = FALSE; sua_prim.aff_pc_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(0x0003); 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; } } /* 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)) { /* 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){ msg.resize(pdu_index + address.hostname.length() + 2 + 4); 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) { for (i=0; i < (4 - mod_nr); i++) { OVERLAY.dw[0] = htons(0x0000);; 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_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 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 = 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 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.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_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_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; } } /* 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; 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))){ /* 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 not supported, so we jump over it */ 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; 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; } } /* 2.2 Message decoding procedures */ /* 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 0x0003 : 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 : /* tag may change, see SUA v9 */ 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 0x0003 : 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 0x0003 : 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; 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 0x0003 : 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; 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 0x0003 : 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 0x0003 : 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 0x0003 : 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_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; } ///:~