⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 en_encap.c

📁 基于EthernetIP协议的应用程序,可以读取AB公司Controllogix系列Ethernetip协议PLC数据. 此软件代码可用于工业控制.
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*****************************************************************************
**
** 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 + -