libsua/sualibrary/sua/sua_sual.cpp

686 lines
20 KiB
C++

/***************************************************************************
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.2 2002/04/11 14:13:34 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_DatabaseList 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();
sua.local_sua.initialize();
sua.remote_sua.initialize();
sua.AssocDB.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++