1149 lines
39 KiB
C++
1149 lines
39 KiB
C++
/***************************************************************************
|
|
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.5 2003/09/09 08:43:25 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 SUA message(CL or CO) to SCTP
|
|
* - route a SUA message(CL or CO)
|
|
* - 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_DatabaseList sua;
|
|
|
|
extern tcb_Sua_msgqueue_pool msg_store;
|
|
|
|
// import the received msg pool
|
|
extern vector<sua_save_str> rec_msg_pool;
|
|
|
|
|
|
/***********************************************************************/
|
|
/* sua_send_Message */
|
|
/***********************************************************************/
|
|
int sua_send_Message( signed int sctp_assoc_id,
|
|
short int sctp_stream_id,
|
|
int sctp_delivery_type,
|
|
unsigned int sctp_loadshare,
|
|
char *databuf,
|
|
unsigned int datalen
|
|
)
|
|
{
|
|
signed int result;
|
|
/* send data to SCTP */
|
|
/* yes it does, continue, no problem, send the msg */
|
|
#ifdef DEBUG
|
|
/* display byte array */
|
|
display_byte_array(databuf , datalen);
|
|
#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,datalen);
|
|
|
|
result = sctp_send ( sctp_assoc_id,
|
|
sctp_stream_id,
|
|
(unsigned char *) databuf,
|
|
datalen,
|
|
SUA_PPI,
|
|
SCTP_USE_PRIMARY, /* replace in future with sctp_loadshare*/
|
|
SCTP_NO_CONTEXT, SCTP_INFINITE_LIFETIME,
|
|
sctp_delivery_type,
|
|
SCTP_BUNDLING_DISABLED
|
|
);
|
|
|
|
|
|
#ifdef DEBUG
|
|
cout << "sua_cl.c:result sctp send = "<< result << "\n";
|
|
printf( "%d \n", result);
|
|
#endif
|
|
|
|
return(result);
|
|
}
|
|
|
|
|
|
/***********************************************************************/
|
|
/* sua_send_UDTService */
|
|
/***********************************************************************/
|
|
int sua_send_UDTService ( Sua_container &org_msg,
|
|
sccp_addr_str &called_pty_address,
|
|
sccp_addr_str &calling_pty_address,
|
|
unsigned int UDTS_reason
|
|
)
|
|
{
|
|
Sua_container msg;
|
|
Sua_syntax_error_struct error;
|
|
int error_value = 0;
|
|
int string_size, datalen;
|
|
signed int sctp_assoc_id;
|
|
int sua_assoc_id;
|
|
short sctp_stream_id = 0;
|
|
signed int sctp_loadshare = SCTP_USE_PRIMARY;
|
|
int sctp_delivery_type = 0 , result;
|
|
tcb_Sua_msg_elem sua_msg;
|
|
|
|
// init the message
|
|
msg.sua_init();
|
|
|
|
// copy original msg into outgoing msg and change a few fields
|
|
msg.sua_prim = org_msg.sua_prim;
|
|
|
|
// fill in the main sua header
|
|
msg.sua_prim.hdr_msg_class = sua_cl;
|
|
msg.sua_prim.hdr_msg_type.cl = cl_data_response;
|
|
|
|
// UDTService cause
|
|
msg.sua_prim.SCCP_cause_pres = true;
|
|
msg.sua_prim.SCCP_cause.cause_type = ctp_return_cause;
|
|
msg.sua_prim.SCCP_cause.cause_value = UDTS_reason;
|
|
|
|
// fill in the source address (=local sua address/CLG)
|
|
// destination of the received UDT, becomes source of sending UDTS
|
|
msg.sua_prim.source_addr = org_msg.sua_prim.dest_addr;
|
|
|
|
|
|
// fill in the destination address(=remote sua address/CLD)
|
|
// source of the received UDT, becomes destination of sending UDTS
|
|
msg.sua_prim.dest_addr = org_msg.sua_prim.source_addr;
|
|
|
|
// 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 = sua.route_msg( called_pty_address,
|
|
calling_pty_address,
|
|
sua_assoc_id
|
|
);
|
|
#ifdef DEBUG
|
|
cout << "routed to SCTP assoc " << sctp_assoc_id << "\n";
|
|
#endif
|
|
/* 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;
|
|
#ifdef DEBUG
|
|
cout << "sua_cl.c:result sctp send = "<< result << "\n";
|
|
#endif
|
|
error_value = 0;
|
|
}
|
|
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. */
|
|
/* weird?? */
|
|
/* - received a msg from a non existing association */
|
|
/* - routing database is not correct, no return path for this msg */
|
|
error_value = -1;
|
|
}
|
|
return(error_value);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
/* sua_route_Message */
|
|
/***********************************************************************/
|
|
int sua_route_Message( unsigned int &sctp_assoc_id,
|
|
unsigned int local_sua_id,
|
|
Sua_container &msg,
|
|
sccp_addr_str &called_pty_address,
|
|
sccp_addr_str &calling_pty_address
|
|
)
|
|
{
|
|
int result = 0;
|
|
short int sctp_stream_id = 0;
|
|
int sctp_delivery_type = SCTP_UNORDERED_DELIVERY;
|
|
signed int sctp_loadshare = SCTP_USE_PRIMARY;
|
|
int sua_assoc_id = 0;
|
|
int datalen = 0;
|
|
int UDTS_reason = 0;
|
|
Sua_syntax_error_struct error;
|
|
|
|
// 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 = sua.route_msg( called_pty_address,
|
|
calling_pty_address,
|
|
sua_assoc_id
|
|
);
|
|
#ifdef DEBUG
|
|
cout << "routed to SCTP assoc " << sctp_assoc_id << "/SUA assoc id " << sua_assoc_id <<"\n";
|
|
#endif
|
|
|
|
if ((msg.sua_prim.hop_count_pres) && (msg.sua_prim.hop_count <= 0))
|
|
{
|
|
sctp_assoc_id = 0;
|
|
#ifdef DEBUG
|
|
cout << "Hopcounter reach 0: drop/send response back msg\n";
|
|
#endif
|
|
}
|
|
|
|
|
|
/* does association exist? */
|
|
if (sctp_assoc_id > 0)
|
|
{
|
|
/* if hopcounter present decrement him */
|
|
if (msg.sua_prim.hop_count_pres)
|
|
msg.sua_prim.hop_count--;
|
|
|
|
/* YES, encode the SUA unitdata message and ... */
|
|
error = msg.sua_encode();
|
|
|
|
/* figure out SCTP delivery type, stream to send msg on,...and.. */
|
|
if (msg.sua_prim.prot_class_pres)
|
|
{
|
|
switch(msg.sua_prim.prot_class.pcl)
|
|
{
|
|
case(prot_class_0): /* connectionless transport, non sequenced */
|
|
sctp_delivery_type = SCTP_UNORDERED_DELIVERY;
|
|
break;
|
|
case(prot_class_1): /* connectionless transport, sequenced */
|
|
sctp_delivery_type = SCTP_ORDERED_DELIVERY;
|
|
break;
|
|
case(prot_class_2): /* connection-oriented transport, ... */
|
|
sctp_delivery_type = SCTP_ORDERED_DELIVERY;
|
|
break;
|
|
case(prot_class_3): /* connection-oriented transport, ... */
|
|
sctp_delivery_type = SCTP_ORDERED_DELIVERY;
|
|
break;
|
|
default:
|
|
sctp_delivery_type = SCTP_UNORDERED_DELIVERY;
|
|
break;
|
|
}
|
|
sctp_stream_id = sua.AssocDB.instance[sua_assoc_id].nr_of_outbound_streams;
|
|
sctp_stream_id = 0;
|
|
}
|
|
else
|
|
{
|
|
|
|
sctp_stream_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;
|
|
|
|
#ifdef DEBUG
|
|
cout.setf(ios::internal);
|
|
cout << "sua_cl.c:result sua send = "<< result << "\n";
|
|
#endif
|
|
|
|
}
|
|
else if (sctp_assoc_id < 0)
|
|
{
|
|
/* NOPE, message is routable, but destination is blocked */
|
|
/* due to administration or management descisions */
|
|
#ifdef DEBUG
|
|
cout << "sua_cl.c:sending msg prohibited \n";
|
|
#endif
|
|
result = -1;
|
|
}
|
|
else
|
|
{
|
|
/* NOPE message is NOT routable, destination not found. */
|
|
/* return a unitdata service msg indicating routing failure */
|
|
if ((msg.sua_prim.prot_class_pres) && (msg.sua_prim.prot_class.return_option))
|
|
{
|
|
UDTS_reason = SUA_UDTS_NO_TRANSLATION_FOR_SPECIFIC_ADDRES;
|
|
result = sua_send_UDTService ( msg,
|
|
calling_pty_address, /* CLD */
|
|
called_pty_address, /* CLG */
|
|
UDTS_reason
|
|
);
|
|
}
|
|
/* drop the message, no route present for that address */
|
|
else
|
|
{
|
|
;
|
|
}
|
|
|
|
result = 0;
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
/* 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 = 0;
|
|
int i, string_size, datalen;
|
|
signed int sctp_assoc_id;
|
|
int sua_assoc_id;
|
|
short sctp_stream_id = 0;
|
|
signed int sctp_loadshare = SCTP_USE_PRIMARY;
|
|
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_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 = 0;
|
|
sctp_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;
|
|
sctp_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 IP/PC 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;
|
|
if (calling_pty_address.address_fields_present.name_gt == hostname_present){
|
|
msg.sua_prim.source_addr_pres = TRUE;
|
|
msg.sua_prim.source_addr.rout_ind = ri_route_hostname;
|
|
msg.sua_prim.source_addr.hostname_pres = TRUE;
|
|
msg.sua_prim.source_addr.gt_pres = FALSE;
|
|
msg.sua_prim.source_addr.hostname = calling_pty_address.name.HostName;
|
|
|
|
}
|
|
else if (calling_pty_address.address_fields_present.name_gt == GT_present){
|
|
msg.sua_prim.source_addr_pres = TRUE;
|
|
msg.sua_prim.source_addr.rout_ind = ri_route_GT;
|
|
msg.sua_prim.source_addr.hostname_pres = FALSE;
|
|
msg.sua_prim.source_addr.gt_pres = TRUE;
|
|
msg.sua_prim.source_addr.gt.translation_type = calling_pty_address.name.GT.Translation_Type;
|
|
msg.sua_prim.source_addr.gt.num_plan = calling_pty_address.name.GT.Numbering_Plan;
|
|
msg.sua_prim.source_addr.gt.nat_addr = calling_pty_address.name.GT.Nature_of_Address;
|
|
msg.sua_prim.source_addr.gt.nr_of_digits = calling_pty_address.name.GT.nr_of_digits;
|
|
for (i=0; i < calling_pty_address.name.GT.nr_of_digits; i++)
|
|
msg.sua_prim.source_addr.gt.digits[i] = calling_pty_address.name.GT.digits[i];
|
|
|
|
}
|
|
else
|
|
cout << "unsupported CLG name/GT address option\n";
|
|
|
|
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.pc_pres = FALSE;
|
|
if (called_pty_address.address_fields_present.name_gt == hostname_present){
|
|
msg.sua_prim.dest_addr_pres = TRUE;
|
|
msg.sua_prim.dest_addr.rout_ind = ri_route_hostname;
|
|
msg.sua_prim.dest_addr.hostname_pres = TRUE;
|
|
msg.sua_prim.dest_addr.gt_pres = FALSE;
|
|
msg.sua_prim.dest_addr.hostname = called_pty_address.name.HostName;
|
|
|
|
}
|
|
else if (called_pty_address.address_fields_present.name_gt == GT_present){
|
|
msg.sua_prim.dest_addr_pres = TRUE;
|
|
msg.sua_prim.dest_addr.rout_ind = ri_route_GT;
|
|
msg.sua_prim.dest_addr.hostname_pres = FALSE;
|
|
msg.sua_prim.dest_addr.gt_pres = TRUE;
|
|
msg.sua_prim.dest_addr.gt.translation_type = called_pty_address.name.GT.Translation_Type;
|
|
msg.sua_prim.dest_addr.gt.num_plan = called_pty_address.name.GT.Numbering_Plan;
|
|
msg.sua_prim.dest_addr.gt.nat_addr = called_pty_address.name.GT.Nature_of_Address;
|
|
msg.sua_prim.dest_addr.gt.nr_of_digits = called_pty_address.name.GT.nr_of_digits;
|
|
for (i=0; i < called_pty_address.name.GT.nr_of_digits; i++)
|
|
msg.sua_prim.dest_addr.gt.digits[i] = called_pty_address.name.GT.digits[i];
|
|
}
|
|
else
|
|
cout << "unsupported CLG name/GT address option\n";
|
|
|
|
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 = sua.route_msg( called_pty_address,
|
|
calling_pty_address,
|
|
sua_assoc_id
|
|
);
|
|
#ifdef DEBUG
|
|
cout << "routed to SCTP assoc " << sctp_assoc_id << "\n";
|
|
#endif
|
|
/* 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;
|
|
#ifdef DEBUG
|
|
cout << "sua_cl.c:result sctp send = "<< result << "\n";
|
|
#endif
|
|
error_value = 0;
|
|
}
|
|
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 = sua.Dynamic_Associate ( 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 = 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 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;
|
|
int result = 0;
|
|
unsigned int sctp_assoc_id = 0;
|
|
char digit_char;
|
|
|
|
temp.primitive = N_UNITDATA;
|
|
temp.user_ref = 0;
|
|
/* change routing context hard coded for test with CMG-logica */
|
|
/*msg.sua_prim.rout_con = 6;*/
|
|
|
|
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 = sua.AssocDB.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 = sua.AssocDB.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 = sua.AssocDB.instance[sua_assoc_id].Dest.pc.ITU14.family;
|
|
temp.calling_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.source_addr.pc;
|
|
}
|
|
if (msg.sua_prim.source_addr.gt_pres == TRUE)
|
|
{
|
|
temp.calling_pty_address.address_fields_present.name_gt = GT_present;
|
|
temp.calling_pty_address.name.GT.Translation_Type = msg.sua_prim.source_addr.gt.translation_type ;
|
|
temp.calling_pty_address.name.GT.Numbering_Plan = msg.sua_prim.source_addr.gt.num_plan ;
|
|
temp.calling_pty_address.name.GT.Nature_of_Address = msg.sua_prim.source_addr.gt.nat_addr ;
|
|
temp.calling_pty_address.name.GT.nr_of_digits = msg.sua_prim.source_addr.gt.nr_of_digits ;
|
|
|
|
for (int i=0; i < temp.calling_pty_address.name.GT.nr_of_digits; i++){
|
|
sprintf(&digit_char, "%d", msg.sua_prim.source_addr.gt.digits[i]);
|
|
temp.calling_pty_address.name.GT.digits[i] = digit_char;
|
|
}
|
|
|
|
temp.calling_pty_address.name.GT.digits[temp.calling_pty_address.name.GT.nr_of_digits] = '\0';
|
|
|
|
}
|
|
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.ip_addr_pres == TRUE)
|
|
{
|
|
temp.called_pty_address.address_fields_present.pc = ipvx_pc_present;
|
|
if (msg.sua_prim.dest_addr.ip_addr_type == ip_v4) {
|
|
temp.called_pty_address.pc.ipvx.sin = msg.sua_prim.dest_addr.ip_addr.ipv4;
|
|
temp.called_pty_address.pc.ipvx.sa.sa_family = AF_INET;
|
|
temp.called_pty_address.pc.ipvx.sin.sin_port = sua.AssocDB.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port;
|
|
}
|
|
else if (msg.sua_prim.dest_addr.ip_addr_type == ip_v6) {
|
|
temp.called_pty_address.pc.ipvx.sin6 = msg.sua_prim.dest_addr.ip_addr.ipv6;
|
|
temp.called_pty_address.pc.ipvx.sa.sa_family = AF_INET6;
|
|
temp.called_pty_address.pc.ipvx.sin6.sin6_port = sua.AssocDB.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port;
|
|
}
|
|
}
|
|
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 = sua.AssocDB.instance[sua_assoc_id].Dest.pc.ITU14.family;
|
|
temp.called_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.dest_addr.pc;
|
|
}
|
|
|
|
if (msg.sua_prim.dest_addr.gt_pres == TRUE)
|
|
{
|
|
temp.called_pty_address.address_fields_present.name_gt = GT_present;
|
|
temp.called_pty_address.name.GT.Translation_Type = msg.sua_prim.dest_addr.gt.translation_type ;
|
|
temp.called_pty_address.name.GT.Numbering_Plan = msg.sua_prim.dest_addr.gt.num_plan ;
|
|
temp.called_pty_address.name.GT.Nature_of_Address = msg.sua_prim.dest_addr.gt.nat_addr ;
|
|
temp.called_pty_address.name.GT.nr_of_digits = msg.sua_prim.dest_addr.gt.nr_of_digits ;
|
|
|
|
for (int i=0; i < temp.called_pty_address.name.GT.nr_of_digits; i++){
|
|
sprintf(&digit_char, "%d", msg.sua_prim.dest_addr.gt.digits[i]);
|
|
temp.called_pty_address.name.GT.digits[i] = digit_char;
|
|
}
|
|
|
|
temp.called_pty_address.name.GT.digits[temp.called_pty_address.name.GT.nr_of_digits] = '\0';
|
|
|
|
}
|
|
|
|
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";
|
|
|
|
/* Is this the final destination ? */
|
|
if ( sua.Find_local_sua ( temp.called_pty_address) > 0 )
|
|
{
|
|
/* Yes, message has arrived at its final destination -> send to upper layer */
|
|
/* store primitive in a list(is retrieve via sua_receive_msg) */
|
|
rec_msg_pool.push_back(temp);
|
|
|
|
/* call the application/user callBack function */
|
|
sua.local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ClDataIndNotif
|
|
( local_sua_id,
|
|
N_UNITDATA,
|
|
temp.userdata.length()
|
|
);
|
|
}
|
|
else
|
|
{
|
|
/* No, Message has not arrived at its final destination -> */
|
|
/* route it to the next SUA node via an SCTP association nr x */
|
|
result = sua_route_Message( sctp_assoc_id,
|
|
local_sua_id,
|
|
msg,
|
|
temp.called_pty_address,
|
|
temp.calling_pty_address
|
|
);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/***********************************************************************/
|
|
/* sua_process_UDTService */
|
|
/***********************************************************************/
|
|
short process_UDTService_msg ( int local_sua_id,
|
|
unsigned int sua_assoc_id,
|
|
Sua_container &msg
|
|
)
|
|
{
|
|
sua_save_str temp;
|
|
int i, result = 0;
|
|
unsigned int sctp_assoc_id = 0;
|
|
char digit_char;
|
|
|
|
temp.primitive = N_NOTICE;
|
|
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 = sua.AssocDB.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 = sua.AssocDB.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 = sua.AssocDB.instance[sua_assoc_id].Dest.pc.ITU14.family;
|
|
temp.calling_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.source_addr.pc;
|
|
}
|
|
|
|
if (msg.sua_prim.source_addr.gt_pres == TRUE)
|
|
{
|
|
temp.calling_pty_address.address_fields_present.name_gt = GT_present;
|
|
temp.calling_pty_address.name.GT.Translation_Type = msg.sua_prim.source_addr.gt.translation_type;
|
|
temp.calling_pty_address.name.GT.Numbering_Plan = msg.sua_prim.source_addr.gt.num_plan;
|
|
temp.calling_pty_address.name.GT.Nature_of_Address = msg.sua_prim.source_addr.gt.nat_addr;
|
|
temp.calling_pty_address.name.GT.nr_of_digits = msg.sua_prim.source_addr.gt.nr_of_digits;
|
|
for (i=0; i < temp.calling_pty_address.name.GT.nr_of_digits; i++){
|
|
sprintf(&digit_char, "%d", msg.sua_prim.source_addr.gt.digits[i]);
|
|
temp.calling_pty_address.name.GT.digits[i] = digit_char;
|
|
}
|
|
temp.calling_pty_address.name.GT.digits[temp.calling_pty_address.name.GT.nr_of_digits] = '\0';
|
|
}
|
|
|
|
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.ip_addr_pres == TRUE)
|
|
{
|
|
temp.called_pty_address.address_fields_present.pc = ipvx_pc_present;
|
|
if (msg.sua_prim.dest_addr.ip_addr_type == ip_v4) {
|
|
temp.called_pty_address.pc.ipvx.sin = msg.sua_prim.dest_addr.ip_addr.ipv4;
|
|
temp.called_pty_address.pc.ipvx.sa.sa_family = AF_INET;
|
|
temp.called_pty_address.pc.ipvx.sin.sin_port = sua.AssocDB.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port;
|
|
}
|
|
else if (msg.sua_prim.dest_addr.ip_addr_type == ip_v6) {
|
|
temp.called_pty_address.pc.ipvx.sin6 = msg.sua_prim.dest_addr.ip_addr.ipv6;
|
|
temp.called_pty_address.pc.ipvx.sa.sa_family = AF_INET6;
|
|
temp.called_pty_address.pc.ipvx.sin6.sin6_port = sua.AssocDB.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port;
|
|
}
|
|
}
|
|
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 = sua.AssocDB.instance[sua_assoc_id].Dest.pc.ITU14.family;
|
|
temp.called_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.dest_addr.pc;
|
|
}
|
|
|
|
if (msg.sua_prim.dest_addr.gt_pres == TRUE)
|
|
{
|
|
temp.called_pty_address.address_fields_present.name_gt = GT_present;
|
|
temp.called_pty_address.name.GT.Translation_Type = msg.sua_prim.dest_addr.gt.translation_type;
|
|
temp.called_pty_address.name.GT.Numbering_Plan = msg.sua_prim.dest_addr.gt.num_plan;
|
|
temp.called_pty_address.name.GT.Nature_of_Address = msg.sua_prim.dest_addr.gt.nat_addr;
|
|
temp.called_pty_address.name.GT.nr_of_digits = msg.sua_prim.dest_addr.gt.nr_of_digits;
|
|
for (i=0; i < temp.called_pty_address.name.GT.nr_of_digits; i++){
|
|
sprintf(&digit_char, "%d", msg.sua_prim.dest_addr.gt.digits[i]);
|
|
temp.called_pty_address.name.GT.digits[i] = digit_char;
|
|
}
|
|
temp.called_pty_address.name.GT.digits[temp.called_pty_address.name.GT.nr_of_digits] = '\0';
|
|
}
|
|
|
|
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 service msg \n";
|
|
|
|
/* Is this the final destination ? */
|
|
if ( sua.Find_local_sua ( temp.called_pty_address) > 0 )
|
|
{
|
|
/* Yes, message has arrived at its final destination -> send to upper layer */
|
|
/* store primitive in a list(is retrieve via sua_receive_msg) */
|
|
rec_msg_pool.push_back(temp);
|
|
|
|
/* call the application/user callBack function */
|
|
sua.local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ClDataIndNotif
|
|
( local_sua_id,
|
|
N_NOTICE,
|
|
temp.userdata.length()
|
|
);
|
|
}
|
|
else
|
|
{
|
|
/* No, Message has not arrived at its final destination -> */
|
|
/* route it to the next SUA node via an SCTP association nr x */
|
|
result = sua_route_Message( sctp_assoc_id,
|
|
local_sua_id,
|
|
msg,
|
|
temp.called_pty_address,
|
|
temp.calling_pty_address
|
|
);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
// end of module sua_cl.c
|
|
|
|
|
|
|
|
|
|
|