📄 en_encap.c
字号:
}
return ( psPktbuf );
} /* end en_cd_PktbufAlloc( ) */
/*---------------------------------------------------------------------------
** en_cd_PktbufFree( )
**---------------------------------------------------------------------------
*/
void
en_cd_PktbufFree( PKTBUF_P psPktbuf )
{
/*
** Since the buffer is being released, there should be no pending I/O
** operations.
*/
psPktbuf->lFlags &= ( ~PKTBUF_F_PENDING );
/*
** Delete pktbuf which was allocated as a combuf
*/
gs_Free_FL( ( void * ) psPktbuf,__FILE__,__LINE__ );
} /* end en_cd_PktbufFree( ) */
#undef PROC
#define PROC "en_cd_CloseEce"
/*---------------------------------------------------------------------------
** en_cd_CloseEce( )
**---------------------------------------------------------------------------
*/
void en_cd_CloseEce( OE_Q_ID OutputQ )
{
EnCdMessageType EnCdMessage; /* Message to be sent out via tcpip */
/*
** Command to the write task to close the connection
*/
EnCdMessage.Command = CLOSECONNECTION;
OE_MsgQSend( OutputQ,
( char * ) &EnCdMessage.Command,
sizeof EnCdMessage,
WAIT_FOREVER,
MSG_PRI_NORMAL );
} /* end en_cd_CloseEce( ) */
/*---------------------------------------------------------------------------
** en_cd_CheckAndGetServices( )
**---------------------------------------------------------------------------
*/
INT32 en_cd_CheckAndGetServices( void *data, INT32 lLen, ENCAP_SERVICE * psServices )
{
ENCAP_OBJ_LIST *psObjList;
ENCAP_OBJ_HDR *psObjHdr;
ENCAP_SERVICE *psEncapService;
INT32 nObjCount;
INT32 nObjLen;
INT32 i;
INT32 nValid = FALSE;
do
{
/*
** Must have at least a standard object list header
*/
if ( lLen < ENCAP_OBJ_LIST_SIZE )
break;
psObjList = data;
nObjCount = ENCAP_TO_HS( psObjList->iO_count );
lLen -= ENCAP_OBJ_LIST_SIZE;
psObjHdr = ( ENCAP_OBJ_HDR * ) ( ( INT32 ) psObjList + ENCAP_OBJ_LIST_SIZE );
psEncapService = ( ENCAP_SERVICE * ) NULL;
for ( i = 0; i < nObjCount; i++ )
{
/*
** Check the length to make sure a standard object header exists.
** Extract the object length, and make sure that it is consistent with
** the remaining length.
*/
if ( lLen < ENCAP_OBJ_HDR_SIZE )
break;
nObjLen = ENCAP_TO_HS( psObjHdr->iObj_length );
lLen -= ENCAP_OBJ_HDR_SIZE;
if ( lLen < nObjLen )
break;
/*
** The desired object is COMMSERVICE
*/
if ( psObjHdr->iObj_type == ENCAP_VALUE_SHORT( ENCAP_OBJTYPE_SERVICE_COMM ) )
{
psEncapService = ( ENCAP_SERVICE * ) & ( ( ( ENCAP_OBJ_TARGET * ) psObjHdr )->sS );
break;
}
else
{
psObjHdr = ( ENCAP_OBJ_HDR * ) ( ( INT32 ) psObjHdr + ENCAP_OBJ_HDR_SIZE + nObjLen );
lLen -= nObjLen;
}
}
/*
** Check version and flags in any COMMSERVICE object which was found
*/
if ( psEncapService )
{
ENCAP_CVT_HS( psEncapService->iS_version );
if ( psEncapService->iS_version != ENCAP_COMMSERVICE_VERSION )
{
sEncapStats.lErrUnSupportedRev++;
break;
}
ENCAP_CVT_HS( psEncapService->iS_flags );
if ( ( psEncapService->iS_flags & ENCAP_COMMSERVICE_CIP_DIRECT ) == 0 )
break;
*psServices = *psEncapService;
nValid = TRUE;
}
} while ( 0 );
return ( nValid );
} /* end en_cd_CheckAndGetServices( ) */
/*---------------------------------------------------------------------------
** en_cd_EncapErrorReply( )
**---------------------------------------------------------------------------
*/
void en_cd_EncapErrorReply( PKTBUF_P psPktBuf, UINT32 lValue,
void *data, INT32 nDataLen )
{
ENCAPH *psEncapHdr = ( ENCAPH * ) ( &psPktBuf->sEncap.sHdr );
sEncapStats.lRepliesSentErrs++;
psPktBuf->pData = &psPktBuf->abData[ 0 ];
psPktBuf->lLength = nDataLen;
if ( nDataLen )
{
UC_CopyMem( ( caddr_t ) &psPktBuf->abData[ 0 ], ( caddr_t ) data, nDataLen );
}
psEncapHdr->iEncaph_length = nDataLen;
psEncapHdr->lEncaph_status = lValue;
psPktBuf->sEncap.lValid = 0;
en_cd_SendEncapCommand( psPktBuf );
} /* end en_cd_EncapErrorReply( ) */
/*---------------------------------------------------------------------------
** en_cd_RegisterRequest( )
**---------------------------------------------------------------------------
*/
PKTBUF_P en_cd_RegisterRequest( ECE * psEce )
{
PKTBUF_P psPktBuf;
ENCAP_RC_DATA *psRCData;
if ( psPktBuf = PktBufAlloc( ) )
{
psPktBuf->sEncap.sHdr.iEncaph_command = ENCAP_CMD_REGISTERSESSION;
psPktBuf->sEncap.sHdr.lEncaph_status = 0;
psPktBuf->sEncap.sHdr.lEncaph_session = 0;
psPktBuf->sEncap.sHdr.alEncaph_context[ 0 ] = 0;
psPktBuf->sEncap.sHdr.alEncaph_context[ 1 ] = 0;
psPktBuf->sEncap.sHdr.iEncaph_length = ENCAP_RC_DATA_SIZE;
psRCData = psPktBuf->pData;
psRCData->iRc_version = ENCAP_VALUE_SHORT( ENCAP_PROTOCOL_VERSION );
psRCData->iRc_flags = 0;
psPktBuf->sEncap.lValid = 0;
psPktBuf->lLength = ENCAP_RC_DATA_SIZE;
psPktBuf->sOutputQ = psEce->sOutputQ;
}
return ( psPktBuf );
}
/*---------------------------------------------------------------------------
** en_cd_ListServicesReceived( )
**---------------------------------------------------------------------------
*/
void en_cd_ListServicesReceived( ECE * psEce, PKTBUF_P psPktBuf )
{
ENCAPH *psEncapHdr = ( ENCAPH * ) ( &psPktBuf->sEncap.sHdr );
OE_Q_ID sOutputQ;
switch ( ECE_TYPE( psEce->sEid ) )
{
/*
** Process a request from a client for a list of our services
*/
case ECE_TYPE_INBOUND:
sEncapStats.lCommandsReceived++;
/*
** Check length of command specific data. There shouldn't be any.
*/
if ( psEncapHdr->iEncaph_length != 0 )
{
sEncapStats.lErrBadData++;
en_cd_EncapErrorReply( psPktBuf, ENCAP_E_BADDATA, NULL, 0 );
}
else
{
if ( psEncapHdr->lEncaph_status == ENCAP_E_SUCCESS )
{
UC_CopyMem( ( caddr_t ) &psPktBuf->abData[ 0 ], ( caddr_t ) &list_services_data,
sizeof( list_services_data ) );
psPktBuf->lLength = sizeof( list_services_data );
psPktBuf->sEncap.sObj_list.iO_count = 1;
psPktBuf->sEncap.lValid = PKTBUF_ENCAPV_OBJ;
psEncapHdr->lEncaph_status = 0;
psEncapHdr->iEncaph_length = ENCAP_OBJ_LIST_SIZE + psPktBuf->lLength;
sEncapStats.lRepliesSent++;
en_cd_SendEncapCommand( psPktBuf );
}
else
PktBufFree( psPktBuf );
}
break;
case ECE_TYPE_OUTBOUND:
/*
** Process a ListServices reply. Parse the reply to
** verify that the Communications service is supported, has the correct
** version, and supports CIP direct execution. If all of the criteria are
** met, then attempt to register with the server.
*/
{
INT32 valid = FALSE;
if ( psEncapHdr->lEncaph_status == ENCAP_E_SUCCESS )
sEncapStats.lRepliesReceived++;
else
sEncapStats.lRepliesReceivedErrs++;
do
{
/*
** Only valid state for the ECE is CONNECTED
*/
if ( psEce->lState != ECE_STATE_CONNECTED )
break;
/*
** A non-zero status indicates that the request was not accepted.
*/
if ( psEncapHdr->lEncaph_status != ENCAP_E_SUCCESS )
break;
/*
** The ENCAP length must be consistent with remaining data
*/
if ( psEncapHdr->iEncaph_length != psPktBuf->lLength )
break;
/*
** Call function to parse the packet and verify that the server
** supports the requested function.
*/
valid = en_cd_CheckAndGetServices( psPktBuf->pData, psPktBuf->lLength, &psEce->sServices );
} while ( 0 );
/*
** Free the incoming request so that a buffer is available for the
** next ENCAP command that we may potentially send. If all the checks
** have passed, then attempt to Register with the server. Close out
** the ECE if the ListServices was incorrect or the Register request
** could not be generated.
*/
sOutputQ = psPktBuf->sOutputQ;
PktBufFree( psPktBuf );
if ( valid == FALSE )
en_cd_CloseEce( sOutputQ );
else
{
PKTBUF_P psRRequest;
if ( psRRequest = en_cd_RegisterRequest( psEce ) )
{
sEncapStats.lCommandsSent++;
en_cd_SendEncapCommand( psRRequest );
if ( psEce->lState == ECE_STATE_CONNECTED )
psEce->lState = ECE_STATE_REGISTER;
}
else
en_cd_CloseEce( sOutputQ );
}
}
break;
/*
** Not sure how this could happen, but we should crash on the error.
*/
default:
GS_LogEvent( CD_UNSUPPORTED_CONFIG_REQUEST, /* Incorrect type code specified in ECE */
ECE_TYPE( psEce->sEid ),
0,
FATAL );
break;
}
}
#undef PROC
#define PROC "en_cd_ListInterfacesReceived"
/*----------------------------------------------------------------------------
** en_cd_ListInterfacesReceived( )
**---------------------------------------------------------------------------
**/
void en_cd_ListInterfacesReceived( ECE * psEce, PKTBUF_P psPktBuf )
{
ENCAPH *psEncapHdr = ( ENCAPH * ) ( &psPktBuf->sEncap.sHdr );
switch ( ECE_TYPE( psEce->sEid ) )
{
/*
** Process a request from a client for a list of our services
*/
case ECE_TYPE_INBOUND:
sEncapStats.lCommandsReceived++;
/*
** Check length of command specific data. There shouldn't be any.
*/
if ( psEncapHdr->iEncaph_length != 0 )
{
sEncapStats.lErrBadData++;
en_cd_EncapErrorReply( psPktBuf, ENCAP_E_BADDATA, NULL, 0 );
}
else
{
if ( psEncapHdr->lEncaph_status == ENCAP_E_SUCCESS )
{
psPktBuf->sEncap.sObj_list.iO_count = 0; /* Currently not implemented */
psPktBuf->lLength = psPktBuf->sEncap.sObj_list.iO_count * ENCAP_OBJ_TARGET_SIZE;
psPktBuf->sEncap.lValid = PKTBUF_ENCAPV_OBJ;
psEncapHdr->lEncaph_status = 0;
psEncapHdr->iEncaph_length = ENCAP_OBJ_LIST_SIZE + psPktBuf->lLength;
sEncapStats.lRepliesSent++;
en_cd_SendEncapCommand( psPktBuf );
}
else
PktBufFree( psPktBuf );
}
break;
/*
** Silently ignore the command...
*/
case ECE_TYPE_OUTBOUND:
if ( psEncapHdr->lEncaph_status == ENCAP_E_SUCCESS )
sEncapStats.lRepliesReceived++;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -