
/*********************************************************/
/*Title:  sccpmib.c                                      */
/*Descr:  SCCP Management information Base Interface     */
/*Author: Liang Hanxi                                    */
/*Create: 2002-4-16                                      */
/*Modify:                                                */

/*********************************************************/

#include "./include/sccp.h"

/*===========import================*/
extern int BuildRouteIndex (  );        //gtt.c
extern int sccp_loadparam (  ); //sccpparam.c
extern void sccp_saveparam (  );
extern int sccp_setparam ( DWORD * oid, BYTE * pdata, WORD datalen );
extern int sccp_getparam ( DWORD * oid, BYTE * pdata, BYTE * vartype );
extern void sccp_reset (  );    //sccp.c
extern void DWORD2BYTE ( BYTE * pdword, BYTE * pbyte, int len );        //sccpfun.c
extern void spLogDebug ( DWORD mask, const char *fmt, ... );
/* by simon at 23/9/26 */
extern SCCP_CSTA SccpCsta[96];
extern DWORD SccpCstaInd;
/* by simon at 23/9/26*/
extern int RelatedSSNNum;
extern RL_SSN RelatedSSN[SCCP_RLSSN_NUM];
extern SCOC_BUF ScocBuf;
extern SCCP_ROUTE RouteList[SCCP_ROUTE_NUM];
extern LOCAL_SSN LocalSSN[256];
extern SCCP_ROUTE RouteList[SCCP_ROUTE_NUM];
extern SCCP_OPT SCCP_Param;

/*===========export================*/
void sccpmib_init (  );
void sccp_sethb (  );

/*===========private===============*/
int sccp_setmib ( BYTE oidlen, DWORD * oid, BYTE * pdata, WORD datalen );
int sccp_getmib ( BYTE oidlen, DWORD * oid, BYTE * pdata, BYTE * vartype );
void sccp_trapcallback ( BYTE oidlen, DWORD * oid, BYTE * pdata, WORD len, snmp_addr * addr );

void sccpmib_init (  )
{
    DWORD oid[20] = SCCP_OID;

    inquire_setmsg ( SCCP_OIDLEN, oid, sccp_setmib );
    inquire_getmsg ( SCCP_OIDLEN, oid, sccp_getmib );
    inquire_trapmsg ( sccp_trapcallback );
}

void sccp_sethb (  )
{
    set_status ( 2, 4 + SCCP_Param.RegNum, SCCP_Param.version );
    set_led ( 4, 9 );
}

/************************************************/
//MIB Interface=================================>

/************************************************/
int sccp_setmib ( BYTE oidlen, DWORD * oid, BYTE * pdata, WORD datalen )
{
    switch ( oid[SCCP_OIDLEN] )
    {
    case 1:                    //CSTA, read only
        return -1;
    case 2:                    //Paramter
        return sccp_setparam ( &oid[SCCP_OIDLEN + 1], pdata, datalen );
    case 3:                    //Status
        switch ( oid[SCCP_OIDLEN + 1] )
        {
        case 1:                //version, read only
            return -1;
        case 2:                //command
            switch ( pdata[0] )
            {
            case 0:            //reset
                spLogDebug ( SCCPDB_SNMP, "Reset SCCP..." );
                sccp_reset (  );
                break;
            case 1:            //load
                return -1;
            case 2:            //save
                spLogDebug ( SCCPDB_SNMP, "Save Parameter..." );
                sccp_saveparam (  );
                break;
            }
            return 1;
        case 3:                //status, read only
            return -1;
        }
        break;
    }
    return -1;
}

int sccp_getmib ( BYTE oidlen, DWORD * oid, BYTE * pdata, BYTE * vartype )
{
    DWORD instance;
    SCCP_CSTA *pcsta;

    spLogDebug ( SCCPDB_SNMP, "get sccp mib..." );
    switch ( oid[SCCP_OIDLEN] )
    {
    case 1:                    //CSTA          
        instance = oid[SCCP_OIDLEN + 1];
        if( instance == SccpCstaInd || instance > 95 )
        {
            *vartype = NosuchInstance;
            spLogDebug ( SCCPDB_SNMP, "csta message not ready. instance=%d", instance );
            return 0;
        }
        pcsta = &SccpCsta[instance];
        if( pcsta->timestamp == 0 )
        {
            spLogDebug ( SCCPDB_SNMP, "csta message is expired" );
            *vartype = 5;
            return 0;
        }
        *vartype = 4;
        spLogDebug ( SCCPDB_SNMP, "Respond csta message" );
        DWORD2BYTE ( ( BYTE * ) & pcsta->timestamp, pdata, sizeof ( SCCP_CSTA ) );
        return sizeof ( SCCP_CSTA );
    case 2:                    //Config
        return sccp_getparam ( &oid[SCCP_OIDLEN + 1], pdata, vartype );
    case 3:                    //Status
        switch ( oid[SCCP_OIDLEN + 1] )
        {
        case 1:                //version
            spLogDebug ( SCCPDB_SNMP, "Get SCCP Version" );
            memcpy ( pdata, SCCP_Param.version, 3 );
            *vartype = 4;
            return 3;
        case 2:                //command, write only
            return -1;
        case 3:                //status
            pdata[0] = SCCP_Param.status;
            *vartype = 2;
            return 1;
        }
        break;
    }
    return -1;
}

//#define OMC_HB_OID     {1,3,6,1,4,1,1373,1,4,1,1}
#define OMC_HB_OID     {1,3,6,1,4,1,1373,2,4,1}
#define OMC_HB_OIDLEN  10
int AddToIpList ( DWORD ip, BYTE ssn );

void sccp_OMCIP_detect ( DWORD ip )
{
    int i;
    BYTE index = 0;

    for ( i = 0; i <= 1; i++ )
    {
        if( SCCP_Param.OMCIP[i] == ip )
            return;
        else if( SCCP_Param.OMCIP[i] == 0 )
            index = i;
    }
    SCCP_Param.OMCIP[index] = ip;
    AddToIpList ( ip, 4 );
}

extern ull SCCPSerialNumber;

void sccp_trapcallback ( BYTE oidlen, DWORD * oid, BYTE * pdata, WORD len, snmp_addr * addr )
{
    DWORD ObjID[20] = FLATFORM_HB_OID;
    BYTE ssn;
    short infolen, i, pos = 2;  //component_id=0:iptrans
    heartbeat_msg *phbmsg = ( heartbeat_msg * ) pdata;
    BYTE *pstatus = phbmsg->info;
    DWORD OMCHLObjID[20] = OMC_HB_OID;
    BYTE newHeartbeat = 0;

    if( memcmp ( &oid[7], &OMCHLObjID[7], ( OMC_HB_OIDLEN - 7 ) * 4 ) == 0 )    //omc heartbeat
    {                           //automatic add omc ip into ip list,
        //if receive omc heartbeat and the omc serial number is equial to the local serial number,
        //then the platform will send heartbeat if received omc heartbeat
        if( ( SCCPSerialNumber == 0 ) ||        //support old version, do not have serial number
            ( Bcd2Ull ( &pdata[39], SCCP_SERNUM_LEN ) == SCCPSerialNumber ) )
            sccp_OMCIP_detect ( addr->remote_ip );
    }

    if( memcmp ( &oid[9], &ObjID[9], ( FLATFORM_HB_OIDLEN - 9 ) * 4 ) != 0 || addr->remote_ip == SCCP_Param.ip )
        return;

    if( sizeof ( struct heartbeat_msg ) > ( INFO_LEN + 18 ) )
        newHeartbeat = 1;

    if( !newHeartbeat )
    {                           //old version heartbeat, length and component_id are one octet
        pos = 1;
        pos += pstatus[pos] + 1;        //length of iptrans status
        pos++;                  //component_id=1:mtp3
        pos += pstatus[pos] + 1;        //length of mtp3
        pos++;                  //component_id=2:sccp
    }
    else
    {                           //new version heartbeat, length and component_id are 2 octets
        pos++;                  //length is 2 octets
        pos += pstatus[pos] + 1;        //length of iptrans     status  
        pos++;                  //component_id=1:mtp3
        pos++;                  //component_id is 2 octets

        pos++;                  //length is 2 octets
        pos += pstatus[pos] + 1;        //length of mtp3

        pos++;                  //component_id=2:sccp
        pos++;                  //component_id is 2 octets

        pos++;                  //sccp length 1
    }
    infolen = pstatus[pos++];

    if( infolen <= 4 || infolen > 32 )
        return;

    for ( i = pos + 4; i < pos + infolen; i++ )
    {
        ssn = pstatus[i];
        //      printf("beat recieve,ssn=%d\n",ssn);
        if( ssn <= 1 )
            continue;
        if( addr->remote_ip == LocalSSN[ssn].ip[0] )
        {
            LocalSSN[ssn].status[0] = ST_Enable;
            LocalSSN[ssn].timeout[0] = T_hbrecv;
        }
        else if( addr->remote_ip == LocalSSN[ssn].ip[1] )
        {
            LocalSSN[ssn].status[1] = ST_Enable;
            LocalSSN[ssn].timeout[1] = T_hbrecv;
        }
    }

}
