/************************************************************/ /*Title: scmg.c */ /*Descr: SCCP Management */ /*Author: Liang Hanxi */ /*Create: 2002-2-19 */ /*Modify: 2002-5-7 */ /************************************************************/ #include "./include/sccp.h" /*===========export================*/ void localssn_timer ( ); void sst_timer ( ); int sclc2scmg ( Intra_Msg * intramsg ); BOOL CheckAvail ( SCCP_ADDR * addr ); /*===========import================*/ extern int scrc_route ( Intra_Msg * pIntraMsg, BOOL ForceAnsi ); extern int send_msg ( Intra_Msg * pIntraMsg, BYTE ansi_flag ); extern void sccp_sethb ( ); extern int CollectLocalInfo ( ); extern int AddToIpList ( DWORD ip, BYTE ssn ); extern void snmpLogInfo ( char *logInfo ); extern void spLogDebug ( DWORD mask, const char *fmt, ... ); /*===========private================*/ static BYTE ssn_status ( int spc, BYTE ssn, BYTE NetID ); void spac ( int spc, BYTE NetID ); void sppc ( int spc, BYTE NetID ); void spcc ( int spc, BYTE NetID ); static void ssac ( int spc, BYTE ssn, BYTE NetID, BOOL relay ); static void sscc ( int spc, BYTE ssn, BYTE NetID ); static void sspc ( int spc, BYTE ssn, BYTE NetID, BOOL relay ); static void lcst ( int spc, BYTE ssn, BYTE ntype, BYTE NetID ); static void bcst ( BYTE ssn, BYTE ntype ); static void bcst_relay ( int spc, BYTE ssn, BYTE ntype, BYTE NetID ); static int build_scmgmsg ( BYTE * intramsg, BYTE type, int spc, BYTE ssn, BYTE NetID ); static int parse_scmgmsg ( BYTE * data, BYTE * type, int *spc, BYTE * ssn, BYTE NetID ); /* by simon at 23/9/25 */ extern DWORD ExistIP[64]; extern DWORD ExistIPNum; extern SCOC_BUF ScocBuf; extern LOCAL_SSN LocalSSN[256]; extern u8 ExistSSN[64]; extern u8 ExistSSNNum; extern struct _dpc2sls { int dpc; u8 sls; } dpc2sls[256]; // used for sequence control, add by Roy Jiang, 2007-09-17 extern SCCP_OPT SCCP_Param; extern u8 MNP_Flag[2]; extern SCCP_ROUTE RouteList[SCCP_ROUTE_NUM]; extern int RelatedSSNNum; extern RL_SSN RelatedSSN[SCCP_RLSSN_NUM]; extern int RelatedSPCNum; extern RL_SPC RelatedSPC[SCCP_RLSPC_NUM]; extern GTTATT_OMC GTTAttribute[SCCP_ROUTE_NUM]; extern SCCP_CSTA SccpCsta[96]; extern DWORD SccpCstaInd; extern SCCP_Capture_Buf SCCPCapBuf; void localssn_timer ( ) //called per 1s { int i; LOCAL_SSN *pSSN; for ( i = 0; i < ExistSSNNum; i++ ) { pSSN = &LocalSSN[ExistSSN[i]]; if( pSSN->status[0] == ST_Enable && pSSN->local != 1 && pSSN->timeout[0]-- <= 0 ) pSSN->status[0] = ST_Disable; if( pSSN->status[1] == ST_Enable && pSSN->local != 2 && pSSN->timeout[1]-- <= 0 ) pSSN->status[1] = ST_Disable; } } int sclc2scmg ( Intra_Msg * intramsg ) { BYTE *pmsg; BYTE ntype, ssn; int spc; BOOL relay = 0; intramsg->msgsource = FROM_SCMG; pmsg = intramsg->data; parse_scmgmsg ( intramsg->data, &ntype, &spc, &ssn, intramsg->NetID ); snmpLogInfo ( "sclc2scmg (): start..." ); spLogDebug ( SCCPDB_SCMG, "Receive %s Message.ssn=%d,src_spc=%X", ntype == SSA_MSG ? "SSA" : ( ntype == SSP_MSG ? "SSP" : ( ntype == SST_MSG ? "SST" : "SCMG" ) ), ssn, spc ); switch ( ntype ) { case SSA_MSG: //to enable subsystem SccpCsta[SccpCstaInd].avail[11]++; if( intramsg->OPC != SCCP_Param.spc[intramsg->NetID] && intramsg->CGA.DPC != SCCP_Param.spc[intramsg->NetID] ) { lcst ( spc, ssn, SSA_MSG, intramsg->NetID ); if( spc == intramsg->CGA.DPC ) relay = 1; } ssac ( spc, ssn, intramsg->NetID, relay ); break; case SSC_MSG: SccpCsta[SccpCstaInd].avail[7]++; sscc ( spc, ssn, intramsg->NetID ); break; case SSP_MSG: SccpCsta[SccpCstaInd].avail[10]++; if( intramsg->OPC != SCCP_Param.spc[intramsg->NetID] && intramsg->CGA.DPC != SCCP_Param.spc[intramsg->NetID] ) { lcst ( spc, ssn, SSP_MSG, intramsg->NetID ); if( spc == intramsg->CGA.DPC ) relay = 1; } sspc ( spc, ssn, intramsg->NetID, relay ); break; case SST_MSG: if( LocalSSN[ssn].status[0] == ST_Enable || LocalSSN[ssn].status[1] == ST_Enable ) pmsg[0] = SSA_MSG; else return 1; memcpy ( &intramsg->CDA, &intramsg->CGA, sizeof ( SCCP_ADDR ) ); intramsg->CGA.DPC = SCCP_Param.spc[intramsg->NetID]; intramsg->CGA.GTI = 0; intramsg->CGA.SSN = 1; intramsg->CGA.RI = RI_SSN; intramsg->CGA.len = 0; spLogDebug ( SCCPDB_SCMG, "Send %s Message.ssn=%d,dst_spc=%X", ( pmsg[0] == SSA_MSG ) ? "SSA" : ( ( pmsg[0] == SSP_MSG ) ? "SSP" : "SSC" ), ssn, intramsg->CDA.DPC ); send_msg ( intramsg, mtp3_ansiFlag ( intramsg->NetID ) ); break; case SOR_MSG: //to send SOG pmsg[0] = SOG_MSG; //to send SOG memcpy ( &intramsg->CDA, &intramsg->CGA, sizeof ( SCCP_ADDR ) ); scrc_route ( intramsg, 0 ); break; case SOG_MSG: //to disable local subsystem break; } snmpLogInfo ( "sclc2scmg (): end..." ); return 1; } BOOL CheckAvail ( SCCP_ADDR * addr ) { BYTE status; status = ssn_status ( addr->DPC, addr->SSN, addr->NetID ); if( status == ST_Disable ) { spLogDebug ( SCCPDB_ERR, "<009>Subsystem Failure.NetID=%d,SPC=%x,SSN=%d", addr->NetID, addr->DPC, addr->SSN ); SccpCsta[SccpCstaInd].error[4]++; return 0; } else if( status == ST_Congest ) { spLogDebug ( SCCPDB_ERR, "<010>Subsystem Congest.NetID=%d,SPC=%x,SSN=%d", addr->NetID, addr->DPC, addr->SSN ); SccpCsta[SccpCstaInd].error[5]++; return 0; } //else if(sccp_status(addr->DPC,addr->NetID)==ST_Disable) // return 0; else return 1; } BYTE ssn_status ( int spc, BYTE ssn, BYTE NetID ) //related subsystem { int i; for ( i = 0; i < RelatedSSNNum; i++ ) { if( RelatedSSN[i].status == 0 ) continue; if( RelatedSSN[i].DPC != spc || RelatedSSN[i].SSN != ssn || RelatedSSN[i].NetID != NetID ) continue; return RelatedSSN[i].status; } return ST_Enable; } ///////////////////////// /*SPAC Module----------> */ ///////////////////////// void spac ( int spc, BYTE NetID ) { int i, j; for ( i = 0; i < RelatedSPCNum; i++ ) { if( spc == RelatedSPC[i].DPC && NetID == RelatedSPC[i].NetID ) { RelatedSPC[i].status = ST_Enable; for ( j = 0; j < RelatedSSNNum; j++ ) { if( RelatedSSN[j].status == 0 ) continue; if( spc == RelatedSSN[j].DPC && NetID == RelatedSSN[j].NetID ) { if( RelatedSPC[i].status == ST_Disable ) RelatedSSN[j].SST = 1; RelatedSSN[j].status = ST_Enable; } } } } } ///////////////////////// /*SPPC Module----------> */ ///////////////////////// void sppc ( int spc, BYTE NetID ) { int i, j; for ( i = 0; i < RelatedSPCNum; i++ ) { if( spc == RelatedSPC[i].DPC && NetID == RelatedSPC[i].NetID ) { RelatedSPC[i].status = ST_Disable; for ( j = 0; j < RelatedSSNNum; j++ ) { if( RelatedSSN[j].status == 0 ) continue; if( spc == RelatedSSN[j].DPC && NetID == RelatedSSN[j].NetID ) { RelatedSSN[j].SST = 0; RelatedSSN[j].status = ST_Disable; } } } } } ///////////////////////// /*SPCC Module----------> */ ///////////////////////// void spcc ( int spc, BYTE NetID ) { int i; for ( i = 0; i < RelatedSPCNum; i++ ) { if( spc == RelatedSSN[i].DPC && NetID == RelatedSSN[i].NetID ) RelatedSSN[i].status = ST_Congest; } } ///////////////////////// /*SSAC Module----------> */ ///////////////////////// int register_ssn ( BYTE ssn, BYTE usertype ) //enable local subsystem { BYTE localindex = LocalSSN[ssn].local % 3; LocalSSN[ssn].RegFlag = 1; if( localindex > 0 ) { CollectLocalInfo ( ); LocalSSN[ssn].status[localindex - 1] = ST_Enable; } else { printf ( "Subsystem %d not equiped.check your GTT Table.\n", ssn ); return 0; } if( usertype == 3 ) SCCP_Param.CO_SSN = ssn; SccpCsta[SccpCstaInd].avail[8]++; LocalSSN[ssn].nbuf = usertype % 4; if( LocalSSN[ssn].nbuf == 3 ) SCCP_Param.CO_SSN = ssn; bcst ( ssn, SSA_MSG ); return 1; } void ssac ( int spc, BYTE ssn, BYTE NetID, BOOL relay ) //enable remote subsystem { int i; for ( i = 0; i < RelatedSSNNum; i++ ) { if( RelatedSSN[i].status == 0 ) continue; if( RelatedSSN[i].DPC != spc || RelatedSSN[i].SSN != ssn || RelatedSSN[i].NetID != NetID ) continue; if( RelatedSSN[i].status == ST_Disable && relay ) //Disable->Enable bcst_relay ( spc, ssn, SSA_MSG, NetID ); RelatedSSN[i].SST = 0; RelatedSSN[i].status = ST_Enable; } } void sscc ( int spc, BYTE ssn, BYTE NetID ) //enable remote subsystem { int i; for ( i = 0; i < RelatedSSNNum; i++ ) { if( RelatedSSN[i].status == 0 ) continue; if( RelatedSSN[i].DPC != spc || RelatedSSN[i].SSN != ssn || RelatedSSN[i].NetID != NetID ) continue; RelatedSSN[i].status = ST_Congest; } } ///////////////////////// /*SSPC Module----------> */ ///////////////////////// int stop_ssn ( BYTE ssn ) //disable local subsystem { BYTE localindex = LocalSSN[ssn].local % 3; int i; LocalSSN[ssn].RegFlag = 0; spLogDebug ( SCCPDB_SCMG, "Disable local subsystem. ssn=%d", ssn ); if( localindex > 0 ) { CollectLocalInfo ( ); /* add by daniel on 2005-9-15 */ for ( i = 0; i <= 1; i++ ) { if( SCCP_Param.OMCIP[i] > 0 ) AddToIpList ( SCCP_Param.OMCIP[i], ssn ); } /* add by daniel on 2005-9-15 */ LocalSSN[ssn].status[localindex - 1] = ST_Disable; } else return -1; sccp_sethb ( ); SccpCsta[SccpCstaInd].avail[9]++; bcst ( ssn, SSP_MSG ); return 1; } void sspc ( int spc, BYTE ssn, BYTE NetID, BOOL relay ) //disable remote subsystem { int i; for ( i = 0; i < RelatedSSNNum; i++ ) { if( RelatedSSN[i].status == 0 ) continue; if( RelatedSSN[i].DPC != spc || RelatedSSN[i].SSN != ssn || RelatedSSN[i].NetID != NetID ) continue; if( RelatedSSN[i].status == ST_Enable ) //Enable->Disable { RelatedSSN[i].timeout = T_sst; RelatedSSN[i].SST = 1; if( relay ) bcst_relay ( spc, ssn, SSP_MSG, NetID ); } RelatedSSN[i].status = ST_Disable; } } ///////////////////////// /*SSTC Module----------> */ ///////////////////////// void sst_timer ( ) { Intra_Msg outmsg; RL_SSN *pSSN; int i; for ( i = 0; i < RelatedSSNNum; i++ ) { pSSN = &RelatedSSN[i]; if( !pSSN->SST ) continue; if( pSSN->timeout-- > 0 ) continue; if( pSSN->DPC == SCCP_Param.spc[pSSN->NetID] ) continue; outmsg.msgtype = UDT_MSG; outmsg.msgsource = FROM_SCMG; outmsg.CGA.DPC = SCCP_Param.spc[pSSN->NetID]; outmsg.CGA.SSN = 1; outmsg.CGA.GTI = 0; outmsg.CGA.RI = RI_SSN; outmsg.CGA.len = 0; outmsg.CDA.DPC = pSSN->DPC; outmsg.CDA.SSN = 1; //SCMG outmsg.CDA.GTI = 0; //No GT outmsg.CDA.RI = 1; outmsg.CDA.len = 0; outmsg.NetID = pSSN->NetID; outmsg.CDA.ip = INADDR_NONE; outmsg.msglen = build_scmgmsg ( outmsg.data, SST_MSG, pSSN->DPC, pSSN->SSN, pSSN->NetID ); spLogDebug ( SCCPDB_SCMG, "SST spc=%X,ssn=%d", pSSN->DPC, pSSN->SSN ); send_msg ( &outmsg, mtp3_ansiFlag ( pSSN->NetID ) ); pSSN->timeout = T_sst; } } ///////////////////////// /*LCST Module----------> */ ///////////////////////// void lcst ( int spc, BYTE ssn, BYTE ntype, BYTE NetID ) { Intra_Msg outmsg; int i; spLogDebug ( SCCPDB_SCMG, "Start Local Broatcast.spc=%X,ssn=%d,ntype=%d", spc, ssn, ntype ); outmsg.msgtype = UDT_MSG; outmsg.msgsource = FROM_SCMG; outmsg.CGA.SSN = 1; outmsg.CGA.GTI = 0; outmsg.CGA.len = 0; outmsg.CGA.RI = 1; outmsg.CGA.DPC = SCCP_Param.spc[NetID]; outmsg.CDA.GTI = 0; outmsg.NetID = outmsg.CDA.NetID = outmsg.CGA.NetID = NetID; outmsg.CDA.DPC = SCCP_Param.spc[NetID]; outmsg.CDA.SSN = 1; outmsg.CDA.RI = 1; outmsg.CDA.len = 0; outmsg.msglen = build_scmgmsg ( outmsg.data, ntype, spc, ssn, NetID ); for ( i = 2; i < 256; i++ ) { if( LocalSSN[i].status[0] > 0 && LocalSSN[i].local != 1 ) { outmsg.CDA.ip = LocalSSN[i].ip[0]; send_msg ( &outmsg, mtp3_ansiFlag ( NetID ) ); } if( LocalSSN[i].status[1] > 0 && LocalSSN[i].local != 2 ) { outmsg.CDA.ip = LocalSSN[i].ip[1]; send_msg ( &outmsg, mtp3_ansiFlag ( NetID ) ); } } } ///////////////////////// /*BCST Module----------> */ ///////////////////////// void bcst ( BYTE ssn, BYTE ntype ) { Intra_Msg outmsg; int i; spLogDebug ( SCCPDB_SCMG, "Start Remote Broadcase ssn=%d,ntype=%d", ssn, ntype ); outmsg.msgtype = UDT_MSG; outmsg.msgsource = FROM_SCMG; outmsg.CDA.GTI = 0; for ( i = 0; i < RelatedSPCNum; i++ ) { if( RelatedSPC[i].status != ST_Enable ) continue; outmsg.CGA.SSN = 1; outmsg.CGA.GTI = 0; outmsg.CGA.len = 0; outmsg.CGA.RI = 1; outmsg.CGA.DPC = SCCP_Param.spc[RelatedSPC[i].NetID]; outmsg.CDA.ip = INADDR_NONE; outmsg.CDA.DPC = RelatedSPC[i].DPC; outmsg.CDA.SSN = 1; outmsg.CDA.RI = 1; outmsg.CDA.len = 0; outmsg.NetID = outmsg.CDA.NetID = outmsg.CGA.NetID = RelatedSPC[i].NetID; outmsg.msglen = build_scmgmsg ( outmsg.data, ntype, SCCP_Param.spc[outmsg.NetID], ssn, outmsg.NetID ); send_msg ( &outmsg, mtp3_ansiFlag ( outmsg.NetID ) ); } } void bcst_relay ( int spc, BYTE ssn, BYTE ntype, BYTE NetID ) { Intra_Msg outmsg; int i; spLogDebug ( SCCPDB_SCMG, "relay Broadcase spc:%X,ssn%d,ntype:%d", spc, ssn, ntype ); outmsg.msgtype = UDT_MSG; outmsg.msgsource = FROM_SCMG; outmsg.CDA.GTI = 0; outmsg.CGA.SSN = 1; outmsg.CGA.GTI = 0; outmsg.CGA.len = 0; outmsg.CGA.RI = 1; outmsg.NetID = outmsg.CGA.NetID = outmsg.CDA.NetID = NetID; for ( i = 0; i < RelatedSPCNum; i++ ) { if( NetID != RelatedSPC[i].NetID ) return; if( RelatedSPC[i].status == ST_Disable || spc == RelatedSPC[i].DPC ) continue; outmsg.CGA.DPC = SCCP_Param.spc[RelatedSPC[i].NetID]; outmsg.CDA.ip = INADDR_NONE; outmsg.CDA.DPC = RelatedSPC[i].DPC; outmsg.CDA.SSN = 1; outmsg.CDA.RI = 1; outmsg.CDA.len = 0; outmsg.msglen = build_scmgmsg ( outmsg.data, ntype, spc, ssn, NetID ); send_msg ( &outmsg, mtp3_ansiFlag ( NetID ) ); } } int build_scmgmsg ( BYTE * data, BYTE type, int spc, BYTE ssn, BYTE NetID ) { int pos = 0; data[pos++] = type; data[pos++] = ssn; memcpy ( data + pos, ( BYTE * ) & spc, SCCP_Param.spclen[NetID] ); pos += SCCP_Param.spclen[NetID]; data[pos++] = 0; if( type == SSC_MSG ) data[pos++] = 0; return pos; } int parse_scmgmsg ( BYTE * data, BYTE * type, int *spc, BYTE * ssn, BYTE NetID ) { int pos = 0; *type = data[pos++]; *ssn = data[pos++]; *spc = 0; memcpy ( ( BYTE * ) spc, data + pos, SCCP_Param.spclen[NetID] ); pos += SCCP_Param.spclen[NetID]; return 1; }