/*************************************************************************** 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.7 2002/11/12 11:02:49 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 #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; // 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 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 i, 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; 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 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 = 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 = sua.Dynamic_Associate ( called_pty_address, calling_pty_address, 1, 1, 1 ); /* save newly assigned SCTP association id in SCOC TCB */ tcb_ptr->sctp_Association_id = sua.AssocDB.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): // connection-oriented 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 = sua.AssocDB.Find_association( SCTP_assoc_id, local_sua_id, remote_sua_id ); if (sua.AssocDB.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 = sua.AssocDB.Find_association( SCTP_assoc_id, local_sua_id, remote_sua_id ); if (sua.AssocDB.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 = sua.AssocDB.Find_association( SCTP_assoc_id, local_sua_id, remote_sua_id ); if (sua.AssocDB.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 = sua.AssocDB.Find_association( SCTP_assoc_id, local_sua_id, remote_sua_id ); if (sua.AssocDB.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 = sua.AssocDB.Find_association( SCTP_assoc_id, local_sua_id, remote_sua_id ); if (sua.AssocDB.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 ) { int i, result = 0; int sctp_assoc_id = 0; unsigned int local_sua_id = 0; sua_save_str temp; unsigned int Sua_Out_ConnId; tcb_Sua_TCB_str *tcb_out_ptr; 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 = 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].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.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; } 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.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].sin6.sin6_port; } else cout << "Unknown IP address format\n"; } 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.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_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 = sua.AssocDB.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 = sua.AssocDB.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"; /* 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_ConnIndNotif ( local_sua_id, Sua_ConnId, 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 */ /* setup TCB linkage for CO */ tcb_out_ptr = tcb_pool.allocate_TCB(Sua_Out_ConnId); msg.sua_prim.source_ref = Sua_Out_ConnId; result = sua_route_Message( sctp_assoc_id, local_sua_id, msg, temp.called_pty_address, temp.calling_pty_address ); // fill in the allocated TCB tcb_out_ptr->Source_LR = Sua_Out_ConnId; tcb_out_ptr->User_ref_id = 1; tcb_out_ptr->sctp_Association_id = sctp_assoc_id; /* fill in link from TCB_out to first TCB */ tcb_out_ptr->scoc_tcb_id = Sua_ConnId; tcb_out_ptr->state = scoc_outgoing; tcb_out_ptr->remote_address = temp.called_pty_address; tcb_out_ptr->seq_number = Sua_Out_ConnId % 255; /* fill in the link from the first TCB to the TCB_out */ tcb_ptr->scoc_tcb_id = Sua_Out_ConnId; } 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; unsigned int Sua_Out_ConnId; tcb_Sua_TCB_str *tcb_out_ptr; Sua_syntax_error_struct error; 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 = sua.AssocDB.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"; /* Look if this is the end or intermediate node */ Sua_Out_ConnId = tcb_ptr->scoc_tcb_id; /* Is this the final destination ? */ if ( Sua_Out_ConnId == 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_ConnConfIndNotif ( local_sua_id, sua_ConnId, 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 */ /* get association id from SCOC TCB */ tcb_out_ptr = tcb_pool.get_tcb(Sua_Out_ConnId); msg.sua_prim.source_ref = tcb_out_ptr->Source_LR; msg.sua_prim.dest_ref = tcb_out_ptr->Dest_LR; error = msg.sua_encode(); /* copy data into buffer, then finally... */ signed int sctp_loadshare = SCTP_USE_PRIMARY; short sctp_stream_id = 0; int sctp_delivery_type = 0 ,datalen , result = 0; 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( tcb_out_ptr->sctp_Association_id, sctp_stream_id, sctp_delivery_type, sctp_loadshare, databuf, datalen ); delete databuf; // set the outgoing TCB on active tcb_out_ptr->state = scoc_active; } 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; unsigned int Sua_Out_ConnId; tcb_Sua_TCB_str *tcb_out_ptr; Sua_syntax_error_struct error; //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 = sua.AssocDB.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"; /* Look if this is the end or intermediate node */ Sua_Out_ConnId = tcb_ptr->scoc_tcb_id; /* Is this the final destination ? */ if ( Sua_Out_ConnId == 0 ) { // 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_ConnDataIndNotif ( local_sua_id, sua_ConnId, 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 */ /* get association id from SCOC TCB */ tcb_out_ptr = tcb_pool.get_tcb(Sua_Out_ConnId); msg.sua_prim.source_ref = tcb_out_ptr->Source_LR; msg.sua_prim.dest_ref = tcb_out_ptr->Dest_LR; error = msg.sua_encode(); /* copy data into buffer, then finally... */ signed int sctp_loadshare = SCTP_USE_PRIMARY; short sctp_stream_id = 0; int sctp_delivery_type = 0 ,datalen , result = 0; 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( tcb_out_ptr->sctp_Association_id, sctp_stream_id, sctp_delivery_type, sctp_loadshare, databuf, datalen ); delete databuf; } 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; unsigned int Sua_Out_ConnId; tcb_Sua_TCB_str *tcb_out_ptr; Sua_syntax_error_struct error; 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"; /* Look if this is the end or intermediate node */ Sua_Out_ConnId = tcb_ptr->scoc_tcb_id; /* Is this the final destination ? */ if ( Sua_Out_ConnId == 0 ) { // 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 = sua.AssocDB.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 */ sua.local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif ( local_sua_id, sua_ConnId, release_cause, 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 */ /* get association id from SCOC TCB */ tcb_out_ptr = tcb_pool.get_tcb(Sua_Out_ConnId); msg.sua_prim.source_ref = tcb_out_ptr->Source_LR; msg.sua_prim.dest_ref = tcb_out_ptr->Dest_LR; error = msg.sua_encode(); /* copy data into buffer, then finally... */ signed int sctp_loadshare = SCTP_USE_PRIMARY; short sctp_stream_id = 0; int sctp_delivery_type = 0 ,datalen , result = 0; 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( tcb_out_ptr->sctp_Association_id, sctp_stream_id, sctp_delivery_type, sctp_loadshare, databuf, datalen ); delete databuf; } 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; unsigned int Sua_Out_ConnId; tcb_Sua_TCB_str *tcb_out_ptr; Sua_syntax_error_struct error; 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 = sua.AssocDB.instance[sua_assoc_id].local_sua_id; /* Look if this is the end or intermediate node */ Sua_Out_ConnId = tcb_ptr->scoc_tcb_id; /* Is this the final destination ? */ if ( Sua_Out_ConnId == 0 ) { // 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 */ sua.local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif ( local_sua_id, sua_ConnId, release_cause, 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 */ /* get association id from SCOC TCB */ tcb_out_ptr = tcb_pool.get_tcb(Sua_Out_ConnId); msg.sua_prim.source_ref = tcb_out_ptr->Source_LR; msg.sua_prim.dest_ref = tcb_out_ptr->Dest_LR; error = msg.sua_encode(); /* copy data into buffer, then finally... */ signed int sctp_loadshare = SCTP_USE_PRIMARY; short sctp_stream_id = 0; int sctp_delivery_type = 0 ,datalen , result = 0; 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( tcb_out_ptr->sctp_Association_id, sctp_stream_id, sctp_delivery_type, sctp_loadshare, databuf, datalen ); delete databuf; } 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; unsigned int Sua_Out_ConnId; tcb_Sua_TCB_str *tcb_out_ptr; Sua_syntax_error_struct error; 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; /* Look if this is the end or intermediate node */ Sua_Out_ConnId = tcb_ptr->scoc_tcb_id; /* Is this the final destination ? */ if ( Sua_Out_ConnId == 0 ) { // 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 */ sua.local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif ( local_sua_id, sua_ConnId, release_cause, 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 */ /* get association id from SCOC TCB */ tcb_out_ptr = tcb_pool.get_tcb(Sua_Out_ConnId); msg.sua_prim.source_ref = tcb_out_ptr->Source_LR; msg.sua_prim.dest_ref = tcb_out_ptr->Dest_LR; error = msg.sua_encode(); /* copy data into buffer, then finally... */ signed int sctp_loadshare = SCTP_USE_PRIMARY; short sctp_stream_id = 0; int sctp_delivery_type = 0 ,datalen , result = 0; 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( tcb_out_ptr->sctp_Association_id, sctp_stream_id, sctp_delivery_type, sctp_loadshare, databuf, datalen ); delete databuf; } return(0); } // end of module sua_co.c