enip

package
v0.397.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 1, 2026 License: AGPL-3.0 Imports: 4 Imported by: 0

Documentation

Overview

Package enip decodes EtherNet/IP encapsulation packets and the CIP (Common Industrial Protocol) messages they carry — the ODVA factory-automation protocol family used by Allen-Bradley / Rockwell ControlLogix / CompactLogix / MicroLogix PLCs, Omron NJ/NX, Cognex vision systems, and a long tail of CIP-compliant I/O modules and drives.

EtherNet/IP is the dominant factory-floor protocol on the **North American** plant floor — the regional counterpart to S7Comm (Siemens, EU/Asia) and the third leg of the factory PLC trifecta alongside Modbus (universal). Operationally, EtherNet/ IP carries:

  • **Explicit Messaging** over TCP/44818 — the request/reply channel used by HMIs and SCADA layers to call CIP services (Get_Attribute_Single, Set_Attribute_Single, Read_Tag, Write_Tag, Forward_Open, ...).
  • **Implicit Messaging** over UDP/2222 — the high-rate I/O channel that delivers process data (input I/O scans, output I/O writes) at sub-millisecond cadences. Carried in Class 1 connected packets after a Forward_Open negotiates the connection.
  • **CIP service requests** that map onto a target object's class / instance / attribute address (the EPATH). Logix- family PLCs additionally accept tag-based addressing via services 0x4C `Read_Tag` / 0x4D `Write_Tag`.

Wrap-vs-native judgement

Native. The ODVA CIP specification (Vol 1 + Vol 2) is
publicly available; both the EtherNet/IP encapsulation
header (24 bytes LE) and the Common Packet Format are
tight, deterministic structures. The CIP service request /
response shape is also fixed: 1-byte service code (high
bit = response indicator) + per-direction body. No crypto
at the parse layer; CIP Security is a separate decoder.

