diff options
author | Harald Welte <laforge@gnumonks.org> | 2010-07-09 20:55:33 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-07-09 20:55:33 +0200 |
commit | 86d1df86c7da9a35004e6a9a326f10b8167c9179 (patch) | |
tree | dbc1d77a33fe77d9e23a66115b899a271d3c5d39 /sualibrary/sua |
import sualibrary-0.1.0 from 2002-02-15
Diffstat (limited to 'sualibrary/sua')
27 files changed, 15655 insertions, 0 deletions
diff --git a/sualibrary/sua/Makefile.am b/sualibrary/sua/Makefile.am new file mode 100644 index 0000000..b7fa555 --- /dev/null +++ b/sualibrary/sua/Makefile.am @@ -0,0 +1,30 @@ +####### kdevelop will overwrite this part!!! (begin)########## +noinst_LIBRARIES = libsua.a + +libsua_a_SOURCES = sua_tcb.cpp sua_syntax.cpp sua_sual.cpp sua_logging.cpp sua_file.cpp sua_distribution.cpp sua_dataname.cpp sua_database.cpp sua_co.cpp sua_datassoc.cpp sua_cl.cpp sua_asp_mgnt.cpp sua_adapt.cpp + + +EXTRA_DIST = sua.h sua_adapt.cpp sua_adapt.h sua_asp_mgnt.cpp sua_asp_mgnt.h sua_cl.cpp sua_cl.h sua_datassoc.cpp sua_co.cpp sua_co.h sua_database.cpp sua_database.h sua_dataname.cpp sua_debug.h sua_distribution.cpp sua_distribution.h sua_file.cpp sua_file.h sua_logging.cpp sua_logging.h sua_sual.cpp sua_sual.h sua_syntax.cpp sua_syntax.h sua_tcb.cpp sua_tcb.h + +####### kdevelop will overwrite this part!!! (end)############ +SOMAJOR = 1 +SOMINOR = 0 +SOSUBMINOR = 0 + +libsua_la_LIBADD = @glib_LIBS@ @sctp_LIBS@ + +# here you should add all header files, which contains the functionality +# of your shared lib (published for the users) +include_HEADERS = sua.h + +INCLUDES = -I/usr/local/include + +#build a libtool library for installation in libdir +lib_LTLIBRARIES = libsua.la +libsua_la_SOURCES = sua_tcb.cpp sua_syntax.cpp sua_sual.cpp sua_logging.cpp sua_file.cpp sua_distribution.cpp sua_dataname.cpp sua_database.cpp sua_co.cpp sua_datassoc.cpp sua_cl.cpp sua_asp_mgnt.cpp sua_adapt.cpp + + +libsua_la_LDFLAGS = -no-undefined -version-info $(SOMAJOR):$(SOMINOR):$(SOSUBMINOR) $(LDFLAGS) + + + diff --git a/sualibrary/sua/sua.h b/sualibrary/sua/sua.h new file mode 100644 index 0000000..d0e5e02 --- /dev/null +++ b/sualibrary/sua/sua.h @@ -0,0 +1,388 @@ +/*************************************************************************** + sua.h - 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.h,v 1.3 2002/02/15 16:19:46 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Marleen + * "El Loco was here." + * "He drinks boiling motor oil and likes his meat alive in the cantina." + * + * Purpose: This header-file defines the SUA interface used by the + * SUA application for: + * - SUA address information structure + * - SUA Quality-Of-Service(QOS) structure + * - SUA callback function structure + * and adaptation functions used by the SUA application for: + * - initialising the SUA layer + * - reading the SUA configuration file + * - registering a local SUA instance + * - Setting up the association with a remote SUA node + * - get info on a certain (SUA) association + * - terminate a association + * - Send a SUA primtive to SUA + * - Receive a SUA primitive from SUA + * - convert Hostname(string) to SUAname(Character array) + * - convert SUAname(Character array) to Hostname(Character array) + */ + +#define __EXTENSIONS__ +#ifndef SUA_GLOBAL_H +#define SUA_GLOBAL_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <string> + +#ifdef STDC_HEADERS + #ifdef HAVE_SYS_TIME_H + #include <sys/time.h> + #ifdef TIME_WITH_SYS_TIME + #include <time.h> + #endif + #endif + #ifdef HAVE_UNISTD_H + #include <unistd.h> + #endif +#endif + +#ifdef FreeBSD +#include <netinet/in_systm.h> +#include <sys/types.h> +#endif + +#ifdef SOLARIS +#include <netinet/in_systm.h> +#include <stdarg.h> +#endif + +#include <netinet/in.h> + + +/* turn on Posix 1g for compatible cmsg structure */ +#ifdef USE_RFC2292BIS + #define _XPG4_2 +#endif + +#include <sys/socket.h> + +/* turn off Posix 1g for compatible cmsg structure */ +#ifdef USE_RFC2292BIS + #undef _XPG4_2 +#endif + +#include <netdb.h> +#include <arpa/inet.h> + +#include "sctp.h" /* SCTP library */ + +#define SUA_PORT 14001 +#define SUA_PPI 4 +#define IPPROTO_SCTP 132 + +#define SUA_MAX_MSG_LEN 2000 + +/*#define HAVE_UNISTD_H TRUE */ + +#define N_UNITDATA 1 +#define N_NOTICE 2 +#define N_CONNECT_REQ 10 +#define N_CONNECT_IND 11 +#define N_CONNECT_REFUSED 12 +#define N_CONNECT_RESP 13 +#define N_CONNECT_CONF 14 +#define N_DATA_REQ 20 +#define N_DATA_IND 21 +#define N_RELEASE_REQ 30 +#define N_RELEASE_CONF 31 + +typedef unsigned char boolean; + +#define FALSE (0) +#define TRUE (!FALSE) + + +#define OK 0 +#define PROTOCOL_CLASS_NOT_SPECIFIED -10 +#define INVALID_CLG_ADDRESS -20 +#define INVALID_CLD_ADDRESS -30 +#define MSG_ENCODING_FAILED -40 + +/* shortcut macro to specify address field of struct sockaddr */ +#define sockunion_family(X) (X)->sa.sa_family +#define sock2ip(X) (((struct sockaddr_in *)(X))->sin_addr.s_addr) +#define sock2ip6(X) (((struct sockaddr_in6 *)(X))->sin6_addr.s6_addr) + +#define SUPPORT_ADDRESS_TYPE_IPV4 0x00000001 +#define SUPPORT_ADDRESS_TYPE_IPV6 0x00000002 +#define SUPPORT_ADDRESS_TYPE_DNS 0x00000004 + + +/* union for handling either type of addresses: ipv4 and ipv6 */ +/*#ifndef SOCKUNION_DEFINE*/ +#define SOCKUNION_DEFINE 1 +/* define structure of IPv4/6 address */ +union sockunion +{ + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + unsigned char ch[SCTP_MAX_IP_LEN]; +}; +/*#endif SOCKUNION_DEFINE */ + +#define ipvxunion sockunion + +/*union ipvxunion +{ + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + unsigned char ch[SCTP_MAX_IP_LEN]; +};*/ + +typedef enum { ITU14bit, + ITU24bit, + ANSI24bit +} SS7pc_set; + +typedef struct { + SS7pc_set family; + uint32_t pc; +} SS7_ITU14_str; + +/* define structure of SS7 MTP pointcode (ITU/ANSI/other...) */ +union SS7union +{ + SS7_ITU14_str ITU14; + SS7_ITU14_str ITU24; + SS7_ITU14_str ANSI24; +}; + +typedef enum { no_pc_present, + ipvx_pc_present, // IPvx(4 or 6) present in pc field + ss7_pc_present // SS7 pointcode present in pc field +} pointcode_set; + +typedef enum { no_name_present, + hostname_present, + GT_present +} name_gt_set; + +typedef enum { no_sap_present, + ssn_present, + portnumber_presentr +} application_SAP_set; + +typedef enum { include_nothing, + include_pc_in_header, + include_ssn_port_in_header +} sua_header_set; + +typedef struct { + pointcode_set pc; + name_gt_set name_gt; + application_SAP_set ssn_port; + sua_header_set field_in_header; +} addr_elements_str; + +typedef struct { + SS7union ss7; + sockunion ipvx; + /*ipvxunion ipvx;*/ +} pointcode_str; + +typedef char hostname_str[255]; + +typedef char global_title_str[255]; + +typedef union { + global_title_str GT; + hostname_str HostName; +}name_str; + +typedef short application_sap_str; + +typedef enum { route_on_ssn, // use pointcode for routing + route_on_name_gt, // use gt/name for routing + route_on_name_gt_next_office, // perform GTT in next node + no_address_present // no routing requested +} routing_type_set; + +typedef struct { + addr_elements_str address_fields_present; // which fields are present? + pointcode_str pc; // pointcode field + name_str name; //global title/hostname field + application_sap_str ssn; // application ssn/port + routing_type_set routing_ind; // how must msg be routed + short network_apperance; +} sccp_addr_str; + +typedef enum { class0, // connectionless transport, non-sequenced + class1, // connectionless transport, sequenced + class2, // connectionoriented + class3 // connectionoriented with flow control +} protocol_class_set; + +typedef struct { + protocol_class_set prot_class; // class 0, 1 or 2 + bool in_sequence; // msg delivevered in sequence + short sequence_number; // = stream number + bool return_msg_on_error; // return a UDT service on err + short importance; // importance of msg(0..7) + short hopcounter; // hopcounter +} sccp_QOS_str; + +typedef struct { + void (*ulp_ClDataIndNotif) ( unsigned int local_sua_Id, + unsigned int primitive, + unsigned int datalen + ); + void (*ulp_ConnIndNotif) ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ); + void (*ulp_ConnConfIndNotif) ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ); + void (*ulp_ConnDataIndNotif) ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ); + void (*ulp_DisConnIndNotif) ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int reason, + unsigned int datalen + ); +} Sua_ULP_CallBacks; + + +void sua_initialisation(); + +#define SUA_CFG_NO_ERROR 0 +#define SUA_CFG_FILE_UNKNOWN 1 +#define SUA_CFG_NO_SOURCE_ADDR 2 +#define SUA_CFG_NO_SOURCE_SSN 3 +#define SUA_CFG_NO_SOURCE_PORT 4 + +unsigned int sua_read_config_file + ( char *pConfFile + ); + +#define SUA_REG_NO_ERROR 0 + +unsigned int sua_registerInstance + ( short local_ssn, + Sua_ULP_CallBacks ulp_callback + ); + + +#define SUA_ASS_NO_ERROR 0 + +unsigned int sua_associate ( ); + +typedef struct { + sccp_addr_str remote_addr; + sccp_addr_str local_addr; + int blabla; + unsigned int ASP_status; +} sua_Path_str; + +#define SUA_PATH_NO_ERROR 0 +#define SUA_PATH_NO_DEST_ADDR_PRESENT 1 + +unsigned int sua_getPath( unsigned int assoc_id, + sua_Path_str &pathinfo + ); + +#define SUA_TERM_NO_ERROR 0 +#define SUA_TERM_NO_DEST_ADDR_PRESENT 1 + +unsigned int sua_terminate(); + + +#define SUA_SEND_NO_ERROR 0 +#define SUA_SEND_PRIM_NOT_SENT 1 + +unsigned int Send_sua_primitive( unsigned int primitive, + unsigned int &sua_ConnId, + sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len + ); + +#define SUA_REC_NO_ERROR 0 +#define SUA_REC_NO_DATA_PRESENT 1 + +unsigned int Receive_sua_primitive( unsigned int &primitive, + unsigned int &sua_ConnId, + sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len + ); + + + +#endif // SUA_GLOBAL_H + +// end of module sua.h + + + + + + + + + + + diff --git a/sualibrary/sua/sua_adapt.cpp b/sualibrary/sua/sua_adapt.cpp new file mode 100644 index 0000000..5dcb396 --- /dev/null +++ b/sualibrary/sua/sua_adapt.cpp @@ -0,0 +1,222 @@ +/*************************************************************************** + sua_adapt.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_adapt.cpp,v 1.2 2002/02/15 16:19:46 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Katrien + * "Come on barbie, let's go party" + * + * Purpose: This code-file defines the SUA adaptation functions used by + * the SUA application for: + * - initialising the SUA layer + * - reading the SUA configuration file + * - registering a local SUA instance + * - Setting up the association with a remote SUA node + * - get info on a certain (SUA) association + * - terminate a association + * - convert Hostname(string) to SUAname(Character array) + * - convert SUAname(Character array) to Hostname(Character array) + */ + +// sua_adapt.c++ +// SCCP user adaptation program + +#include "sua_debug.h" +#include "sua_database.h" +#include "sua_file.h" +#include "sua_distribution.h" +#include "sua_logging.h" + +#ifdef LINUX + #include <unistd.h> +#endif + +#include <sctp.h> + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> + +#include <netinet/in_systm.h> +#include <netinet/ip.h> /* includes <netinet/in.h> also ! */ +#include <netinet/ip_icmp.h> +#include <netdb.h> +#include <arpa/inet.h> + +using namespace std; +/* definition of SUA local object and of remote object */ +db_Sua_LocalList local_sua; +db_Sua_RemoteList remote_sua; +db_Sua_AssociationList Assoc_sua; +db_Sua_NameList NameDB_sua; +db_Sua_ASList ApplicServ_sua; + +/***********************************************************************/ +/* sua_initialisation */ +/***********************************************************************/ +void sua_initialisation() +{ + int res; + cout << "Initialising SCTP & SUA\n "; + res = sctp_initLibrary(); + init_logging_file(); + local_sua.initialize(); + remote_sua.initialize(); + Assoc_sua.initialize(); + cout << "Finished initialising SUA data\n "; + +} /* end of sua_initialisation */ + +/***********************************************************************/ +/* sua_read_configuration file */ +/***********************************************************************/ +unsigned int sua_read_config_file( char *pConfFile) +{ + unsigned int result = SUA_CFG_NO_ERROR; + string sua_filename; + sua_filename = pConfFile; + result = read_sua_file( sua_filename, + local_sua, + remote_sua, + Assoc_sua, + NameDB_sua, + ApplicServ_sua + ); + return(result); +} + +/***********************************************************************/ +/* sua_registerInstance */ +/***********************************************************************/ +unsigned int sua_registerInstance ( short local_ssn, + Sua_ULP_CallBacks ulp_callback + ) +{ + unsigned int result = SUA_REG_NO_ERROR; + SCTP_ulp_Callbacks SCTPCallbackFunctions; + + SCTPCallbackFunctions.dataArriveNotif = &sctp_DataArriveNotif; + SCTPCallbackFunctions.networkStatusChangeNotif = &sctp_NetworkStatusChangeNotif; + SCTPCallbackFunctions.sendFailureNotif = &sctp_SentFailureNotif; + SCTPCallbackFunctions.communicationLostNotif = &sctp_CommunicationLostNotif; + SCTPCallbackFunctions.communicationUpNotif = &sctp_CommunicationUpNotif; + SCTPCallbackFunctions.communicationErrorNotif = &sctp_CommunicationErrorNotif; + SCTPCallbackFunctions.restartNotif = &sctp_RestartNotif; + SCTPCallbackFunctions.shutdownCompleteNotif = &sctp_ShutDownCompleteNotif; + + result = Assoc_sua.register_instance ( SCTPCallbackFunctions, + ulp_callback, + local_sua + ); + + return(result); +} + + +/***********************************************************************/ +/* sua_associate */ +/***********************************************************************/ +unsigned int sua_associate ( ) +{ + unsigned int result = SUA_ASS_NO_ERROR; + result = Assoc_sua.associate_instance( local_sua, + remote_sua + ); + return(result); + +} + + +/***********************************************************************/ +/* sua_getPath */ +/***********************************************************************/ +unsigned int sua_getPath( unsigned int assoc_id, + sua_Path_str &pathinfo + ) +{ + unsigned int result = SUA_PATH_NO_ERROR; + + if ( Assoc_sua.instance[assoc_id].Dest.nr_of_addrs > 0) + { + /*pathinfo.remote_addr.*/ + pathinfo.remote_addr.pc.ipvx = Assoc_sua.instance[assoc_id].Dest.addrs[0]; + /*pathinfo.remote_addr.pc.ss7 = Assoc_sua.instance[assoc_id].Dest.pc;*/ + pathinfo.remote_addr.ssn = remote_sua.instance[Assoc_sua.instance[assoc_id].remote_sua_id].ssn.ssn; + + pathinfo.ASP_status = Assoc_sua.instance[assoc_id].asp.status; + +#ifdef DEBUG + //cout << "remote ssn = " << pathinfo.remote_addr.ssn << "\n"; + //cout << "remote sua_id = " << Assoc_sua.instance[assoc_id].remote_sua_id << "\n"; +#endif + } + else + result = SUA_PATH_NO_DEST_ADDR_PRESENT; + pathinfo.local_addr.pc.ipvx = Assoc_sua.instance[assoc_id].Source.addrs[0]; + pathinfo.local_addr.pc.ss7 = Assoc_sua.instance[assoc_id].Source.pc; + pathinfo.local_addr.ssn = local_sua.instance[Assoc_sua.instance[assoc_id].local_sua_id].ssn.ssn; + + return (result); + +} + +/***********************************************************************/ +/* sua_terminate */ +/***********************************************************************/ +unsigned int sua_terminate( ) +{ + unsigned int result = SUA_TERM_NO_ERROR; + + Assoc_sua.shutdown(); + close_logging_file(); + + return (result); + +} + + + +// end of module sua_adapt.c++ diff --git a/sualibrary/sua/sua_adapt.h b/sualibrary/sua/sua_adapt.h new file mode 100644 index 0000000..190c425 --- /dev/null +++ b/sualibrary/sua/sua_adapt.h @@ -0,0 +1,79 @@ +/*************************************************************************** + sua_adapt.h - 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_adapt.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 + * + * Purpose: This header-file defines the SUA adaptation functions used by + * the SUA application for: + * - Nope + */ + +#include "sua_database.h" + +#ifdef LINUX + #include <unistd.h> +#endif + + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> + +#include <netinet/in_systm.h> +#include <netinet/ip.h> /* includes <netinet/in.h> also ! */ +#include <netinet/ip_icmp.h> +#include <netdb.h> +#include <arpa/inet.h> + + +using namespace std; + + + + + +// end of module sua_adapt.h + + diff --git a/sualibrary/sua/sua_asp_mgnt.cpp b/sualibrary/sua/sua_asp_mgnt.cpp new file mode 100644 index 0000000..93f0b9e --- /dev/null +++ b/sualibrary/sua/sua_asp_mgnt.cpp @@ -0,0 +1,1030 @@ +/*************************************************************************** + sua_asp_mgnt.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_asp_mgnt.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Sabine + * "Due to small parts(Booleans), this code is not suitable for" + * "childeren under 3 years." + * + * Purpose: This code-file defines the SUA management handling functions for + * sending and receiving Application Server Process(ASP) messages: + * - send a ASP-UP msg to remote node + * - send a ASP-UP ACKnowledge msg to remote node + * - send a ASP-DOWN ACKnowledge msg to remote node + * - send a Hearbeat msg to remote node + * - send a Heartbeat ACKnowledge msg to remote node + * - send a ASP-ACTIVE msg to remote node + * - send a ASP-ACTIVE ACKnowledge msg to remote node + * - send a ASP-INactive Acknowledge msg to remote node + * - Receive/process ASP UP msg + * - Receive/process ASP UP ACKnowladge msg + * - Receive/process ASP DOWN msg + * - Receive/process ASP DOWN ACKnowledge msg + * - Receive/process Heartbeat msg + * - Receive/process Heartbeat ACKnowledge msg + * - Receive/process ASP ACTIVE msg + * - Receive/process ASP ACTIVE ACKnowladge msg + * - Receive/process ASP INactive msg + * - Receive/process ASP INactive ACKnowledge msg + */ + +#include "sua_debug.h" +#include "sua_asp_mgnt.h" +#include "sua_database.h" +#include "sua_syntax.h" +#include "sua_logging.h" +#include "sua_tcb.h" + +#include <cstdio> +#include <string> + +extern db_Sua_LocalList local_sua; +extern db_Sua_RemoteList remote_sua; +extern db_Sua_AssociationList Assoc_sua; +extern db_Sua_ASList ApplicServ_sua; +extern tcb_Sua_msgqueue_pool msg_store; + +/***********************************************************************/ +/* Sending SUA Management msg */ +/***********************************************************************/ +/***********************************************************************/ +/* sua_send_ASPUP */ +/***********************************************************************/ +int sua_send_ASPUP( unsigned int Sua_assoc_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_aspsm; + msg.sua_prim.hdr_msg_type.aspsm = aspsm_up; + msg.sua_prim.ASP_id_pres = TRUE; + msg.sua_prim.ASP_id = 1; + msg.sua_prim.asp_cap_pres = FALSE; + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPUP sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_ASPUP_ACK */ +/***********************************************************************/ +int sua_send_ASPUP_ACK( unsigned int Sua_assoc_id, + boolean ASP_id_pres, + uint32_t ASP_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_aspsm; + msg.sua_prim.hdr_msg_type.aspsm = aspsm_up_ack; + /* rest is optional */ + msg.sua_prim.ASP_id_pres = ASP_id_pres; + if ( ASP_id_pres) + msg.sua_prim.ASP_id = ASP_id; + + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPUP_ACK sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_ASPDOWN_ACK */ +/***********************************************************************/ +int sua_send_ASPDOWN_ACK( unsigned int Sua_assoc_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_aspsm; + msg.sua_prim.hdr_msg_type.aspsm = aspsm_down_ack; + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPDOWN_ACK sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_BEAT */ +/***********************************************************************/ +int sua_send_BEAT( unsigned int Sua_assoc_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_aspsm; + msg.sua_prim.hdr_msg_type.aspsm = aspsm_beat; + msg.sua_prim.hb_data_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result BEAT sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_BEAT_ACK */ +/***********************************************************************/ +int sua_send_BEAT_ACK( unsigned int Sua_assoc_id, + bool HB_data_present, + string HB_data + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_aspsm; + msg.sua_prim.hdr_msg_type.aspsm = aspsm_beat_ack; + msg.sua_prim.hb_data_pres = HB_data_present; + if (HB_data_present) + msg.sua_prim.hb_data = HB_data; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result BEAT_ACK sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_ASPAC */ +/***********************************************************************/ +int sua_send_ASPAC( unsigned int Sua_assoc_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_asptm; + msg.sua_prim.hdr_msg_type.asptm = asptm_act; + /* traffic mode is optional mandatory */ + msg.sua_prim.traf_mode_pres = TRUE; + msg.sua_prim.traf_mode = tmt_loadshare; + /* rest is optional */ + msg.sua_prim.rout_con_pres = FALSE; + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPAC sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_ASPAC_ACK */ +/***********************************************************************/ +int sua_send_ASPAC_ACK( unsigned int Sua_assoc_id, + boolean traffic_mode_present, + Sua_traffic_mode_type traffic_mode, + boolean routing_context_present, + uint32_t routing_context + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_asptm; + msg.sua_prim.hdr_msg_type.asptm = asptm_act_ack; + + /* rest is optional */ + msg.sua_prim.traf_mode_pres = traffic_mode_present; + if ( traffic_mode_present) + msg.sua_prim.traf_mode = traffic_mode; + + msg.sua_prim.rout_con_pres = routing_context_present; + if (routing_context_present) + msg.sua_prim.rout_con = routing_context; + + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPAC_ACK sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + + +/***********************************************************************/ +/* sua_send_ASPINAC_ACK */ +/***********************************************************************/ +int sua_send_ASPINAC_ACK( unsigned int Sua_assoc_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_asptm; + msg.sua_prim.hdr_msg_type.asptm = asptm_inact_ack; + msg.sua_prim.rout_con_pres = FALSE; + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPINAC_ACK sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* Receiving SUA Management msg */ +/***********************************************************************/ +/***********************************************************************/ +/* sua_process_ASPUP_msg */ +/***********************************************************************/ +int process_ASPUP_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + + int error_value; + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPUP received, send back a ASPUP_ACK and set state to ASP-INACTIVE.\n"; +#endif + + Assoc_sua.up(sua_assoc_id,0); + + error_value = sua_send_ASPUP_ACK( sua_assoc_id , + sua_asp_msg.sua_prim.ASP_id_pres, + sua_asp_msg.sua_prim.ASP_id + ); +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result send ASPUP_ACK = "<< error_value << "\n"; + cout << "sua_asp_mgnt.c:ASPUP processing state = "<< Assoc_sua.instance[sua_assoc_id].asp.status << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPUP_ACK_msg */ +/***********************************************************************/ +int process_ASPUP_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value = 0; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPUP_ACK received, looks like remote is inactive.\n"; +#endif + + Assoc_sua.up(sua_assoc_id,0); + + /* send activation to remote */ + error_value = sua_send_ASPAC( sua_assoc_id ); +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result send ASPAC = "<< error_value << "\n"; + cout << "sua_asp_mgnt.c:ASPUP_ACK processing state = "<< Assoc_sua.instance[sua_assoc_id].asp.status << "\n"; +#endif + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPDOWN_msg */ +/***********************************************************************/ +int process_ASPDOWN_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + + int error_value; + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPDOWN received, send back a ASPDOWN_ACK and set state to ASP-DOWN.\n"; +#endif + + Assoc_sua.down(sua_assoc_id,0); + + + error_value = sua_send_ASPDOWN_ACK( sua_assoc_id ); +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result send ASPDOWN_ACK = "<< error_value << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPDOWN_ACK_msg */ +/***********************************************************************/ +int process_ASPDOWN_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value = 0; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPDOWN_ACK received, remote looks down.\n"; +#endif + + Assoc_sua.down(sua_assoc_id,0); + + return(error_value); +} + +/***********************************************************************/ +/* sua_process_BEAT_msg */ +/***********************************************************************/ +int process_BEAT_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + + int error_value; + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:HEARTBEAT received, send back a HEARTBEAT_ACK.\n"; +#endif + + error_value = sua_send_BEAT_ACK( sua_assoc_id, + sua_asp_msg.sua_prim.hb_data_pres, + sua_asp_msg.sua_prim.hb_data + ); +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result send HEARTBEAT_ACK = "<< error_value << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_process_BEAT_ACK_msg */ +/***********************************************************************/ +int process_BEAT_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value = 0; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:HEARTBEAT_ACK received, nothing further to do.\n"; +#endif + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPAC_msg */ +/***********************************************************************/ +int process_ASPAC_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + bool holdtraffic_pres = FALSE; + int error_value; + tcb_Sua_msg_elem sua_msg; + int datalen; + signed int sctp_assoc_id; + int result; + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPAC received, send back a ASPAC_ACK and set state to ASP-ACTIVE.\n"; +#endif + + if (sua_asp_msg.sua_prim.traf_mode_pres) + holdtraffic_pres = Assoc_sua.activate(sua_assoc_id, + sua_asp_msg.sua_prim.traf_mode); + else + holdtraffic_pres = Assoc_sua.activate(sua_assoc_id,0); + + error_value = sua_send_ASPAC_ACK( sua_assoc_id, + sua_asp_msg.sua_prim.traf_mode_pres, + sua_asp_msg.sua_prim.traf_mode, + sua_asp_msg.sua_prim.rout_con_pres, + sua_asp_msg.sua_prim.rout_con + ); + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPAC_ACK send = "<< error_value << "\n"; + cout << "sua_asp_mgnt.c:ASPAC processing state = "<< Assoc_sua.instance[sua_assoc_id].asp.status << "\n"; +#endif + + if (holdtraffic_pres) + { + /* send all stored msg for this association to remote side */ + /* should be looping to get all waiting messages */ + /* - get the saved msg ansd send it on the association that is setup */ + sua_msg = msg_store.get_msg ( sua_assoc_id ); + + while ( sua_msg.valid) + { + char* databuf = new char[sua_msg.byte.length()]; + sua_msg.byte.copy(databuf, sua_msg.byte.length()); + datalen = sua_msg.byte.length(); + + /* msg retrieved and copied, may now remove it from queue */ + msg_store.delete_msg ( sua_assoc_id ); + + sctp_assoc_id = Assoc_sua.instance[sua_assoc_id].SCTP_assoc_id; + +#ifdef DEBUG + display_byte_array(databuf , sua_msg.byte.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_distribution.c",logstring); + log_byte_array("sua_distribution.c", databuf,sua_msg.byte.length()); + + result = sctp_send ( sctp_assoc_id, + sua_msg.stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + sua_msg.delivery_type, + SCTP_BUNDLING_DISABLED + ); + + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result sctp send = "<< result << "\n"; +#endif + /* get the next saved msg ansd send if any ? */ + sua_msg = msg_store.get_msg ( sua_assoc_id ); + + } + + } + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPAC_ACK_msg */ +/***********************************************************************/ +int process_ASPAC_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value = 0; + bool holdtraffic_pres = FALSE; + +#ifdef SG_ASP_MODE + if (sua_asp_msg.sua_prim.traf_mode_pres) + holdtraffic_pres = Assoc_sua.activate(sua_assoc_id, + sua_asp_msg.sua_prim.traf_mode); + else + holdtraffic_pres = Assoc_sua.activate(sua_assoc_id,0); + +#endif + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPAC_ACK received, nothing further to do.\n"; +#endif + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPINAC_msg */ +/***********************************************************************/ +int process_ASPINAC_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value; + tcb_Sua_msg_elem sua_msg; + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPINAC received, send back a ASPINAC_ACK and set state to ASP-INACTIVE.\n"; +#endif + Assoc_sua.deactivate(sua_assoc_id,0); + + error_value = sua_send_ASPINAC_ACK( sua_assoc_id ); +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPINAC_ACK send = "<< error_value << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPINAC_ACK_msg */ +/***********************************************************************/ +int process_ASPINAC_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value = 0; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPINAC_ACK received, nothing further to do.\n"; +#endif + return(error_value); +} + +/***********************************************************************/ +/* Asp_mngt_standby */ +/***********************************************************************/ +void Asp_mngt_standby ( unsigned int sua_AS_id, + unsigned int sua_asp_id, + short mode + ) +{ + ApplicServ_sua.override_ASP( sua_asp_id, + sua_AS_id, + mode + ); +} + +void asp_activate_override ( unsigned int asp_sua_assoc_id ) +{ + Assoc_sua.activate(asp_sua_assoc_id,0); +} + +void asp_deactivate ( unsigned int asp_sua_assoc_id) +{ + Assoc_sua.deactivate(asp_sua_assoc_id,0); +} + + +//end of module sua_asp_mgnt.c++ + + + + + + + + + + + + + diff --git a/sualibrary/sua/sua_asp_mgnt.h b/sualibrary/sua/sua_asp_mgnt.h new file mode 100644 index 0000000..6531d17 --- /dev/null +++ b/sualibrary/sua/sua_asp_mgnt.h @@ -0,0 +1,190 @@ +/*************************************************************************** + sua_asp_mgnt.h - 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_asp_mgnt.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 + * + * Purpose: This header-file defines the SUA management handling functions for + * sending and receiving Application Server Process(ASP) messages: + * - send a ASP-UP msg to remote node + * - send a ASP-ACTIVE msg to remote node + * - Receive/process ASP UP msg + * - Receive/process ASP UP ACKnowladge msg + * - Receive/process ASP DOWN msg + * - Receive/process ASP DOWN ACKnowledge msg + * - Receive/process Heartbeat msg + * - Receive/process Heartbeat ACKnowledge msg + * - Receive/process ASP ACTIVE msg + * - Receive/process ASP ACTIVE ACKnowladge msg + * - Receive/process ASP INactive msg + * - Receive/process ASP INactive ACKnowledge msg + * Contains also the ASP management states set + */ + +#ifndef SUA_ASP_MGNT_H +#define SUA_ASP_MGNT_H + +#include "sua.h" +#include "sua_syntax.h" + +#include <string> + + + +typedef enum {asp_idle, // 0 + asp_down, // 1 + asp_down_traf_hold, // 2 + asp_inactive, // 3 + asp_inactive_traf_hold, // 4 + asp_active // 5 +} asp_Sua_asp_state_set; + + +typedef enum {as_idle, // 0 + as_down, // 1 + as_pending, // 2 + as_inactive, // 3 + as_active // 4 +} asp_Sua_as_state_set; + +typedef enum { lm_override, // 0: standard loadshare: only 1 ASP + lm_share_RR, // 1: Round robin load sharing + lm_share_XX, // 2: unknown load sharing + lm_share_BC // 3: Broadcasting +}asp_Sua_loadmode_set; + +int sua_send_ASPUP( unsigned int Sua_assoc_id + ); + +int sua_send_ASPAC( unsigned int Sua_assoc_id + ); + + +int process_ASPUP_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPUP_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPDOWN_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPDOWN_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_BEAT_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_BEAT_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPAC_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPAC_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPINAC_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPINAC_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +void Asp_mngt_standby ( unsigned int sua_AS_id, + unsigned int sua_asp_id, + short mode + ); + +void asp_activate_override ( unsigned int asp_sua_assoc_id ); + +void asp_deactivate ( unsigned int asp_sua_assoc_id); + + + + +#endif // SUA_ASP_MGNT_H + +//end of module sua_asp_mgnt.h + + + + + + + + + + + + + diff --git a/sualibrary/sua/sua_cl.cpp b/sualibrary/sua/sua_cl.cpp new file mode 100644 index 0000000..4ec0bb7 --- /dev/null +++ b/sualibrary/sua/sua_cl.cpp @@ -0,0 +1,550 @@ +/*************************************************************************** + sua_cl.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_cl.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Dorothee + * "Always admire the local beauties in their natural enviroment." + * + * Purpose: This code-file defines the SUA connectionless message handling: + * - send a Unitdata msg to remote node + * (- send a Unitdata Service msg to remote node) + * - Process a Unitdata msg + * (- Process a Unitdata Service msg) + */ + + +#include "sua_debug.h" +#include "sua_syntax.h" +#include "sua_database.h" +#include "sua_logging.h" +#include "sua_distribution.h" +#include "sua_tcb.h" + +#ifdef LINUX + #include <unistd.h> +#endif + + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> +#include <vector> + +#include <netinet/in_systm.h> +#include <netinet/ip.h> /* includes <netinet/in.h> also ! */ +#include <netinet/ip_icmp.h> +#include <netdb.h> +#include <arpa/inet.h> + +using namespace std; + +// import the dataobjects of SUA +extern db_Sua_LocalList local_sua; +extern db_Sua_RemoteList remote_sua; +extern db_Sua_AssociationList Assoc_sua; + +extern tcb_Sua_msgqueue_pool msg_store; + +// import the received msg pool +extern vector<sua_save_str> rec_msg_pool; + +/***********************************************************************/ +/* sua_send_Unitdata */ +/***********************************************************************/ +int sua_send_Unitdata(sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + signed int sctp_assoc_id; + unsigned int sua_assoc_id; + short stream_id = 0; + int delivery_type, result; + tcb_Sua_msg_elem sua_msg; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_cl; + msg.sua_prim.hdr_msg_type.cl = cl_data_transfer; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class0): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_0; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = QOS.sequence_number; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class1): + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_1; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = QOS.sequence_number; + delivery_type = SCTP_ORDERED_DELIVERY; + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + // fill in the source address (=local sua address/CLG) + switch (calling_pty_address.routing_ind) + { + case (route_on_ssn): + + if (calling_pty_address.address_fields_present.pc == ipvx_pc_present) + { + msg.sua_prim.source_addr.ip_addr_pres = TRUE; + msg.sua_prim.source_addr.pc_pres = FALSE; + if (calling_pty_address.pc.ipvx.sa.sa_family == AF_INET) + { + msg.sua_prim.source_addr.ip_addr_type = ip_v4; + msg.sua_prim.source_addr.ip_addr.ipv4 = calling_pty_address.pc.ipvx.sin; + } + else if (calling_pty_address.pc.ipvx.sa.sa_family == AF_INET6) + { + msg.sua_prim.source_addr.ip_addr_type = ip_v6; + msg.sua_prim.source_addr.ip_addr.ipv6 = calling_pty_address.pc.ipvx.sin6; + } + else + cout << "error filling in CLG IP address \n"; + + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.rout_ind = ri_route_IP_SSN; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = FALSE; + msg.sua_prim.source_addr.gt_incl = FALSE; + msg.sua_prim.source_addr.ssn = calling_pty_address.ssn; + } + else if (calling_pty_address.address_fields_present.pc == ss7_pc_present) + { + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.ip_addr_pres = FALSE; + msg.sua_prim.source_addr.pc_pres = TRUE; + msg.sua_prim.source_addr.pc = calling_pty_address.pc.ss7.ITU24.pc; + msg.sua_prim.source_addr.rout_ind = ri_route_PC_SSN; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = TRUE; + msg.sua_prim.source_addr.gt_incl = FALSE; + msg.sua_prim.source_addr.ssn = calling_pty_address.ssn; + cout << "SS7 PC in CLG address \n"; + } + else + cout << "unsupported CLG address option\n"; + break; + case(route_on_name_gt): + msg.sua_prim.source_addr.ip_addr_pres = FALSE; + msg.sua_prim.source_addr.pc_pres = FALSE; + msg.sua_prim.source_addr.hostname_pres = TRUE; + msg.sua_prim.source_addr.hostname = calling_pty_address.name.HostName; + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.rout_ind = ri_route_hostname; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = FALSE; + msg.sua_prim.source_addr.gt_incl = TRUE; + msg.sua_prim.source_addr.ssn = called_pty_address.ssn; + break; + case(route_on_name_gt_next_office): + break; + default: + return(INVALID_CLG_ADDRESS); + break; + } + + + // fill in the destination address(=remote sua address/CLD) + switch (called_pty_address.routing_ind) + { + case (route_on_ssn): + + if (called_pty_address.address_fields_present.pc == ipvx_pc_present) + { + msg.sua_prim.dest_addr.ip_addr_pres = TRUE; + msg.sua_prim.dest_addr.pc_pres = FALSE; + if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v4; + msg.sua_prim.dest_addr.ip_addr.ipv4 = called_pty_address.pc.ipvx.sin; + } + else if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET6) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v6; + msg.sua_prim.dest_addr.ip_addr.ipv6 = called_pty_address.pc.ipvx.sin6; + } + else + cout << "error filling in CLD IP address \n"; + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.rout_ind = ri_route_IP_SSN; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = FALSE; + msg.sua_prim.dest_addr.gt_incl = FALSE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + } + else if (called_pty_address.address_fields_present.pc == ss7_pc_present) + { + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.ip_addr_pres = FALSE; + msg.sua_prim.dest_addr.pc_pres = TRUE; + msg.sua_prim.dest_addr.pc = called_pty_address.pc.ss7.ITU24.pc; + msg.sua_prim.dest_addr.rout_ind = ri_route_PC_SSN; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = TRUE; + msg.sua_prim.dest_addr.gt_incl = FALSE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + cout << "SS7 PC in CLD address \n"; + } + else + cout << "unsupported CLD address option\n"; + + break; + case(route_on_name_gt): + msg.sua_prim.dest_addr.ip_addr_pres = FALSE; + msg.sua_prim.dest_addr.hostname_pres = TRUE; + msg.sua_prim.dest_addr.pc_pres = FALSE; + msg.sua_prim.dest_addr.hostname = called_pty_address.name.HostName; + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.rout_ind = ri_route_hostname; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = FALSE; + msg.sua_prim.dest_addr.gt_incl = TRUE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + break; + case(route_on_name_gt_next_office): + break; + default: + return(INVALID_CLD_ADDRESS); + break; + } + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + // call routing to figure out which association to take for sending + // out the message +#ifdef DEBUG + cout << "call routing function\n"; +#endif + sctp_assoc_id = Assoc_sua.route_msg( called_pty_address, + calling_pty_address + ); +#ifdef DEBUG + cout << "routed to SCTP assoc " << sctp_assoc_id << "\n"; +#endif + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_cl.c",logstring); + log_byte_array("sua_cl.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_cl.c:result sctp send = "<< result << "\n"; +#endif + } + else if (sctp_assoc_id < 0) + { +#ifdef DEBUG + cout << "sua_cl.c:sending msg prohibited \n"; +#endif + error_value = -1; + } + else + { + /* NO it does NOT exist. */ + /* - Try to set up the association */ + sua_assoc_id = Assoc_sua.Dynamic_Associate ( local_sua, + remote_sua, + called_pty_address, + calling_pty_address, + 1, + 1, + 1 + ); + + /* - save the msg till the association is setup or */ + /* association setup fails -> drop saved msg */ + sua_msg.byte = msg.sua_msg; + sua_msg.delivery_type = delivery_type; + sua_msg.stream_id = stream_id; + sua_msg.valid = true; + msg_store.add_msg ( sua_assoc_id, + sua_msg + ); + + error_value = -1; + } + return(error_value); +} + + +/***********************************************************************/ +/* SUA receive a connectionless message */ +/***********************************************************************/ +/***********************************************************************/ +/* sua_process_unitdata */ +/***********************************************************************/ +short process_unitdata_msg ( int local_sua_id, + unsigned int sua_assoc_id, + Sua_container &msg + ) +{ + + sua_save_str temp; + + temp.primitive = N_UNITDATA; + temp.user_ref = 0; + + if (msg.sua_prim.prot_class_pres) + { + // QOS choice + switch ( msg.sua_prim.prot_class.pcl) + { + case(prot_class_0): // connectionless transport, non-sequenced + temp.QOS.prot_class = class0; + temp.QOS.in_sequence = false; + break; + case(prot_class_1): + temp.QOS.prot_class = class1; + temp.QOS.in_sequence = true; + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + } + + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + // which types are present in the address(ip pc, SS7 pc, GT, hostname) + if (msg.sua_prim.source_addr.ip_addr_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.pc = ipvx_pc_present; + if (msg.sua_prim.source_addr.ip_addr_type == ip_v4) { + temp.calling_pty_address.pc.ipvx.sin = msg.sua_prim.source_addr.ip_addr.ipv4; + temp.calling_pty_address.pc.ipvx.sa.sa_family = AF_INET; + temp.calling_pty_address.pc.ipvx.sin.sin_port = Assoc_sua.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port; + } + else if (msg.sua_prim.source_addr.ip_addr_type == ip_v6) { + temp.calling_pty_address.pc.ipvx.sin6 = msg.sua_prim.source_addr.ip_addr.ipv6; + temp.calling_pty_address.pc.ipvx.sa.sa_family = AF_INET6; + temp.calling_pty_address.pc.ipvx.sin6.sin6_port = Assoc_sua.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port; + } + else + cout << "Unknown IP address format\n"; + } + if (msg.sua_prim.source_addr.pc_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.pc = ss7_pc_present; + temp.calling_pty_address.pc.ss7.ITU24.family = ITU24bit; + temp.calling_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.source_addr.pc; + } + if (msg.sua_prim.source_addr.gt_pres == TRUE) + { + cout << "Global Title : unsupported address format\n"; + } + if (msg.sua_prim.source_addr.hostname_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.name_gt = hostname_present; + msg.sua_prim.source_addr.hostname.copy( temp.calling_pty_address.name.HostName, + (msg.sua_prim.source_addr.hostname.length()+1 ) + ); + temp.calling_pty_address.name.HostName[msg.sua_prim.source_addr.hostname.length()] = '\0'; + } + if ((msg.sua_prim.source_addr.ip_addr_pres /= TRUE) && + (msg.sua_prim.source_addr.pc_pres /= TRUE) && + (msg.sua_prim.source_addr.gt_pres /= TRUE) && + (msg.sua_prim.source_addr.hostname_pres /= TRUE)) + { + cout << "No valid address format found in msg\n"; + } + + // routing indicator + switch (msg.sua_prim.source_addr.rout_ind) + { + case(ri_route_PC_SSN): + temp.calling_pty_address.routing_ind = route_on_ssn; + break; + case(ri_route_IP_SSN): + temp.calling_pty_address.routing_ind = route_on_ssn; + break; + case (ri_route_GT): + temp.calling_pty_address.routing_ind = route_on_name_gt; + break; + case (ri_route_hostname): + temp.calling_pty_address.routing_ind = route_on_name_gt; + break; + default: + break; + } + + temp.calling_pty_address.address_fields_present.ssn_port = ssn_present; + temp.calling_pty_address.ssn = msg.sua_prim.source_addr.ssn; + + + // retrieve the called(=destination) address(=should be our own local addr) + // not completely done yet + if (msg.sua_prim.dest_addr.pc_pres == TRUE) + { + temp.called_pty_address.address_fields_present.pc = ss7_pc_present; + temp.called_pty_address.pc.ss7.ITU24.family = ITU24bit; + temp.called_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.source_addr.pc; + } + + if (msg.sua_prim.dest_addr.hostname_pres == TRUE) + { + temp.called_pty_address.address_fields_present.name_gt = hostname_present; + msg.sua_prim.dest_addr.hostname.copy( temp.called_pty_address.name.HostName, + (msg.sua_prim.dest_addr.hostname.length()+1 ) + ); + temp.called_pty_address.name.HostName[msg.sua_prim.dest_addr.hostname.length()] = '\0'; + } + // routing indicator + switch (msg.sua_prim.dest_addr.rout_ind) + { + case(ri_route_PC_SSN): + temp.called_pty_address.routing_ind = route_on_ssn; + break; + case(ri_route_IP_SSN): + temp.called_pty_address.routing_ind = route_on_ssn; + break; + case (ri_route_GT): + temp.called_pty_address.routing_ind = route_on_name_gt; + break; + case (ri_route_hostname): + temp.called_pty_address.routing_ind = route_on_name_gt; + break; + default: + break; + } + + temp.called_pty_address.address_fields_present.ssn_port = ssn_present; + temp.called_pty_address.ssn = msg.sua_prim.dest_addr.ssn; + + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_cl.c: no sua user data in unitdata msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ClDataIndNotif + ( local_sua_id, + N_UNITDATA, + temp.userdata.length() + ); + + return(0); +} + + +// end of module sua_cl.c + + + + + diff --git a/sualibrary/sua/sua_cl.h b/sualibrary/sua/sua_cl.h new file mode 100644 index 0000000..6c32df3 --- /dev/null +++ b/sualibrary/sua/sua_cl.h @@ -0,0 +1,88 @@ +/*************************************************************************** + sua_cl.h - 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_cl.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 + * + * Purpose: This header-file defines the SUA connectionless message handling: + * - send a Unitdata msg to remote node + * (- send a Unitdata Service msg to remote node) + * - Process a Unitdata msg + * (- Process a Unitdata Service msg) + */ + +#ifndef SUA_CL_H +#define SUA_CL_H + +#include "sua_database.h" + +#ifdef LINUX + #include <unistd.h> +#endif + + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> + + +using namespace std; + +int sua_send_Unitdata(sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len + ); + +short process_unitdata_msg ( int local_sua_id, + unsigned int sua_assoc_id, + Sua_container &sua_msg + ); + +#endif // SUA_CL_H + +// end of module sua_cl.h + + diff --git a/sualibrary/sua/sua_co.cpp b/sualibrary/sua/sua_co.cpp new file mode 100644 index 0000000..0b08a1f --- /dev/null +++ b/sualibrary/sua/sua_co.cpp @@ -0,0 +1,1768 @@ +/*************************************************************************** + sua_co.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_co.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Virginie + * "This code was written using the KISS methodology. (Yes, we kissed a " + * "lot of beautifull girls) We always use this method." + * + * Purpose: This code-file defines the SUA connection-oriented message + * handling: + * - send a COnnect REquest msg to remote node + * - send a COnnect RESPonse msg to remote node + * - send a CO DATA msg to remote node + * - send a CO RELease REQuest msg to remote node + * - send a CO RELease COnfirm msg to remote node + * - Process a COnnect REquest msg + * - Process a COnnect RESPonse msg + * - Process a CO DATA msg + * - Process a CO RELease REQuest msg + * - Process a CO RELease COnfirm msg + * - Process a COnnect REFuse msg + */ + +#include "sua_debug.h" +#include "sua_syntax.h" +#include "sua_database.h" +#include "sua_distribution.h" +#include "sua_logging.h" +#include "sua_tcb.h" + + +#ifdef LINUX + #include <unistd.h> +#endif + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> +#include <vector> + +#include <netinet/in_systm.h> +#include <netinet/ip.h> /* includes <netinet/in.h> also ! */ +#include <netinet/ip_icmp.h> +#include <netdb.h> +#include <arpa/inet.h> + +using namespace std; + +// import the dataobjects of SUA +extern db_Sua_LocalList local_sua; +extern db_Sua_RemoteList remote_sua; +extern db_Sua_AssociationList Assoc_sua; + +// import the TCB pool of SUA +extern tcb_Sua_TCB_arr tcb_pool; +extern tcb_Sua_msgqueue_pool msg_store; + +// import the received msg pool +extern vector<sua_save_str> rec_msg_pool; + +/***********************************************************************/ +/* Send sua connection-oriented request primitive to remote side */ +/***********************************************************************/ +/***********************************************************************/ +/* sua_send_CORE */ +/***********************************************************************/ +int sua_send_CORE( sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + signed int SCTP_assoc_id; + unsigned int sua_assoc_id; + short stream_id = 0; + int delivery_type, result; + tcb_Sua_msg_elem sua_msg; + + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_core; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = 1; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + // fill in the source address (=local sua address/CLG) + switch (calling_pty_address.routing_ind) + { + case (route_on_ssn): + + if (calling_pty_address.address_fields_present.pc == ipvx_pc_present) + { + msg.sua_prim.source_addr.ip_addr_pres = TRUE; + msg.sua_prim.source_addr.pc_pres = FALSE; + if (calling_pty_address.pc.ipvx.sa.sa_family == AF_INET) + { + msg.sua_prim.source_addr.ip_addr_type = ip_v4; + msg.sua_prim.source_addr.ip_addr.ipv4 = calling_pty_address.pc.ipvx.sin; + } + else if (calling_pty_address.pc.ipvx.sa.sa_family == AF_INET6) + { + msg.sua_prim.source_addr.ip_addr_type = ip_v6; + msg.sua_prim.source_addr.ip_addr.ipv6 = calling_pty_address.pc.ipvx.sin6; + } + else + cout << "error filling in CLG IP address \n"; + + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.rout_ind = ri_route_IP_SSN; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = FALSE; + msg.sua_prim.source_addr.gt_incl = FALSE; + msg.sua_prim.source_addr.ssn = calling_pty_address.ssn; + } + else if (calling_pty_address.address_fields_present.pc == ss7_pc_present) + { + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.ip_addr_pres = FALSE; + msg.sua_prim.source_addr.pc_pres = TRUE; + msg.sua_prim.source_addr.pc = calling_pty_address.pc.ss7.ITU24.pc; + msg.sua_prim.source_addr.rout_ind = ri_route_PC_SSN; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = TRUE; + msg.sua_prim.source_addr.gt_incl = FALSE; + msg.sua_prim.source_addr.ssn = calling_pty_address.ssn; + cout << "SS7 PC in CLG address \n"; + } + else + cout << "unsupported CLG address option\n"; + + break; + case(route_on_name_gt): + msg.sua_prim.source_addr.ip_addr_pres = FALSE; + msg.sua_prim.source_addr.pc_pres = FALSE; + msg.sua_prim.source_addr.hostname_pres = TRUE; + msg.sua_prim.source_addr.hostname = calling_pty_address.name.HostName; + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.rout_ind = ri_route_hostname; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = FALSE; + msg.sua_prim.source_addr.gt_incl = TRUE; + msg.sua_prim.source_addr.ssn = called_pty_address.ssn; + break; + case(route_on_name_gt_next_office): + break; + default: + return(INVALID_CLG_ADDRESS); + break; + } + + + // fill in the destination address(=remote sua address/CLD) + switch (called_pty_address.routing_ind) + { + case (route_on_ssn): + + if (called_pty_address.address_fields_present.pc == ipvx_pc_present) + { + msg.sua_prim.dest_addr.ip_addr_pres = TRUE; + msg.sua_prim.dest_addr.pc_pres = FALSE; + if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v4; + msg.sua_prim.dest_addr.ip_addr.ipv4 = called_pty_address.pc.ipvx.sin; + } + else if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET6) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v6; + msg.sua_prim.dest_addr.ip_addr.ipv6 = called_pty_address.pc.ipvx.sin6; + } + else + cout << "error filling in CLD IP address \n"; + + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.rout_ind = ri_route_IP_SSN; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = FALSE; + msg.sua_prim.dest_addr.gt_incl = FALSE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + } + else if (called_pty_address.address_fields_present.pc == ss7_pc_present) + { + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.ip_addr_pres = FALSE; + msg.sua_prim.dest_addr.pc_pres = TRUE; + msg.sua_prim.dest_addr.pc = called_pty_address.pc.ss7.ITU24.pc; + msg.sua_prim.dest_addr.rout_ind = ri_route_PC_SSN; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = TRUE; + msg.sua_prim.dest_addr.gt_incl = FALSE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + cout << "SS7 PC in CLD address \n"; + } + else + cout << "unsupported CLD address option\n"; + + break; + case(route_on_name_gt): + msg.sua_prim.dest_addr.ip_addr_pres = FALSE; + msg.sua_prim.dest_addr.hostname_pres = TRUE; + msg.sua_prim.dest_addr.pc_pres = FALSE; + msg.sua_prim.dest_addr.hostname = called_pty_address.name.HostName; + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.rout_ind = ri_route_hostname; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = FALSE; + msg.sua_prim.dest_addr.gt_incl = TRUE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + break; + case(route_on_name_gt_next_office): + break; + default: + return(INVALID_CLD_ADDRESS); + break; + } + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = TRUE; + msg.sua_prim.source_ref = Sua_ConnId; + msg.sua_prim.dest_ref = FALSE; + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + +#ifdef DEBUG + cout << "Data = " << stemp << "\n"; + cout << "Source LR = " << Sua_ConnId << "\n"; +#endif + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + // call routing to figure out which association to take for sending + // out the message +#ifdef DEBUG + cout << "call routing function\n"; +#endif + SCTP_assoc_id = Assoc_sua.route_msg( called_pty_address, + calling_pty_address + ); +#ifdef DEBUG + cout << "routed to SCTP assoc " << SCTP_assoc_id << "\n"; +#endif + + // fill in the TCB + tcb_ptr->Source_LR = Sua_ConnId; + tcb_ptr->User_ref_id = 1; + tcb_ptr->sctp_Association_id = SCTP_assoc_id; + tcb_ptr->state = scoc_outgoing; + tcb_ptr->remote_address = called_pty_address; + tcb_ptr->seq_number = Sua_ConnId % 256 ; + + /* does association exist? */ + if (SCTP_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + } + else if (SCTP_assoc_id < 0) + { +#ifdef DEBUG + cout << "sua_co.c:sending msg prohibited \n"; +#endif + error_value = -1; + } + else + { + /* NO it does NOT exist. */ + /* - Try to set up the association */ + sua_assoc_id = Assoc_sua.Dynamic_Associate ( local_sua, + remote_sua, + called_pty_address, + calling_pty_address, + 1, + 1, + 1 + ); + /* save newly assigned SCTP association id in SCOC TCB */ + tcb_ptr->sctp_Association_id = Assoc_sua.instance[sua_assoc_id].SCTP_assoc_id; + + /* - save the msg till the association is setup or */ + /* association setup fails -> drop saved msg */ + sua_msg.byte = msg.sua_msg; + sua_msg.delivery_type = delivery_type; + sua_msg.stream_id = stream_id; + sua_msg.valid = true; + msg_store.add_msg ( sua_assoc_id, + sua_msg + ); + + error_value = -1; + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_CORESP */ +/***********************************************************************/ +int sua_send_CORESP( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + unsigned int SCTP_assoc_id; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + short stream_id = 0; + int delivery_type, result = 0; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_coak; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = tcb_ptr->seq_number ; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = TRUE; + msg.sua_prim.source_ref = tcb_ptr->Source_LR ; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + + tcb_ptr->state = scoc_active; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + // fill in the user data + if (len > 0) + { + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + } + else + msg.sua_prim.data_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + SCTP_assoc_id = tcb_ptr->sctp_Association_id; + +#ifdef DEBUG + cout << "routed to SCTP assoc " << SCTP_assoc_id << "\n"; +#endif + +#ifdef SUA_MANAGEMENT + sua_assoc_id = Assoc_sua.Find_association( SCTP_assoc_id, + local_sua_id, + remote_sua_id + ); + + if (Assoc_sua.instance[sua_assoc_id].asp.status == asp_active) + { +#endif + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef SUA_MANAGEMENT + } + else + { +#ifdef DEBUG + cout << "sua_co.c:message sending prohibited\n"; +#endif + error_value = -1; + } +#endif + +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_CODATA */ +/***********************************************************************/ +int sua_send_CODATA( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + unsigned int SCTP_assoc_id; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + short stream_id = 0; + int delivery_type, result = 0; + + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_data; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = tcb_ptr->seq_number ; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = FALSE; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + msg.sua_prim.seq_nr_pres = TRUE; + msg.sua_prim.seq_nr.more_data = FALSE; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + SCTP_assoc_id = tcb_ptr->sctp_Association_id; + +#ifdef DEBUG + cout << "routed to SCTP assoc " << SCTP_assoc_id << "\n"; +#endif +#ifdef SUA_MANAGEMENT + sua_assoc_id = Assoc_sua.Find_association( SCTP_assoc_id, + local_sua_id, + remote_sua_id + ); + + if (Assoc_sua.instance[sua_assoc_id].asp.status == asp_active) + { +#endif + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef SUA_MANAGEMENT + } + else + { +#ifdef DEBUG + cout << "sua_co.c:message sending prohibited\n"; +#endif + error_value = -1; + } +#endif + +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_CO Release request */ +/***********************************************************************/ +int sua_send_CORELRQ( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + unsigned int SCTP_assoc_id; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + short stream_id = 0; + int delivery_type, result = 0; + + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_relre; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = tcb_ptr->seq_number ; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = TRUE; + msg.sua_prim.source_ref = tcb_ptr->Source_LR ; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + msg.sua_prim.SCCP_cause_pres = TRUE; + msg.sua_prim.SCCP_cause.cause_type = ctp_release_cause; + msg.sua_prim.SCCP_cause.cause_value = 3; + + tcb_ptr->state = scoc_disconnect; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + SCTP_assoc_id = tcb_ptr->sctp_Association_id; + +#ifdef DEBUG + cout << "routed to SCTP assoc " << SCTP_assoc_id << "\n"; +#endif + +#ifdef SUA_MANAGEMENT + sua_assoc_id = Assoc_sua.Find_association( SCTP_assoc_id, + local_sua_id, + remote_sua_id + ); + + if (Assoc_sua.instance[sua_assoc_id].asp.status == asp_active) + { +#endif + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef SUA_MANAGEMENT + } + else + { +#ifdef DEBUG + cout << "sua_co.c:message sending prohibited\n"; +#endif + error_value = -1; + } +#endif + +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_CO Release Confirm */ +/***********************************************************************/ +int sua_send_CORELCO( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + unsigned int SCTP_assoc_id; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + short stream_id = 0; + int delivery_type, result = 0; + + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_relco; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 7; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = tcb_ptr->seq_number ; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = TRUE; + msg.sua_prim.source_ref = tcb_ptr->Source_LR ; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + msg.sua_prim.SCCP_cause_pres = TRUE; + msg.sua_prim.SCCP_cause.cause_type = ctp_release_cause; + msg.sua_prim.SCCP_cause.cause_value = 3; + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + SCTP_assoc_id = tcb_ptr->sctp_Association_id; + + tcb_ptr->state = scoc_idle; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + +#ifdef SUA_MANAGEMENT + sua_assoc_id = Assoc_sua.Find_association( SCTP_assoc_id, + local_sua_id, + remote_sua_id + ); + + if (Assoc_sua.instance[sua_assoc_id].asp.status == asp_active) + { +#endif + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef SUA_MANAGEMENT + } + else + { +#ifdef DEBUG + cout << "sua_co.c:message sending prohibited\n"; +#endif + error_value = -1; + } +#endif + +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + + // release the TCB of this connection + tcb_pool.release_TCB(Sua_ConnId); + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_CO Connection Refused */ +/***********************************************************************/ +int sua_send_COREF( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + unsigned int SCTP_assoc_id; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + short stream_id = 0; + int delivery_type, result = 0; + sccp_addr_str called_pty_address; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_coref; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = tcb_ptr->seq_number ; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + called_pty_address = tcb_ptr->remote_address; + + // fill in the destination address(=remote sua address/CLD) + switch (called_pty_address.routing_ind) + { + case (route_on_ssn): + + if (called_pty_address.address_fields_present.pc == ipvx_pc_present) + { + msg.sua_prim.dest_addr.ip_addr_pres = TRUE; + if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v4; + msg.sua_prim.dest_addr.ip_addr.ipv4 = called_pty_address.pc.ipvx.sin; + } + else if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET6) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v6; + msg.sua_prim.dest_addr.ip_addr.ipv6 = called_pty_address.pc.ipvx.sin6; + } + else + cout << "error filling in CLD IP address \n"; + } + else + cout << "unsupported CLD address option\n"; + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.rout_ind = ri_route_IP_SSN; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = FALSE; + msg.sua_prim.dest_addr.gt_incl = FALSE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + break; + case(route_on_name_gt): + break; + case(route_on_name_gt_next_office): + break; + default: + return(INVALID_CLD_ADDRESS); + break; + } + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = FALSE; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + msg.sua_prim.SCCP_cause_pres = TRUE; + msg.sua_prim.SCCP_cause.cause_type = ctp_refusal_cause; + msg.sua_prim.SCCP_cause.cause_value = 3; + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + SCTP_assoc_id = tcb_ptr->sctp_Association_id; + + tcb_ptr->state = scoc_idle; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + +#ifdef SUA_MANAGEMENT + sua_assoc_id = Assoc_sua.Find_association( SCTP_assoc_id, + local_sua_id, + remote_sua_id + ); + + if (Assoc_sua.instance[sua_assoc_id].asp.status == asp_active) + { +#endif + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef SUA_MANAGEMENT + } + else + { +#ifdef DEBUG + cout << "sua_co.c:message sending prohibited\n"; +#endif + error_value = -1; + } +#endif + +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + + // release the TCB of this connection + tcb_pool.release_TCB(Sua_ConnId); + + return(error_value); +} + +/***********************************************************************/ +/* Receive a sua connection-oriented message from the remote side */ +/***********************************************************************/ +/***********************************************************************/ +/* sua_process_CORE */ +/***********************************************************************/ +short process_CORE_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + sua_save_str temp; + + temp.primitive = N_CONNECT_IND; + temp.user_ref = Sua_ConnId; + + if ( msg.sua_prim.prot_class_pres ) + { + // QOS choice + switch ( msg.sua_prim.prot_class.pcl) + { + case(prot_class_2): // connectionoriented transport, non-sequenced + temp.QOS.prot_class = class2; + temp.QOS.in_sequence = true; + break; + case(prot_class_3): + temp.QOS.prot_class = class3; + temp.QOS.in_sequence = true; + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + } + + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + // which types are present in the address(ip pc, SS7 pc, GT, hostname) + if (msg.sua_prim.source_addr.ip_addr_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.pc = ipvx_pc_present; + if (msg.sua_prim.source_addr.ip_addr_type == ip_v4) { + temp.calling_pty_address.pc.ipvx.sin = msg.sua_prim.source_addr.ip_addr.ipv4; + temp.calling_pty_address.pc.ipvx.sa.sa_family = AF_INET; + temp.calling_pty_address.pc.ipvx.sin.sin_port = Assoc_sua.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port; + } + else if (msg.sua_prim.source_addr.ip_addr_type == ip_v6) { + temp.calling_pty_address.pc.ipvx.sin6 = msg.sua_prim.source_addr.ip_addr.ipv6; + temp.calling_pty_address.pc.ipvx.sa.sa_family = AF_INET6; + temp.calling_pty_address.pc.ipvx.sin6.sin6_port = Assoc_sua.instance[sua_assoc_id].Dest.addrs[0].sin6.sin6_port; + } + else + cout << "Unknown IP address format\n"; + } + if (msg.sua_prim.source_addr.pc_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.pc = ss7_pc_present; + temp.calling_pty_address.pc.ss7.ITU24.family = ITU24bit; + temp.calling_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.source_addr.pc; + } + if (msg.sua_prim.source_addr.gt_pres == TRUE) + { + cout << "Global Title : unsupported address format\n"; + } + if (msg.sua_prim.source_addr.hostname_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.name_gt = hostname_present; + msg.sua_prim.source_addr.hostname.copy( temp.calling_pty_address.name.HostName, + (msg.sua_prim.source_addr.hostname.length()+1 ) + ); + temp.calling_pty_address.name.HostName[msg.sua_prim.source_addr.hostname.length()] = '\0'; + } + if ((msg.sua_prim.source_addr.ip_addr_pres /= TRUE) && + (msg.sua_prim.source_addr.pc_pres /= TRUE) && + (msg.sua_prim.source_addr.gt_pres /= TRUE) && + (msg.sua_prim.source_addr.hostname_pres /= TRUE)) + { + cout << "No valid address format found in msg\n"; + } + + // routing indicator + switch (msg.sua_prim.source_addr.rout_ind) + { + case(ri_route_PC_SSN): + temp.calling_pty_address.routing_ind = route_on_ssn; + break; + case(ri_route_IP_SSN): + temp.calling_pty_address.routing_ind = route_on_ssn; + break; + case (ri_route_GT): + temp.calling_pty_address.routing_ind = route_on_name_gt; + break; + case (ri_route_hostname): + temp.calling_pty_address.routing_ind = route_on_name_gt; + break; + default: + break; + } + + if (msg.sua_prim.source_addr.ssn_incl == TRUE) { + temp.calling_pty_address.address_fields_present.ssn_port = ssn_present; + temp.calling_pty_address.ssn = msg.sua_prim.source_addr.ssn; + } + else + temp.calling_pty_address.address_fields_present.ssn_port = no_sap_present; + + + // retrieve the called(=destination) address(=should be our own local addr) + // not completely done yet + if (msg.sua_prim.dest_addr.pc_pres == TRUE) + { + temp.called_pty_address.address_fields_present.pc = ss7_pc_present; + temp.called_pty_address.pc.ss7.ITU24.family = ITU24bit; + temp.called_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.source_addr.pc; + } + + if (msg.sua_prim.dest_addr.hostname_pres == TRUE) + { + temp.called_pty_address.address_fields_present.name_gt = hostname_present; + msg.sua_prim.dest_addr.hostname.copy( temp.called_pty_address.name.HostName, + (msg.sua_prim.dest_addr.hostname.length()+1 ) + ); + temp.called_pty_address.name.HostName[msg.sua_prim.dest_addr.hostname.length()] = '\0'; + } + // routing indicator + switch (msg.sua_prim.dest_addr.rout_ind) + { + case(ri_route_PC_SSN): + temp.called_pty_address.routing_ind = route_on_ssn; + break; + case (ri_route_GT): + temp.called_pty_address.routing_ind = route_on_name_gt; + break; + case (ri_route_hostname): + temp.called_pty_address.routing_ind = route_on_name_gt; + break; + default: + break; + } + + temp.called_pty_address.address_fields_present.ssn_port = ssn_present; + temp.called_pty_address.ssn = msg.sua_prim.dest_addr.ssn; + + // fill in the allocated TCB + tcb_ptr->Source_LR = Sua_ConnId; + tcb_ptr->Dest_LR = msg.sua_prim.source_ref; + tcb_ptr->User_ref_id = 1; + tcb_ptr->sctp_Association_id = Assoc_sua.instance[sua_assoc_id].SCTP_assoc_id; + tcb_ptr->state = scoc_incoming; + tcb_ptr->remote_address = temp.calling_pty_address; + tcb_ptr->seq_number = Sua_ConnId % 255; + + local_sua_id = Assoc_sua.instance[sua_assoc_id].local_sua_id; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_co.c: no sua user data in CORE msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + +#ifdef DEBUG + cout << "primitive stored , local_sua_id = " << local_sua_id << "\n"; +#endif + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ConnIndNotif + ( local_sua_id, + Sua_ConnId, + temp.userdata.length() + ); + + return(0); +} + +/***********************************************************************/ +/* sua_process_COAK */ +/***********************************************************************/ +short process_COAK_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + sua_save_str temp; + + temp.primitive = N_CONNECT_CONF; + temp.user_ref = sua_ConnId; + + if (msg.sua_prim.prot_class_pres) + { + // QOS choice + switch ( msg.sua_prim.prot_class.pcl) + { + case(prot_class_2): // connectionoriented transport, non-sequenced + temp.QOS.prot_class = class2; + temp.QOS.in_sequence = true; + break; + case(prot_class_3): + temp.QOS.prot_class = class3; + temp.QOS.in_sequence = true; + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + } + + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + + // retrieve the called(=destination) address(=should be our own local addr) + + // fill in the allocated TCB + tcb_ptr->Dest_LR = msg.sua_prim.source_ref; + tcb_ptr->User_ref_id = 1; + tcb_ptr->state = scoc_active; + + local_sua_id = Assoc_sua.instance[sua_assoc_id].local_sua_id; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_co.c: no sua user data in CODATA msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ConnConfIndNotif + ( local_sua_id, + sua_ConnId, + temp.userdata.length() + ); + + return(0); + +} +/***********************************************************************/ +/* sua_process_CODATA */ +/***********************************************************************/ +short process_CODATA_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + sua_save_str temp; + + //temp.primitive = N_CODATA; + temp.user_ref = sua_ConnId; + + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + // not needed -> to be found in TCB + // retrieve the called(=destination) address(=should be our own local addr) + // not needed -> to be found in TCB + + local_sua_id = Assoc_sua.instance[sua_assoc_id].local_sua_id; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_co.c: no sua user data in CODATA msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ConnDataIndNotif + ( local_sua_id, + sua_ConnId, + temp.userdata.length() + ); + + return(0); + +} + +/***********************************************************************/ +/* sua_process_CORELRQ */ +/***********************************************************************/ +short process_CORELRQ_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + unsigned int release_cause = 0; + unsigned int routing_Contex = 0; + sua_save_str temp; + + temp.primitive = N_RELEASE_REQ; + temp.user_ref = sua_ConnId; + routing_Contex = msg.sua_prim.rout_con; + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + + // retrieve the called(=destination) address(=should be our own local addr) + tcb_ptr->state = scoc_disconnect; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_co.c: no sua user data in CODATA msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + // send a CORELCONF back to the remote node + Sua_syntax_error_struct error; + int datalen; + unsigned int assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_relco; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = routing_Contex; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 7; + + // QOS choice + delivery_type = SCTP_UNORDERED_DELIVERY; + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = TRUE; + msg.sua_prim.source_ref = tcb_ptr->Source_LR ; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + msg.sua_prim.SCCP_cause_pres = FALSE; + + // fill in the user data + msg.sua_prim.data_pres = FALSE; + + // encode the SUA Release complete message + error = msg.sua_encode(); + //string_size = msg.sua_msg.size(); + + assoc_id = tcb_ptr->sctp_Association_id; + local_sua_id = Assoc_sua.instance[sua_assoc_id].local_sua_id; + +#ifdef DEBUG + cout << "routed to SCTP assoc " << assoc_id << "\n"; +#endif + + tcb_ptr->state = scoc_idle; + + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + delete databuf; + + // release the TCB of this connection + tcb_pool.release_TCB(sua_ConnId); + +#ifdef DEBUG + cout << "local_sua_id = " << local_sua_id << "\n"; +#endif + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif + ( local_sua_id, + sua_ConnId, + release_cause, + temp.userdata.length() + ); + + return(0); + +} + +/***********************************************************************/ +/* sua_process_CORELCO */ +/***********************************************************************/ +short process_CORELCO_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + unsigned int release_cause = 0; + sua_save_str temp; + + temp.primitive = N_RELEASE_CONF; + temp.user_ref = sua_ConnId; + + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + + // retrieve the called(=destination) address(=should be our own local addr) + + tcb_ptr->state = scoc_idle; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + local_sua_id = Assoc_sua.instance[sua_assoc_id].local_sua_id; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + // release the TCB of this connection + tcb_pool.release_TCB(sua_ConnId); + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif + ( local_sua_id, + sua_ConnId, + release_cause, + temp.userdata.length() + ); + + return(0); +} + + +/***********************************************************************/ +/* sua_process_COREF */ +/***********************************************************************/ +short process_COREF_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + unsigned int release_cause = 0; + sua_save_str temp; + + temp.primitive = N_CONNECT_REFUSED; + temp.user_ref = sua_ConnId; + + if ( msg.sua_prim.prot_class_pres ) + { + // QOS choice + switch ( msg.sua_prim.prot_class.pcl) + { + case(prot_class_2): // connectionoriented transport, non-sequenced + temp.QOS.prot_class = class2; + temp.QOS.in_sequence = true; + break; + case(prot_class_3): + temp.QOS.prot_class = class3; + temp.QOS.in_sequence = true; + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + } + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + + // retrieve the called(=destination) address(=should be our own local addr) + tcb_ptr->state = scoc_idle; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_co.c: no sua user data in CODATA msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + // release the TCB of this connection + tcb_pool.release_TCB(sua_ConnId); + +#ifdef DEBUG + cout << "local_sua_id = " << local_sua_id << "\n"; +#endif + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif + ( local_sua_id, + sua_ConnId, + release_cause, + temp.userdata.length() + ); + + return(0); + +} +// end of module sua_co.c + + + + + + diff --git a/sualibrary/sua/sua_co.h b/sualibrary/sua/sua_co.h new file mode 100644 index 0000000..8f4fd11 --- /dev/null +++ b/sualibrary/sua/sua_co.h @@ -0,0 +1,170 @@ +/*************************************************************************** + sua_co.h - 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_co.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 + * + * Purpose: This header-file defines the SUA connection-oriented message + * handling: + * - send a COnnect REquest msg to remote node + * - send a COnnect RESPonse msg to remote node + * - send a CO DATA msg to remote node + * - send a CO RELease REQuest msg to remote node + * - send a CO RELease COnfirm msg to remote node + * - Process a COnnect REquest msg + * - Process a COnnect RESPonse msg + * - Process a CO DATA msg + * - Process a CO RELease REQuest msg + * - Process a CO RELease COnfirm msg + * - Process a COnnect REFuse msg + */ + +#ifndef SUA_CO_H +#define SUA_CO_H + +#include "sua_database.h" + +#ifdef LINUX + #include <unistd.h> +#endif + + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> + + +using namespace std; + + +/***********************************************************************/ +/* Send sua connection-oriented request primitive to remote side */ +/***********************************************************************/ +int sua_send_CORE( sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +int sua_send_CORESP( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +int sua_send_CODATA( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +int sua_send_CORELRQ( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +int sua_send_CORELCO( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +int sua_send_COREF( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +/***********************************************************************/ +/* Receive a sua connection-oriented message from the remote side */ +/***********************************************************************/ +short process_CORE_msg( unsigned int sua_Assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); + +short process_COAK_msg( unsigned int local_sua_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); + +short process_CODATA_msg( unsigned int local_sua_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); + +short process_CORELRQ_msg( unsigned int local_sua_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); + +short process_CORELCO_msg( unsigned int local_sua_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); + +short process_COREF_msg( unsigned int local_sua_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); +#endif // SUA_CO_H + +// end of module sua_co.h + + diff --git a/sualibrary/sua/sua_database.cpp b/sualibrary/sua/sua_database.cpp new file mode 100644 index 0000000..ce953e1 --- /dev/null +++ b/sualibrary/sua/sua_database.cpp @@ -0,0 +1,642 @@ +/*************************************************************************** + sua_database.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_database.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Ann V. + * "What does reuse of code mean if the code is NOT even used yet." + * + * Purpose: This code-file defines the SUA database access functions for: + * - dummy Indication Notifications + * - dummy DISxx indciation Notifications + * Sybsystem Number(SSN) Object: + * - read SSN + * Address Object: + * - read IP address parameter + * - read IP portnumber + * Local SUA Object: + * - initialise Local SUA Object + * Local SUA List: + * - initialise Local SUA List + * - read SSN + * - increase instance + * - unregister instance + * - register instance + * Remote SUA object: + * - initialise Remote SUA Object + * Remote SUA List + * - initialise Remote SUA list + * - read SSN + * - increase instance + * SUA Application Server list + * - initialise AS List + * + */ + +#include "sctp.h" + +#include "sua_debug.h" +#include "sua_database.h" +#include "sua_logging.h" + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> + +#include "unistd.h" + + + +using namespace std; + + +/***********************************************************************/ +/*Initialisation dummy functions for the object class SUA List & Object*/ +/***********************************************************************/ +void db_dummy_xxxxIndNotif ( unsigned int local_sua_Id, + unsigned int primitive, + unsigned int datalen + ) +{ + cout << "You've just called the dummy_xxxxIndNotif function ! \n"; + cout << "Better check youre initialisation and registration !! \n"; +} + +void db_dummy_DisxIndNotif ( unsigned int local_sua_Id, + unsigned int primitive, + unsigned int cause, + unsigned int datalen + ) +{ + cout << "You've just called the dummy_DisxIndNotif function ! \n"; + cout << "Better check youre initialisation and registration !! \n"; +} +/***********************************************************************/ +/* functions of the object class SUA SSN Object */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_SSNObject::read_ssn */ +/***********************************************************************/ +void db_Sua_SSNObject::read_ssn(string ssn_str){ + + char *tokstr = new char[ssn_str.length()+1]; + short sua_ssn; + + + ssn_str.copy(tokstr,ssn_str.length()); + tokstr[ssn_str.length()] = '\0'; + sua_ssn = atoi(tokstr); + + ssn = sua_ssn; + +#ifdef DEBUG + //cout << "SSN value = " << sua_ssn << "\n"; +#endif +}; + +/***********************************************************************/ +/* functions of the object class SUA Address Object */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_AddressObject::read_addr_param */ +/***********************************************************************/ +void db_Sua_AddressObject::read_addr_param(string address_str){ + int b=0,len=0,count_punct=0, count_colon=0; + unsigned int i=0; + int tokstr_len = 0; + char *tokstr; + int result; + +#ifdef DEBUG + cout << "address = " << address_str << " len = " <<address_str.length() << "\n"; +#endif + + while ((i <= address_str.length())) + { + if (address_str[i] == '.') count_punct++; + if (address_str[i] == ':') count_colon++; + if ((address_str[i] == ',') || (i == address_str.length())) + { + len = i - b; + string dest(address_str,b,len); + + tokstr_len = dest.length()+1; + tokstr = new char[tokstr_len]; + + dest.copy(tokstr,dest.length()); + // we are dealing with char arrays, so.... + tokstr[dest.length()] = '\0'; + short k; + for(k=0; k < tokstr_len; k++) + address_string[nr_of_addrs][k] = tokstr[k]; + if (count_punct == 3) + { // IPv4 address parameters + addrs[nr_of_addrs].sa.sa_family = AF_INET; + addrs[nr_of_addrs].sin.sin_port = SUA_PORT; + result = inet_pton(AF_INET, tokstr,&addrs[nr_of_addrs].sin.sin_addr); + if (result != 1) + cout << "IPvx address conversion returned "<< result << " \n"; +#ifdef DEBUG + cout << "IPv4 = " << addrs[nr_of_addrs].sin.sin_addr.s_addr << " \n"; +#endif + } + if (count_colon >= 2) + { // IPv6 address parameters + addrs[nr_of_addrs].sa.sa_family = AF_INET6; + addrs[nr_of_addrs].sin6.sin6_port = SUA_PORT; + result = inet_pton(AF_INET6, tokstr,&addrs[nr_of_addrs].sin6.sin6_addr); + if (result != 1) + cout << "IPvx address conversion returned "<< result << " \n"; +#ifdef DEBUG + cout << "IPv6 = " << &addrs[nr_of_addrs].sin6.sin6_addr << " \n"; +#endif + } + + nr_of_addrs++; + b = i + 1; + count_punct = 0; + count_colon = 0; + + } + + i++; + + } +#ifdef DEBUG + cout << "number of address = " << nr_of_addrs << " \n"; +#endif +} + +/***********************************************************************/ +/* Sua_AddressObject::read_pointcode */ +/***********************************************************************/ +void db_Sua_AddressObject::read_pointcode_param(string pointcode_str) { + int b=0,len=0; + unsigned int i=0; + int tokstr_len = 0; + char *tokstr; + +#ifdef DEBUG + cout << "Pointcode string = " << pointcode_str << " len = " << pointcode_str.length() << "\n"; +#endif + + while ((i <= pointcode_str.length())) + { + if (i == pointcode_str.length()) + { + len = i - b; + string dest(pointcode_str,b,len); + + tokstr_len = dest.length()+1; + tokstr = new char[tokstr_len]; + + dest.copy(tokstr,dest.length()); + // we are dealing with char arrays, so.... + tokstr[dest.length()] = '\0'; + + pc.ITU24.family = ITU24bit; + pc.ITU24.pc = atoi(tokstr); + +#ifdef DEBUG + cout << "Pointcode value = " << pc.ITU24.pc << " \n"; +#endif + b = i + 1; + } + i++; + } + +#ifdef DEBUG + cout << "Only 1 pointcode per association allowed \n"; +#endif +} + +/***********************************************************************/ +/* Sua_AddressObject::read_port_num */ +/***********************************************************************/ +void db_Sua_AddressObject::read_port_num(string port_str){ + int i=0; + char *tokstr = new char[port_str.length()+1]; + int sua_port_number; + + + port_str.copy(tokstr,port_str.length()); + tokstr[port_str.length()] = '\0'; + sua_port_number = atoi(tokstr); + + for(i = 0; i < nr_of_addrs ; i++) + addrs[i].sin6.sin6_port = sua_port_number; + +#ifdef DEBUG + //cout << "Portnumber = " << sua_port_number << " * " << nr_of_addrs << " times \n"; +#endif +} + +/***********************************************************************/ +/* functions of the object class SUA Local Object */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_LocalObject::initalize */ +/***********************************************************************/ +void db_Sua_LocalObject::initialize(){ + + + SUA_APLCallBack.ulp_ClDataIndNotif = &db_dummy_xxxxIndNotif; + SUA_APLCallBack.ulp_ConnIndNotif = &db_dummy_xxxxIndNotif; + SUA_APLCallBack.ulp_ConnConfIndNotif = &db_dummy_xxxxIndNotif; + SUA_APLCallBack.ulp_ConnDataIndNotif = &db_dummy_xxxxIndNotif; + SUA_APLCallBack.ulp_DisConnIndNotif = &db_dummy_DisxIndNotif; + +} + +/***********************************************************************/ +/* functions of the object class SUA LocalList */ +/***********************************************************************/ +/***********************************************************************/ +/* Sua_LocalList::initialize */ +/***********************************************************************/ +void db_Sua_LocalList::initialize(){ + short i; + num_of_instance = 0; + for (i=0; i < db_MAX_LOCAL_SUA; i++) + { + instance[i].initialize(); + } +} + +/***********************************************************************/ +/* Sua_LocalList::read_ssn */ +/***********************************************************************/ +void db_Sua_LocalList:: read_ssn(string ssn_str){ + + instance[num_of_instance].ssn.read_ssn(ssn_str); +}; + +/***********************************************************************/ +/* Sua_LocalList::increase_instance */ +/***********************************************************************/ +void db_Sua_LocalList:: increase_instance(){ + + num_of_instance++; +#ifdef DEBUG + cout << "New instance nr " << (num_of_instance - 1) << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "New instance nr %d", num_of_instance - 1); + event_log("sua_database.c",logstring); + +}; + + +/***********************************************************************/ +/* Sua_LocalList::unregister_instance */ +/***********************************************************************/ +short db_Sua_LocalList:: unregister_instance(){ + + int i; + + for(i=0; i < num_of_instance; i++) + { +#ifdef DEBUG + cout << "UnRegister SUA(& SCTP) local instance nr " << i << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "Unregister SUA(& SCTP) local instance nr %d", i); + event_log("sua_database.c",logstring); + /* result = sctp_unregisterSCTP_instance ( instance[i].assoc_id ); + */ + } + return(0); +}; + +/***********************************************************************/ +/* Sua_LocalList::register_instance */ +/***********************************************************************/ +short db_Sua_LocalList:: +register_instance( unsigned int local_sua_id, + Sua_ULP_CallBacks SUACallbackFunctions, + unsigned int init_association + ){ + + + instance[local_sua_id].SUA_APLCallBack.ulp_ClDataIndNotif = SUACallbackFunctions.ulp_ClDataIndNotif; + instance[local_sua_id].SUA_APLCallBack.ulp_ConnIndNotif = SUACallbackFunctions.ulp_ConnIndNotif; + instance[local_sua_id].SUA_APLCallBack.ulp_ConnConfIndNotif = SUACallbackFunctions.ulp_ConnConfIndNotif; + instance[local_sua_id].SUA_APLCallBack.ulp_ConnDataIndNotif = SUACallbackFunctions.ulp_ConnDataIndNotif; + instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif = SUACallbackFunctions.ulp_DisConnIndNotif; + + instance[local_sua_id].init_assoc_id = init_association; + + return(0); +} + +/***********************************************************************/ +/* functions of the object class SUA Remote Object */ +/***********************************************************************/ +/***********************************************************************/ +/* Sua_RemoteObject::initalize */ +/***********************************************************************/ +void db_Sua_RemoteObject::initialize(){ + + ; +} + +/***********************************************************************/ +/* functions of the object class SUA RemoteList */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_RemoteList::initialize */ +/***********************************************************************/ +void db_Sua_RemoteList::initialize(){ + short i; + num_of_instance = 0; + for (i=0; i < db_MAX_REMOTE_SUA; i++) + { + instance[i].initialize(); + } +} + +/***********************************************************************/ +/* Sua_RemoteList::read_ssn */ +/***********************************************************************/ +void db_Sua_RemoteList:: read_ssn(string ssn_str){ + + instance[num_of_instance].ssn.read_ssn(ssn_str); +}; + +/***********************************************************************/ +/* Sua_RemoteList::increase_instance */ +/***********************************************************************/ +void db_Sua_RemoteList:: increase_instance(){ + + num_of_instance++; +#ifdef DEBUG + cout << "New instance nr " << (num_of_instance - 1) << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "New instance nr %d", num_of_instance - 1); + event_log("sua_database.c",logstring); + +}; +/***********************************************************************/ +/* functions of the object class SUA Application Server Process (ASP) */ +/***********************************************************************/ +/***********************************************************************/ +/* Sua_ASPObject::initalize */ +/***********************************************************************/ +void db_Sua_ASPObject::initialize(){ + short j; + + status = asp_idle; + for (j=0; j < db_MAX_1ASP_IN_AS ; j++) + linked_to_AS[j] = 0; +} + +/***********************************************************************/ +/* Sua_ASPObject::Activate ASP */ +/***********************************************************************/ +bool db_Sua_ASPObject::activate(unsigned int sua_assoc_id, + short mode + ) +{ + bool traf_hold=FALSE; + short i; + + + switch ( status) + { + case (asp_inactive): + { + switch (mode) + { + case (tmt_override ): + { + cout << "ASP in override mode\n"; + /* this node becomes the override node for processing */ + /* all other ASP of this AS must be put in standby */ + i = 0; + /*while (i <= db_MAX_1ASP_IN_AS) + { + if ((linked_to_AS[i] > 0) && + (linked_to_AS[i] <= db_MAX_SUA_AS)) + Asp_mngt_standby ( linked_to_AS[i], + sua_assoc_id, + mode + ); + }*/ + } + case (tmt_loadshare): + { + cout << "ASP in loadshare mode\n"; + } + case (tmt_max/*broadcast*/): + { + cout << "ASP in broadcast -> very dangerous\n"; + } + default: + { + cout << "default mode in activation\n"; + } + } + status = asp_active; + } + case (asp_inactive_traf_hold): + { + status = asp_active; + traf_hold = TRUE; + } + default: + { + /* remain in same state */ + /* depdending on the mode of the ASPAC */ + ; + } + } + return(traf_hold); +} + +/***********************************************************************/ +/* Sua_ASPObject::inactivate ASP */ +/***********************************************************************/ +void db_Sua_ASPObject::deactivate( unsigned int sua_assoc_id, + short mode + ) +{ + if( status == asp_active) + status = asp_inactive; +} + +/***********************************************************************/ +/* Sua_ASPObject::put ASP up = inactive */ +/***********************************************************************/ +void db_Sua_ASPObject::up( unsigned int sua_assoc_id, + short mode + ) +{ + switch(status) + { + case( asp_down): + { + status = asp_inactive; + } + case (asp_down_traf_hold): + { + status = asp_inactive_traf_hold; + } + default: + { + // do nothing , state is not changed + } + } +} + +/***********************************************************************/ +/* Sua_ASPObject::put ASP in down mode */ +/***********************************************************************/ +void db_Sua_ASPObject::down( unsigned int sua_assoc_id, + short mode + ) +{ + status = asp_down; +} + +/***********************************************************************/ +/* functions of the object class SUA Application Server List */ +/***********************************************************************/ +/***********************************************************************/ +/* Sua_ASList::initalize */ +/***********************************************************************/ +void db_Sua_ASList::initialize(){ + + short i,j; + num_of_instance = 0; + for (i=0; i < db_MAX_SUA_AS; i++) + { + instance[i].status = as_idle; + for (j=0; j < db_MAX_ASP_IN_1AS; j++) + instance[i].ASP_linked_to_this_AS[j] = 0; + } +} + +/***********************************************************************/ +/* Sua_ASList::read_AS string */ +/***********************************************************************/ +short db_Sua_ASList::read_AS( string as_str, + unsigned int sua_id + ){ + int i=0; + char *tokstr = new char[as_str.length()+1]; + int as_number; + bool cont_loop; + + + as_str.copy(tokstr,as_str.length()); + tokstr[as_str.length()] = '\0'; + as_number = atoi(tokstr); + + if ( instance[as_number].status == as_idle) + instance[as_number].status = as_down; + + i= 0; + cont_loop = (i < db_MAX_ASP_IN_1AS); + while (cont_loop) + { + if (instance[as_number].ASP_linked_to_this_AS[i] == 0) + { + instance[as_number].ASP_linked_to_this_AS[i] = sua_id; + cont_loop = false; + } + } +#ifdef DEBUG + cout << "Application Server number used " << as_number << " for ASP " << sua_id << "\n"; +#endif + + return(as_number); + +} + +/***********************************************************************/ +/* AS_override_ASP */ +/***********************************************************************/ +void db_Sua_ASList::override_ASP( unsigned int asp_sua_assoc_id, + unsigned int AS_id, + short mode + ) +{ + short i; + short asp_present_nr = 0; + unsigned short processed_ASP = 0; + + for (i=0; i <= db_MAX_ASP_IN_1AS; i++){ + processed_ASP = instance[AS_id].ASP_linked_to_this_AS[i]; + if (processed_ASP == asp_sua_assoc_id ) + { + asp_present_nr++; + asp_activate_override(asp_sua_assoc_id); + } + else if ((processed_ASP > 0) && + (processed_ASP <= db_MAX_REMOTE_SUA)) + { + asp_present_nr++; + asp_deactivate(asp_sua_assoc_id); + } + /*else nothing to do */ + + } + //if (asp_present_nr = 0) + // instance(AS_id).status = as_ +} + +// end of module sua_database.c + + + + + + diff --git a/sualibrary/sua/sua_database.h b/sualibrary/sua/sua_database.h new file mode 100644 index 0000000..9b2005a --- /dev/null +++ b/sualibrary/sua/sua_database.h @@ -0,0 +1,397 @@ +/*************************************************************************** + sua_database.h - 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_database.h,v 1.2 2002/02/07 16:34:27 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 8. + * + * Author(s): 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 : Ann S. + * "Don't mention the war." + * + * Purpose: This code-file defines the SUA database objects for: + * - Sybsystem Number(SSN) Object + * - Address Object + * - Local SUA Object + * - Local SUA List + * - Remote SUA object + * - Remote SUA List + * - SUA Name Object(host names/Global Titles) + * - SUA Name List + * - SUA Association Object + * - SUA Association List + * - SUA Application Server Process (ASP) Object + * - SUA Application Server (AS) Object + * - SUA Application Server (AS) List + */ + +#ifndef SUA_DATABASE_H +#define SUA_DATABASE_H + +#include "sua.h" +#include "sua_asp_mgnt.h" + +#include <string> + + + +typedef enum {nc_empty, nc_ipv4, nc_ipv6} db_net_class; + +const int db_MAX_MULTIHOME_ADDR = 10; +const int db_MAX_LOCAL_SUA = 10; +const int db_MAX_REMOTE_SUA = 1000; +const int db_MAX_SSN_SUA = 256; +const int db_MAX_SUA_AS = 100; +const int db_MAX_ASP_IN_1AS = 8; /* maximal 8 ASP's can be covered by a single AS */ +const int db_MAX_1ASP_IN_AS = 4; /* 1 ASP can appear in maximal up till 4 different AS's */ + +/***********************************************************************/ +/* Sua_SSNObject */ +/***********************************************************************/ +class db_Sua_SSNObject { + public: + short ssn; + public: + void read_ssn(string ssn); +}; ///:~ + +/***********************************************************************/ +/* Sua_LocalObject */ +/***********************************************************************/ +class db_Sua_LocalObject{ + public: + db_Sua_SSNObject ssn; + /* contains the initial SUA association */ + unsigned int init_assoc_id; + /* the local sua id with which it is linked. */ + unsigned int sua_id; + Sua_ULP_CallBacks SUA_APLCallBack; + public: + // functions of the Class + void initialize(); +}; ///:~ + +/***********************************************************************/ +/* Sua_LocalList */ +/***********************************************************************/ +class db_Sua_LocalList{ + public: + int num_of_instance; + db_Sua_LocalObject instance[db_MAX_LOCAL_SUA]; + void initialize(); + void read_ssn(string ssn); + short register_instance( unsigned int local_sua_id, + Sua_ULP_CallBacks SUACallbackFunctions, + unsigned int init_assoc_id + ); + short unregister_instance(); + void increase_instance(); +}; ///:~ + +/***********************************************************************/ +/* Sua_RemoteObject */ +/***********************************************************************/ +class db_Sua_RemoteObject{ + public: + db_Sua_SSNObject ssn; + /* contains the SCTP assoc id */ + unsigned int SCTP_assoc_id; + /* contains the local sua id with which it is linked. */ + unsigned int sua_id; + public: + // functions of the Class + void initialize(); +}; ///:~ + +/***********************************************************************/ +/* Sua_RemoteList */ +/***********************************************************************/ +class db_Sua_RemoteList{ + public: + int num_of_instance; + public: + db_Sua_RemoteObject instance[db_MAX_REMOTE_SUA]; + void initialize(); + void read_ssn(string ssn); + void increase_instance(); + +}; ///:~ + + +/***********************************************************************/ +/* Sua_AddressObject */ +/***********************************************************************/ +class db_Sua_AddressObject { + public: + int nr_of_addrs; // number of ip addresses used(multihoming) + unsigned char address_string[db_MAX_MULTIHOME_ADDR][SCTP_MAX_IP_LEN]; + ipvxunion addrs[db_MAX_MULTIHOME_ADDR]; + SS7union pc; + public: + void read_addr_param(string address); + void read_pointcode_param(string point_code); + void read_port_num(string port); +}; ///:~ + +/***********************************************************************/ +/* Sua_ApplicationServerProcessObject (ASP) */ +/***********************************************************************/ +class db_Sua_ASPObject { + public: + asp_Sua_asp_state_set status; /* status of the ASP */ + short linked_to_AS[db_MAX_1ASP_IN_AS]; /* this ASP may belong to different Application Servers(AS) */ + public: + void initialize(); + bool activate( unsigned int sua_assoc_id, short mode ); + void deactivate( unsigned int sua_assoc_id, short mode ); + void down( unsigned sua_assoc_id, short mode ); + void up( unsigned sua_assoc_id, short mode ); +}; ///:~ + +/***********************************************************************/ +/* Sua_LS_OverRideObject (LS_OverRide) */ +/***********************************************************************/ +class db_Sua_LS_OverRideObject { + private: + short ASP_to_use; /* ASP presently being the workhorse)*/ + public: + void assign_ASP(short ASP_num); + short ASP_used(); +}; ///:~ + +/***********************************************************************/ +/* Sua_LS_RoundRobinObject (LS_RoundRobin) */ +/***********************************************************************/ +class db_Sua_LS_RoundRobinObject { + private: + short ASP_to_use; /* ASP presently being the workhorse)*/ + public: + short ASP_used(); +}; + +/***********************************************************************/ +/* Sua_LoadShareObject (LS_AS) */ +/***********************************************************************/ +class db_Sua_LoadShareObject { + public: + asp_Sua_loadmode_set load_mode; /* mode of loadsharing)*/ + db_Sua_LS_OverRideObject override; /* AS has a ASP in override */ + db_Sua_LS_RoundRobinObject RRobin; /* AS is RR all active ASP's */ +}; ///:~ + + +/***********************************************************************/ +/* Sua_ApplicationServerObject (AS) */ +/***********************************************************************/ +class db_Sua_ASObject { + public: + asp_Sua_as_state_set status; /* status of the AS */ + short ASP_linked_to_this_AS[db_MAX_ASP_IN_1AS];/* AS may contain a couple of ASP's */ + db_Sua_LoadShareObject loadshare; + public: + void initialize(); +}; ///:~ + +/***********************************************************************/ +/* Sua_ApplicationServerList (AS list) */ +/***********************************************************************/ +class db_Sua_ASList{ + public: + int num_of_instance; + db_Sua_ASObject instance[db_MAX_SUA_AS]; + public: + void initialize(); + short read_AS( string address_str, + unsigned int sua_id + ); + void override_ASP( unsigned int asp_sua_assoc_id, + unsigned int AS_id, + short mode + ); +}; ///:~ + +/***********************************************************************/ +/* Sua_AssociationsObject */ +/***********************************************************************/ +class db_Sua_AssociationObject { + public: + unsigned int SCTP_assoc_id; + unsigned int SCTP_instance_name; + unsigned int remote_sua_id; + unsigned int local_sua_id; + short nr_of_inbound_streams; + short nr_of_outbound_streams; + db_Sua_ASPObject asp; + db_net_class netw; // sort of network(v4/v6) to be used + // ip source/destination addresses , should be the same network type + db_Sua_AddressObject Source; + db_Sua_AddressObject Dest; + public: + void initialize(); + short shutdown(); +}; ///:~ + +/***********************************************************************/ +/* Sua_AssociationList */ +/***********************************************************************/ +class db_Sua_AssociationList{ + public: + int num_of_instance; + db_Sua_AssociationObject instance[db_MAX_REMOTE_SUA]; + public: + void initialize(); + void read_Source_addr(string address); + void read_Dest_addr(string address); + void read_Source_pointcode(string address); + void read_Dest_pointcode(string address); + void read_Source_port(string port); + void read_Dest_port(string port); + void read_stream_number(string stream_num); + short register_instance(SCTP_ulp_Callbacks APLCallbackFunctions, + Sua_ULP_CallBacks SUACallbackFunctions, + db_Sua_LocalList& local_sua + ); + short unregister_instance(); + unsigned int Find_association( unsigned int sctp_assoc_id, + unsigned int &Local_sua_id, + unsigned int &Remote_sua_id + ); + unsigned int Find_local_sua( sccp_addr_str& local_address + ); + short associate_instance( db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua + ); + unsigned int passive_associate( unsigned int assoc_id, + db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua, + unsigned short nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams + ); + unsigned int Dynamic_Associate( db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua, + sccp_addr_str& cld, + sccp_addr_str& clg, + unsigned short nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams + ); + short Terminate_remote_assoc_instance(); + short shutdown(); + signed int route_msg(sccp_addr_str& cld, + sccp_addr_str& clg + ); + signed int route_on_IPpc ( ipvxunion& dest_pc, + ipvxunion& org_pc, + int& sua_assoc_id + ); + signed int route_on_SS7pc ( SS7union& dest_pc, + SS7union& org_pc, + int& sua_assoc_id + ); + signed int route_on_GTname ( hostname_str& dest_name, + hostname_str& org_name, + int& sua_assoc_id, + pointcode_str& dest_pc, + pointcode_str& org_pc + ); + void increase_instance(); + bool activate( unsigned int sua_id, + short mode + ); + void deactivate( unsigned int sua_id, + short mode + ); + void down( unsigned int sua_id, + short mode + ); + void up( unsigned int sua_id, + short mode + ); +}; ///:~ + +/***********************************************************************/ +/* Sua_NameObject */ +/***********************************************************************/ +class db_Sua_NameObject { + public: + unsigned int SUA_assoc_id; + public: + void initialize(); + +}; ///:~ + +/***********************************************************************/ +/* Sua_NameList */ +/***********************************************************************/ +class db_Sua_NameList{ + public: + int num_of_instance; + db_Sua_NameObject instance[db_MAX_REMOTE_SUA]; + public: + void initialize(); + string read_host_name(string name); + string read_Global_Title(string name); + unsigned int perform_GTT( sccp_addr_str& cld_in, + sccp_addr_str& clg_in, + sccp_addr_str& cld_out, + sccp_addr_str& clg_out + ); + void increase_instance(); +}; ///:~ + +#endif // SUA_DATABASE_H + +//end of module sua_database.h + + + + + + + + + + + + + diff --git a/sualibrary/sua/sua_dataname.cpp b/sualibrary/sua/sua_dataname.cpp new file mode 100644 index 0000000..b1e6914 --- /dev/null +++ b/sualibrary/sua/sua_dataname.cpp @@ -0,0 +1,174 @@ +/*************************************************************************** + sua_dataname.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_dataname.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Vicky + * "This module reuse some code, thus it will mostly reuse trouble." + * + * Purpose: This code-file defines the SUA database access functions for: + * SUA Name Object (host names/Global Titles): + * - initialise Name + * SUA Name List: + * - initialise Name List + * - read hostname + */ + +#include "sctp.h" + +#include "sua_debug.h" +#include "sua_database.h" +#include "sua_asp_mgnt.h" +#include "sua_logging.h" + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> + +#include "unistd.h" + + + +using namespace std; + +/***********************************************************************/ +/* functions of the object class SUA name Object */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_NameObject::initalize */ +/***********************************************************************/ +void db_Sua_NameObject::initialize(){ + + // initialise to point to a invalid SUA association + SUA_assoc_id = 0; +} + + + +/***********************************************************************/ +/* functions of the object class SUA NameList */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_NameList::initalize */ +/***********************************************************************/ +void db_Sua_NameList::initialize(){ + short i; + num_of_instance = 0; + for (i=0; i < db_MAX_REMOTE_SUA; i++) { + instance[i].initialize(); + } +} + +string db_Sua_NameList::read_host_name(string name){ + + char *hostname; + const char *ip_addr_ptr; + struct hostent *hptr; + char str[INET6_ADDRSTRLEN]; + char **pptr; + string addr_str; + + hostname = new char[name.length()+1]; + name.copy(hostname,name.length()); + // we are dealing with char arrays, so.... + hostname[name.length()] = '\0'; + + if ((hptr = gethostbyname(hostname)) == NULL){ + cout << "Determination of hostname failed\n"; + return("127.0.0.1"); + } + +#ifdef DEBUG + cout << "Hostname " << hptr->h_name << " has the following IP address(es)\n"; +#endif + + pptr = hptr->h_addr_list; + for ( ; *pptr != NULL;pptr++) + { + ip_addr_ptr = inet_ntop(hptr->h_addrtype, *pptr, str,sizeof(str)); + addr_str = addr_str + ip_addr_ptr; + if ((*(pptr+1)) != NULL) + /* another ip address is comming after the present one */ + addr_str = addr_str + ","; + /*else this is the last ip address */ +#ifdef DEBUG + cout << ip_addr_ptr << "\n"; +#endif + } + +#ifdef DEBUG + cout << "output IP list = " << addr_str << "\n"; +#endif + + string name_str; + int last= name.size(); + unsigned int current = name.rfind('.'); + while(current != string::npos){ + name_str = name_str + name.substr(current+1,(last-current)) + "."; + last= current - 1; + current = name.rfind('.', last); + } + name_str = name_str + name.substr(0,last+1); + +#ifdef DEBUG + cout << "Ready for storing SUA dest hostname = " << name_str << " in NameDB\n"; +#endif + + + return(addr_str); + +} + + +// end of module sua_dataname.c + + + + + + diff --git a/sualibrary/sua/sua_datassoc.cpp b/sualibrary/sua/sua_datassoc.cpp new file mode 100644 index 0000000..c3bcc5f --- /dev/null +++ b/sualibrary/sua/sua_datassoc.cpp @@ -0,0 +1,1000 @@ +/*************************************************************************** + sua_datassoc.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_datassoc.cpp,v 1.3 2002/02/15 16:19:46 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Vera + * "You ain't seen nothing yet" + * "said Garfield the Ripper while putting on his binbag" + * + * Purpose: This code-file defines the SUA database access functions for + * SUA Association Object: + * - initialise association object + * - shutdown association + * - Dynamic association + * SUA Association List: + * - initialise association list + * - read source address + * - read Destination address + * - read source port + * - read destination port + * - read stream number + * - register instance + * - associate instance(initiating) + * - Find a association + * - Find a local SUA instance + * - Passive association instantiation(terminating) + * - shutdown a association + * - route on IP pointcode address + * - route on Global Title/Hostname + * - route message to a association + * - increase instance + * - Dynamic association setup(initiating) + */ + +#include "sctp.h" + +#include "sua_debug.h" +#include "sua_database.h" +#include "sua_asp_mgnt.h" +#include "sua_logging.h" + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> +#include <netinet/in.h> + +#include "unistd.h" + + + +using namespace std; + +struct ulp_data_str { + int maximumStreamID; + unsigned int chunkCount; +}; + +static ulp_data_str ULPData[db_MAX_MULTIHOME_ADDR]; + + +/***********************************************************************/ +/* functions of the object class SUA Association Object */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_AssociationObject::initalize */ +/***********************************************************************/ +void db_Sua_AssociationObject::initialize(){ + short i; + Source.nr_of_addrs = 0; + Dest.nr_of_addrs = 0; + netw = nc_empty; + nr_of_inbound_streams = 0; + nr_of_outbound_streams = 0; + asp.status = asp_down; + for (i=0; i < db_MAX_MULTIHOME_ADDR; i++) { + Source.addrs[i].sa.sa_family = AF_INET; + Dest.addrs[i].sa.sa_family = AF_INET; + } + Source.pc.ITU24.pc = 0; + Dest.pc.ITU24.pc = 0; + for (i=0; i < db_MAX_1ASP_IN_AS; i++) + asp.linked_to_AS[i] = 0; +} + +/***********************************************************************/ +/* Sua_RemoteObject::shutdown_instance */ +/***********************************************************************/ +short db_Sua_AssociationObject:: shutdown(){ + + int result; + result = sctp_shutdown( SCTP_assoc_id ); + + return(result); + +}; + +/***********************************************************************/ +/* Sua_AssociationL::Dynamic_Associate */ +/***********************************************************************/ +unsigned int Dynamic_Associate( sccp_addr_str& cld, + sccp_addr_str& clg + ) +{ + return(0); +} + +/***********************************************************************/ +/* functions of the object class SUA AssociationList */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_AssociationList::initalize */ +/***********************************************************************/ +void db_Sua_AssociationList::initialize(){ + short i; + num_of_instance = 0; + for (i=0; i < db_MAX_REMOTE_SUA; i++) { + instance[i].initialize(); + } +} + + +/***********************************************************************/ +/* Sua_AssociationList::read_Source_addr */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Source_addr(string address){ + + instance[num_of_instance].Source.read_addr_param(address); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_Dest_addr */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Dest_pointcode(string address){ + + instance[num_of_instance].Dest.read_pointcode_param(address); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_Source_pointcode */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Source_pointcode(string address){ + + instance[num_of_instance].Source.read_pointcode_param(address); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_Dest_addr */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Dest_addr(string address){ + + instance[num_of_instance].Dest.read_addr_param(address); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_Source_port */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Source_port(string port){ + + instance[num_of_instance].Source.read_port_num(port); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_Dest_port */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Dest_port(string port){ + + instance[num_of_instance].Dest.read_port_num(port); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_stream_number */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_stream_number(string stream_num){ + + + int i=0; + char *tokstr = new char[stream_num.length()+1]; + int sua_stream_nr; + + + stream_num.copy(tokstr,stream_num.length()); + tokstr[stream_num.length()] = '\0'; + sua_stream_nr = atoi(tokstr); + + for(i = 1; i <= num_of_instance ; i++) { + instance[i].nr_of_inbound_streams = sua_stream_nr; + instance[i].nr_of_outbound_streams = sua_stream_nr; + } +} + +/***********************************************************************/ +/* Sua_AssociationList::register_instance */ +/***********************************************************************/ +short db_Sua_AssociationList:: +register_instance( SCTP_ulp_Callbacks APLCallbackFunctions, + Sua_ULP_CallBacks SUACallbackFunctions, + db_Sua_LocalList& local_sua + ){ + + int i; + unsigned int local_sua_idx; + short sua_portnumber = SUA_PORT; + + for(i=1; i <= num_of_instance; i++) + { + local_sua_idx = instance[i].local_sua_id; +#ifdef DEBUG + cout << "Register SUA(& SCTP) local instance nr " << local_sua_idx << " with association " << i << " ,SSN = "<< local_sua.instance[local_sua_idx].ssn.ssn <<" \n"; +#endif + char logstring[100]; + sprintf(logstring, "Register SUA(& SCTP) local instance nr %d with association %d, SSN = %d", local_sua_idx,i,local_sua.instance[local_sua_idx].ssn.ssn ); + event_log("sua_database.c",logstring); + local_sua.register_instance( instance[i].local_sua_id, + SUACallbackFunctions, + i + ); + if (instance[i].Source.addrs[0].sa.sa_family == AF_INET) + sua_portnumber = instance[i].Source.addrs[0].sin.sin_port; + else if (instance[i].Source.addrs[0].sa.sa_family == AF_INET6) + sua_portnumber = instance[i].Source.addrs[0].sin6.sin6_port; + + instance[i].SCTP_instance_name = + sctp_registerInstance( sua_portnumber, + instance[i].nr_of_inbound_streams, + instance[i].nr_of_outbound_streams, + instance[i].Source.nr_of_addrs, + instance[i].Source.address_string, + APLCallbackFunctions + ); + +#ifdef DEBUG + cout << "SCTP instance name = " << instance[i].SCTP_instance_name << " \n"; +#endif + sprintf(logstring, "Local SCTP instance nr %d name = %d", i, instance[i].SCTP_instance_name); + event_log("sua_database.c",logstring); + + } +return(0); +}; + +/***********************************************************************/ +/* Sua_AssociationList::associate_instance */ +/***********************************************************************/ +short db_Sua_AssociationList:: +associate_instance( db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua + ){ + + int i; + SCTP_InstanceParameters SCTP_assoc_parms; + SCTP_InstanceParameters *SCTP_assoc_status = &SCTP_assoc_parms; + short sua_portnumber = SUA_PORT; + int res=0; + + // get default values of association + res = sctp_getAssocDefaults( instance[1].SCTP_instance_name, + SCTP_assoc_status + ); + + // fill in the TOS field needed for DIFFSERV + SCTP_assoc_status->ipTos = 'a'; + + // set the new value for all associations + res = sctp_setAssocDefaults( instance[1].SCTP_assoc_id, + SCTP_assoc_status + ); + + for(i=1; i <= num_of_instance; i++) + { + if (instance[i].Dest.nr_of_addrs != 0) { +#ifdef DEBUG + cout << "Associate remote SUA(& SCTP) instance nr " << i << " with local SUA(& SCTP) instance nr " << instance[i].local_sua_id <<" \n"; +#endif + char logstring[100]; + sprintf(logstring, "Associate Remote SUA(& SCTP) instance nr %d with local SUA(& SCTP) instance nr %d", i, instance[i].local_sua_id ); + event_log("sua_database.c",logstring); + + if (instance[i].Dest.addrs[0].sa.sa_family == AF_INET) + sua_portnumber = instance[i].Dest.addrs[0].sin.sin_port; + else if (instance[i].Dest.addrs[0].sa.sa_family == AF_INET6) + sua_portnumber = instance[i].Dest.addrs[0].sin6.sin6_port; + + ULPData[0].maximumStreamID = -1; + + short unsigned instance_name = instance[i].SCTP_instance_name ; + instance[i].SCTP_assoc_id = + sctp_associate( instance_name, + instance[i].nr_of_outbound_streams, + instance[i].Dest.address_string[0], + sua_portnumber, + NULL + ); + + /* no msg queued, mark assoc down(from sua management viewpoint)*/ + instance[i].asp.status = asp_down; + +#ifdef DEBUG + cout << "SCTP association result = " << instance[i].SCTP_assoc_id <<" \n"; +#endif + + } + } + return(0); +}; + + +/***********************************************************************/ +/* Sua_AssociationList::Find_association */ +/***********************************************************************/ +unsigned int db_Sua_AssociationList:: +Find_association( unsigned int sctp_assoc_id, + unsigned int &Local_sua_id, + unsigned int &Remote_sua_id + ) +{ + short i = 0; + unsigned int sua_assoc_id = 0; + bool result = FALSE; + Local_sua_id = 0; + Remote_sua_id = 0; + + while ((i < db_MAX_REMOTE_SUA) && !(result)) + { + + result = (instance[i].SCTP_assoc_id == sctp_assoc_id); + if (result) { + Local_sua_id = instance[i].local_sua_id; + Remote_sua_id = instance[i].remote_sua_id; + sua_assoc_id = i; + } + i++; + } + + return(sua_assoc_id); +}; + +/***********************************************************************/ +/* Sua_AssociationList::Find_local_sua */ +/***********************************************************************/ +unsigned int db_Sua_AssociationList:: +Find_local_sua( sccp_addr_str& local_address + ) +{ + short i = 1, j = 0; + unsigned int Local_sua_id = 0; + bool result = FALSE; + + while ((i < db_MAX_REMOTE_SUA) && !(result) && (instance[i].Source.nr_of_addrs != 0)) + { + j = 0; + while ((j < instance[i].Source.nr_of_addrs) && !(result)) + { + result = ((instance[i].Source.addrs[j].sin.sin_addr.s_addr == local_address.pc.ipvx.sin.sin_addr.s_addr) || + (instance[i].Source.addrs[j].sin6.sin6_addr.s6_addr == local_address.pc.ipvx.sin6.sin6_addr.s6_addr)); + if (result) + { + Local_sua_id = instance[i].local_sua_id; +#ifdef DEBUG + cout << "local_sua_id = " << Local_sua_id << " , instance "<< i << "\n"; +#endif + } + j++; + } + i++; + } + + return(Local_sua_id); +}; + +/***********************************************************************/ +/* Sua_AssociationList::passive_associate */ +/***********************************************************************/ +unsigned int db_Sua_AssociationList:: +passive_associate( unsigned int assoc_id, + db_Sua_LocalList &local_sua, + db_Sua_RemoteList &remote_sua, + unsigned short nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams + ){ + + SCTP_AssociationStatus status; + int result; + short k; + int bla; + short i = 1, assoc_instance_idx = 1; + bool cont, partial_assoc_found = FALSE; + + while ((i <= num_of_instance) && !(partial_assoc_found)){ + partial_assoc_found = (instance[i].Dest.nr_of_addrs == 0); + if (partial_assoc_found) + assoc_instance_idx = i; + + i++; + } + + if (!(partial_assoc_found)) + { + /* new association added */ + num_of_instance++; + assoc_instance_idx = num_of_instance; + instance[assoc_instance_idx].Source = instance[assoc_instance_idx-1].Source; + + instance[assoc_instance_idx].nr_of_inbound_streams = nr_of_input_streams ; + instance[assoc_instance_idx].nr_of_outbound_streams = nr_of_input_streams ; + } + + remote_sua.increase_instance(); + + instance[assoc_instance_idx].SCTP_assoc_id = assoc_id; + instance[assoc_instance_idx].remote_sua_id = remote_sua.num_of_instance; + remote_sua.instance[remote_sua.num_of_instance].ssn.ssn = local_sua.instance[local_sua.num_of_instance].ssn.ssn; + // should search for the correct sua local instance(future) + instance[assoc_instance_idx].local_sua_id = local_sua.num_of_instance; +#ifdef DEBUG + cout << "Associate remote SUA(& SCTP) instance nr " << assoc_id << " with local SUA(& SCTP) instance nr " << assoc_instance_idx << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "Associate Remote SUA(& SCTP) instance nr %d with local SUA(& SCTP) instance nr %d", assoc_id, assoc_instance_idx ); + event_log("sua_database.c",logstring); + + + result = sctp_getAssocStatus(instance[assoc_instance_idx].SCTP_assoc_id, &status); + + /* conversion and fill in the destination address */ + instance[assoc_instance_idx].Dest.nr_of_addrs = nr_of_dest_addr; + instance[assoc_instance_idx].Dest.address_string[0] = status.primaryDestinationAddress; + instance[assoc_instance_idx].Dest.addrs[0].sin.sin_port = status.destPort; + + /* try to figure out ipv4 or v6 address family: get it from the source address */ + k = 0; + instance[assoc_instance_idx].Dest.addrs[0].sa.sa_family = AF_LOCAL; + cont = true; + while ((k < 24) && (cont)) + { + if (instance[assoc_instance_idx].Dest.address_string[0][k] == '.') + { + cont = false; + instance[assoc_instance_idx].Dest.addrs[0].sa.sa_family = AF_INET; + } + if (instance[assoc_instance_idx].Dest.address_string[0][k] == ':') + { + cont = false; + instance[assoc_instance_idx].Dest.addrs[0].sa.sa_family = AF_INET6; + } + k++; + } + + for(k=0; k < instance[assoc_instance_idx].Dest.nr_of_addrs ; k++) + { + if (instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family == AF_INET) + bla = inet_pton( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family, + (char *)instance[assoc_instance_idx].Dest.address_string[k], + &instance[assoc_instance_idx].Dest.addrs[k].sin.sin_addr + ); + else if (instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family == AF_INET6) + bla = inet_pton( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family, + (char *)instance[assoc_instance_idx].Dest.address_string[k], + &instance[assoc_instance_idx].Dest.addrs[k].sin6.sin6_addr + ); + else + cout << "Unsupported address family in passive associate\n"; + + } + + /* no msg queued, mark assoc down(from sua management viewpoint)*/ + instance[assoc_instance_idx].asp.status = asp_down; + + return(assoc_instance_idx); +} + +/***********************************************************************/ +/* Sua_AssociationList::shutdown_instance */ +/***********************************************************************/ +short db_Sua_AssociationList:: shutdown(){ + + int i; + short result; + + for(i=1; i <= num_of_instance; i++) + { +#ifdef DEBUG + cout << "shutdown remote SUA(& SCTP) instance nr " << i << " with local SUA(& SCTP) instance nr " << instance[i].local_sua_id <<" \n"; +#endif + char logstring[100]; + sprintf(logstring, "Associate Remote SUA(& SCTP) instance nr %d with local SUA(& SCTP) instance nr %d", i, instance[i].local_sua_id ); + event_log("sua_database.c",logstring); + + result = instance[i].shutdown(); + + } + + return(0); +}; + +/***********************************************************************/ +/* Sua_AssociationList::route_on_IPpc */ +/***********************************************************************/ +signed int db_Sua_AssociationList:: +route_on_IPpc ( ipvxunion& dest_pc, + ipvxunion& org_pc, + int& sua_assoc_id + ) +{ + int j=0,i=1,count, addr_start, addr_stop; + unsigned int sctp_assoc_id = 0; + + sua_assoc_id = 0; + bool cont = (i <= num_of_instance); + bool found_assoc = false; + + while (cont) + { + found_assoc = false; + j = 0; + while ((j < instance[i].Dest.nr_of_addrs) && (!found_assoc)) + { + found_assoc = (dest_pc.sa.sa_family == instance[i].Dest.addrs[j].sa.sa_family); + if (dest_pc.sa.sa_family == AF_INET) + { + addr_start = 4; + addr_stop = addr_start + 4; + } + else if (dest_pc.sa.sa_family == AF_INET6) + { + addr_start = 8; + addr_stop = addr_start + 16; + } + else + { + addr_start = 0; + addr_stop = 0; + found_assoc = false; + cout << "ERROR route_on_IPpc: Unknown addresstype\n"; + } + /* compare the address family field */ + found_assoc = found_assoc && (dest_pc.ch[1] == instance[i].Dest.addrs[j].ch[1]); + + /* compare the ipv4/ipv6 address field */ + for (count = addr_start; count < addr_stop; count++) + { + found_assoc = found_assoc + && (dest_pc.ch[count] == instance[i].Dest.addrs[j].ch[count]); + } + j++; + } + + if (found_assoc) + { + cont = false; + sctp_assoc_id = instance[i].SCTP_assoc_id; + sua_assoc_id = i; +#ifdef DEBUG + cout << "Found Sua association " << i << " with SCTP assoc " << sctp_assoc_id << "\n"; + + if (dest_pc.sa.sa_family == AF_INET) + { + cout << "CLD ip v4 = " << dest_pc.sin.sin_addr.s_addr << "\n"; + cout << "Remote IP = " << instance[i].Dest.addrs[0].sin.sin_addr.s_addr << "\n"; + } + else if (dest_pc.sa.sa_family == AF_INET6) + { + cout << "CLD ip v6 = " << dest_pc.sin6.sin6_addr.s6_addr << "\n"; + cout << "Remote IP = " << instance[i].Dest.addrs[0].sin6.sin6_addr.s6_addr << "\n"; + } + else + cout << "Unknown CLD IP address type format\n"; +#endif + } + else + { + i++; + cont = (i <= num_of_instance); + } + } + + return(sctp_assoc_id); +}; + + +/***********************************************************************/ +/* Sua_AssociationList::route_on_SS7pc */ +/***********************************************************************/ +signed int db_Sua_AssociationList:: +route_on_SS7pc ( SS7union& dest_pc, + SS7union& org_pc, + int& sua_assoc_id + ) +{ + int i=1; + unsigned int sctp_assoc_id = 0; + +#ifdef DEBUG + cout << "route on SS7 PC\n"; + cout << "PC family = " << dest_pc.ITU24.family << "\n"; + cout << "PC value = " << dest_pc.ITU24.pc << "\n"; +#endif + + sua_assoc_id = 0; + bool cont = (i <= num_of_instance); + bool found_assoc = false; + + while (cont) + { + + if (dest_pc.ITU14.family == ITU14bit) // standard ITU: 14 bits + found_assoc = ((dest_pc.ITU14.pc == instance[i].Dest.pc.ITU14.pc)); + else if (dest_pc.ITU24.family == ITU24bit) // chinese PC length: 24 bits + found_assoc = ((dest_pc.ITU24.pc == instance[i].Dest.pc.ITU24.pc)); + else if (dest_pc.ANSI24.family == ANSI24bit) // ANSI PC length: 24 bits + found_assoc = ((dest_pc.ANSI24.pc == instance[i].Dest.pc.ANSI24.pc)); + else + found_assoc = false; + + + if (found_assoc) + { + cont = false; + sctp_assoc_id = instance[i].SCTP_assoc_id; + sua_assoc_id = i; +#ifdef DEBUG + cout << "Found Sua association " << i << " with SCTP assoc " << sctp_assoc_id << "\n"; + + cout << "CLD SS7 PC = " << dest_pc.ITU24.pc << "\n"; + cout << "Remote PC = " << instance[i].Dest.pc.ITU24.pc << "\n"; + +#endif + } + else + { + i++; + cont = (i <= num_of_instance); + } + } + + return(sctp_assoc_id); +}; + +/***********************************************************************/ +/* Sua_AssociationList::route_on_GTname */ +/***********************************************************************/ +signed int db_Sua_AssociationList:: +route_on_GTname ( hostname_str& dest_name, + hostname_str& org_name, + int& sua_assoc_id, + pointcode_str& dest_pc, + pointcode_str& org_pc + ) +{ + struct hostent *hptr; + char **pptr; + unsigned int sctp_assoc_id = 0; + char str[INET6_ADDRSTRLEN]; + char *dest_carr; + + sua_assoc_id = 0; + + /* resolving can be done via: */ + /* - local global Titel database */ + /* - resolve hostname via DNS(simplest for single hop translations) */ + dest_carr = dest_name; + + if ((hptr = gethostbyname( dest_carr )) == NULL) + { + cout << "Hostname " << dest_name << " not known in DNS.\n"; + return(-1); + } + +#ifdef DEBUG + cout << "Hostname " << dest_name << " resolved to dest IP address(es)\n"; + cout << "IP address length = "<< hptr->h_length << "\n"; +#endif + + /* initialise the length field of the structure: */ + /* length field is NOT always present in every Unix like operating system */ + dest_pc.ipvx.ch[0] = 0; + org_pc.ipvx.ch[0] = 0; + + pptr = hptr->h_addr_list; + for ( ; (*pptr != NULL) ;pptr++) + { + inet_ntop(hptr->h_addrtype, *pptr, str,sizeof(str)); +#ifdef DEBUG + cout << str << "\n"; +#endif + /* got IP address, look if association already exists */ + dest_pc.ipvx.sa.sa_family = hptr->h_addrtype; + if (dest_pc.ipvx.sa.sa_family == AF_INET) + inet_pton( AF_INET, + str, + &dest_pc.ipvx.sin.sin_addr + ); + else if (dest_pc.ipvx.sa.sa_family == AF_INET6) + inet_pton( AF_INET6, + str, + &dest_pc.ipvx.sin6.sin6_addr + ); + else + cout << "ERROR route_on_GTname: Unknown IP addresstype\n"; + + sctp_assoc_id = route_on_IPpc( dest_pc.ipvx, + org_pc.ipvx, + sua_assoc_id + ); + + if (sctp_assoc_id != 0 ) + return(sctp_assoc_id); + + } + + return(sctp_assoc_id); +}; + +/***********************************************************************/ +/* Sua_AssociationList::route_msg */ +/***********************************************************************/ +signed int db_Sua_AssociationList:: +route_msg( sccp_addr_str& cld, + sccp_addr_str& clg + ){ + + unsigned int sctp_assoc_id = 0; + int sua_assoc_id = 0; + +#ifdef DEBUG + cout << "num_of_instance : "<< num_of_instance << "\n"; +#endif + + if ((cld.address_fields_present.pc == ipvx_pc_present) && + (cld.routing_ind == route_on_ssn)) + { + sctp_assoc_id = route_on_IPpc( cld.pc.ipvx, + clg.pc.ipvx, + sua_assoc_id + ); + } + else if ((cld.address_fields_present.name_gt == hostname_present) && + (cld.routing_ind == route_on_name_gt)) + { + sctp_assoc_id = route_on_GTname( cld.name.HostName, + clg.name.HostName, + sua_assoc_id, + cld.pc, + clg.pc + ); + } + else if ((cld.address_fields_present.name_gt == hostname_present) && + (cld.address_fields_present.pc == ipvx_pc_present) && + (cld.routing_ind == route_on_name_gt_next_office)) + { + sctp_assoc_id = route_on_IPpc( cld.pc.ipvx, + clg.pc.ipvx, + sua_assoc_id + ); + } + else if ((cld.address_fields_present.pc == ss7_pc_present) && + (cld.routing_ind == route_on_ssn)) + { + sctp_assoc_id = route_on_SS7pc( cld.pc.ss7, + clg.pc.ss7, + sua_assoc_id + ); + } + else + { + cout << "Unknown routing requested\n"; + } + +#ifdef SUA_MANAGEMENT + /* check if allowed to send msg over the association */ + if ((sua_assoc_id > 0) && + (sua_assoc_id <= num_of_instance) && + (instance[sua_assoc_id].asp.status != asp_active)) + { + sctp_assoc_id = (-sctp_assoc_id); + } +#endif + +#ifdef DEBUG + cout << "route msg towards remote SUA(& SCTP) association " << sctp_assoc_id << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "Route msg towards Remote SUA(& SCTP) instance nr %d", sctp_assoc_id ); + event_log("sua_database.c",logstring); + + return(sctp_assoc_id); +}; + + +/***********************************************************************/ +/* Sua_AssociationList::increase_instance */ +/***********************************************************************/ +void db_Sua_AssociationList:: increase_instance(){ + + num_of_instance++; + +} + +/***********************************************************************/ +/* Sua_AssociationList::Dynamic_Associate */ +/***********************************************************************/ +unsigned int db_Sua_AssociationList::Dynamic_Associate( + db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua, + sccp_addr_str& cld, + sccp_addr_str& clg, + unsigned short nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams + ) +{ + short sua_portnumber = SUA_PORT; + + short i = 1, assoc_instance_idx = 1, assoc_source_idx = 0; + bool partial_assoc_found = FALSE; + + while ((i <= num_of_instance) && !(partial_assoc_found)){ + partial_assoc_found = (instance[i].Dest.nr_of_addrs == 0); + if (partial_assoc_found) + assoc_instance_idx = i; + i++; + } + + if (!(partial_assoc_found)) + { + /* all assoc's are complete, allocate a new one */ + num_of_instance++; + assoc_instance_idx = num_of_instance; + + } + + assoc_source_idx = Find_local_sua ( clg); + +#ifdef DEBUG + cout << " assoc source idx = " << assoc_source_idx << ", assoc_instance_idx = " << assoc_instance_idx << "\n"; +#endif + + instance[assoc_instance_idx].Source = instance[assoc_source_idx].Source; + instance[assoc_instance_idx].SCTP_instance_name = instance[assoc_source_idx].SCTP_instance_name; + instance[assoc_instance_idx].local_sua_id = instance[assoc_source_idx].local_sua_id; + instance[assoc_instance_idx].nr_of_inbound_streams = nr_of_input_streams ; + instance[assoc_instance_idx].nr_of_outbound_streams = nr_of_input_streams ; + + /* conversion and fill in the destination address */ + instance[assoc_instance_idx].Dest.nr_of_addrs = 1; + instance[assoc_instance_idx].Dest.addrs[0] = cld.pc.ipvx; + + short k; + const char *ptr; + for(k=0; k < instance[assoc_instance_idx].Dest.nr_of_addrs ; k++) + { + if ( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family == AF_INET ) + ptr = inet_ntop( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family, + &instance[assoc_instance_idx].Dest.addrs[k].sin.sin_addr, + (char *)instance[assoc_instance_idx].Dest.address_string[k], + SCTP_MAX_IP_LEN + ); + else if ( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family == AF_INET6 ) + ptr = inet_ntop( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family, + &instance[assoc_instance_idx].Dest.addrs[k].sin6.sin6_addr, + (char *)instance[assoc_instance_idx].Dest.address_string[k], + SCTP_MAX_IP_LEN + ); + else + cout << "Unsupported address family in dynamic associate\n"; + } + + remote_sua.increase_instance(); + + instance[assoc_instance_idx].SCTP_assoc_id = + sctp_associate( instance[assoc_instance_idx].SCTP_instance_name, + instance[assoc_instance_idx].nr_of_outbound_streams, + instance[assoc_instance_idx].Dest.address_string[0], + sua_portnumber, + NULL + ); + instance[assoc_instance_idx].remote_sua_id = remote_sua.num_of_instance; + remote_sua.instance[remote_sua.num_of_instance].ssn.ssn = local_sua.instance[instance[assoc_instance_idx].local_sua_id].ssn.ssn; + + /* a message is queued for this association -> send decision is taken */ + /* on receiving the communicationUp notification of SCTP AND whether */ + /* SUA management is going to be used */ + instance[assoc_instance_idx].asp.status = asp_down_traf_hold; + +#ifdef DEBUG + cout << "Dynamic Associate remote SUA(& SCTP) instance nr " << assoc_instance_idx << " with local SUA(& SCTP) instance nr " << instance[assoc_instance_idx].local_sua_id << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "Dynamic Associate Remote SUA(& SCTP) instance nr %d with local SUA(& SCTP) instance nr %d", assoc_instance_idx, instance[assoc_instance_idx].local_sua_id ); + event_log("sua_datasoc.c",logstring); + + return(assoc_instance_idx); +} + +/***********************************************************************/ +/* Sua_AssociationList::Activate_Association */ +/***********************************************************************/ +bool db_Sua_AssociationList::activate( unsigned int sua_assoc_id, + short mode + ) +{ + return(instance[sua_assoc_id].asp.activate(mode, + sua_assoc_id + )); +} + +/***********************************************************************/ +/* Sua_AssociationList::DeActivate_Association */ +/***********************************************************************/ +void db_Sua_AssociationList::deactivate( unsigned int sua_assoc_id, + short mode + ) +{ + instance[sua_assoc_id].asp.deactivate(mode, + sua_assoc_id + ); +} + +/***********************************************************************/ +/* Sua_AssociationList::Down_Association */ +/***********************************************************************/ +void db_Sua_AssociationList::down( unsigned int sua_assoc_id, + short mode + ) +{ + instance[sua_assoc_id].asp.down(mode, + sua_assoc_id + ); +} + +/***********************************************************************/ +/* Sua_AssociationList::Up_Association */ +/***********************************************************************/ +void db_Sua_AssociationList::up( unsigned int sua_assoc_id, + short mode + ) +{ + instance[sua_assoc_id].asp.up(mode, + sua_assoc_id + ); +} + +// end of module sua_database.c + + + + + + diff --git a/sualibrary/sua/sua_debug.h b/sualibrary/sua/sua_debug.h new file mode 100644 index 0000000..a4e3d83 --- /dev/null +++ b/sualibrary/sua/sua_debug.h @@ -0,0 +1,79 @@ +/*************************************************************************** + sua_debug.h - 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_debug.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * Gery Verwimp + * + * 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 : Michelle + * "The debugger with the cape rides again" + * "He will hunt bugs as long as they do not reside in dark memory lanes" + * + * Purpose: This header-file defines the SUA debugging constants used + * for dumping debug info to the screen, dump debug info to file, + * activate ASP management...etc.... + */ + +#ifndef SUA_DEBUG_H +#define SUA_DEBUG_H + +/*#define DEBUG activates debuging msg on screen */ +/*#define FILE_DEBUG activates debugging info to output file */ +#define SUA_MANAGEMENT /* activates SUA management */ +#define SG_ASP_MODE /* implementation acts as ASP towards a SG */ + + +#endif // SUA_DEBUG_H + +// end of module sua_debug.h + + + + + + + + + + + diff --git a/sualibrary/sua/sua_distribution.cpp b/sualibrary/sua/sua_distribution.cpp new file mode 100644 index 0000000..c588f49 --- /dev/null +++ b/sualibrary/sua/sua_distribution.cpp @@ -0,0 +1,1167 @@ +/*************************************************************************** + sua_distribution.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_distribution.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Pascale + * "We are continously looking for Ghostwriters." + * "When we find one, he will be terminated on the spot. Nobody writes (into) + * "my lifes variables without my permission." + * + * Purpose: This code-file defines the SUA distributor functions for: + * - Data arrive notification(from SCTP) -> receive the msg data + * from SCTP(use receive_sua_primitive function below), process it + * and call the aproriate SUA msg handling function + * - Network status change Notification(from SCTP) + * - Sent Failure Notification(from SCTP) + * - Communication Lost Notification(from SCTP) + * - Communication Up Notification(from SCTP) + * - Communication Error Notification(from SCTP) + * - Restart Notification(from SCTP) + * - Shutdown Notification(from SCTP) + * - Send a SUA primitive -> generate and send the msg to SCTP + * - Receive the sua "primitive"/msg data from SCTP + */ + +#include "sua_debug.h" +#include "sua_database.h" +#include "sua_tcb.h" +#include "sua_logging.h" +#include "sua_syntax.h" +#include "sua_cl.h" +#include "sua_co.h" +#include "sua_distribution.h" + + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> +#include <map> +#include <vector> + +using namespace std; + +#define BUFSIZE 2000 + +// syntax definitions of the sua message +Sua_container msg; + +// storage for received SUA messages +vector<sua_save_str> rec_msg_pool; + +extern db_Sua_LocalList local_sua; +extern db_Sua_RemoteList remote_sua; +extern db_Sua_AssociationList Assoc_sua; +extern tcb_Sua_TCB_arr tcb_pool; +extern tcb_Sua_msgqueue_pool msg_store; + +/***********************************************************************/ +/* sctp_DataArriveNotif */ +/***********************************************************************/ +void sctp_DataArriveNotif( unsigned int sctp_assoc_id, + unsigned int stream_id, + unsigned int len, + unsigned int protocol_id, + unsigned int unordered_flag, + void * ulp_data_ptr + ) +{ + + unsigned short result; + unsigned int Sua_ConnId; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + tcb_Sua_TCB_str *tcb_ptr; + Sua_syntax_error_struct error; + char databuf[BUFSIZE]; + unsigned int flags = SCTP_MSG_DEFAULT; + +#ifdef DEBUG + cout << "Received a Data notification from SCTP for association " << sctp_assoc_id << " : handle and distribute\n"; +#endif + + + + // receive data from SCTP + result = sctp_receive( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + &len, + flags + ); + + // display byte array +#ifdef DEBUG + display_byte_array(databuf ,len); +#endif + char logstring[100]; + sprintf(logstring, "SUA message, just received from SCTP"); + event_log("sua_distribution.c",logstring); + log_byte_array("sua_distribution.c", databuf,len); + + + // copy received data from databuf to msg object -> byte array + msg.sua_msg.insert(0, databuf, len); + // decode data to figure which SUA message we received + error = msg.sua_decode(); + + if (!error.no_error) + { + char logstring[100]; + sprintf(logstring, "Decoding error in received SUA message : index = %d,", error.msg_index); + event_log("sua_distribution.c",logstring); + char *spare = new char[error.error_text.length()]; + error.error_text.copy(spare, error.error_text.length()); + sprintf(logstring, "Error string = %s,", spare); + event_log("sua_distribution.c",logstring); + cout << "Decoding error in received SUA message : "<< error.error_text << ", index = " << error.msg_index << "\n"; + msg.sua_prim.hdr_msg_class = sua_max; + return; + } + + // distribute the message based on some parameters + // Connectionless or connection-oriented + switch (msg.sua_prim.hdr_msg_class) + { + case (sua_cl): + + // connectionless : strip of header and send to user + switch (msg.sua_prim.hdr_msg_type.cl) + { + case cl_data_transfer /*N_UNITDATA*/: + { +#ifdef DEBUG + cout << "CL: Unitdata message handling\n"; +#endif + unsigned int local_sua_id,remote_sua_id; + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + result = process_unitdata_msg ( local_sua_id, + sua_assoc_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received Unitdata msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case cl_data_response /*N_UNITDATA_SERVICE*/: + { +#ifdef DEBUG + cout << "CL: Unitdata Service message handling\n"; +#endif + char logstring[100]; + sprintf(logstring, "Received Unitdata Service msg"); + event_log("sua_distribution.c",logstring); + + break; + } + default: + { + cout << "Unknown connectionless message type !!\n"; + char logstring[100]; + sprintf(logstring, "Unknown connectionless message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + + break; + + case (sua_co): + + // connectionoriented: get SCOC TCB, do state-event handling and send to use + switch (msg.sua_prim.hdr_msg_type.co) + { + case co_core /*N_CONNECT_IND */: + { +#ifdef DEBUG + cout << "CO: Connect indication message handling\n"; +#endif + char logstring[100]; + sprintf(logstring, "Received Connect Indication msg"); + event_log("sua_distribution.c",logstring); + + + unsigned int local_sua_id,remote_sua_id; + + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + + tcb_ptr = tcb_pool.allocate_TCB(Sua_ConnId); + + result = process_CORE_msg ( sua_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + break; + } + case co_coak /*connect confirm */: + { +#ifdef DEBUG + cout << "CO: Connection request acknowledge message handling\n"; +#endif + Sua_ConnId = msg.sua_prim.dest_ref; + tcb_ptr = tcb_pool.get_tcb(Sua_ConnId); + if (( msg.sua_prim.dest_ref_pres)) + { + char logstring[100]; + sprintf(logstring, "Received Connect Confirm Indication msg"); + event_log("sua_distribution.c",logstring); + + // call connection request acknowledge message handling + result = process_COAK_msg ( sctp_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + } + else + cout << "ERROR: TCB " << Sua_ConnId << " was not retrieved?!!\n"; + + } + case co_data /*data*/: + { +#ifdef DEBUG + cout << "CO: Data message handling\n"; +#endif + Sua_ConnId = msg.sua_prim.dest_ref; + tcb_ptr = tcb_pool.get_tcb(Sua_ConnId); + if (( msg.sua_prim.dest_ref_pres)/* && + ( tcb_ptr /= NULL)*/) + { + char logstring[100]; + sprintf(logstring, "Received Data Indication msg"); + event_log("sua_distribution.c",logstring); + + // call data message handling function + result = process_CODATA_msg ( sctp_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + } + else + cout << "ERROR: TCB " << Sua_ConnId << " was not retrieved?!!\n"; + + break; + } + case co_relre /*release request*/: + { +#ifdef DEBUG + cout << "CO: Release Request message handling\n"; +#endif + Sua_ConnId = msg.sua_prim.dest_ref; + tcb_ptr = tcb_pool.get_tcb(Sua_ConnId); + if (( msg.sua_prim.dest_ref_pres)) + { + char logstring[100]; + sprintf(logstring, "Received Release Request Indication msg"); + event_log("sua_distribution.c",logstring); + + // call release request message handling function + result = process_CORELRQ_msg ( sctp_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + } + else + cout << "ERROR: TCB " << Sua_ConnId << " was not retrieved?!!\n"; + + + break; + } + case co_relco /*release completed */: + { +#ifdef DEBUG + cout << "CO: Release Complete message handling\n"; +#endif + Sua_ConnId = msg.sua_prim.dest_ref; + tcb_ptr = tcb_pool.get_tcb(Sua_ConnId); + if (( msg.sua_prim.dest_ref_pres)) + { + char logstring[100]; + sprintf(logstring, "Received Release Confirm Indication msg"); + event_log("sua_distribution.c",logstring); + + // call release complete message handling function + result = process_CORELCO_msg ( sctp_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + } + else + cout << "ERROR: TCB " << Sua_ConnId << " was not retrieved?!!\n"; + + + break; + } + case co_coref /*connection refused */: + { +#ifdef DEBUG + cout << "CO: Connection refused message handling\n"; +#endif + Sua_ConnId = msg.sua_prim.dest_ref; + tcb_ptr = tcb_pool.get_tcb(Sua_ConnId); + if (( msg.sua_prim.dest_ref_pres)) + { + char logstring[100]; + sprintf(logstring, "Received Connect Confirm Indication msg"); + event_log("sua_distribution.c",logstring); + + // call connection request acknowledge message handling + result = process_COREF_msg ( sctp_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + } + else + cout << "ERROR: TCB " << Sua_ConnId << " was not retrieved?!!\n"; + + } + default: + { + char logstring[100]; + sprintf(logstring, "Unknown connectionoriented message type"); + event_log("sua_distribution.c",logstring); + cout << "Unknown connectionoriented message type !!\n"; + break; + } + } + + break; + + case (sua_mngt): + // SUA management msg + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + + switch (msg.sua_prim.hdr_msg_type.mngt) + { + case mngt_error : + { +#ifdef DEBUG + cout << "SUA Management: ERROR message handling\n"; +#endif + + + char logstring[100]; + sprintf(logstring, "Received ERROR msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case mngt_notify : + { +#ifdef DEBUG + cout << "SUA Management: NOTIFY message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received NOTIFY msg"); + event_log("sua_distribution.c",logstring); + + break; + } + default: + { + cout << "Unknown SUA managment message type !!\n"; + char logstring[100]; + sprintf(logstring, "Unknown SUA Management message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + + break; + + + + case (sua_ssnm): + // Signalling Network Management(SNM) msg + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + + switch (msg.sua_prim.hdr_msg_type.ssnm) + { + case ssnm_duna : + { +#ifdef DEBUG + cout << "SNM: Destination unavialable\n"; +#endif + + + char logstring[100]; + sprintf(logstring, "Received DUNA msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case ssnm_dava : + { +#ifdef DEBUG + cout << "SNM: Destination avialable message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received DAVA msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case ssnm_daud : + { +#ifdef DEBUG + cout << "SNM: Destination state audit message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received DAUD msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case ssnm_scon : + { +#ifdef DEBUG + cout << "SNM: Network congestion message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received SCON msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case ssnm_dupu : + { +#ifdef DEBUG + cout << "SNM: Destination User Part Unavialable message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received DUPU msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case ssnm_drst : + { +#ifdef DEBUG + cout << "SNM: Destination restricted message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received DRST msg"); + event_log("sua_distribution.c",logstring); + + break; + } + default: + { + cout << "Unknown SUA managment message type !!\n"; + char logstring[100]; + sprintf(logstring, "Unknown SUA Management message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + + break; + + case (sua_aspsm): + // ASP State maintenance msg + + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + + switch (msg.sua_prim.hdr_msg_type.aspsm) + { + case aspsm_up : + { +#ifdef DEBUG + cout << "ASPSM: ASP_UP message handling\n"; +#endif + result = process_ASPUP_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPUP msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case aspsm_up_ack : + { +#ifdef DEBUG + cout << "ASPSM: ASP_UP_ACK message handling\n"; +#endif + result = process_ASPUP_ACK_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPUP ACK msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case aspsm_down : + { +#ifdef DEBUG + cout << "ASPSM: ASP_DOWN message handling\n"; +#endif + result = process_ASPDOWN_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPDO msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case aspsm_down_ack : + { +#ifdef DEBUG + cout << "ASPSM: ASP_DOWN_ACK message handling\n"; +#endif + result = process_ASPDOWN_ACK_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPDOWN ACK msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case aspsm_beat : + { +#ifdef DEBUG + cout << "ASPSM: HEARTBEAT message handling\n"; +#endif + result = process_BEAT_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received HEARTBEAT msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case aspsm_beat_ack : + { +#ifdef DEBUG + cout << "ASPSM: HEARTBEAT_ACK message handling\n"; +#endif + result = process_BEAT_ACK_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received HEARTBEAT ACK msg"); + event_log("sua_distribution.c",logstring); + + break; + } + default: + { + cout << "Unknown ASP State Maintenance message type !!\n"; + char logstring[100]; + sprintf(logstring, "Unknown ASP State Maintenance message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + + break; + + case (sua_asptm): + // ASP Traffic maintenance msg + + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + + switch (msg.sua_prim.hdr_msg_type.asptm) + { + case asptm_act : + { +#ifdef DEBUG + cout << "ASPTM: ASPAC message handling\n"; +#endif + result = process_ASPAC_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPAC msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case asptm_act_ack : + { +#ifdef DEBUG + cout << "ASPSM: ASPAC_ACK message handling\n"; +#endif + result = process_ASPAC_ACK_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPAC ACK msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case asptm_inact : + { +#ifdef DEBUG + cout << "ASPTM: ASPINAC message handling\n"; +#endif + result = process_ASPINAC_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPINAC msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case asptm_inact_ack : + { +#ifdef DEBUG + cout << "ASPSM: ASPINAC_ACK message handling\n"; +#endif + result = process_ASPINAC_ACK_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPINAC ACK msg"); + event_log("sua_distribution.c",logstring); + + break; + } + default: + { + cout << "Unknown ASP Traffic Maintenance message type !!\n"; + char logstring[100]; + sprintf(logstring, "Unknown ASP Traffic Maintenance message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + + break; + + default: + { + char logstring[100]; + sprintf(logstring, "Unknown message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + // return +#ifdef DEBUG + cout << "Received message processed\n"; +#endif +} + +/***********************************************************************/ +/* sctp_NetworkStatusChangeNotif */ +/***********************************************************************/ +void sctp_NetworkStatusChangeNotif( unsigned int assoc_id, + short dest_addr_index, + unsigned short new_path_state, + void * ulp_data_ptr + ) +{ +#ifdef DEBUG + cout << "Received a Network status change notification from SCTP for association " << assoc_id << "\n"; +#endif +} + +/***********************************************************************/ +/* sctp_SentFailureNotif */ +/***********************************************************************/ +void sctp_SentFailureNotif( unsigned int assoc_id, + unsigned char * unsent_data_sent_ptr, + unsigned int len, + unsigned int * sctp_send_context_ptr, + void * ulp_data_ptr + ) +{ +#ifdef DEBUG + cout << "Received a send failure notification from SCTP for association " << assoc_id << " Ignore it, not supported.\n"; +#endif +} + +/***********************************************************************/ +/* sctp_communicationLostNotif */ +/***********************************************************************/ +void sctp_CommunicationLostNotif( unsigned int sctp_assoc_id, + unsigned short status_event, + void * ulp_data_ptr + ) +{ + unsigned int sua_assoc_id,local_sua_id, remote_sua_id; + +#ifdef DEBUG + cout << "Received indication that communication with remote peer was lost for association " << sctp_assoc_id << "\n"; + cout << "Status CommunicationLostNotif = " << status_event << "\n"; +#endif + /* Put in debugging file */ + char logstring[100]; + sprintf(logstring, "CommunicationLostNotif received from SCTP"); + event_log("sua_distribution.c",logstring); + sprintf(logstring,"assoc_id = %d, status = %d ",sctp_assoc_id,status_event); + event_log("sua_distribution.c",logstring); + +#ifdef SUA_MANAGEMENT + if ((sua_assoc_id = Assoc_sua.Find_association(sctp_assoc_id, local_sua_id,remote_sua_id)) != 0) + { + /* if we found the sua assoc then the SUA ASP is marked down, */ + /* as the sctp association has failed */ + Assoc_sua.down(sua_assoc_id, 0); +#ifdef DEBUG + cout << "ASP down for SUA association " << sua_assoc_id << "\n"; +#endif + + } +#endif + +} + +/***********************************************************************/ +/* sctp_CommunicationUpNotif */ +/***********************************************************************/ +void *sctp_CommunicationUpNotif( unsigned int sctp_assoc_id, + unsigned short status_event, + int nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams, + void * ulp_data_ptr + ) +{ + + unsigned int sua_assoc_id,local_sua_id, remote_sua_id; + char logstring[100]; + int result; + tcb_Sua_msg_elem sua_msg; + +#ifdef DEBUG + cout << "Received Communication Up indication for association " << sctp_assoc_id <<"\n"; + cout << "Status CommunicationUpNotif = " << status_event << ", number of addresses used = " << nr_of_dest_addr << "\n"; + cout << "Number of input streams = " << nr_of_input_streams << ", number of output streams = " << nr_of_output_streams << "\n"; +#endif + + /* Put in debugging file */ + sprintf(logstring, "CommunicationUpNotif received from SCTP"); + event_log("sua_distribution.c",logstring); + sprintf(logstring,"assoc_id = %d, status = %d , number of dest addr = %d",sctp_assoc_id,status_event, nr_of_dest_addr); + event_log("sua_distribution.c",logstring); + sprintf(logstring,"Number of input streams = %d, number of output streams = %d", nr_of_input_streams,nr_of_output_streams); + event_log("sua_distribution.c",logstring); + + + + if ((sua_assoc_id = Assoc_sua.Find_association(sctp_assoc_id, local_sua_id,remote_sua_id)) == 0) { +#ifdef DEBUG + cout << "association " << sctp_assoc_id << " is not present\n"; +#endif + sua_assoc_id = Assoc_sua.passive_associate( sctp_assoc_id, + local_sua, + remote_sua, + nr_of_dest_addr, + nr_of_input_streams, + nr_of_output_streams + ); + } + + /* code include if SUA management is NOT used */ +#ifndef SUA_MANAGEMENT + if ( Assoc_sua.instance[sua_assoc_id].status == asp_down_traf_hold) + { + /* - get the saved msg ansd send it on the association that is setup */ + sua_msg = msg_store.get_msg ( sua_assoc_id ); + + while ( sua_msg.valid) + { + char* databuf = new char[sua_msg.byte.length()]; + sua_msg.byte.copy(databuf, sua_msg.byte.length()); + datalen = sua_msg.byte.length(); + + /* msg retrieved and copied, may now remove it from queue */ + msg_store.delete_msg ( sua_assoc_id ); + +#ifdef DEBUG + display_byte_array(databuf , sua_msg.byte.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_distribution.c",logstring); + log_byte_array("sua_distribution.c", databuf,sua_msg.byte.length()); + + result = sctp_send ( sctp_assoc_id, + sua_msg.stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + sua_msg.delivery_type, + SCTP_BUNDLING_DISABLED + ); + + delete databuf; +#ifdef DEBUG + cout << "sua_distribution.c:result sctp send = "<< result << "\n"; +#endif + /* get the next saved msg ansd send if any ? */ + sua_msg = msg_store.get_msg ( sua_assoc_id ); + + } + /* SUA ASP is marked down */ + Assoc_sua.down(sua_assoc_id,0); + } + +#endif + + /* code include if SUA management IS used */ +#ifdef SUA_MANAGEMENT +#ifdef DEBUG + cout << "sua_distribution.c:should send ASPUP\n"; +#endif + /* send ASP-UP to remote to start activating local & remote ASP */ + result = sua_send_ASPUP( sua_assoc_id + ); +#endif + + return NULL; +} + +/***********************************************************************/ +/* sctp_CommunicationErrorNotif */ +/***********************************************************************/ +void sctp_CommunicationErrorNotif( unsigned int assoc_id, + unsigned short error_status, + void * ulp_data_ptr + ) +{ +#ifdef DEBUG + cout << "Received Error indication for association " << assoc_id << " with error status " << error_status << "\n"; + cout << "Aborting association \n"; +#endif + sctp_deleteAssociation(assoc_id); +} + + +/***********************************************************************/ +/* sctp_RestartNotif */ +/***********************************************************************/ +void sctp_RestartNotif( unsigned int sctp_assoc_id, + void * ulp_data_ptr + ) +{ + unsigned int sua_assoc_id,local_sua_id, remote_sua_id; + int result; + +#ifdef DEBUG + cout << "Received Restart indication for association " << sctp_assoc_id << "\n"; +#endif + +#ifdef SUA_MANAGEMENT + if ((sua_assoc_id = Assoc_sua.Find_association(sctp_assoc_id, local_sua_id,remote_sua_id)) == 0) + { +#ifdef DEBUG + cout << "ASP status = " << Assoc_sua.instance[sua_assoc_id].asp.status <<" for SUA association " << sua_assoc_id << "\n"; +#endif + + /* restart association: ASP state should be set to down */ + Assoc_sua.down(sua_assoc_id,0); + + /* if we found the sua assoc then we restart the ASP bringup sequence */ + /* as the sctp association has come back online */ + /* send ASP-UP to remote to start activating local & remote ASP */ + result = sua_send_ASPUP( sua_assoc_id + ); + } +#endif + +} + +/***********************************************************************/ +/* sctp_ShutDownCompleteNotif */ +/***********************************************************************/ +void sctp_ShutDownCompleteNotif( unsigned int assoc_id, + void * ulp_data_ptr + ) +{ +#ifdef DEBUG + cout << "Received shutdown indication for association " << assoc_id << "\n"; +#endif +} + + + +/***********************************************************************/ +/* Send_sua_primitive */ +/***********************************************************************/ +unsigned int Send_sua_primitive( unsigned int primitive, + unsigned int &sua_ConnId, + sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len + ) +{ + int error; + char logstring[100]; + tcb_Sua_TCB_str *tcb_ptr; +#ifdef DEBUG + cout << "Send SUA primitive to local SUA instance\n"; + cout << "ConnId = " << sua_ConnId << "\n"; +#endif + + // search for the required local_ref + if (sua_ConnId != 0) + { + //handle connection oriented primitves which have already a TCB + tcb_ptr = tcb_pool.get_tcb(sua_ConnId); + + switch (primitive) + { + case N_CONNECT_RESP: + //send back response on received CORE of connection + sprintf(logstring, "CO N-CONNECT RESPONSE primitive req"); + event_log("sua_distribution.c",logstring); + + error = sua_send_CORESP( QOS, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + + break; + case N_DATA_REQ: + //send data on existing connection + sprintf(logstring, "CO N-DATA REQ primitive req"); + event_log("sua_distribution.c",logstring); + error = sua_send_CODATA( QOS, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + + break; + case N_RELEASE_REQ: + //Disconnect request on existing connection + sprintf(logstring, "CO N-RELEASE REQ primitive req"); + event_log("sua_distribution.c",logstring); + error = sua_send_CORELRQ( QOS, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + + break; + case N_RELEASE_CONF: + //Disconnect confirm request on existing connection + sprintf(logstring, "CO N-RELEASE CONFIRM primitive req"); + event_log("sua_distribution.c",logstring); + error = sua_send_CORELCO( QOS, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + + break; + case N_CONNECT_REFUSED: + //send a connect refused on connection + sprintf(logstring, "CO N-CONNECT REFUSED primitive req"); + event_log("sua_distribution.c",logstring); + + error = sua_send_COREF( QOS, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + + break; + default: + sua_ConnId = 0; + error = 1; + break; + } + } + else + { + //handle connectionless primitives + //handle connection oriented primitives for which no TCB was yet alllocated + // figured out connectionless/connection-oriented primitived + switch (primitive) + { + case N_UNITDATA: + sprintf(logstring, "Unitdata primitive req"); + event_log("sua_distribution.c",logstring); + sua_ConnId = 0; + error = sua_send_Unitdata(QOS, + called_pty_address, + calling_pty_address, + buffer, + len + ); + break; + case N_CONNECT_REQ: + sprintf(logstring, "CO N-CONNECT REQ primitive req"); + event_log("sua_distribution.c",logstring); + + tcb_ptr = tcb_pool.allocate_TCB(sua_ConnId); + + error = sua_send_CORE( QOS, + called_pty_address, + calling_pty_address, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + break; + default: + sua_ConnId = 0; + error = 1; + break; + } + } + + return(error); + +} + +/***********************************************************************/ +/* receive_sua_primitive */ +/***********************************************************************/ +unsigned int Receive_sua_primitive( unsigned int &primitive, + unsigned int &Sua_ConnId, + sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char* buffer, + unsigned int len + ) +{ + + + // retrieve the stored user data from the received msg list + sua_save_str temp=rec_msg_pool.front(); + // delete the user data in the received msg list + rec_msg_pool.erase(rec_msg_pool.begin()); + + // primitive and address parameters + primitive = temp.primitive; + Sua_ConnId = temp.user_ref; + QOS = temp.QOS; + called_pty_address = temp.called_pty_address; + calling_pty_address = temp.calling_pty_address; + // put in supplied byte array(space is allocated beforehand by application) + temp.userdata.copy(buffer, temp.userdata.length()); + len = temp.userdata.length(); + + return(len); +} + +// end of module sua_distribution.c diff --git a/sualibrary/sua/sua_distribution.h b/sualibrary/sua/sua_distribution.h new file mode 100644 index 0000000..f384f29 --- /dev/null +++ b/sualibrary/sua/sua_distribution.h @@ -0,0 +1,170 @@ +/*************************************************************************** + sua_distribution.h - 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_distribution.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 + * "When B.B. releases one of his pearls of wisedom and " + * "starts one of his walks around the block, then this designer says:" + * "I am getting tired of running in circles even if it is " + * "a nice block in a nice neighbourhood(maybe his walks are recursive)" + * + * Purpose: This header-file defines the SUA distributor functions for: + * - Data arrive notification(from SCTP) -> receive the msg data + * from SCTP(use receive_sua_primitive function below), process it + * and call the aproriate SUA msg handling function + * - Network status change Notification(from SCTP) + * - Sent Failure Notification(from SCTP) + * - Communication Lost Notification(from SCTP) + * - Communication Up Notification(from SCTP) + * - Communication Error Notification(from SCTP) + * - Restart Notification(from SCTP) + * - Shutdown Notification(from SCTP) + * - Send a SUA primitive -> generate and send the msg to SCTP + * - Receive the sua "primitive"/msg data from SCTP + */ + + +#ifndef SUA_DISTRIBUTION_H +#define SUA_DISTRIBUTION_H + + +#include "sua.h" +#include <string> + + +using namespace std; + +typedef struct { + unsigned int primitive; + unsigned int user_ref; + sccp_QOS_str QOS; + sccp_addr_str called_pty_address; + sccp_addr_str calling_pty_address; + string userdata; +} sua_save_str; + +/***********************************************************************/ +/* sctp_DataArriveNotif */ +/***********************************************************************/ +void sctp_DataArriveNotif( unsigned int assoc_id, + unsigned int stream_id, + unsigned int len, + unsigned int protocol_id, + unsigned int unordered_flag, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_NetworkStatusChangeNotif */ +/***********************************************************************/ +void sctp_NetworkStatusChangeNotif( unsigned int assoc_id, + short dest_addr_index, + unsigned short new_path_state, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_SentFailureNotif */ +/***********************************************************************/ +void sctp_SentFailureNotif( unsigned int assoc_id, + unsigned char * unsent_data_sent_ptr, + unsigned int len, + unsigned int * sctp_send_context_ptr, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_communicationLostNotif */ +/***********************************************************************/ +void sctp_CommunicationLostNotif( unsigned int assoc_id, + unsigned short status_event, + void * ulp_data_ptr + ); + +/***********************************************************************/ +/* sctp_CommunicationUpNotif */ +/***********************************************************************/ +void* sctp_CommunicationUpNotif( unsigned int assoc_id, + unsigned short status_event, + int nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_CommunicationErrorNotif */ +/***********************************************************************/ +void sctp_CommunicationErrorNotif( unsigned int assoc_id, + unsigned short error_status, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_RestartNotif */ +/***********************************************************************/ +void sctp_RestartNotif( unsigned int assoc_id, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_ShutDownCompleteNotif */ +/***********************************************************************/ +void sctp_ShutDownCompleteNotif( unsigned int assoc_id, + void * ulp_data_ptr + ); + +#endif // SUA_DISTRIBUTION_H + +// end of module sua_distribution.h + + diff --git a/sualibrary/sua/sua_file.cpp b/sualibrary/sua/sua_file.cpp new file mode 100644 index 0000000..c5ad667 --- /dev/null +++ b/sualibrary/sua/sua_file.cpp @@ -0,0 +1,401 @@ +/*************************************************************************** + sua_file.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_file.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Martine + * "This is the module of the fallen function with the big files by + * "Von Craenendonck!" + * "This module contains some real schoftware" + * + * Purpose: This code-file defines the SUA file access functions for: + * - get a argument in the line(delimited by a space) + * - read the sua file(containing arguments for the SUA database) + */ + + +#ifdef LINUX + #include <unistd.h> +#endif + +#include "sua_debug.h" +#include "sua_database.h" + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> +#include <fstream> + +#include <netinet/in_systm.h> +#include <netinet/ip.h> /* includes <netinet/in.h> also ! */ +#include <netinet/ip_icmp.h> +#include <netdb.h> +#include <arpa/inet.h> + +#define SUA_PORT 14001 +#define SUA_PPI 4 + +using namespace std; + + +string get_argument(string line, + int& begin, + int& end, + unsigned int& num_of_char_in_line) +{ + int len = 0; + bool cont = true; + while ((num_of_char_in_line <= line.length()) && (cont)) + { + + if ((line[num_of_char_in_line] == ' ') || + (num_of_char_in_line >= line.length())) + { + end = num_of_char_in_line - 1; + len = num_of_char_in_line - begin; + cont = false; + } + num_of_char_in_line++; + + } + + char *temp = new char[len]; + + // convert to lowercase characters for easier processing + int i=0; + for(i = 0; i < len ; i++) + temp[i] = tolower(line[begin+i]); + string sua_arg(temp, len); + +#ifdef DEBUGFILE + cout << "indexes = "<< begin << " , " << end << " , " << len << "\n"; + cout << temp << "\n"; + cout << "got argument = " << sua_arg << " \n"; + char v; + cin >> v; +#endif + + begin = end + 2; + end = 0; + delete temp; + + return(sua_arg); +} + + +int read_sua_file(string filename, + db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua, + db_Sua_AssociationList& Assoc_sua, + db_Sua_NameList& NameDB_sua, + db_Sua_ASList& ApplicServ_sua + ) +{ + string sua_filename; + string sua_arg; + string address_str,ip_addr_str; + char ch1, ch2; + string sua_line; + int num_of_char = 0; + int num_of_arg = 0; + int num_of_lines = 0; + int present_local_instance = 0; + int present_remote_instance = 0; + +#ifdef DEBUG + cout << "file to read = " << filename << " \n"; +#endif + cout << "SUA local sua instantation parameters(mandatory) \n"; + cout << "-s x.x.x.x -l yyy [-u] \n"; + cout << "-s : source address \n"; + cout << "-l : source local sua portnumber \n"; + cout << "-u : listen on local port number \n"; + cout << "SUA parameters of the sua tester (optional)\n"; + cout << "Not supported yet (-b 1000 -o -v) \n"; + cout << "SUA parameters of the SUA remote instantation(s) (optional)\n"; + cout << "-d x.x.x.x -r yyy [-g tt-nat-np-digits] [-a ASnumber] \n"; + cout << "-d : destination address \n"; + cout << "-r : destination sua portnumber \n"; + cout << "-g : global title(TTID-NAT-NUMPLAN-Digits) linked to destination address \n"; + cout << "-a : Application Server(AS) this address belongs to \n"; + + ifstream infile(filename.c_str()); + while (getline(infile, sua_line)) + { + num_of_lines++; + // analyse input line and split up in arguments according to + // the spaces in the line: each argument is then processed + unsigned int num_of_char_in_line = 0; + int b=0, e=0; + bool next_arg; + + sua_arg = get_argument(sua_line,b,e,num_of_char_in_line); + next_arg = false; + + // make selection on cmd argument + while (num_of_char_in_line < sua_line.length()) + { + ch2 = ' '; + if (sua_arg[0] == '-') + { + ch1 = sua_arg[1]; + ch2 = sua_arg[2]; + } + else if (sua_arg[0] == '/') + ch1 = sua_arg[0]; + else + { + cout << "weird option \n"; + ch1 = ' '; + } + + switch (ch1) + { + case 's': // read source addresses for sua + { + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + if (present_local_instance > 0) { + present_local_instance= 0; + } + local_sua.increase_instance(); + Assoc_sua.increase_instance(); + present_remote_instance = 0; + Assoc_sua.instance[Assoc_sua.num_of_instance].local_sua_id = local_sua.num_of_instance; + Assoc_sua.instance[Assoc_sua.num_of_instance].nr_of_inbound_streams = 1; + Assoc_sua.instance[Assoc_sua.num_of_instance].nr_of_outbound_streams = 1; + + if (ch2 == 'n') { + ip_addr_str = NameDB_sua.read_host_name(address_str); + Assoc_sua.read_Source_addr(ip_addr_str); + } + else { + Assoc_sua.read_Source_addr(address_str); + } + + present_local_instance++; + break; + } + case 'd': + { // read destination addresses for sua + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + remote_sua.increase_instance(); + if (present_remote_instance > 0) { + Assoc_sua.increase_instance(); + Assoc_sua.instance[Assoc_sua.num_of_instance].Source = + Assoc_sua.instance[Assoc_sua.num_of_instance-1].Source; + Assoc_sua.instance[Assoc_sua.num_of_instance].local_sua_id = + Assoc_sua.instance[Assoc_sua.num_of_instance-1].local_sua_id; + Assoc_sua.instance[Assoc_sua.num_of_instance].nr_of_inbound_streams = 1; + Assoc_sua.instance[Assoc_sua.num_of_instance].nr_of_outbound_streams = 1; + present_remote_instance = 0; + } + if (ch2 == 'n') { + ip_addr_str = NameDB_sua.read_host_name(address_str); + Assoc_sua.read_Dest_addr(ip_addr_str); + } + else { + Assoc_sua.read_Dest_addr(address_str); + } + Assoc_sua.instance[Assoc_sua.num_of_instance].remote_sua_id = remote_sua.num_of_instance; + + present_remote_instance++; + + break; + } + case 'l': + { // read local portnumber for sua + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + Assoc_sua.read_Source_port(address_str); + + break; + } + case 'r': + { // read remote portnumber for sua + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + Assoc_sua.read_Dest_port(address_str); + + break; + } + case 'a': + { // read Application Server number this remote ASP belongs to + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + + Assoc_sua.instance[Assoc_sua.num_of_instance].asp.linked_to_AS[0] = ApplicServ_sua.read_AS(address_str, Assoc_sua.num_of_instance ); + + break; + } + case 'b': + { + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); +#ifdef DEBUG + cout << "discard option b \n"; +#endif + + + } + case 'n': + { // read sybsytem number = SSN (valid for both local and remote) + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + remote_sua.read_ssn(address_str); + local_sua.read_ssn(address_str); + + break; + } + case 'q': // read QOS fields for sua + { + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + + + break; + } + case 'u': + { // + break; + } + case 'm': + { // + break; + } + case 'o': + { // + break; + } + case 't': + { // number of streams incoming AND outgoing + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + Assoc_sua.read_stream_number(address_str); + break; + } + case 'v': + { // + break; + } + case 'f': + { // file option: we are in file mode could later be used for + // recursive filereading. Ignore for the moment + num_of_arg++; + break; + } + case 'i': + { + // ignore character, is not a error, go to next argument + break; + } + case '7': + { /* read SS7 pointcodes */ + switch (ch2) + { + case 's': // read source pointcode for sua + { + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + + Assoc_sua.read_Source_pointcode(address_str); + + break; + } + case 'd': + { // read destination pointcode for sua + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + + Assoc_sua.read_Dest_pointcode(address_str); + + break; + } + default: + { + break; + } + } + break; + } + case '/': + { + // comment: skip this line + num_of_char_in_line = num_of_char_in_line + sua_line.length(); + b=0; + e=0; + break; + } + default: + { + break; + } + } + sua_arg = get_argument(sua_line,b,e,num_of_char_in_line); + num_of_arg++; + } + // finished reading the whole line + num_of_char = num_of_char + num_of_char_in_line; + cout << "Line " << num_of_lines << " : " << sua_line << "\n"; + } + +#ifdef DEBUG + cout << "End of file: statistics \n"; + cout << "Number of lines = " << num_of_lines <<"\n"; + cout << "Number of characters in file = " << num_of_char << "\n"; + +#endif + + return (0); + +} /* end of read_sua_file */ + + +// end of module sua_file.c + + + diff --git a/sualibrary/sua/sua_file.h b/sualibrary/sua/sua_file.h new file mode 100644 index 0000000..df7c3d5 --- /dev/null +++ b/sualibrary/sua/sua_file.h @@ -0,0 +1,74 @@ +/*************************************************************************** + sua_file.h - 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_file.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Annemie + * "" + * + * Purpose: This header-file defines the SUA file access functions for: + * - get a argument in the line(delimited by a space) + * - read the sua file(containing arguments for the SUA database) + */ + +#ifndef SUA_FILE_H +#define SUA_FILE_H + + +#include <string> + +using namespace std; + +int read_sua_file(string filename, + db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua, + db_Sua_AssociationList& Assoc_sua, + db_Sua_NameList& NameDB_sua, + db_Sua_ASList& ApplicServ_sua + ); + +#endif // SUA_FILE_H + +// end of module sua_file.h diff --git a/sualibrary/sua/sua_logging.cpp b/sualibrary/sua/sua_logging.cpp new file mode 100644 index 0000000..8bc9757 --- /dev/null +++ b/sualibrary/sua/sua_logging.cpp @@ -0,0 +1,268 @@ +/*************************************************************************** + sua_logging.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_logging.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Cindy + * "KISS (ME * ) methodology applies" + * " * The extended KISS method only applies to beautifull girls." + * + * Purpose: This code-file defines the SUA logging(error or normal stuff) + * functions for: + * - initialise the logging file + * - log events to logging file + * - log byte arrya to logging file + * - Display byte array to screen + * - close logging file + */ + + +#include "sua_debug.h" +#include "sua.h" + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +#include <string> +#include <iostream> +#include <iomanip> +#include <fstream.h> + +#include <sys/time.h> +#include <time.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + + +#define MAX_BYTES_IN_LINE 20 + +ofstream logfile; +char log_filename[100]; + +typedef enum { min = -127, + max = 128 +} sua_byte_str; + +/***********************************************************************/ +/* init_logging_file */ +/***********************************************************************/ +void init_logging_file() +{ + struct timeval tv; + struct timezone tz; + struct tm *the_time; + // random temporary logfile + //sprintf(log_filename, "./tmp%d.log",(int)getpid()); + sprintf(log_filename, "./tmp2603.log"); + cout << "Logging all errors and events to file " << log_filename <<"\n"; + // creation of random logfile: overwrite file if already exists + logfile.open(log_filename); + if (!logfile) + { + cout << "Logging file " << log_filename << " could not be created\n"; + exit(0); + } + gettimeofday(&tv, &tz); + the_time = localtime((time_t *) & (tv.tv_sec)); + logfile << the_time->tm_hour << ":" << the_time->tm_min << ":" << the_time->tm_sec << ":" << (int) (tv.tv_usec / 1000) << " >> Logfile " << log_filename << " created \n" << flush; + +} + + + +/* This function logs events. + Parameters: + @param event_log_level : INTERNAL_EVENT_0 INTERNAL_EVENT_1 EXTERNAL_EVENT_X EXTERNAL_EVENT + @param module_name : the name of the module that received the event. + @param log_info : the info that is printed with the modulename. + @param anyno : optional pointer to unsigned int, which is printed along with log_info. + The conversion specification must be contained in log_info. + @author Hölzlwimmer +*/ + +/***********************************************************************/ +/* event_log */ +/***********************************************************************/ +void event_log( char *module_name, char *log_info, ...) +{ + +#ifdef FILE_DEBUG + struct timeval tv; + struct timezone tz; + struct tm *the_time; + + gettimeofday(&tv, &tz); + the_time = localtime((time_t *) & (tv.tv_sec)); + logfile << the_time->tm_hour << ":" << the_time->tm_min << ":" << the_time->tm_sec << ":" << (int) (tv.tv_usec / 1000) << " >> " << module_name << " >> " << log_info << " \n" << flush; +#endif + + return; +} + +/***********************************************************************/ +/* event_log_byte_array */ +/***********************************************************************/ +void log_byte_array( char *module_name, char *log_info, int len) +{ +#ifdef FILE_DEBUG + int i,space; + int li; + int lines; + int index; + struct timeval tv; + struct timezone tz; + struct tm *the_time; + + + gettimeofday(&tv, &tz); + the_time = localtime((time_t *) & (tv.tv_sec)); + logfile << the_time->tm_hour << ":" << the_time->tm_min << ":" << the_time->tm_sec << ":" << (int) (tv.tv_usec / 1000) << " >> " << module_name << " >> " ; + logfile << "Display byte array(in Hex), length " << len << "(hex " << hex << len << ")\n"; + + lines = (len / MAX_BYTES_IN_LINE) + 1; + li = 0; + index = 0; + logfile.setf(ios::hex); + while ( li < lines){ + i = 0; + space = 0; + while (( i < MAX_BYTES_IN_LINE) && (index < len)) { + /* what is needed to display a single byte in hex */ + /* convert the char element to a unsigned character : weird??? */ + /* then convert the unsigned char to a unsigned short */ + /* do the display of the unsigned short */ + unsigned char usc = (log_info[index]); + unsigned short c = usc; + logfile << hex << setfill('0') << setw(2) << c; + space++; + if (space >= 4) { + logfile << " "; + space = 0; + } + index++; + i++; + } + logfile << "\n"; + li++; + } + logfile.setf(ios::dec); + logfile << flush; +#endif + + return; +} + + +/***********************************************************************/ +/* display_byte_array */ +/***********************************************************************/ +void display_byte_array( char *log_info, int len) +{ + int i,li, lines,index, space; + + lines = (len / MAX_BYTES_IN_LINE) + 1; + li = 0; + index = 0; + + + //cout << "lines = " << lines << " , len = " << len << "\n"; + cout.setf(ios::hex); + while ( li < lines){ + i = 0; + space = 0; + while (( i < MAX_BYTES_IN_LINE) && (index < len)) { + /* what is needed to display a single byte in hex */ + /* convert the char element to a unsigned character : weird??? */ + /* then convert the unsigned char to a unsigned short */ + /* do the display of the unsigned short */ + unsigned char usc = (log_info[index]); + unsigned short c = usc; + cout << hex << setfill('0') << setw(2) << c; + space++; + if (space >= 4) { + cout << " "; + space = 0; + } + index++; + i++; + } + cout << "\n"; + // cout << dec << "i = " << i << " , li = " << li << " , index = " << index << "\n"; + li++; + } + cout.setf(ios::dec); + cout << "SUA message size = " << len << "\n"; + +} + + +/***********************************************************************/ +/* close_logging_file */ +/***********************************************************************/ +void close_logging_file() +{ + struct timeval tv; + struct timezone tz; + struct tm *the_time; + + gettimeofday(&tv, &tz); + the_time = localtime((time_t *) & (tv.tv_sec)); + logfile << the_time->tm_hour << ":" << the_time->tm_min << ":" << the_time->tm_sec << ":" << (int) (tv.tv_usec / 1000) << " >> Logfile " << log_filename << " closed \n" << flush; + + // closing of random logfile + logfile.close(); + +} + + + + + + + + diff --git a/sualibrary/sua/sua_logging.h b/sualibrary/sua/sua_logging.h new file mode 100644 index 0000000..850be1e --- /dev/null +++ b/sualibrary/sua/sua_logging.h @@ -0,0 +1,72 @@ +/*************************************************************************** + sua_logging.h - 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_logging.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Annick + * "" + * + * Purpose: This header-file defines the SUA logging(error or normal stuff) + * functions for: + * - initialise the logging file + * - log events to logging file + * - log byte arrya to logging file + * - Display byte array to screen + * - close logging file + */ + +#ifndef SUA_LOGGING_H +#define SUA_LOGGING_H + +void init_logging_file(); +void event_log( char *module_name, char *log_info, ...); +void log_byte_array( char *module_name, char *log_info, int len); +void display_byte_array( char *log_info, int len); +void close_logging_file(); + +#endif // SUA_LOGGING_H + + + diff --git a/sualibrary/sua/sua_sual.cpp b/sualibrary/sua/sua_sual.cpp new file mode 100644 index 0000000..1b23cc0 --- /dev/null +++ b/sualibrary/sua/sua_sual.cpp @@ -0,0 +1,686 @@ +/*************************************************************************** + sua_sual.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_sual.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Patricia + * "a straight line version of SUA, really " + * "without the handpainted perrywinkels according to Hyacinth Bucket" + * + * Purpose: This code-file defines the SUA light interface: + * - SUAL Callback function + * and SUA light functions for: + * - SUAL initialisation + * - SUAL Connectionless data Notification + * - SUAL CO Connect Notification + * - SUAL CO Connect Confirm Notification + * - SUAL CO Data Notification + * - SUAL CO DisConnect Notification + * - SUAL Register Instance + * - SUAL Connectionless Data Request to SUA + * - SUAL CO Connect Request to SUA + * - SUAL CO Connect Confirm Request to SUA + * - SUAL CO Data Request to SUA + * - SUAL CO DisConnect Request to SUA + * - SUAL CO Data read from SUA + * - SUAL Connectionless Data read from SUA + */ + +#include "sua_sual.h" +#include "sua_database.h" +#include "sua_file.h" +#include "sua_distribution.h" +#include "sua_logging.h" + +#ifdef LINUX + #include <unistd.h> +#endif + + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> +#include <map> +#include <vector> + +#include <netinet/in_systm.h> +#include <netinet/ip.h> /* includes <netinet/in.h> also ! */ +#include <netinet/ip_icmp.h> +#include <netdb.h> +#include <arpa/inet.h> + +#define MAX_DATA_LENGTH 2000 + +using namespace std; +/* definition of SUA local object and of remote object */ +extern db_Sua_LocalList local_sua; +extern db_Sua_RemoteList remote_sua; +extern db_Sua_AssociationList Assoc_sua; + +typedef struct { + unsigned int local_sua_id; + unsigned int user_ref; + string userdata; +} sual_save_str; + +vector <sual_save_str> sual_rec_msg; + +SUAL_ULP_CallBacks sual_callback; + +/***********************************************************************/ +/* SUA light clone interface functions and structs with SUA */ +/***********************************************************************/ +/***********************************************************************/ +/* sual_init */ +/***********************************************************************/ + +int sual_init(unsigned char *pConfFile) +{ + + cout << "Initialising SUA datastructures\n "; + init_logging_file(); + local_sua.initialize(); + remote_sua.initialize(); + Assoc_sua.initialize(); + cout << "Finished initialising SUAL data\n "; + return (0); +} /* end of sua_initialisation */ + +/***********************************************************************/ +/* SUAL_ClDataIndNotif */ +/***********************************************************************/ +void SUAL_ClDataIndNotif ( unsigned int local_sua_id, + unsigned int primitive, + unsigned int datalen + ) +{ + unsigned int ControlNumber; + unsigned int length = 0; + sual_PeerAddr PeerAddr; + sual_PeerAddr *pPeerAddr; + unsigned int Sua_ConnId = 0; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + sual_save_str temp; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + // fill in the source address (=local sua address/CLG) + switch (clg.routing_ind) + { + case (route_on_ssn): + + if (clg.address_fields_present.pc == ipvx_pc_present) + { + if (clg.pc.ipvx.sa.sa_family == AF_INET) + { + PeerAddr.AddrType = SUAL_ADDRTYPE_IPV4; + PeerAddr.uPeerAddr.ip4 = clg.pc.ipvx.sin.sin_addr; + } + else if (clg.pc.ipvx.sa.sa_family == AF_INET6) + { + PeerAddr.AddrType = SUAL_ADDRTYPE_IPV6; + PeerAddr.uPeerAddr.ip6 = clg.pc.ipvx.sin6.sin6_addr; + } + else + cout << "error filling in CLG IP address \n"; + } + else + cout << "unsupported CLG address option\n"; + + break; + default: + cout << "Invalid CLG address option\n"; + break; + } + + ControlNumber = QOS.sequence_number; + pPeerAddr = &PeerAddr; + + temp.user_ref = Sua_ConnId; + temp.local_sua_id = local_sua_id; + // copy character array to temp string + temp.userdata.insert(0,databuffer,length); + + sual_rec_msg.push_back(temp); + + sual_callback.ClDataIndNotif ( local_sua_id, + ControlNumber, + pPeerAddr, + datalen + ); + + +} + +/***********************************************************************/ +/* SUAL_ConnIndNotif */ +/***********************************************************************/ +void SUAL_ConnIndNotif ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ) +{ + unsigned int primitive; + unsigned int length = 0; + sual_PeerAddr PeerAddr; + sual_PeerAddr *pPeerAddr; + unsigned int Sua_ConnId = 0; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + sual_save_str temp; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + // fill in the source address (=local sua address/CLG) + switch (clg.routing_ind) + { + case (route_on_ssn): + + if (clg.address_fields_present.pc == ipvx_pc_present) + { + if (clg.pc.ipvx.sa.sa_family == AF_INET) + { + PeerAddr.AddrType = SUAL_ADDRTYPE_IPV4; + PeerAddr.uPeerAddr.ip4 = clg.pc.ipvx.sin.sin_addr; + } + else if (clg.pc.ipvx.sa.sa_family == AF_INET6) + { + PeerAddr.AddrType = SUAL_ADDRTYPE_IPV6; + PeerAddr.uPeerAddr.ip6 = clg.pc.ipvx.sin6.sin6_addr; + } + else + cout << "error filling in CLG IP address \n"; + } + else + cout << "unsupported CLG address option\n"; + + break; + default: + cout << "Invalid CLG address option\n"; + break; + } + + pPeerAddr = &PeerAddr; + + temp.user_ref = Sua_ConnId; + temp.local_sua_id = local_sua_id; + // copy character array to temp string + temp.userdata.insert(0,databuffer,length); + + sual_rec_msg.push_back(temp); + + sual_callback.ConnIndNotif ( Sua_ConnId, + pPeerAddr, + datalen + ); + + +} + +/***********************************************************************/ +/* SUAL_ConnConfIndNotif */ +/***********************************************************************/ +void SUAL_ConnConfIndNotif ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ) +{ + unsigned int primitive; + unsigned int length = 0; + unsigned int Sua_ConnId = 0; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + sual_save_str temp; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + + temp.user_ref = Sua_ConnId; + temp.local_sua_id = local_sua_id; + // copy character array to temp string + temp.userdata.insert(0,databuffer,length); + + sual_rec_msg.push_back(temp); + + sual_callback.ConnConfNotif ( Sua_ConnId, + datalen + ); + + +} + +/***********************************************************************/ +/* SUAL_CoDataIndNotif */ +/***********************************************************************/ +void SUAL_CoDataIndNotif ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ) +{ + unsigned int primitive; + unsigned int length = 0; + unsigned int Sua_ConnId = 0; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + sual_save_str temp; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + + temp.user_ref = Sua_ConnId; + temp.local_sua_id = local_sua_id; + // copy character array to temp string + temp.userdata.insert(0,databuffer,length); + + sual_rec_msg.push_back(temp); + + sual_callback.CoDataIndNotif ( Sua_ConnId, + datalen + ); + + +} + +/***********************************************************************/ +/* SUAL_DisConnIndNotif */ +/***********************************************************************/ +void SUAL_DisConnIndNotif ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int reason, + unsigned int datalen + ) +{ + unsigned int primitive; + unsigned int length = 0; + unsigned int Sua_ConnId = 0; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + sual_save_str temp; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + + temp.user_ref = Sua_ConnId; + temp.local_sua_id = local_sua_id; + // copy character array to temp string + temp.userdata.insert(0,databuffer,length); + + sual_rec_msg.push_back(temp); + + sual_callback.DisconnIndNotif ( Sua_ConnId, + reason, + datalen + ); + + +} + +/***********************************************************************/ +/* sual_RegisterSUAL_instance */ +/***********************************************************************/ +extern sual_InstId_t sual_RegisterSUAL_instance ( sual_port_t local_ssn, + SUAL_ULP_CallBacks *callback + ) +{ + Sua_ULP_CallBacks ULP_CallbackFunctions; + int res; + + sual_callback.ClDataIndNotif = callback->ClDataIndNotif; + sual_callback.ConnIndNotif = callback->ConnIndNotif; + sual_callback.ConnConfNotif = callback->ConnConfNotif; + sual_callback.CoDataIndNotif = callback->CoDataIndNotif; + sual_callback.DisconnIndNotif = callback->DisconnIndNotif; + + + ULP_CallbackFunctions.ulp_ClDataIndNotif = &SUAL_ClDataIndNotif; + ULP_CallbackFunctions.ulp_ConnIndNotif = &SUAL_ConnIndNotif; + ULP_CallbackFunctions.ulp_ConnConfIndNotif = &SUAL_ConnConfIndNotif; + ULP_CallbackFunctions.ulp_ConnDataIndNotif = &SUAL_CoDataIndNotif; + ULP_CallbackFunctions.ulp_DisConnIndNotif = &SUAL_DisConnIndNotif; + + // register all the local SUA together with their SCTP instances + res = sua_registerInstance( local_ssn, + ULP_CallbackFunctions + ); + + return(0); +} + +/***********************************************************************/ +/* sual_ClDataReq : send Connectionless UnitData request to SUAL/SUA */ +/***********************************************************************/ +int sual_ClDataReq( sual_id_t InstId, + sual_PeerAddr_t *pPeerAddr, + uint ControlNumber, + unsigned char *pUserData, + uint UserDataLen + ) +{ + + unsigned int Sua_ConnId = 0; + sccp_addr_str cl_clg, cl_cld; + sccp_QOS_str cl_QOS; + unsigned int xsxx; + + cl_QOS.prot_class = class0; + cl_QOS.in_sequence = false; + cl_QOS.sequence_number = ControlNumber; + cl_QOS.return_msg_on_error = 0; + cl_QOS.importance = 0; + + /* indicate to SUA to get own(=source) address from the sua database */ + cl_clg.address_fields_present.pc = no_pc_present; + cl_clg.address_fields_present.name_gt = no_name_present; + cl_clg.address_fields_present.ssn_port = no_sap_present; + cl_clg.address_fields_present.field_in_header = include_nothing; + + /* convert destination address (only pointcodes supported) */ + cl_cld.address_fields_present.pc = ipvx_pc_present; + cl_cld.address_fields_present.name_gt = no_name_present; + cl_cld.address_fields_present.ssn_port = no_sap_present; + cl_cld.address_fields_present.field_in_header = include_nothing; + cl_cld.routing_ind = route_on_ssn; + + if (pPeerAddr->AddrType == SUAL_ADDRTYPE_IPV4) + { + cl_cld.pc.ipvx.sa.sa_family = AF_INET; + cl_cld.pc.ipvx.sin.sin_addr = pPeerAddr->uPeerAddr.ip4; + cl_cld.pc.ipvx.sin.sin_port = SUAL_DEF_PORTNUMBER; + } + else if (pPeerAddr->AddrType == SUAL_ADDRTYPE_IPV6) + { + cl_cld.pc.ipvx.sa.sa_family = AF_INET6; + cl_cld.pc.ipvx.sin6.sin6_addr = pPeerAddr->uPeerAddr.ip6; + cl_cld.pc.ipvx.sin6.sin6_port = SUAL_DEF_PORTNUMBER; + } + else + { + cout << "Invalid Destination address option\n"; + } + + char *databuffer = (char *) pUserData; + + xsxx = Send_sua_primitive(N_UNITDATA, + Sua_ConnId, + cl_QOS, + cl_cld, + cl_clg, + databuffer, + UserDataLen + ); + return(xsxx); +} + +/***********************************************************************/ +/* sual_ConnReq : send connect request to SUAL/SUA */ +/***********************************************************************/ +sual_id_t sual_ConnReq( sual_id_t InstId, + sual_PeerAddr_t *pPeerAddr, + unsigned char *pUserData, + uint UserDataLen + ) +{ + + unsigned int Sua_ConnId = 0; + sccp_addr_str clg, cld; + sccp_QOS_str QOS; + unsigned int xsxx; + + QOS.prot_class = class2; + QOS.in_sequence = false; + QOS.sequence_number = 0; + QOS.return_msg_on_error = 0; + QOS.importance = 0; + + /* indicate to SUA to get own(=source) address from the sua database */ + clg.address_fields_present.pc = no_pc_present; + clg.address_fields_present.name_gt = no_name_present; + clg.address_fields_present.ssn_port = no_sap_present; + clg.address_fields_present.field_in_header = include_nothing; + + /* convert destination address (only pointcodes supported) */ + cld.address_fields_present.pc = ipvx_pc_present; + cld.address_fields_present.name_gt = no_name_present; + cld.address_fields_present.ssn_port = no_sap_present; + cld.address_fields_present.field_in_header = include_nothing; + cld.routing_ind = route_on_ssn; + + if (pPeerAddr->AddrType == SUAL_ADDRTYPE_IPV4) + { + cld.pc.ipvx.sa.sa_family = AF_INET; + cld.pc.ipvx.sin.sin_addr = pPeerAddr->uPeerAddr.ip4; + cld.pc.ipvx.sin.sin_port = SUAL_DEF_PORTNUMBER; + } + else if (pPeerAddr->AddrType == SUAL_ADDRTYPE_IPV6) + { + cld.pc.ipvx.sa.sa_family = AF_INET6; + cld.pc.ipvx.sin6.sin6_addr = pPeerAddr->uPeerAddr.ip6; + cld.pc.ipvx.sin6.sin6_port = SUAL_DEF_PORTNUMBER; + } + else + { + cout << "Invalid Destination address option\n"; + } + + char *databuffer = (char *) pUserData; + + xsxx = Send_sua_primitive(N_UNITDATA, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + UserDataLen + ); + return(xsxx); + +} + +/***********************************************************************/ +/* sual_ConnResp : send connect response to SUAL/SUA */ +/***********************************************************************/ +int sual_ConnResp( sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen + ) +{ + return(0); +} + +/***********************************************************************/ +/* sual_CoDataReq : send Connection-oriented Data request to SUAL/SUA */ +/***********************************************************************/ +int sual_CoDataReq( sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen + ) +{ + + unsigned int Sua_ConnId = sual_ConnId; + sccp_addr_str clg, cld; + sccp_QOS_str QOS; + unsigned int xsxx; + + QOS.prot_class = class2; + QOS.in_sequence = false; + QOS.sequence_number = 0; + QOS.return_msg_on_error = 0; + QOS.importance = 0; + + /* no source address needed */ + clg.address_fields_present.pc = no_pc_present; + clg.address_fields_present.name_gt = no_name_present; + clg.address_fields_present.ssn_port = no_sap_present; + clg.address_fields_present.field_in_header = include_nothing; + + /* no destinationaddres needed */ + cld.address_fields_present.pc = no_pc_present; + cld.address_fields_present.name_gt = no_name_present; + cld.address_fields_present.ssn_port = no_sap_present; + cld.address_fields_present.field_in_header = include_nothing; + + char *databuffer = (char *) pUserData; + + xsxx = Send_sua_primitive(N_DATA_REQ, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + UserDataLen + ); + return(xsxx); +} + + +/***********************************************************************/ +/* sual_DisconnReq : send Disconnect request to SUAL/SUA */ +/***********************************************************************/ +int sual_DisconnReq( sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen + ) +{ + return(0); +} + +/***********************************************************************/ +/* sual_CoDataRead : read Connection-oriented Data from SUA/SUAL */ +/***********************************************************************/ +int sual_CoDataRead( sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pBuff, + uint BuffLen + ) +{ + sual_save_str temp = sual_rec_msg.front(); + sual_rec_msg.erase( sual_rec_msg.begin()); + + sual_ConnId = temp.user_ref; + InstId = temp.local_sua_id; + // put in supplied byte array(space is allocated beforehand by application) + temp.userdata.copy((char *)pBuff, temp.userdata.length(),0); + BuffLen = temp.userdata.length(); + return(SUAL_OK); +} + +/***********************************************************************/ +/* sual_ClDataRead : read Connectionless Data from SUA/SUAL */ +/***********************************************************************/ +int sual_ClDataRead( sual_id_t InstId, + sual_DataId_t DataId, + unsigned char *pBuff, + uint BuffLen + ) +{ + sual_save_str temp = sual_rec_msg.front(); + sual_rec_msg.erase( sual_rec_msg.begin()); + + DataId = temp.user_ref; + InstId = temp.local_sua_id; + // put in supplied byte array(space is allocated beforehand by application) + temp.userdata.copy((char *)pBuff, temp.userdata.length(),0); + BuffLen = temp.userdata.length(); + return(SUAL_OK); +} + + +/***********************************************************************/ +/* sual_snapshot : get snapshot of sua data */ +/***********************************************************************/ +extern int sual_snapshot( unsigned char *pSnapshotFile /* if NULL: stdout */ + ) + +{ + return(0); +} + +// end of module sua_sual.c++ + diff --git a/sualibrary/sua/sua_sual.h b/sualibrary/sua/sua_sual.h new file mode 100644 index 0000000..dd92084 --- /dev/null +++ b/sualibrary/sua/sua_sual.h @@ -0,0 +1,459 @@ +/*************************************************************************** + sua_sual.h - 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_sual.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Marie-Ange + * "A ligth weigth version of SUA, just what the doctor ordered" + * + * Purpose: This header-file defines the SUA light interface: + * - SUAL address structure + * - SUAL Callback function + * - SUAL function return values + * and SUA light functions for: + * - SUAL initialisation + * - SUAL Connectionless data Notification + * - SUAL CO Connect Notification + * - SUAL CO Connect Confirm Notification + * - SUAL CO Data Notification + * - SUAL CO DisConnect Notification + * - SUAL Register Instance + * - SUAL Connectionless Data Request to SUA + * - SUAL CO Connect Request to SUA + * - SUAL CO Connect Confirm Request to SUA + * - SUAL CO Data Request to SUA + * - SUAL CO DisConnect Request to SUA + * - SUAL CO Data read from SUA + * - SUAL Connectionless Data read from SUA + */ + +#ifndef SUA_SUAL_H +#define SUA_SUAL_H + +/* + *************************************************************************** + * + * Module: sua_sual.h + * + * Purpose: definition of SUALight API + * + *************************************************************************** + */ + +#ifdef LINUX + #include <unistd.h> +#endif + +//#include <cdefs.h> + +#include <sys/types.h> +#include <netinet/in.h> + +#define SUAL_SUALSERVICE_NAME "sual" +#define SUAL_SUALSERVICE_TRANSPORTPCOL "sctp" +#define SUAL_DEF_PORTNUMBER 14002 + +#define SUA_SCTP_PAYLOAD_PCOL_ID 0x04 + + +/* structures for API functions */ +typedef int sual_id_t; +typedef unsigned short sual_port_t; +typedef sual_id_t sual_InstId_t; +typedef sual_id_t sual_ConnId_t; +typedef sual_id_t sual_DataId_t; +typedef int reason_t; + +#define SUAL_DEF_NOSTREAMS 127 + + +extern int sual_errno; + + +typedef struct sual_PeerAddr { + int AddrType; /* predefined values for AddrType to indicate which + type is used in uPeerAddr: SUAL_ADDRTYPE_IPV4, + SUAL_ADDRTYPE_IPV6 */ + union uPeerAddr { + struct in_addr ip4; + struct in6_addr ip6; + } uPeerAddr; +} sual_PeerAddr_t; + +/* SUAL_ULP_CallBacks definitions */ +typedef struct sual_ULPcallbackFunctions { + + void (*ConnIndNotif)( sual_id_t sual_ConnId, + sual_PeerAddr_t *pPeerAddr, + uint UserDataLen + ); + void (*ConnConfNotif)( sual_id_t sual_ConnId, + uint UserDataLen + ); + void (*CoDataIndNotif)( sual_id_t sual_ConnId, + uint UserDataLen + ); + void (*DisconnIndNotif)( sual_id_t sual_ConnId, + reason_t reason, + uint UserDataLen + ); + void (*ClDataIndNotif)( sual_id_t sual_DataId, + uint ControlNumer, + sual_PeerAddr_t *pPeerAddr, + uint UserDataLen + ); +} sual_ULPcallbackFunctions_t; + + +typedef sual_ULPcallbackFunctions_t sualUif_Cbacks_t; + +typedef sual_ULPcallbackFunctions_t SUAL_ULP_CallBacks; + +typedef enum { + SUAL_ADDRTYPE_IPV4, + SUAL_ADDRTYPE_IPV6 +} sual_IpAddrType_t; + + +/* + * API-functions + */ +extern int sual_init( + unsigned char *pConfFile +); + +extern sual_InstId_t sual_RegisterSUAL_Instance( + sual_port_t LocalPort, + sual_ULPcallbackFunctions_t *pULPcallbackFunctions +); + + +sual_id_t +sual_ConnReq( + sual_id_t InstId, + sual_PeerAddr_t *pPeerAddr, + unsigned char *pUserData, + uint UserDataLen +); + +int +sual_ConnResp( + sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen +); + +int +sual_DisconnReq( + sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen +); + +int +sual_CoDataRead( + sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pBuff, + uint BuffLen +); + +int +sual_ClDataRead( + sual_id_t InstId, + sual_DataId_t DataId, + unsigned char *pBuff, + uint BuffLen +); + + +int +sual_CoDataReq( + sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen +); + +int +sual_ClDataReq( + sual_id_t InstId, + sual_PeerAddr_t *pPeerAddr, + uint ControlNumber, + unsigned char *pUserData, + uint UserDataLen +); + +extern int +sual_snapshot( + unsigned char *pSnapshotFile /* if NULL: stdout */ +); + +/*====================== reasons of ulp_DisconnIndNotif: ======================*/ + +typedef enum { + SUAL_DISCONN_NOMORE_STREAMS=100, + SUAL_DISCONN_SCTP_ASSOCIATION_LOST, + SUAL_DISCONN_USERDATA_NOTREAD, + SUAL_DISCONN_READUSERDATA_ILLPARAM, + SUAL_DISCONN_CO_DATAREQ_WITHOUT_PAYLOAD, + SUAL_DISCONN_WRONGEVENT_FROM_OTHER_PEER, + SUAL_DISCONN_BY_COMMUNICATION_LOST, + SUAL_DISCONN_BY_NETWORKSTATUSCHANGE, + SUAL_DISCONN_COAC_CC_NOT_IN_CONNREQ_SENT, /* new */ + SUAL_DISCONN_BY_COAK_REF, /*new*/ + SUAL_DISCONN_NOMEM, + + SUAL_DISCONN_NOTABLE2SEND_SCTP_RELEASEREQUEST_MSG, + + SUAL_DISCONN_NOTABLE2SEND_SCTP_CONNECTREQUEST_MSG, + SUAL_DISCONN_NOTABLE2SEND_SCTP_MSG, + SUAL_DISCONN_NOTABLE2SEND_SCTP_COAK_REF_MSG, + + SUAL_DISCONN_SENDFAILURENOTIF, /* new */ + + SUAL_DISCONN_LAST +} sual_disconnReason_t; + +/*====================== returns of sual-API-functions: ======================*/ + +#define SUAL_OK 0 + + +typedef enum { + SUAL_API_RETURNS_FIRST=-1999, /* is no return */ + + +/* + * Returns of all function exept sual_init() + */ + SUAL_EERR_ENTITYSTATE, /* entity error */ + SUAL_UERR_WRONG_INSTID, /* ULP error */ + SUAL_ERR_NOMEM, /* no more memory */ + +/* + * Returns of all connection oriented api-functions + */ + SUAL_UERR_NOSUCH_CONN, /* obsolete */ + SUAL_UERR_CONNSTATE, + SUAL_UERR_ILLPARAM_USERDATA,/* concerning UserDataLen, pUserData */ + SUAL_UERR_USERDATA_NOTREAD, /* new */ + +/* + * sual_init() + */ + SUAL_EERR_ILLPARAM, /* e.g. Null-pointer */ + SUAL_CFG_ENOFILENAME, + SUAL_CFG_EOPENFILE, + SUAL_CFG_ENOPARAM, + SUAL_CFG_EPARAMVALUE, + SUAL_CFG_EPARAMFORMAT, + SUAL_CFG_EBUFFERLNG, + SUAL_CERR_NOLOCAL_ADDRS_IN_CONFFILE, + SUAL_SERR_SCTP_REGISTER, /* sctp error */ +/* new */ + SUAL_WARN_LOCKED_REINIT, + +/* + * Returns of sual_RegisterSUAL_Instance() + */ + SUAL_UERR_NULLPOINTER_CALLBACK, + SUAL_UERR_CBMISSING_CONCONFNOTIF, + SUAL_UERR_CBMISSING_CONINDNOTIF, + SUAL_UERR_CBMISSING_DISCONNINDNOTIF, + SUAL_UERR_CBMISSING_CODATAINDNOTIF, + SUAL_UERR_CBMISSING_CLDATAINDNOTIF, + + SUAL_UERR_LOCALPORT_NOTUNIQUE, + +/* + * Returns of sual_ConnReq() + */ + SUAL_UERR_NO_PEERADDR, + SUAL_UERR_IPV4_NOTYET, + SUAL_UERR_WRONG_ADDRTYPE, + SUAL_WARN_SHORTAGE_OF_STREAMS, + +/* + * Returns of sual_ConnResp() + * see common returns: + - SUAL_UERR_ILLPARAM_USERDATA + - SUAL_UERR_CONNSTATE + */ + + +/* + * Returns of sual_DisconnReq() + * see common returns: + - SUAL_UERR_ILLPARAM_USERDATA + - SUAL_UERR_CONNSTATE + */ + + +/* + * Returns of sual_CoDataRead() and sual_ClDataRead() + */ + SUAL_UERR_MISSING_DATABUFFER, + SUAL_UERR_MISSING_USERDATALEN, + SUAL_UERR_BUFFLEN_TOOLESS, + /* + * Returns of sual_CoDataRead() + */ + SUAL_UERR_WRONG_CONNID, + SUAL_UERR_CO_NODATA2READ, + /* + * Returns of sual_ClDataRead() + */ + SUAL_UERR_WRONG_DATAID, + SUAL_UERR_CL_NODATA2READ, /* e.g. already read */ + +/* + * Returns of sual_CoDataReq() and sual_ClDataReq() + */ + SUAL_UERR_DATAREQ_MISSING_DATABUFFER, /* obsolete */ + SUAL_UERR_DATAREQ_MISSING_USERDATALEN,/* obsolete */ + +/* + * Returns of sual_ClDataReq() + - SUAL_UERR_NO_PEERADDR + - SUAL_UERR_IPV4_NOTYET + - SUAL_UERR_WRONG_ADDRTYPE + */ + SUAL_UERR_CONTROLNUMBER_OUT_OF_RANGE, + +/*==============================================*/ + + +/* + * errors on LIF + */ + + SUAL_RCVCLDATATRANSFER_USERDATA_NOTREAD, /* new */ + + SUAL_ERR_NOSUCH_SCTP_ASSOCIATION, + SUAL_ERR_ULP_SSN_NOTREGISTERED, + SUAL_ERR_STREAMID_TOOBIG, + SUAL_ERR_NOMEM_TO_RECEIVE_SCTPCHUNK, + SUAL_ERR_FAILURE_SCTP_ASSOCIATE, + SUAL_ERR_WRONG_AF_INET_TYPE, + SUAL_ERR_SUAL_RELRE_MSG_ON_FREE_STREAM, + SUAL_ERR_SUAL_COAK_CC_MSG_ON_FREE_STREAM, + SUAL_ERR_SUAL_RELCO_MSG_ON_FREE_STREAM, + SUAL_ERR_SUAL_CODT_MSG_ON_FREE_STREAM, + SUAL_ERR_COAC_CC_NOT_IN_CONNREQ_SENT, + SUAL_ERR_RCV_RELCO_BUTNOTWAITING_FOR, + + SUAL_SERR_NOTEXIST_DESTADDR, + SUAL_SERR_NOTSUPPORTED_ADDRFORMAT, + SUAL_SERR_WRONG_MSGTYP_ONSTREAM, + SUAL_SERR_WRONG_MSGLEN, + SUAL_SERR_WRONGEVENT_FROM_OTHER_PEER, + SUAL_SERR_NOMORE_STREAMS, + SUAL_SERR_NOTABLE2SEND_SCTP_MSG, + + + +/* + * Errors concerning the SUAL-message + */ + SUAL_MSGERR_WRONG_PCOL_VERS=-600, + SUAL_MSGERR_WRONG_MSGLEN, /* new */ + SUAL_MSGERR_LEN_TOOLESS_MSGHDR, + SUAL_MSGERR_UNKNOWN_MSGTYPE, + SUAL_MSGERR_WRONG_VALUES4SPARE, + +/* + * Errors in syslog + */ + SUAL_SSN_NOTREGISTERED, + +/* + * Program errors, which should newer occur + */ + SUAL_PERR_NO_SNAPSHOT_FD=-580, + SUAL_PERR_ASS_NOTESTABL, + SUAL_PERR_ASS_STATE_UNKNOWN, + SUAL_PERR_WRONG_STATE, + SUAL_PERR_ALREADY_REGISTERED, + + SUAL_PERR_NULLPOINTER, + SUAL_PERR_PARAM_NULLPOINTER, + + SUAL_PERR_NULLPOINTER_PEERADDR, + SUAL_PERR_NULLPOINTER_SOCKUNION, + + SUAL_PERR_NULLPOINTER_INSTEL, + SUAL_PERR_NULLPOINTER_ASSEL, + SUAL_PERR_NULLPOINTER_CONNEL, + SUAL_PERR_NULLPOINTER_STREAMEL, + + SUAL_PERR_NULLPOINTER_RCVMSG, + SUAL_PERR_NULLPOINTER_POIPOIRCVMSG, + SUAL_PERR_NULLPOINTER_USERDATA, + + SUAL_PERR_WRONG_CONNID_INREAD, + SUAL_PERR_CONNSTATE, + SUAL_PERR_INCONSISTENT_LEN, + SUAL_PERR_NOASS_IN_CONNEL, + SUAL_PERR_ARG_IS_NULL_POINTER, + + SUAL_PERR_WRONG_ASS_STATE, + SUAL_PERR_WRONG_EVENT_ONFREESTREAM, + SUAL_PERR_NOSUCH_SCTPASSOC, + + /* 19.06.2001: additional errors: */ + /* sual_init(): */ + SUAL_SERR_SYSTEMFUNCTION, + SUAL_PERR_ERROR, + SUAL_CFG_ERROR, + + SUAL_LAST_RET_VALUE +} sual_api_returns_t; + +#endif // SUA_SUAL_H + +// end of module sua_sual.h diff --git a/sualibrary/sua/sua_syntax.cpp b/sualibrary/sua/sua_syntax.cpp new file mode 100644 index 0000000..f7d67f4 --- /dev/null +++ b/sualibrary/sua/sua_syntax.cpp @@ -0,0 +1,4733 @@ +/*************************************************************************** + 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 <iostream> +#include <iomanip> +using namespace std; + +/********************************************************************/ +/* General error structure, returned by main en/decoder */ +/********************************************************************/ + +Sua_syntax_error_struct SYNTAX_ERR; + +/********************************************************************/ +/* General purpose overlay structure, used everywhere */ +/********************************************************************/ + +union Four_bytes_overlay { + uint32_t dq; + uint16_t dw[2]; + uint8_t db[4]; +}; + +Four_bytes_overlay OVERLAY; + +/********************************************************************/ +/* Sua_container method sua_init : Initialize SUA container element */ +/********************************************************************/ + +void Sua_container::sua_init () { + /* Initialize primitive */ + /* Initialize SUA header */ + sua_prim.hdr_version = Sua_unknown; + sua_prim.hdr_msg_class = sua_mngt; + sua_prim.hdr_msg_type.mngt = mngt_error; + /* Initialize every boolean parameter to FALSE */ + sua_prim.data_pres = FALSE; + sua_prim.info_pres = FALSE; + sua_prim.rout_con_pres = FALSE; + sua_prim.diag_info_pres = FALSE; + sua_prim.hb_data_pres = FALSE; + sua_prim.traf_mode_pres = FALSE; + sua_prim.err_code_pres = FALSE; + sua_prim.status_pres = FALSE; + sua_prim.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; +} + + + + ///:~ + + + + + + diff --git a/sualibrary/sua/sua_syntax.h b/sualibrary/sua/sua_syntax.h new file mode 100644 index 0000000..0295a8f --- /dev/null +++ b/sualibrary/sua/sua_syntax.h @@ -0,0 +1,447 @@ +/*************************************************************************** + sua_syntax.h - 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.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 5. + * + * Author(s): Gery Verwimp + * + * 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 : Kathleen + * "Computers/networks must be female, because if they were male, " + * "they would be perfectably predictable and computers/networks are " + * "never predictable. If you do not believe this, just ask any women." + * + * Purpose: This header-file defines the SUA syntax class for SUA + * primitives and messages, including the en/decoding routines. + */ + +#ifndef SUA_SYNTAX_H +#define SUA_SYNTAX_H + +#include "sua.h" +#include <string> + +/********************************/ +/* 0. SUA message header syntax */ +/********************************/ + +enum Sua_version { + Sua_unknown, + Sua_version1 +}; + +enum Sua_msg_class { + sua_mngt, + sua_reserved1, + sua_ssnm, + sua_aspsm, + sua_asptm, + sua_reserved5, + sua_reserved6, + sua_cl, + sua_co, + sua_rkm, + sua_max +}; + +enum Sua_mngt_msg_type { + mngt_error, + mngt_notify, + mngt_max +}; + +enum Sua_ssnm_msg_type { + ssnm_reserved0, + ssnm_duna, + ssnm_dava, + ssnm_daud, + ssnm_scon, + ssnm_dupu, + ssnm_drst, + ssnm_max +}; + +enum Sua_aspsm_msg_type { + aspsm_reserved0, + aspsm_up, + aspsm_down, + aspsm_beat, + aspsm_up_ack, + aspsm_down_ack, + aspsm_beat_ack, + aspsm_max +}; + +enum Sua_asptm_msg_type { + asptm_reserved0, + asptm_act, + asptm_inact, + asptm_act_ack, + asptm_inact_ack, + asptm_max +}; + +enum Sua_cl_msg_type { + cl_reserved0, + cl_data_transfer, /* unitdata */ + cl_data_response, /* unitdata service */ + cl_max +}; + +enum Sua_co_msg_type { + co_reserved0, + co_core, /* connection request */ + co_coak, /* connection confirm */ + co_coref, /* connection refused */ + co_relre, /* release request */ + co_relco, /* release confirm */ + co_resco, /* reset confirm */ + co_resre, /* reset request */ + co_data, /* data transfer, expedited data */ + co_data_ack, /* (expedited) data acknowledge */ + co_err, /* PDU error */ + co_it, /* inactivity test */ + co_max +}; + +enum Sua_rkm_msg_type { + rkm_reserved0, + rkm_reg_req, /* registration request */ + rkm_reg_resp, /* registration response */ + rkm_dereg_req, /* deregistration request */ + rkm_dereg_resp, /* deregistration response */ + rkm_max +}; + +union Sua_msg_type { + Sua_mngt_msg_type mngt; + Sua_ssnm_msg_type ssnm; + Sua_aspsm_msg_type aspsm; + Sua_asptm_msg_type asptm; + Sua_cl_msg_type cl; + Sua_co_msg_type co; + Sua_rkm_msg_type rkm; +}; + +/***********************************/ +/* 1. SUA management message modes */ +/***********************************/ + +enum Sua_traffic_mode_type { + tmt_unknown, + tmt_override, + tmt_loadshare, + tmt_broadcast, + tmt_max +}; + +enum Sua_error_code_type { + ect_unknown, + ect_invalid_version, + ect_invalid_interface_id, + ect_unsupported_msg_class, + ect_unsupported_msg_type, + ect_unsupported_traffic_handling_mode, + ect_unexpected_msg, + ect_protocol_error, + ect_unsupported_interface_id_type, /* not used in SUA */ + ect_invalid_stream_id, + ect_unassigned_TEI, /* not used in SUA */ + ect_unrecognized_SAPI, /* not used in SUA */ + ect_invalid_TEI_SAPI_comb, /* not used in SUA */ + ect_refused_mngt_blocking, + ect_ASP_id_required, + ect_invalid_ASP_id, + ect_invalid_routing_context, + ect_invalid_parameter_value, + ect_parameter_field_error, + ect_unexpected_parameter, + ect_destination_status_unknown, + ect_invalid_network_appearance, + ect_missing_parameter, + ect_routing_key_change_refused, + ect_invalid_loadsharing_label, + ect_max +}; + +typedef struct { + uint8_t status_type; + uint8_t status_ID; +} Sua_status_struct; + +/* ASP capabilities */ + +enum Sua_interworking_type { + iw_none, /* no interworking with SS7 */ + iw_asp, /* IP endpoint ASP */ + iw_sg, /* Signalling Gateway */ + iw_relay, /* IP relay point */ + iw_max +}; + +typedef struct { + boolean cl0_supp; + boolean cl1_supp; + boolean cl2_supp; + boolean cl3_supp; + uint8_t interworking; +} Sua_asp_cap_struct; + +/*********************************/ +/* 2. SUA protocol message modes */ +/*********************************/ + +enum Sua_protocol_class { + prot_class_0, + prot_class_1, + prot_class_2, + prot_class_3, + prot_max +}; + +typedef struct { + Sua_protocol_class pcl; + boolean return_option; +} Sua_protocol_class_struct; + +/* The SUA address parameter contains following fields : + - routing indicator : see below + - address indicator : for SS7 interworking, defines inclusion of SSN, PC or GT in SS7 address + - address parameters : combination of GT, hostname, IPaddress, SSN, PC +*/ + +enum Sua_rout_ind { + ri_reserved0, + ri_route_GT, + ri_route_PC_SSN, + ri_route_hostname, + ri_route_IP_SSN, + ri_max +}; + +typedef struct { + uint8_t translation_type; + uint8_t num_plan; + uint8_t nat_addr; + uint8_t nr_of_digits; + uint8_t digits[24]; +} SCCP_GT_struct; + +enum Sua_ip_addr_type { + ip_reserved0, + ip_v4, + ip_v6, + ip_max +}; + +union Ip_address { + sockaddr_in ipv4; + sockaddr_in6 ipv6; +}; + +typedef struct { + Sua_rout_ind rout_ind; + /* Flags for address indicator */ + boolean ssn_incl; + boolean gt_incl; + boolean pc_incl; + /* Indication of elements present */ + boolean pc_pres; + boolean ip_addr_pres; + boolean gt_pres; + boolean hostname_pres; + /* An SSN must always be present on the primitive interface, even if unknown (=0) */ + uint8_t ssn; + int pc; + Sua_ip_addr_type ip_addr_type; + Ip_address ip_addr; + SCCP_GT_struct gt; + string hostname; +} Sua_address_struct; + +/* The SCCP Cause parameter can contain the following : + - return cause (in CLDR messages) + - refusal cause (in COREF messages) + - release cause (in RELRE messages) + - reset cause (in RESRE messages) + - error cause (in COERR messages) +*/ +enum SCCP_cause_type { + ctp_reserved0, + ctp_return_cause, + ctp_refusal_cause, + ctp_release_cause, + ctp_reset_cause, + ctp_error_cause, + ctp_max +}; + +typedef struct { + SCCP_cause_type cause_type; + uint16_t cause_value; +} SCCP_cause_struct; + +/* The sequence number parameter contains : + - the sent and received seq numbers (0..127) for protocol class 3 + - the more data indicator for protocol classes 2 and 3 +*/ + +typedef struct { + uint8_t sent_seq_nr; + uint8_t rcvd_seq_nr; + boolean more_data; +} Sua_seq_nr_struct; + +/* The segmentation parameter contains : + - first segment indication + - number of remaining segments (0..15) + - segmentation reference (0..2~24-1) +*/ + +typedef struct { + boolean first; + uint8_t remain; + uint32_t segm_ref; +} Sua_segm_struct; + +/* The label parameter contains : + - start of the label bits (0..31) + - end of the label bits (0..31) + - label value (0..2~16-1) +*/ + +typedef struct { + uint8_t start; + uint8_t end; + uint16_t label_value; +} Sua_label_struct; + +/* And now, we present to you the SUA container, mother of all interfaces */ + +typedef struct { + /* 0. Mandatory header */ + Sua_version hdr_version; + Sua_msg_class hdr_msg_class; + Sua_msg_type hdr_msg_type; + /* 1. Common parameter part presence */ + boolean data_pres; + boolean info_pres; + boolean rout_con_pres; + boolean diag_info_pres; + boolean hb_data_pres; + boolean traf_mode_pres; + boolean err_code_pres; + boolean status_pres; + boolean cong_lvl_pres; + boolean ASP_id_pres; + boolean aff_pc_pres; + /* 1. Common parameter part */ + string data_string; + string info_string; + uint32_t rout_con; + string diag_info; + string hb_data; + Sua_traffic_mode_type traf_mode; + Sua_error_code_type err_code; + Sua_status_struct status; + uint8_t cong_lvl; + uint32_t ASP_id; + uint32_t aff_pc; + /* 2. SUA specific parameter part presence */ + boolean netw_app_pres; + boolean hop_count_pres; + boolean source_addr_pres; + boolean dest_addr_pres; + boolean source_ref_pres; + boolean dest_ref_pres; + boolean SCCP_cause_pres; + boolean seq_nr_pres; + boolean rec_seq_nr_pres; + boolean asp_cap_pres; + boolean credit_pres; + boolean importance_pres; + boolean prot_class_pres; + boolean seq_control_pres; + boolean segm_pres; + boolean TID_label_pres; + boolean DRN_label_pres; + /* 2. SUA specific parameter part */ + uint32_t netw_app; + Sua_address_struct source_addr; + Sua_address_struct dest_addr; + uint32_t source_ref; + uint32_t dest_ref; + SCCP_cause_struct SCCP_cause; + Sua_seq_nr_struct seq_nr; + Sua_asp_cap_struct asp_cap; + Sua_protocol_class_struct prot_class; + uint8_t hop_count; + uint8_t rec_seq_nr; + uint8_t credit; + uint8_t importance; + uint32_t seq_control; + Sua_segm_struct segm; + Sua_label_struct TID_label; + Sua_label_struct DRN_label; +} Sua_primitive_struct; + +typedef struct { + int msg_index; // position in transfer syntax + boolean no_error; + string error_text; // error text, specifying details +} Sua_syntax_error_struct; + +class Sua_container { + public: + Sua_primitive_struct sua_prim; + string sua_msg; + void sua_init (); + Sua_syntax_error_struct sua_encode (); + Sua_syntax_error_struct sua_decode (); +}; + +#endif // SUA_SYNTAX_H + + + + + + diff --git a/sualibrary/sua/sua_tcb.cpp b/sualibrary/sua/sua_tcb.cpp new file mode 100644 index 0000000..e896cb1 --- /dev/null +++ b/sualibrary/sua/sua_tcb.cpp @@ -0,0 +1,218 @@ +/*************************************************************************** + sua_tcb.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_tcb.cpp,v 1.1.1.1 2002/02/04 14:30:42 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Daphne + * "Listen very carefully, I shall say this only once:" + * "a TCB, a TCB, my kingdom for a TCB" + * + * Purpose: This code-file defines the SUA Transaction Control Block(TCB) pool + * functions for(needed for SUA connection oriented): + * - initialising a single TCB + * - initialising the TCB pool + * - allocate a TCB + * - get a TCB + * - release a TCB + * And for the Saved SUA msg queue pool + * - add SUA msg to queue + * - get sua msg from queue + * - release the SUA msg from the queue + */ + +#include "sua_debug.h" +#include "sua_tcb.h" +#include "sua_database.h" +#include "sua_logging.h" +#include "sua.h" + +#include <cstdio> +#include <iostream> +#include <cstdlib> +#include <string> + +#include <netinet/in_systm.h> +#include <netinet/ip.h> /* includes <netinet/in.h> also ! */ +#include <netinet/ip_icmp.h> +#include <netdb.h> +#include <arpa/inet.h> + +using namespace std; + +/* sua SCOC tcb pool */ +tcb_Sua_TCB_arr tcb_pool; + +/* sua temporary message store */ +tcb_Sua_msgqueue_pool msg_store; + +/***********************************************************************/ +/* Sua SCOC TCB: initialise TCB element */ +/***********************************************************************/ +void tcb_Sua_TCB_str::init_TCB_elem() +{ + state = scoc_idle; + Dest_LR = 0; + Source_LR = 0; + User_ref_id = 0; + sctp_Association_id = 0; + prcl_class = class0 ; + return_option = FALSE; +} + +/***********************************************************************/ +/* Sua SCOC TCB arr: initialise TCB pool */ +/***********************************************************************/ +void tcb_Sua_TCB_arr::init_TCB_pool() +{ + cout << "Initialising ?? \n"; + last_allocated_tcb = 0; +} + + +/***********************************************************************/ +/* Sua SCOC TCB arr: allocate a TCB */ +/***********************************************************************/ +tcb_Sua_TCB_str *tcb_Sua_TCB_arr:: allocate_TCB(unsigned int &local_ref){ + + last_allocated_tcb++; + // allocate the TCB + tcb_Sua_TCB_str new_tcb; + new_tcb.init_TCB_elem(); + tcb_sua_pair_str tcb_ref_pair(last_allocated_tcb,new_tcb); + + tcb_sua_map_iterator_str p = tcb.insert(tcb_ref_pair); + + if (p.second) + { + char logstring[100]; + sprintf(logstring, "TCB %d allocated",last_allocated_tcb); + event_log("sua_tcb.c",logstring); + } + else + { + char logstring[100]; + sprintf(logstring, "No TCB allocated, damm"); + event_log("sua_tcb.c",logstring); + } + + local_ref = last_allocated_tcb; + cout << "tcb local ref = " << local_ref << "\n"; + return(&tcb[last_allocated_tcb]); +} + +/***********************************************************************/ +/* Sua SCOC TCB arr: get address of TCB */ +/***********************************************************************/ +tcb_Sua_TCB_str *tcb_Sua_TCB_arr:: get_tcb(unsigned int local_ref) { + + return(&tcb[local_ref]); +} + +/***********************************************************************/ +/* Sua SCOC TCB arr: release the TCB */ +/***********************************************************************/ +void tcb_Sua_TCB_arr:: release_TCB(unsigned int local_reference){ + + int count = tcb.erase(local_reference); + + if (count != 0) + { + char logstring[100]; + sprintf(logstring, "TCB instances %d of LR %d Released : ",count,local_reference); + event_log("sua_tcb.c",logstring); + } + else + { + char logstring[100]; + sprintf(logstring, "TCB instance not released"); + event_log("sua_tcb.c",logstring); + } + +} + +/***********************************************************************/ +/* Sua_msg : save msg */ +/***********************************************************************/ +void tcb_Sua_msgqueue_pool:: add_msg( unsigned int sua_assoc_idx, + tcb_Sua_msg_elem sua_msg + ) +{ + sua_msg.valid = true; + msg_store.instance[sua_assoc_idx].push(sua_msg); +} + +/***********************************************************************/ +/* Sua_msg : get msg */ +/***********************************************************************/ +tcb_Sua_msg_elem tcb_Sua_msgqueue_pool:: get_msg( unsigned int sua_assoc_idx ) +{ + tcb_Sua_msg_elem temp_sua_msg; + + temp_sua_msg.valid = false; + if ( !msg_store.instance[sua_assoc_idx].empty() ) + { + return( msg_store.instance[sua_assoc_idx].front()); + } + else + { + + return(temp_sua_msg); + } +} + +/***********************************************************************/ +/* Sua_msg : Delete msg */ +/***********************************************************************/ +void tcb_Sua_msgqueue_pool:: delete_msg( unsigned int sua_assoc_idx ) +{ + if ( !msg_store.instance[sua_assoc_idx].empty() ) + msg_store.instance[sua_assoc_idx].pop(); +} + +// end of module sua_tcb.c + + + + diff --git a/sualibrary/sua/sua_tcb.h b/sualibrary/sua/sua_tcb.h new file mode 100644 index 0000000..dd2ec60 --- /dev/null +++ b/sualibrary/sua/sua_tcb.h @@ -0,0 +1,153 @@ +/*************************************************************************** + sua_tcb.h - 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_tcb.h,v 1.1.1.1 2002/02/04 14:30:42 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): 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 : Isabelle + * " + * "" + * + * Purpose: This header-file defines the SUA Transaction Control Block(TCB) + * pool functions for(needed for SUA connection oriented): + * - initialising a single TCB + * - initialising the TCB pool + * - allocate a TCB + * - get a TCB + * - release a TCB + * And for the Saved SUA msg queue pool + * - add SUA msg to queue + * - get sua msg from queue + * - release the SUA msg from the queue + */ + +#ifndef SUA_TCB_H +#define SUA_TCB_H + +#include "sua_database.h" +#include "sua_syntax.h" +#include "sua.h" + +#include <string> +#include <map> +#include <queue> +#include <arpa/inet.h> + +enum tcb_scoc_state_set { + scoc_idle, // idle state + scoc_incoming, + scoc_wait_m_CC, + scoc_outgoing, + scoc_active, + scoc_disconnect +}; + +class tcb_Sua_TCB_str +{ + public: + tcb_scoc_state_set state; + unsigned int Dest_LR; + unsigned int Source_LR; + unsigned int User_ref_id; + unsigned int sctp_Association_id; + protocol_class_set prcl_class; + unsigned int seq_number; + bool return_option; + sccp_addr_str remote_address; + public: + void init_TCB_elem(); +}; ///:~ + +typedef map<int,tcb_Sua_TCB_str> tcb_sua_map_str; + +class tcb_Sua_TCB_arr +{ + public: + tcb_sua_map_str tcb; + /*private:*/ + unsigned int last_allocated_tcb; + public: + void init_TCB_pool(); + tcb_Sua_TCB_str *allocate_TCB(unsigned int &Sua_ConnId); + tcb_Sua_TCB_str *get_tcb(unsigned int Sua_ConnId); + void release_TCB(unsigned int Sua_ConnId); +}; ///:~ + +typedef pair<unsigned int, tcb_Sua_TCB_str> tcb_sua_pair_str; + +typedef pair<tcb_sua_map_str::iterator,bool> tcb_sua_map_iterator_str; + +struct tcb_Sua_msg_elem { + string byte; + int delivery_type; + int stream_id; + bool valid; +}; + +typedef queue<tcb_Sua_msg_elem> tcb_Sua_msgqueue; + +class tcb_Sua_msgqueue_pool +{ + public: + tcb_Sua_msgqueue instance[db_MAX_REMOTE_SUA]; + public: + void add_msg( unsigned int sua_assoc_idx, + tcb_Sua_msg_elem sua_msg + ); + tcb_Sua_msg_elem get_msg( unsigned int sua_assoc_idx ); + void delete_msg( unsigned int sua_assoc_idx ); +}; ///:~ + + +#endif // SUA_TCB_H + +//end of module sua_tcb.h + + + + + + + + |