mirror of https://github.com/OISF/suricata
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
6.8 KiB
C
251 lines
6.8 KiB
C
/* Copyright (C) 2015 Open Information Security Foundation
|
|
*
|
|
* You can copy, redistribute or modify this Program under the terms of
|
|
* the GNU General Public License version 2 as published by the Free
|
|
* Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* version 2 along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA.
|
|
*/
|
|
|
|
/**
|
|
* \file
|
|
*
|
|
* \author Kevin Wong <kwong@solananetworks.com>
|
|
*/
|
|
|
|
#ifndef __APP_LAYER_ENIP_COMMON_H__
|
|
#define __APP_LAYER_ENIP_COMMON_H__
|
|
|
|
#include "app-layer-protos.h"
|
|
#include "app-layer-parser.h"
|
|
#include "flow.h"
|
|
#include "queue.h"
|
|
|
|
#define MAX_ENIP_CMD 65535
|
|
|
|
// EtherNet/IP commands
|
|
#define NOP 0x0000
|
|
#define LIST_SERVICES 0x0004
|
|
#define LIST_IDENTITY 0x0063
|
|
#define LIST_INTERFACES 0x0064
|
|
#define REGISTER_SESSION 0x0065
|
|
#define UNREGISTER_SESSION 0x0066
|
|
#define SEND_RR_DATA 0x006F
|
|
#define SEND_UNIT_DATA 0x0070
|
|
#define INDICATE_STATUS 0x0072
|
|
#define CANCEL 0x0073
|
|
|
|
//Common Packet Format Types
|
|
#define NULL_ADDR 0x0000
|
|
#define CONNECTION_BASED 0x00a1
|
|
#define CONNECTED_DATA_ITEM 0x00b1
|
|
#define UNCONNECTED_DATA_ITEM 0x00b2
|
|
#define SEQUENCE_ADDR_ITEM 0xB002
|
|
|
|
//status codes
|
|
#define SUCCESS 0x0000
|
|
#define INVALID_CMD 0x0001
|
|
#define NO_RESOURCES 0x0002
|
|
#define INCORRECT_DATA 0x0003
|
|
#define INVALID_SESSION 0x0064
|
|
#define INVALID_LENGTH 0x0065
|
|
#define UNSUPPORTED_PROT_REV 0x0069
|
|
|
|
#define MAX_CIP_SERVICE 127
|
|
#define MAX_CIP_CLASS 65535
|
|
#define MAX_CIP_ATTRIBUTE 65535
|
|
|
|
// CIP service codes
|
|
#define CIP_RESERVED 0x00
|
|
#define CIP_GET_ATTR_ALL 0x01
|
|
#define CIP_GET_ATTR_LIST 0x03
|
|
#define CIP_SET_ATTR_LIST 0x04
|
|
#define CIP_RESET 0x05
|
|
#define CIP_START 0x06
|
|
#define CIP_STOP 0x07
|
|
#define CIP_CREATE 0x08
|
|
#define CIP_DELETE 0x09
|
|
#define CIP_MSP 0x0a
|
|
#define CIP_APPLY_ATTR 0x0d
|
|
#define CIP_GET_ATTR_SINGLE 0x0e
|
|
#define CIP_SET_ATTR_SINGLE 0x10
|
|
#define CIP_KICK_TIMER 0x4b
|
|
#define CIP_OPEN_CONNECTION 0x4c
|
|
#define CIP_CHANGE_START 0x4f
|
|
#define CIP_GET_STATUS 0x50
|
|
|
|
//PATH sizing codes
|
|
#define PATH_CLASS_8BIT 0x20
|
|
#define PATH_CLASS_16BIT 0x21
|
|
#define PATH_INSTANCE_8BIT 0x24
|
|
#define PATH_INSTANCE_16BIT 0x25
|
|
#define PATH_ATTR_8BIT 0x30
|
|
#define PATH_ATTR_16BIT 0x31 //possible value
|
|
|
|
/**
|
|
* ENIP encapsulation header
|
|
*/
|
|
typedef struct ENIPEncapHdr_
|
|
{
|
|
uint64_t context;
|
|
uint32_t session;
|
|
uint32_t status;
|
|
uint32_t option;
|
|
uint16_t command;
|
|
uint16_t length;
|
|
} ENIPEncapHdr;
|
|
|
|
/**
|
|
* ENIP encapsulation data header
|
|
*/
|
|
typedef struct ENIPEncapDataHdr_
|
|
{
|
|
uint32_t interface_handle;
|
|
uint16_t timeout;
|
|
uint16_t item_count;
|
|
} ENIPEncapDataHdr;
|
|
|
|
/**
|
|
* ENIP encapsulation address item
|
|
*/
|
|
typedef struct ENIPEncapAddresItem_
|
|
{
|
|
uint16_t type;
|
|
uint16_t length;
|
|
uint16_t conn_id;
|
|
uint16_t sequence_num;
|
|
} ENIPEncapAddresItem;
|
|
|
|
/**
|
|
* ENIP encapsulation data item
|
|
*/
|
|
typedef struct ENIPEncapDataItem_
|
|
{
|
|
uint16_t type;
|
|
uint16_t length;
|
|
uint16_t sequence_count;
|
|
} ENIPEncapDataItem;
|
|
|
|
/**
|
|
* CIP Request Header
|
|
*/
|
|
typedef struct CIPReqHdr_
|
|
{
|
|
uint8_t service;
|
|
uint8_t path_size;
|
|
} CIPReqHdr;
|
|
|
|
/**
|
|
* CIP Response Header
|
|
*/
|
|
typedef struct CIPRespHdr_
|
|
{
|
|
uint8_t service;
|
|
uint8_t pad;
|
|
uint8_t status;
|
|
uint8_t status_size;
|
|
} CIPRespHdr;
|
|
|
|
typedef struct SegmentEntry_
|
|
{
|
|
uint16_t segment; /**< segment type */
|
|
uint16_t value; /**< segment value (class or attribute) */
|
|
|
|
TAILQ_ENTRY(SegmentEntry_) next;
|
|
} SegmentEntry;
|
|
|
|
typedef struct AttributeEntry_
|
|
{
|
|
uint16_t attribute; /**< segment class */
|
|
|
|
TAILQ_ENTRY(AttributeEntry_) next;
|
|
} AttributeEntry;
|
|
|
|
typedef struct CIPServiceEntry_
|
|
{
|
|
uint8_t service; /**< cip service */
|
|
uint8_t direction;
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
uint8_t path_size; /**< cip path size */
|
|
uint16_t path_offset; /**< offset to cip path */
|
|
} request;
|
|
struct
|
|
{
|
|
uint8_t status;
|
|
} response;
|
|
};
|
|
|
|
TAILQ_HEAD(, SegmentEntry_) segment_list; /**< list for CIP segment */
|
|
TAILQ_HEAD(, AttributeEntry_) attrib_list; /**< list for CIP segment */
|
|
|
|
TAILQ_ENTRY(CIPServiceEntry_) next;
|
|
} CIPServiceEntry;
|
|
|
|
typedef struct ENIPTransaction_
|
|
{
|
|
struct ENIPState_ *enip;
|
|
uint16_t tx_num; /**< internal: id */
|
|
uint16_t tx_id; /**< transaction id */
|
|
uint16_t service_count;
|
|
|
|
ENIPEncapHdr header; /**< encapsulation header */
|
|
ENIPEncapDataHdr encap_data_header; /**< encapsulation data header */
|
|
ENIPEncapAddresItem encap_addr_item; /**< encapsulated address item */
|
|
ENIPEncapDataItem encap_data_item; /**< encapsulated data item */
|
|
|
|
TAILQ_HEAD(, CIPServiceEntry_) service_list; /**< list for CIP */
|
|
|
|
AppLayerDecoderEvents *decoder_events; /**< per tx events */
|
|
|
|
TAILQ_ENTRY(ENIPTransaction_) next;
|
|
DetectEngineState *de_state;
|
|
} ENIPTransaction;
|
|
|
|
/** \brief Per flow ENIP state container */
|
|
typedef struct ENIPState_
|
|
{
|
|
TAILQ_HEAD(, ENIPTransaction_) tx_list; /**< transaction list */
|
|
ENIPTransaction *curr; /**< ptr to current tx */
|
|
ENIPTransaction *iter;
|
|
uint64_t transaction_max;
|
|
uint64_t tx_with_detect_state_cnt;
|
|
|
|
uint16_t events;
|
|
uint16_t givenup;
|
|
|
|
/* used by TCP only */
|
|
uint16_t offset;
|
|
uint16_t record_len;
|
|
uint8_t *buffer;
|
|
} ENIPState;
|
|
|
|
int DecodeENIPPDU(uint8_t *input, uint32_t input_len,
|
|
ENIPTransaction *enip_data);
|
|
int DecodeCommonPacketFormatPDU(uint8_t *input, uint32_t input_len,
|
|
ENIPTransaction *enip_data, uint16_t offset);
|
|
int DecodeCIPPDU(uint8_t *input, uint32_t input_len,
|
|
ENIPTransaction *enip_data, uint16_t offset);
|
|
int DecodeCIPRequestPDU(uint8_t *input, uint32_t input_len,
|
|
ENIPTransaction *enip_data, uint16_t offset);
|
|
int DecodeCIPResponsePDU(uint8_t *input, uint32_t input_len,
|
|
ENIPTransaction *enip_data, uint16_t offset);
|
|
int DecodeCIPRequestPathPDU(uint8_t *input, uint32_t input_len,
|
|
CIPServiceEntry *node, uint16_t offset);
|
|
int DecodeCIPRequestMSPPDU(uint8_t *input, uint32_t input_len,
|
|
ENIPTransaction *enip_data, uint16_t offset);
|
|
int DecodeCIPResponseMSPPDU(uint8_t *input, uint32_t input_len,
|
|
ENIPTransaction *enip_data, uint16_t offset);
|
|
|
|
#endif /* __APP_LAYER_ENIP_COMMON_H__ */
|