File: cmd_get_session_info.go

package info (click to toggle)
golang-github-bougou-go-ipmi 0.7.8-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,880 kB
  • sloc: makefile: 38
file content (152 lines) | stat: -rw-r--r-- 4,830 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package ipmi

import (
	"context"
	"fmt"
	"net"
)

// 22.20 Get Session Info Command
type GetSessionInfoRequest struct {
	// Session index
	//   00h = Return info for active session associated with session this command was received over.
	//   N = get info for Nth active session
	//   FEh = Look up session info according to Session Handle passed in this request.
	//   FFh = Look up session info according to Session ID passed in this request.
	SessionIndex uint8

	SessionHandle uint8

	SessionID uint32
}

type GetSessionInfoResponse struct {
	SessionHandle          uint8 // Session Handle presently assigned to active session.
	PossibleActiveSessions uint8 // This value reflects the number of possible entries (slots) in the sessions table.
	CurrentActiveSessions  uint8 // Number of currently active sessions on all channels on this controller

	UserID                  uint8
	OperatingPrivilegeLevel PrivilegeLevel

	// [7:4] - Session protocol auxiliary data
	// For Channel Type = 802.3 LAN:
	// 0h = IPMI v1.5
	// 1h = IPMI v2.0/RMCP+
	AuxiliaryData uint8 // 4bits
	ChannelNumber uint8 // 4bits

	// if Channel Type = 802.3 LAN:
	RemoteConsoleIPAddr  net.IP           // IP Address of remote console (MS-byte first).
	RemoteConsoleMacAddr net.HardwareAddr // 6 bytes, MAC Address (MS-byte first)
	RemoteConsolePort    uint16           // Port Number of remote console (LS-byte first)

	// if Channel Type = asynch. serial/modem
	SessionChannelActivityType uint8
	DestinationSelector        uint8
	RemoteConsoleIPAddr_PPP    uint32 // If PPP connection: IP address of remote console. (MS-byte first) 00h, 00h, 00h, 00h otherwise.

	// if Channel Type = asynch. serial/modem and connection is PPP:
	RemoteConsolePort_PPP uint16
}

func (req *GetSessionInfoRequest) Command() Command {
	return CommandGetSessionInfo
}

func (req *GetSessionInfoRequest) Pack() []byte {
	out := make([]byte, 5)
	packUint8(req.SessionIndex, out, 0)
	if req.SessionIndex == 0xfe {
		packUint8(req.SessionHandle, out, 1)
		return out[0:2]
	}
	if req.SessionIndex == 0xff {
		packUint32L(req.SessionID, out, 1)
		return out[0:5]
	}
	return out[0:1]
}

func (res *GetSessionInfoResponse) Unpack(msg []byte) error {
	// at least 3 bytes
	if len(msg) < 3 {
		return ErrUnpackedDataTooShortWith(len(msg), 3)
	}
	res.SessionHandle, _, _ = unpackUint8(msg, 0)
	res.PossibleActiveSessions, _, _ = unpackUint8(msg, 1)
	res.CurrentActiveSessions, _, _ = unpackUint8(msg, 2)

	if len(msg) == 3 {
		return nil
	}

	// if len(msg) > 3, then at least 6 bytes
	if len(msg) < 6 {
		return ErrUnpackedDataTooShortWith(len(msg), 6)
	}
	res.UserID, _, _ = unpackUint8(msg, 3)
	b5, _, _ := unpackUint8(msg, 4)
	res.OperatingPrivilegeLevel = PrivilegeLevel(b5)
	b6, _, _ := unpackUint8(msg, 5)
	res.AuxiliaryData = b6 >> 4
	res.ChannelNumber = b6 & 0x0f

	//  Channel Type = 802.3 LAN:
	if len(msg) >= 18 {
		ipBytes, _, _ := unpackBytes(msg, 6, 4)
		res.RemoteConsoleIPAddr = net.IP(ipBytes)
		macBytes, _, _ := unpackBytes(msg, 10, 6)
		res.RemoteConsoleMacAddr = net.HardwareAddr(macBytes)
		res.RemoteConsolePort, _, _ = unpackUint16L(msg, 16)
	}

	if len(msg) >= 14 {
		res.SessionChannelActivityType, _, _ = unpackUint8(msg, 6)
		res.DestinationSelector, _, _ = unpackUint8(msg, 7)
		res.RemoteConsoleIPAddr_PPP, _, _ = unpackUint32(msg, 8)
		res.RemoteConsolePort_PPP, _, _ = unpackUint16L(msg, 12)
	}

	return nil
}

func (res *GetSessionInfoResponse) CompletionCodes() map[uint8]string {
	return map[uint8]string{}
}

func (res *GetSessionInfoResponse) Format() string {
	var sessionType string
	switch res.AuxiliaryData {
	case 0:
		sessionType = "IPMIv1.5"
	case 1:
		sessionType = "IPMIv2/RMCP+"
	}

	return "" +
		fmt.Sprintf("session handle   : %d\n", res.SessionHandle) +
		fmt.Sprintf("slot count       : %d\n", res.PossibleActiveSessions) +
		fmt.Sprintf("active sessions  : %d\n", res.CurrentActiveSessions) +
		fmt.Sprintf("user id          : %d\n", res.UserID) +
		fmt.Sprintf("privilege level  : %s\n", res.OperatingPrivilegeLevel) +
		fmt.Sprintf("session type     : %s\n", sessionType) +
		fmt.Sprintf("channel number   : %#02x\n", res.ChannelNumber) +
		fmt.Sprintf("console ip       : %s\n", res.RemoteConsoleIPAddr) +
		fmt.Sprintf("console mac      : %s\n", res.RemoteConsoleMacAddr) +
		fmt.Sprintf("console port     : %d\n", res.RemoteConsolePort)
}

func (c *Client) GetSessionInfo(ctx context.Context, request *GetSessionInfoRequest) (response *GetSessionInfoResponse, err error) {
	response = &GetSessionInfoResponse{}
	err = c.Exchange(ctx, request, response)
	return
}

func (c *Client) GetCurrentSessionInfo(ctx context.Context) (response *GetSessionInfoResponse, err error) {
	request := &GetSessionInfoRequest{
		SessionIndex: 0x00,
	}
	response = &GetSessionInfoResponse{}
	err = c.Exchange(ctx, request, response)
	return
}