What this package covers

  • **EtherNet/IP encapsulation header** (ODVA CIP Vol 2 §2.3, 24 bytes, little-endian):

  • bytes 0-1: **Command** (uint16 LE).

  • bytes 2-3: Length (uint16 LE; bytes of data following this 24-byte header).

  • bytes 4-7: Session Handle (uint32 LE; allocated by server on RegisterSession; 0 on commands that don't require a session).

  • bytes 8-11: Status (uint32 LE; per-Command decode).

  • bytes 12-19: Sender Context (8 bytes; opaque correlation cookie the originator can use to pair requests and responses).

  • bytes 20-23: Options (uint32 LE; reserved = 0).

  • **9-entry Command name table** (ODVA CIP Vol 2 §2.3.2): 0x0000 `NOP` / 0x0004 `ListServices` / 0x0063 `ListIdentity` / 0x0064 `ListInterfaces` / 0x0065 `RegisterSession` / 0x0066 `UnRegisterSession` / 0x006F `SendRRData` (CIP request/reply over TCP) / 0x0070 `SendUnitData` (CIP class 1 connected over UDP) / 0x0072 `IndicateStatus` / 0x0073 `Cancel`.

  • **7-entry Status name table**: 0x0000 `Success` / 0x0001 `Invalid_or_Unsupported_Command` / 0x0002 `Insufficient_Memory` / 0x0003 `Incorrect_Data` / 0x0064 `Invalid_Session_Handle` / 0x0065 `Invalid_Length` / 0x0069 `Unsupported_Protocol_Version`.

  • **Common Packet Format walker** for `SendRRData` (0x006F) and `SendUnitData` (0x0070): after the encapsulation header these commands carry a 6-byte Interface Handle + Timeout preamble, then `Item Count` (uint16 LE) followed by `Item Count` items. Each item is laid out as `Type ID` (uint16 LE) + `Length` (uint16 LE) + `Length` bytes of data.

  • **8-entry Common Packet Format item type name table**: 0x0000 `Null` / 0x000C `ListIdentity_item` / 0x00A1 `Connected_Address` (carries 4-byte Connection ID) / 0x00B1 `Connected_Data` (CIP message under a connection) / 0x00B2 `Unconnected_Data` (CIP message without a connection — the common shape for SendRRData) / 0x0100 `ListServices_response` / 0x8000 `Sockaddr_O2T` (target- to-originator address) / 0x8001 `Sockaddr_T2O` (originator-to-target address).

  • **CIP message decoder** for `Unconnected_Data` (0x00B2) items (ODVA CIP Vol 1 §2-4):

  • byte 0: Service Code (the high bit 0x80 indicates a response; the low 7 bits hold the original service code).

  • For requests: byte 1 = Request Path Size in 16-bit words; bytes 2.. = EPATH (segments); remainder = service-specific request data.

  • For responses: byte 1 = Reserved (= 0); byte 2 = General Status; byte 3 = Additional Status Size in 16-bit words; bytes 4.. = Additional Status; remainder = service-specific response data.

  • **30+ entry CIP Service Code name table** (selected high-runners from ODVA CIP Vol 1 §Appendix A): 0x01 `Get_Attributes_All` / 0x02 `Set_Attributes_All` / 0x03 `Get_Attribute_List` / 0x04 `Set_Attribute_List` / 0x05 `Reset` / 0x06 `Start` / 0x07 `Stop` / 0x08 `Create` / 0x09 `Delete` / 0x0A `Multiple_Service_Packet` / 0x0D `Apply_Attributes` / 0x0E `Get_Attribute_Single` / 0x10 `Set_Attribute_Single` / 0x11 `Find_Next_Object_Instance` / 0x4B `Execute_PCCC` (legacy DH+/SLC) / 0x4C `Read_Tag` (Logix tag-based addressing) / 0x4D `Write_Tag` / 0x4E `Read_Modify_Write_Tag` / 0x52 `Read_Tag_Fragmented` / 0x53 `Write_Tag_Fragmented` / 0x54 `Forward_Open` / 0x5B `Forward_Close` / 0x5F `Unconnected_Send`.

  • **20+ entry CIP General Status name table** (ODVA CIP Vol 1 §Appendix B): 0x00 `Success` / 0x01 `Connection_Failure` / 0x02 `Resource_Unavailable` / 0x03 `Invalid_Parameter_Value` / 0x04 `Path_Segment_Error` / 0x05 `Path_Destination_Unknown` / 0x06 `Partial_Transfer` / 0x07 `Connection_Lost` / 0x08 `Service_Not_Supported` / 0x09 `Invalid_Attribute_Value` / 0x0A `Attribute_List_Error` / 0x0B `Already_In_Requested_Mode` / 0x0C `Object_State_Conflict` / 0x0D `Object_Already_Exists` / 0x0E `Attribute_Not_Settable` / 0x0F `Privilege_Violation` / 0x10 `Device_State_Conflict` / 0x11 `Reply_Data_Too_Large` / 0x13 `Not_Enough_Data` / 0x14 `Attribute_Not_Supported` / 0x15 `Too_Much_Data` / 0x16 `Object_Does_Not_Exist`.

What this package does NOT cover (deliberately out of scope)

  • **Network framing** — feed EtherNet/IP bytes after the TCP-segment or UDP-datagram header strip (default TCP port 44818 explicit, UDP 2222 implicit / class 1).
  • **EPATH segment walker** — the Request Path bytes inside CIP requests carry segments (Logical, Symbolic, Network, ANSI Extended Symbolic) per ODVA CIP Vol 1 §C-1; the decoder surfaces the EPATH bytes via `cip_path_hex` for future per-segment walkers (Class/Instance/Attribute resolver, ANSI Extended Symbolic tag-name extraction).
  • **Per-service request/response decoder** — Read_Tag / Write_Tag value-type encoding (BOOL/SINT/INT/DINT/REAL/ STRING/UDT), Forward_Open connection parameters (Connection_Serial_Number, T_O / O_T RPI, Network Connection Parameters), Multiple_Service_Packet bundle unpacking; surfaced as `cip_body_hex` for downstream per-service walkers.
  • **CIP Security** — ODVA CIP Security is a separate decoder; the encapsulation layer transports it transparently but the body is encrypted and authenticated outside this layer.
  • **Class 1 connection state-machine** — Forward_Open negotiates an O→T and T→O connection that subsequently carries class 1 I/O scans under the SendUnitData command; reasoning about the connection state (RPI compliance, COS triggers, timeout multipliers) is higher-level.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CIPMessage

type CIPMessage struct {
	ServiceCode        int    `json:"service_code"`
	ServiceName        string `json:"service_name"`
	IsResponse         bool   `json:"is_response"`
	PathSizeWords      int    `json:"path_size_words,omitempty"`
	PathHex            string `json:"path_hex,omitempty"`
	GeneralStatus      int    `json:"general_status,omitempty"`
	GeneralStatusName  string `json:"general_status_name,omitempty"`
	AddStatusSizeWords int    `json:"additional_status_size_words,omitempty"`
	AddStatusHex       string `json:"additional_status_hex,omitempty"`
	BodyHex            string `json:"body_hex,omitempty"`
}

CIPMessage is the per-Unconnected_Data CIP request / response.

type Item

type Item struct {
	TypeID   int    `json:"type_id"`
	TypeName string `json:"type_name"`
	Length   int    `json:"length"`
	DataHex  string `json:"data_hex,omitempty"`

	// CIP message decode (Unconnected_Data 0x00B2 only).
	CIP *CIPMessage `json:"cip,omitempty"`
}

Item is one entry in the Common Packet Format item list.

type Result

type Result struct {
	TotalBytes int `json:"total_bytes"`

	// Encapsulation header (24 bytes LE)
	Command          int    `json:"command"`
	CommandName      string `json:"command_name"`
	Length           int    `json:"length"`
	SessionHandle    uint32 `json:"session_handle"`
	Status           uint32 `json:"status"`
	StatusName       string `json:"status_name"`
	SenderContextHex string `json:"sender_context_hex"`
	Options          uint32 `json:"options"`

	// SendRRData / SendUnitData common preamble (6 bytes)
	InterfaceHandle uint32 `json:"interface_handle,omitempty"`
	Timeout         int    `json:"timeout,omitempty"`

	// Common Packet Format
	ItemCount int    `json:"item_count,omitempty"`
	Items     []Item `json:"items,omitempty"`

	// Raw bytes past the parsed structure (for downstream
	// per-Command / per-Service walkers).
	PayloadHex string `json:"payload_hex,omitempty"`
}

Result is the structured decode of an EtherNet/IP encapsulation packet plus any per-Command body interpretation.

func Decode

func Decode(hexStr string) (*Result, error)

Decode parses an EtherNet/IP encapsulation packet (starting at the Command bytes) from a hex string. Separators (':' '-' '_' whitespace) are tolerated; a leading '0x' prefix is stripped.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL