IPMI 实用小代码,捕获对应BMC raw命令来实现对上层系统控制

1 背景

我们知道在 IPMI 的环境中,BMC 纳管了很多是管理层面的工作,比如上下电就是其中一个。 这里,我们可以通过捕获对应BMC raw命令来实现对上层系统控制。比如这个例子就实现了对系统关机操作。

2 具体代码实现如下

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
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <linux/ipmi.h>
#include <stdio.h>
#define NETFN 0x2c /* hardware specific */
#define CMD 0x0c /* hardware specific */

int main(void)
{
int fd,ret;
struct ipmi_cmdspec cmdspec;
unsigned char data[IPMI_MAX_MSG_LENGTH];
struct ipmi_addr addr;
struct ipmi_recv recv;
fd = open("/dev/ipmi0", O_RDWR);
if (fd == -1)
{
return 1;
}

cmdspec.netfn = NETFN;
cmdspec.cmd = CMD;

ret = ioctl(fd, IPMICTL_REGISTER_FOR_CMD, &cmdspec); /* checking the signal */
if (ret == -1)
{
perror("ioctl register_for_cmd");
return 1;
}

while (1) /* keep monitoring*/
{
sleep(1);
recv.msg.data = data;
recv.msg.data_len = sizeof(data);
recv.addr = (unsigned char *) &addr;
recv.addr_len = sizeof(addr);
ret = ioctl(fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv);
if ((recv.msg.netfn == NETFN) && (recv.msg.cmd == CMD))
{
system("init 0"); /* shut it down*/
}
}

ret = ioctl(fd, IPMICTL_UNREGISTER_FOR_CMD, &cmdspec);
if (ret == -1)
{
perror("ioctl unregister_for_cmd");
return 1;
}
close(fd);
return 0;
}