/*************************************************************************** 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.8 2002/10/29 16:00:54 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 #endif #include #include #include #include #include #include #include /* includes also ! */ #include #include #include 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 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 /* does association exist? */ if (sctp_assoc_id > 0) { /* 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 = QOS.sequence_number; 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; int sctp_assoc_id = 0; temp.primitive = N_UNITDATA; temp.user_ref = 0; if (msg.sua_prim.prot_class_pres) { // QOS choice switch ( msg.sua_prim.prot_class.pcl) { case(prot_class_0): // connectionless transport, non-sequenced temp.QOS.prot_class = class0; temp.QOS.in_sequence = false; break; case(prot_class_1): temp.QOS.prot_class = class1; temp.QOS.in_sequence = true; break; default: return(PROTOCOL_CLASS_NOT_SPECIFIED); break; } temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); } temp.QOS.sequence_number = 0; temp.QOS.importance = msg.sua_prim.importance; // retrieve the clg(=source) address (=remote sua address) // which types are present in the address(ip pc, SS7 pc, GT, hostname) if (msg.sua_prim.source_addr.ip_addr_pres == TRUE) { temp.calling_pty_address.address_fields_present.pc = ipvx_pc_present; if (msg.sua_prim.source_addr.ip_addr_type == ip_v4) { temp.calling_pty_address.pc.ipvx.sin = msg.sua_prim.source_addr.ip_addr.ipv4; temp.calling_pty_address.pc.ipvx.sa.sa_family = AF_INET; temp.calling_pty_address.pc.ipvx.sin.sin_port = 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) { cout << "Global Title : unsupported address format\n"; } if (msg.sua_prim.source_addr.hostname_pres == TRUE) { temp.calling_pty_address.address_fields_present.name_gt = hostname_present; msg.sua_prim.source_addr.hostname.copy( temp.calling_pty_address.name.HostName, (msg.sua_prim.source_addr.hostname.length()+1 ) ); temp.calling_pty_address.name.HostName[msg.sua_prim.source_addr.hostname.length()] = '\0'; } if ((msg.sua_prim.source_addr.ip_addr_pres /= TRUE) && (msg.sua_prim.source_addr.pc_pres /= TRUE) && (msg.sua_prim.source_addr.gt_pres /= TRUE) && (msg.sua_prim.source_addr.hostname_pres /= TRUE)) { cout << "No valid address format found in msg\n"; } // routing indicator switch (msg.sua_prim.source_addr.rout_ind) { case(ri_route_PC_SSN): temp.calling_pty_address.routing_ind = route_on_ssn; break; case(ri_route_IP_SSN): temp.calling_pty_address.routing_ind = route_on_ssn; break; case (ri_route_GT): temp.calling_pty_address.routing_ind = route_on_name_gt; break; case (ri_route_hostname): temp.calling_pty_address.routing_ind = route_on_name_gt; break; default: break; } temp.calling_pty_address.address_fields_present.ssn_port = ssn_present; temp.calling_pty_address.ssn = msg.sua_prim.source_addr.ssn; // retrieve the called(=destination) address(=should be our own local addr) // not completely done yet if (msg.sua_prim.dest_addr.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.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; int sctp_assoc_id = 0; 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++) temp.calling_pty_address.name.GT.digits[i] = msg.sua_prim.source_addr.gt.digits[i]; 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++) temp.called_pty_address.name.GT.digits[i] = msg.sua_prim.dest_addr.gt.digits[i]; 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