📄 en_encap.c
字号:
/****************************************************************************
*****************************************************************************
**
** File Name
** ---------
**
** EN_ENCAP.C
**
*****************************************************************************
*****************************************************************************
**
** Description
** -----------
**
** Ethernet Encapsulation Protocol interface.
**
*****************************************************************************
*****************************************************************************
**
** Source Change Indices
** ---------------------
**
** Porting: <none>0----<major> Customization: <none>0----<major>
**
*****************************************************************************
*****************************************************************************
** **
** ETHERNET/IP EXAMPLE CODE **
** COPYRIGHT (c) 2000-2005 ODVA (Open DeviceNet Vendor Association) **
** & ControlNet International Ltd. **
** **
** All rights reserved, except as specifically licensed in writing. **
** Use of the Ethernet/IP Example Protocol Software is subject to **
** ODVA's and ControlNet International's Terms of Use Agreement. **
** The following work constitutes example program code and is intended **
** merely to illustrate useful programming techniques. The user is **
** responsible for applying the code correctly. The code is provided **
** AS IS without warranty and is in no way guaranteed to be error-free. **
** **
*****************************************************************************
*****************************************************************************
*/
#ifdef WIN32
#include <limits.h> /* JB: Added for UINT_MAX */
#endif
#include <ctype.h>
#include <stdlib.h>
#ifdef WIN32
#include <winsock2.h> /* WinSock */
#include <ws2tcpip.h> /* WinSock */
#endif
#include <io.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include "fd.h"
#include "ab_env.h"
#include "gs.h"
#include "mr.h"
#include "cd.h"
#include "id.h"
#include "id_obj.h"
#include "cd.h" /* Communications Device public interfaces */
#include "um.h" /* UCMM interfaces ( for rx packet pre-routing ) */
#include "cm.h" /* Connection Manager ( for rx packet pre-routing ) */
#ifdef CD_EN_OBJECTS
#include "cd_util.h"
#include "en.h"
#include "en_sock.h"
#include "ECInterface.h"
/****************************************************************************
**
** Public data
**
*****************************************************************************
*/
extern OE_Q_ID MngOutgoingEncapQueue;
ENCAP_STATS sEncapStats;
CIP_MCAST_TABLE sMcast_table; /* multicast allocation table */
extern UINT32 lECE_connects; /* Current number of TCP connections */
extern UINT32 lECE_connects_in; /* Current number of incoming TCP connections */
extern UINT32 lECE_connects_out; /* Current number of outgoing TCP connections */
extern UINT32 lTotal_lECE_connects; /* Current number of TCP connections */
/****************************************************************************
**
** Private data
**
*****************************************************************************
*/
/* Canned response data for the List Services command */
static ENCAP_OBJ_SERVICE list_services_data = {
{ENCAP_VALUE_SHORT( ENCAP_OBJTYPE_SERVICE_COMM ), ENCAP_VALUE_SHORT( ENCAP_SERVICE_SIZE )},
{ENCAP_VALUE_SHORT( ENCAP_COMMSERVICE_VERSION ),
ENCAP_VALUE_SHORT( ENCAP_COMMSERVICE_CIP_DIRECT | ENCAP_COMMSERVICE_IO_CONNECT ),
ENCAP_COMMSERVICE_NAME
}
};
/* Canned response data for the List Targets command */
/*static*/ ENCAP_OBJ_TARGET list_target_data = {
{ENCAP_VALUE_SHORT( ENCAP_OBJTYPE_TARGET ), ENCAP_VALUE_SHORT( ENCAP_TARGET_SIZE )},
ENCAP_VALUE_SHORT( ENCAP_PROTOCOL_VERSION ), ENCAP_VALUE_SHORT( 0 ),
{0, 0, 0, 0}, /* Target socket address */
'\0' /* Target Name */
};
static ENCAP_RC_DATA register_data = {
ENCAP_VALUE_SHORT( ENCAP_PROTOCOL_VERSION ),
ENCAP_VALUE_SHORT( 0 )
};
/* CPF header template */
static CPFHDR cpfhdr_tmpl = {
ENCAP_VALUE_SHORT( 2 ),
ENCAP_VALUE_SHORT( CPF_TAG_ADR_SEQUENCED ),
ENCAP_VALUE_SHORT( 8 ),
0, 0,
0, 0,
ENCAP_VALUE_SHORT( CPF_TAG_PKT_CONNECTED ),
0
};
/*
** IP Address for use while on debugger, to find out what DNS has
** assigned us.
*/
UINT8 IPAddress[ 32 ];
/****************************************************************************
**
** Private services
**
*****************************************************************************
*/
/*---------------------------------------------------------------------------
** en_cd_CheckSocketAddresses( )
**---------------------------------------------------------------------------
*/
INT32 en_cd_CheckSocketAddresses( ECM_SOCK_ADDR * sa, INT32 i32ReceiveType, INT32 i32TransmitType )
{
unsigned long ip_address;
int ret = TRUE;
if ( sa->sReceive.sin_port )
{
ip_address = ntohl( sa->sReceive.sin_addr.s_addr );
switch ( i32ReceiveType )
{
case CM_CP_TYPE_MULTICAST:
if ( !( IN_MULTICAST( ip_address ) ) )
ret = FALSE;
break;
case CM_CP_TYPE_POINT:
if ( ip_address != INADDR_ANY )
ret = FALSE;
break;
default:
ret = FALSE;
break;
}
}
if ( sa->sTransmit.sin_port )
{
ip_address = ntohl( sa->sTransmit.sin_addr.s_addr );
switch ( i32TransmitType )
{
case CM_CP_TYPE_MULTICAST:
if ( !( IN_MULTICAST( ip_address ) ) )
ret = FALSE;
break;
case CM_CP_TYPE_POINT:
if ( ip_address != INADDR_ANY )
ret = FALSE;
break;
default:
ret = FALSE;
break;
}
}
return ( ret );
} /* end en_cd_CheckSocketAddresses( ) */
/*---------------------------------------------------------------------------
** en_cd_GetSocketAddresses( )
**---------------------------------------------------------------------------
*/
void en_cd_GetSocketAddresses( PKTBUF_P msg, ECM_SOCK_ADDR * sa )
{
CPF_TAG tag;
struct sockaddr_in *sp;
ENCAP_SOCKADDR *st;
/*
** Initialize to default, no socket tags present
*/
UC_SetMem( &sa->sReceive, 0, sizeof( sa->sReceive ) );
sa->sReceive.sin_family = AF_INET;
UC_SetMem( &sa->sTransmit, 0, sizeof( sa->sTransmit ) );
sa->sTransmit.sin_family = AF_INET;
if ( msg->sEncap.lValid & PKTBUF_ENCAPV_ADD )
{
unsigned char *data = msg->pAdd;
int len = msg->lAdd_len;
/*
** Clear flag after extracting the tags
*/
msg->sEncap.lValid &= ( ~PKTBUF_ENCAPV_ADD );
while ( len > 0 )
{
/*
** Copy the tag into a scratch area and convert the fields to host
** byte order.
*/
UC_CopyMem( ( caddr_t ) &tag, ( caddr_t ) data, CPF_TAG_SIZE );
ENCAP_CVT_HS( tag.iTag_type );
ENCAP_CVT_HS( tag.iTag_length );
/*
** Adjust the data length and data pointer to account for the tag
** header. Point at the socket data.
*/
len -= CPF_TAG_SIZE;
data = ( caddr_t ) ( ( int ) data + CPF_TAG_SIZE );
st = ( ENCAP_SOCKADDR * ) data;
switch ( tag.iTag_type )
{
case CPF_TAG_SOCKADDR_OT:
sp = &sa->sReceive;
break;
case CPF_TAG_SOCKADDR_TO:
sp = &sa->sTransmit;
break;
default:
len -= tag.iTag_length;
data = ( caddr_t ) ( ( int ) data + tag.iTag_length );
continue; /* With while loop */
}
/*
** Copy the address and port in the packet to its correct parameter
** and advance the pointers.
*/
#ifndef WIN32
sp->sin_len = sizeof( struct sockaddr_in );
#endif
sp->sin_addr.s_addr = st->lSin_addr;
sp->sin_port = st->iSin_port;
len -= ENCAP_SOCKADDR_SIZE;
data = ( caddr_t ) ( ( int ) data + ENCAP_SOCKADDR_SIZE );
}
}
} /* end en_cd_GetSocketAddresses( ) */
/*---------------------------------------------------------------------------
** en_cd_SetSocketAddresses( )
**---------------------------------------------------------------------------
*/
void en_cd_SetSocketAddresses( PKTBUF_P msg, ECM_SOCK_ADDR * sa )
{
CPF_SOCKADDR_TAG so_tag;
unsigned char *pdata;
int add_len = 0;
int n_tags = 0;
/*
** Set pointer to the start of addenda. On an incoming msg
** the addenda pointer might have already been set up if there
** were TAG_SOCKADDR's, but if there were none, or this is an
** msg we originate, we need to set up the addenda pointer here.
*/
if ( msg->pAdd )
{
pdata = msg->pAdd;
}
else
{
msg->pAdd = pdata = ( void * ) ( ( int ) msg->pData + msg->lLength );
}
/*
** Clear out prototype socket tag and set non-changing fields
*/
UC_SetMem( ( caddr_t ) &so_tag, 0, sizeof( so_tag ) );
so_tag.sTag.iTag_length = ENCAP_VALUE_SHORT( ENCAP_SOCKADDR_SIZE );
so_tag.sock.sSo.iSin_family = htons( AF_INET );
/*
** Create O->T tag and copy it into the packet
*/
if ( sa->sReceive.sin_port )
{
so_tag.sTag.iTag_type = ENCAP_VALUE_SHORT( CPF_TAG_SOCKADDR_OT );
so_tag.sock.sSo.lSin_addr = sa->sReceive.sin_addr.s_addr;
so_tag.sock.sSo.iSin_port = sa->sReceive.sin_port;
UC_CopyMem( ( caddr_t ) pdata, ( caddr_t ) &so_tag, CPF_SOCKADDR_TAG_SIZE );
add_len += CPF_SOCKADDR_TAG_SIZE;
pdata += CPF_SOCKADDR_TAG_SIZE;
n_tags++;
}
/*
** Create T->O tag and copy it into the packet
*/
if ( sa->sTransmit.sin_port )
{
so_tag.sTag.iTag_type = ENCAP_VALUE_SHORT( CPF_TAG_SOCKADDR_TO );
so_tag.sock.sSo.lSin_addr = sa->sTransmit.sin_addr.s_addr;
so_tag.sock.sSo.iSin_port = sa->sTransmit.sin_port;
UC_CopyMem( ( caddr_t ) pdata, ( caddr_t ) &so_tag, CPF_SOCKADDR_TAG_SIZE );
add_len += CPF_SOCKADDR_TAG_SIZE;
pdata += CPF_SOCKADDR_TAG_SIZE;
n_tags++;
}
/*
** Update the PKTBUF fields to indicate the additional tags.
** Note the object count includes the Null Address type, the
** Unconnected message, plus any sockaddr info tags.
*/
if ( n_tags )
{
msg->lAdd_len = add_len;
msg->sEncap.sObj_list.iO_count = n_tags + 2;
msg->sEncap.lValid |= PKTBUF_ENCAPV_ADD;
}
} /* end en_cd_SetSocketAddresses( ) */
/*---------------------------------------------------------------------------
** en_cd_SaveSendToAddress( )
**---------------------------------------------------------------------------
*/
void en_cd_SaveSendToAddress( CM_ConnectionRecordType * psConnRecord )
{
ECM_SOCK_ADDR *sa;
MCAST_P map;
PKTBUF *msg;
/*
** Recover the pointer to the original message,
** point to socket address save area,
** Recover pointer to muticast address
*/
msg = psConnRecord->xCdHandle;
sa = &msg->sEce.sSa;
if( ( psConnRecord->iProConnParams & CM_CP_TYPE_MASK ) == CM_CP_TYPE_MULTICAST )
{
map = psConnRecord->sEce.psMcast;
/*
** copy the multicast address in the connection record to the ECE TO socket save area so
** it can be copied to the transport record
*/
UC_CopyMem( &psConnRecord->sEce.sSa.sTransmit, &map->sMc_addr,
sizeof( struct sockaddr_in ) );
/*
** copy the multicast address in the connection record to the PKTBUF so
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -