这里截取ipmitool Windows 1.8.18的部分代码做说明。
struct ipmi_rs {
uint8_t ccode;
uint8_t data[IPMI_BUF_SIZE];
int data_len;
struct {
uint8_t netfn;
uint8_t cmd;
uint8_t seq;
uint8_t lun;
} msg;
struct {
uint8_t authtype;
uint32_t seq;
uint32_t id;
uint8_t bEncrypted; /* IPMI v2 only */
uint8_t bAuthenticated; /* IPMI v2 only */
uint8_t payloadtype; /* IPMI v2 only */
uint16_t msglen;
} session;
union {
struct {
uint8_t rq_addr;
uint8_t netfn;
uint8_t rq_lun;
uint8_t rs_addr;
uint8_t rq_seq;
uint8_t rs_lun;
uint8_t cmd;
} ipmi_response;
struct {
uint8_t message_tag;
uint8_t rakp_return_code;
uint8_t max_priv_level;
uint32_t console_id;
uint32_t bmc_id;
uint8_t auth_alg;
uint8_t integrity_alg;
uint8_t crypt_alg;
} open_session_response;
struct {
uint8_t message_tag;
uint8_t rakp_return_code;
uint32_t console_id;
uint8_t bmc_rand[16]; /* Random number generated by the BMC */
uint8_t bmc_guid[16];
uint8_t key_exchange_auth_code[20];
} rakp2_message;
struct {
uint8_t message_tag;
uint8_t rakp_return_code;
uint32_t console_id;
uint8_t integrity_check_value[20];
} rakp4_message;
struct {
uint8_t packet_sequence_number;
uint8_t acked_packet_number;
uint8_t accepted_character_count;
uint8_t is_nack; /* bool */
uint8_t transfer_unavailable; /* bool */
uint8_t sol_inactive; /* bool */
uint8_t transmit_overrun; /* bool */
uint8_t break_detected; /* bool */
} sol_packet;
} payload;
};
这段代码不算太复杂,结构体成员里面没有涉及到指针变量,只是有关于结构体的嵌套,结构体含成员union等,本文主要讲解如何层级访问和调用结构体里面的变量。先创建上面结构体实例。
struct ipmi_rs * rsp; #创建ipmi_rs结构体指针
rsp = ipmi_lan_recv_packet(intf); #ipmi_lan_recv_packet()函数返回的是结构体首地址,并将该结构体的首地址赋给rsp指针
这里ipmi_lan_recv_packet()函数不做说明,它是ipmitool里面定义的函数,该函数返回的是ipmi_rs类型的结构体的地址,而指针就是指向地址的,所以可以将返回值赋给指针变量rsp。
可以通俗的打个比喻,这个结构体就像零食大礼包,大礼包名字叫旺旺,等同于结构体的ipmi_rs,里面有不同类型的零食,类似于结构体里定义的不同类型的数据(int/char/bool等),然后被你买了回来,这时你告诉商家你的地址,就有一包这样的零食大礼包根据这个地址被寄到了你的手上,这个地址就是rsp,rsp指向的人就是你,当然可能还有其他吃货也买了这款零食大礼包,地址可以是rsp1、rsp2等等,一个地址相当于一个结构体实例。然后你拿到大礼包,打开一看,发现有的可以直接吃,有的还有嵌套的小包装,就像结构体里的嵌套。接下来就是你如何吃(调用)里面的东西了。
接下来我们要调用这个结构体里面不同层级的变量,这些变量在结构体里面的地位可分为三种情况:
1、可以直接吃的小零食,ccode、data[IPMI_BUF_SIZE]、 data_len这三个变量在结构体里地位一致,属于最外层的成员,可以如下访问并调用:
rsp->ccode
rsp->data[IPMI_BUF_SIZE]
rsp->data_len
2、拆开大礼包还有小包装的,msg、session、payload小包装里面的变量地位是一样的,可以这样访问(各取里面一个变量为例):
rsp->msg.netfn
rsp->session.authtype
3、这时发现payload小包装里面还有5个小袋子(ipmi_response、open_session_response、rakp2_message、rakp4_message、sol_packet),那就要再往下拆:
rsp->payload.ipmi_response.rq_addr
终于所有的零食都可以吃到了。