1711 lines
51 KiB
C++
1711 lines
51 KiB
C++
/***************************************************************************
|
|
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.2 2002/03/01 12:57:38 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"
|
|
#include "sua_cl.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;
|
|
int sua_assoc_id;
|
|
signed int sctp_loadshare = SCTP_USE_PRIMARY;
|
|
short sctp_stream_id = 0;
|
|
int sctp_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;
|
|
sctp_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,
|
|
sua_assoc_id
|
|
);
|
|
#ifdef DEBUG
|
|
cout << "routed to SCTP assoc " << SCTP_assoc_id << "/SUA association " << sua_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)
|
|
{
|
|
/* copy data into buffer, then finally... */
|
|
char* databuf = new char[msg.sua_msg.length()];
|
|
msg.sua_msg.copy(databuf, msg.sua_msg.length());
|
|
|
|
datalen = msg.sua_msg.length();
|
|
|
|
// send data to SCTP
|
|
result = sua_send_Message( SCTP_assoc_id,
|
|
sctp_stream_id,
|
|
sctp_delivery_type,
|
|
sctp_loadshare,
|
|
databuf,
|
|
datalen
|
|
);
|
|
|
|
delete databuf;
|
|
error_value = 0;
|
|
|
|
#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 = sctp_delivery_type;
|
|
sua_msg.stream_id = sctp_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;
|
|
signed int sctp_loadshare = SCTP_USE_PRIMARY;
|
|
short sctp_stream_id = 0;
|
|
int sctp_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 ;
|
|
sctp_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
|
|
/* copy data into buffer, then finally... */
|
|
char* databuf = new char[msg.sua_msg.length()];
|
|
msg.sua_msg.copy(databuf, msg.sua_msg.length());
|
|
|
|
datalen = msg.sua_msg.length();
|
|
|
|
// send data to SCTP
|
|
result = sua_send_Message( SCTP_assoc_id,
|
|
sctp_stream_id,
|
|
sctp_delivery_type,
|
|
sctp_loadshare,
|
|
databuf,
|
|
datalen
|
|
);
|
|
|
|
delete databuf;
|
|
error_value = 0;
|
|
|
|
#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;
|
|
signed int sctp_loadshare = SCTP_USE_PRIMARY;
|
|
short sctp_stream_id = 0;
|
|
int sctp_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 ;
|
|
sctp_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
|
|
/* copy data into buffer, then finally... */
|
|
char* databuf = new char[msg.sua_msg.length()];
|
|
msg.sua_msg.copy(databuf, msg.sua_msg.length());
|
|
|
|
datalen = msg.sua_msg.length();
|
|
|
|
// send data to SCTP
|
|
result = sua_send_Message( SCTP_assoc_id,
|
|
sctp_stream_id,
|
|
sctp_delivery_type,
|
|
sctp_loadshare,
|
|
databuf,
|
|
datalen
|
|
);
|
|
|
|
delete databuf;
|
|
error_value = 0;
|
|
|
|
|
|
#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;
|
|
signed int sctp_loadshare = SCTP_USE_PRIMARY;
|
|
short sctp_stream_id = 0;
|
|
int sctp_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 ;
|
|
sctp_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
|
|
/* copy data into buffer, then finally... */
|
|
char* databuf = new char[msg.sua_msg.length()];
|
|
msg.sua_msg.copy(databuf, msg.sua_msg.length());
|
|
|
|
datalen = msg.sua_msg.length();
|
|
|
|
// send data to SCTP
|
|
result = sua_send_Message( SCTP_assoc_id,
|
|
sctp_stream_id,
|
|
sctp_delivery_type,
|
|
sctp_loadshare,
|
|
databuf,
|
|
datalen
|
|
);
|
|
|
|
delete databuf;
|
|
error_value = 0;
|
|
|
|
#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;
|
|
signed int sctp_loadshare = SCTP_USE_PRIMARY;
|
|
short sctp_stream_id = 0;
|
|
int sctp_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 ;
|
|
sctp_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
|
|
/* copy data into buffer, then finally... */
|
|
char* databuf = new char[msg.sua_msg.length()];
|
|
msg.sua_msg.copy(databuf, msg.sua_msg.length());
|
|
|
|
datalen = msg.sua_msg.length();
|
|
|
|
// send data to SCTP
|
|
result = sua_send_Message( SCTP_assoc_id,
|
|
sctp_stream_id,
|
|
sctp_delivery_type,
|
|
sctp_loadshare,
|
|
databuf,
|
|
datalen
|
|
);
|
|
|
|
delete databuf;
|
|
error_value = 0;
|
|
|
|
#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;
|
|
signed int sctp_loadshare = SCTP_USE_PRIMARY;
|
|
short sctp_stream_id = 0;
|
|
int sctp_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 ;
|
|
sctp_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
|
|
/* copy data into buffer, then finally... */
|
|
char* databuf = new char[msg.sua_msg.length()];
|
|
msg.sua_msg.copy(databuf, msg.sua_msg.length());
|
|
|
|
datalen = msg.sua_msg.length();
|
|
|
|
// send data to SCTP
|
|
result = sua_send_Message( SCTP_assoc_id,
|
|
sctp_stream_id,
|
|
sctp_delivery_type,
|
|
sctp_loadshare,
|
|
databuf,
|
|
datalen
|
|
);
|
|
|
|
delete databuf;
|
|
error_value = 0;
|
|
|
|
#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
|
|
|
|
|
|
|
|
|
|
|
|
|