open

package
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: Aug 31, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package open provides in-band (System Interface) access to a local BMC.

  • Linux: OpenIPMI character device (/dev/ipmiN) via ioctl
  • Windows: Microsoft_IPMI WMI provider (ipmidrv.sys) via COM or PowerShell

Callers build a transport-neutral Request and send it through a Backend. Platform backends map Request onto their native plumbing and return the raw response as "completion code + payload".

Index

Constants

View Source
const (
	BackendAuto       = "auto"
	BackendCOM        = "wmi-com"
	BackendPowerShell = "wmi-ps"
)

Backend names accepted by ResolveBackend (and goipmi's --open-backend). They select which Microsoft_IPMI WMI transport Windows uses; Linux always uses DeviceBackend and ignores the preference.

View Source
const (
	IOC_NRBITS   = 8
	IOC_TYPEBITS = 8
	IOC_SIZEBITS = 14
	IOC_DIRBITS  = 2

	IOC_NONE  = 0x0
	IOC_READ  = 0x1
	IOC_WRITE = 0x2

	IOC_NRMASK   = ((1 << IOC_NRBITS) - 1)
	IOC_TYPEMASK = ((1 << IOC_TYPEBITS) - 1)
	IOC_SIZEMASK = ((1 << IOC_SIZEBITS) - 1)
	IOC_DIRMASK  = ((1 << IOC_DIRBITS) - 1)

	IOC_NRSHIFT   = 0
	IOC_TYPESHIFT = (IOC_NRSHIFT + IOC_NRBITS)
	IOC_SIZESHIFT = (IOC_TYPESHIFT + IOC_TYPEBITS)
	IOC_DIRSHIFT  = (IOC_SIZESHIFT + IOC_SIZEBITS)

	IOC_IN        = (IOC_WRITE << IOC_DIRSHIFT)
	IOC_OUT       = (IOC_READ << IOC_DIRSHIFT)
	IOC_INOUT     = ((IOC_WRITE | IOC_READ) << IOC_DIRSHIFT)
	IOCSIZE_MASK  = (IOC_SIZEMASK << IOC_SIZESHIFT)
	IOCSIZE_SHIFT = (IOC_SIZESHIFT)
)

cSpell:disable

View Source
const (
	IPMI_BUF_SIZE      = 1024
	IPMI_MAX_ADDR_SIZE = 32

	// Channel for talking directly with the BMC (system interface only).
	IPMI_BMC_CHANNEL = 0xf

	IPMI_NUM_CHANNELS = 0x10

	IPMI_RESPONSE_RECV_TYPE     = 1
	IPMI_ASYNC_EVENT_RECV_TYPE  = 2
	IPMI_CMD_RECV_TYPE          = 3
	IPMI_RESPONSE_RESPONSE_TYPE = 4
	IPMI_OEM_RECV_TYPE          = 5

	IPMI_MAINTENANCE_MODE_AUTO = 0
	IPMI_MAINTENANCE_MODE_OFF  = 1
	IPMI_MAINTENANCE_MODE_ON   = 2

	IPMI_SYSTEM_INTERFACE_ADDR_TYPE = 0x0c
	IPMI_IPMB_ADDR_TYPE             = 0x01
	IPMI_IPMB_BROADCAST_ADDR_TYPE   = 0x41 // broadcast get device id (IPMI 1.5 §17.9)
	IPMI_IPMB_DIRECT_ADDR_TYPE      = 0x81
	IPMI_LAN_ADDR_TYPE              = 0x04
)
View Source
const BMCAddr uint8 = 0x20

BMCAddr is the conventional BMC slave address (0x20).

View Source
const DefaultTimeout time.Duration = time.Second * 10

DefaultTimeout is used when Backend.Send is called with timeout == 0.

View Source
const IPMI_IOC_MAGIC uintptr = 'i'

Variables

View Source
var (
	IPMICTL_SEND_COMMAND         = IOW(IPMI_IOC_MAGIC, 13, unsafe.Sizeof(IPMI_REQ{}))
	IPMICTL_SEND_COMMAND_SETTIME = IOW(IPMI_IOC_MAGIC, 21, unsafe.Sizeof(IPMI_REQ_SETTIME{}))

	IPMICTL_RECEIVE_MSG       = IOWR(IPMI_IOC_MAGIC, 12, unsafe.Sizeof(IPMI_RECV{}))
	IPMICTL_RECEIVE_MSG_TRUNC = IOWR(IPMI_IOC_MAGIC, 11, unsafe.Sizeof(IPMI_RECV{}))

	IPMICTL_REGISTER_FOR_CMD   = IOR(IPMI_IOC_MAGIC, 14, unsafe.Sizeof(IPMI_CMDSPEC{}))
	IPMICTL_UNREGISTER_FOR_CMD = IOR(IPMI_IOC_MAGIC, 15, unsafe.Sizeof(IPMI_CMDSPEC{}))

	IPMICTL_REGISTER_FOR_CMD_CHANS   = IOR(IPMI_IOC_MAGIC, 28, unsafe.Sizeof(IPMI_CMDSPEC_CHANS{}))
	IPMICTL_UNREGISTER_FOR_CMD_CHANS = IOR(IPMI_IOC_MAGIC, 29, unsafe.Sizeof(IPMI_CMDSPEC_CHANS{}))

	IPMICTL_SET_GETS_EVENTS_CMD = IOW(IPMI_IOC_MAGIC, 16, unsafe.Sizeof(uint32(0)))

	IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD = IOR(IPMI_IOC_MAGIC, 24, unsafe.Sizeof(IPMI_CHANNEL_LUN_ADDRESS_SET{}))
	IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD = IOR(IPMI_IOC_MAGIC, 25, unsafe.Sizeof(IPMI_CHANNEL_LUN_ADDRESS_SET{}))
	IPMICTL_SET_MY_CHANNEL_LUN_CMD     = IOR(IPMI_IOC_MAGIC, 26, unsafe.Sizeof(IPMI_CHANNEL_LUN_ADDRESS_SET{}))
	IPMICTL_GET_MY_CHANNEL_LUN_CMD     = IOR(IPMI_IOC_MAGIC, 27, unsafe.Sizeof(IPMI_CHANNEL_LUN_ADDRESS_SET{}))

	/* Legacy interfaces, these only set IPMB 0. */
	IPMICTL_SET_MY_ADDRESS_CMD = IOR(IPMI_IOC_MAGIC, 17, unsafe.Sizeof(uint32(0)))
	IPMICTL_GET_MY_ADDRESS_CMD = IOR(IPMI_IOC_MAGIC, 18, unsafe.Sizeof(uint32(0)))
	IPMICTL_SET_MY_LUN_CMD     = IOR(IPMI_IOC_MAGIC, 19, unsafe.Sizeof(uint32(0)))
	IPMICTL_GET_MY_LUN_CMD     = IOR(IPMI_IOC_MAGIC, 20, unsafe.Sizeof(uint32(0)))

	IPMICTL_SET_TIMING_PARAMS_CMD = IOR(IPMI_IOC_MAGIC, 22, unsafe.Sizeof(IPMI_TIMING_PARAMS{}))
	IPMICTL_GET_TIMING_PARAMS_CMD = IOR(IPMI_IOC_MAGIC, 23, unsafe.Sizeof(IPMI_TIMING_PARAMS{}))

	IPMICTL_GET_MAINTENANCE_MODE_CMD = IOR(IPMI_IOC_MAGIC, 30, unsafe.Sizeof(uint32(0)))
	IPMICTL_SET_MAINTENANCE_MODE_CMD = IOW(IPMI_IOC_MAGIC, 31, unsafe.Sizeof(uint32(0)))
)

Functions

func IO

func IO(typ, nr uintptr) uintptr

func IOC

func IOC(dir, typ, nr, size uintptr) uintptr

func IOCTL

func IOCTL(fd, name, data uintptr) error

IOCTL issues SYS_IOCTL against an openipmi file descriptor.

func IOC_DIR

func IOC_DIR(nr uintptr) uintptr

func IOC_NR

func IOC_NR(nr uintptr) uintptr

func IOC_SIZE

func IOC_SIZE(nr uintptr) uintptr

func IOC_TYPE

func IOC_TYPE(nr uintptr) uintptr

func IOR

func IOR(typ, nr, size uintptr) uintptr

func IOW

func IOW(typ, nr, size uintptr) uintptr

func IOWR

func IOWR(typ, nr, size uintptr) uintptr

func OpenDevice

func OpenDevice(devnum int32) (*os.File, error)

OpenDevice opens the OpenIPMI character device for the given device number. It probes /dev/ipmiN, /dev/ipmi/N and /dev/ipmidev/N in order and returns the first path that opens successfully. When no path can be opened, the returned error lists every tried path with its individual failure reason.

Types

type Backend

type Backend interface {
	Connect(ctx context.Context, devnum int32) error
	Close(ctx context.Context) error
	Send(ctx context.Context, req *Request, timeout time.Duration) ([]byte, error)
}

Backend abstracts an Open Interface transport: a local (in-band) path to the host BMC that tunnels a single system-interface-style IPMI request and returns the raw response.

Implementations:

  • linux: DeviceBackend (OpenIPMI /dev/ipmiN)
  • windows: COMBackend / PowerShellBackend (Microsoft_IPMI WMI)

All implementations return a byte slice whose first byte is the IPMI completion code and remaining bytes are the response payload.

func ResolveBackend

func ResolveBackend(pref string, tryCOM, tryPS func() (Backend, error), onCOMFail func(error)) (Backend, error)

ResolveBackend picks a Backend from the preference string using two factory callbacks (COM and PowerShell). "" and BackendAuto try COM first and fall back to PowerShell on failure; an explicit BackendCOM or BackendPowerShell never falls back.

onCOMFail, if non-nil, is invoked with the COM error immediately before the PowerShell fallback attempt (auto path only).

type DeviceBackend

type DeviceBackend struct {
	// contains filtered or unexported fields
}

DeviceBackend implements Backend on top of the Linux OpenIPMI kernel driver (/dev/ipmiN).

func (*DeviceBackend) Close

func (b *DeviceBackend) Close(ctx context.Context) error

Close closes the device file. Closing a backend that was never connected is a no-op.

func (*DeviceBackend) Connect

func (b *DeviceBackend) Connect(ctx context.Context, devnum int32) error

Connect opens the device and enables the event receiver. The devnum selects which /dev/ipmiN device family member to open.

func (*DeviceBackend) Send

func (b *DeviceBackend) Send(ctx context.Context, req *Request, timeout time.Duration) ([]byte, error)

Send maps the transport-neutral Request onto a Linux openipmi ioctl round trip and returns the response in the canonical "cc + payload" form.

type IPMI_ADDR

type IPMI_ADDR struct {
	AddrType int32
	Channel  uint16
	Data     [IPMI_MAX_ADDR_SIZE]byte
}

IPMI_ADDR is the generic openipmi address buffer.

type IPMI_CHANNEL_LUN_ADDRESS_SET

type IPMI_CHANNEL_LUN_ADDRESS_SET struct {
	Channel uint16
	Value   uint8
}

type IPMI_CMDSPEC

type IPMI_CMDSPEC struct {
	NetFn uint8
	Cmd   uint8
}

IPMI_CMDSPEC registers for commands from other entities on this interface.

type IPMI_CMDSPEC_CHANS

type IPMI_CMDSPEC_CHANS struct {
	NetFn int
	Cmd   int
	Chans int
}

type IPMI_IPMB_ADDR

type IPMI_IPMB_ADDR struct {
	AddrType  int32
	Channel   uint16
	SlaveAddr uint8
	LUN       uint8
}

IPMI_IPMB_ADDR is used for IPMB / broadcast-IPMB destinations.

type IPMI_IPMB_DIRECT_ADDR

type IPMI_IPMB_DIRECT_ADDR struct {
	AddrType  int32
	Channel   uint16
	SlaveAddr uint8
	RsLUN     uint8
	RqLUN     uint8
}

IPMI_IPMB_DIRECT_ADDR is for messages received directly from an IPMB.

type IPMI_LAN_ADDR

type IPMI_LAN_ADDR struct {
	AddrType      int32
	Channel       uint16
	Privilege     uint8
	SessionHandle uint8
	RemoteSWID    uint8
	LocalSWID     uint8
	LUN           uint8
}

IPMI_LAN_ADDR is an address to/from a LAN interface bridged by the BMC.

type IPMI_MSG

type IPMI_MSG struct {
	NetFn   uint8
	Cmd     uint8
	DataLen uint16
	Data    *byte
}

IPMI_MSG is the openipmi message body (no addressing). Response data's first byte is the completion code. Size is 16 on amd64.

func (*IPMI_MSG) MsgData

func (msg *IPMI_MSG) MsgData() ([]byte, error)

type IPMI_RECV

type IPMI_RECV struct {
	RecvType int
	Addr     unsafe.Pointer
	AddrLen  int
	MsgID    int64
	Msg      IPMI_MSG
}

IPMI_RECV mirrors struct ipmi_recv. Size is 48 on amd64.

type IPMI_REQ

type IPMI_REQ struct {
	Addr    unsafe.Pointer
	AddrLen int
	MsgID   int64
	Msg     IPMI_MSG
}

IPMI_REQ mirrors struct ipmi_req. Size is 40 on amd64; ioctl numbers encode it. DeviceBackend only — not the Backend.Send public protocol (see Request).

type IPMI_REQ_SETTIME

type IPMI_REQ_SETTIME struct {
	Req             IPMI_REQ
	Retries         int32
	RetryTimeMillis uint32
}

IPMI_REQ_SETTIME mirrors struct ipmi_req_settime.

type IPMI_SYSTEM_INTERFACE_ADDR

type IPMI_SYSTEM_INTERFACE_ADDR struct {
	AddrType int32
	Channel  uint16
	LUN      uint8
}

IPMI_SYSTEM_INTERFACE_ADDR is used for direct BMC system-interface messages.

type IPMI_TIMING_PARAMS

type IPMI_TIMING_PARAMS struct {
	Retries         int
	RetryTimeMillis uint
}

type Request

type Request struct {
	NetFn uint8
	Cmd   uint8
	// LUN is the responder LUN (low 2 bits of NetFn/LUN on the system
	// interface; ipmi_addr.lun / WMI Lun on IPMB paths).
	LUN uint8
	// Data is the command request body (may be nil or empty).
	Data []byte

	// TargetAddr is the destination slave address. 0 means the local
	// system interface (ipmitool open.c). Non-zero and different from
	// MyAddr routes via IPMB / WMI ResponderAddress.
	TargetAddr uint8
	// TargetChannel is the IPMB channel (low 4 bits). Ignored for the
	// local system interface.
	TargetChannel uint8

	// MyAddr is this open interface's own IPMB address. 0 is treated as
	// BMCAddr. Used by the Linux backend for system-interface vs IPMB
	// routing; ignored by Windows WMI backends.
	MyAddr uint8
}

Request is the transport-neutral Open Interface request handed to Backend.Send. It carries the system-interface command body (NetFn/LUN/Cmd/Data — IPMI v2.0 §9.2 / §10.14 / §11.1) plus a logical destination. Individual backends map this onto their native plumbing:

  • Linux DeviceBackend → openipmi ioctl (struct ipmi_req + ipmi_addr)
  • Windows COM/PS → Microsoft_IPMI::RequestResponse parameters

This type deliberately does NOT mirror the Linux UAPI layout; ioctl structs live in uapi_linux.go.

func (*Request) EffectiveMyAddr

func (r *Request) EffectiveMyAddr() uint8

EffectiveMyAddr returns MyAddr, substituting BMCAddr when zero.

func (*Request) EffectiveTarget

func (r *Request) EffectiveTarget() uint8

EffectiveTarget returns TargetAddr, substituting BMCAddr when zero. Used by Windows WMI (ResponderAddress); Linux addressing treats a raw TargetAddr of 0 as "system interface" instead.

func (*Request) UsesIPMB

func (r *Request) UsesIPMB() bool

UsesIPMB reports whether this request should be routed over IPMB rather than the local system interface (ipmitool open.c: target != 0 && target != my).

Jump to

Keyboard shortcuts

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