1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21
22 #ifdef HAVE_OPENIPMI
23
24 #include "log.h"
25 #include "zbxserialize.h"
26 #include "dbcache.h"
27
28 #include "zbxipcservice.h"
29 #include "ipmi_protocol.h"
30 #include "checks_ipmi.h"
31 #include "zbxserver.h"
32 #include "ipmi.h"
33
34 /******************************************************************************
35 * *
36 * Function: zbx_ipmi_port_expand_macros *
37 * *
38 * Purpose: expands user macros in IPMI port value and converts the result to *
39 * to unsigned short value *
40 * *
41 * Parameters: hostid - [IN] the host identifier *
42 * port_orig - [IN] the original port value *
43 * port - [OUT] the resulting port value *
44 * error - [OUT] the error message *
45 * *
46 * Return value: SUCCEED - the value was converted successfully *
47 * FAIL - otherwise *
48 * *
49 ******************************************************************************/
zbx_ipmi_port_expand_macros(zbx_uint64_t hostid,const char * port_orig,unsigned short * port,char ** error)50 int zbx_ipmi_port_expand_macros(zbx_uint64_t hostid, const char *port_orig, unsigned short *port, char **error)
51 {
52 char *tmp;
53 int ret = SUCCEED;
54
55 tmp = zbx_strdup(NULL, port_orig);
56 substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, NULL, NULL,
57 &tmp, MACRO_TYPE_COMMON, NULL, 0);
58
59 if (FAIL == is_ushort(tmp, port) || 0 == *port)
60 {
61 *error = zbx_dsprintf(*error, "Invalid port value \"%s\"", port_orig);
62 ret = FAIL;
63 }
64
65 zbx_free(tmp);
66
67 return ret;
68 }
69
70 /******************************************************************************
71 * *
72 * Function: zbx_ipmi_execute_command *
73 * *
74 * Purpose: executes IPMI command *
75 * *
76 * Parameters: host - [IN] the target host *
77 * command - [IN] the command to execute *
78 * error - [OUT] the error message buffer *
79 * max_error_len - [IN] the size of error message buffer *
80 * *
81 * Return value: SUCCEED - the command was executed successfully *
82 * FAIL - otherwise *
83 * *
84 ******************************************************************************/
zbx_ipmi_execute_command(const DC_HOST * host,const char * command,char * error,size_t max_error_len)85 int zbx_ipmi_execute_command(const DC_HOST *host, const char *command, char *error, size_t max_error_len)
86 {
87 const char *__function_name = "zbx_ipmi_execute_command";
88 zbx_ipc_socket_t ipmi_socket;
89 zbx_ipc_message_t message;
90 char *errmsg = NULL, sensor[ITEM_IPMI_SENSOR_LEN_MAX], *value = NULL;
91 zbx_uint32_t data_len;
92 unsigned char *data = NULL;
93 int ret = FAIL, op;
94 DC_INTERFACE interface;
95 zbx_timespec_t ts;
96
97 zabbix_log(LOG_LEVEL_DEBUG, "In %s() host:\"%s\" command:%s", __function_name, host->host, command);
98
99 if (SUCCEED != zbx_parse_ipmi_command(command, sensor, &op, error, max_error_len))
100 goto out;
101
102 if (FAIL == zbx_ipc_socket_open(&ipmi_socket, ZBX_IPC_SERVICE_IPMI, SEC_PER_MIN, &errmsg))
103 {
104 zabbix_log(LOG_LEVEL_CRIT, "cannot connect to IPMI service: %s", errmsg);
105 exit(EXIT_FAILURE);
106 }
107
108 zbx_ipc_message_init(&message);
109
110 if (FAIL == DCconfig_get_interface_by_type(&interface, host->hostid, INTERFACE_TYPE_IPMI))
111 {
112 zbx_strlcpy(error, "cannot find host IPMI interface", max_error_len);
113 goto cleanup;
114 }
115
116 if (FAIL == zbx_ipmi_port_expand_macros(host->hostid, interface.port_orig, &interface.port, &errmsg))
117 {
118 zbx_strlcpy(error, errmsg, max_error_len);
119 zbx_free(errmsg);
120 goto cleanup;
121 }
122
123 data_len = zbx_ipmi_serialize_request(&data, host->hostid, interface.addr, interface.port, host->ipmi_authtype,
124 host->ipmi_privilege, host->ipmi_username, host->ipmi_password, sensor, op);
125
126 if (FAIL == zbx_ipc_socket_write(&ipmi_socket, ZBX_IPC_IPMI_SCRIPT_REQUEST, data, data_len))
127 {
128 zbx_strlcpy(error, "cannot send script request message to IPMI service", max_error_len);
129 goto cleanup;
130 }
131
132 zbx_ipc_message_init(&message);
133
134 if (FAIL == zbx_ipc_socket_read(&ipmi_socket, &message))
135 {
136 zbx_strlcpy(error, "cannot read script request response from IPMI service", max_error_len);
137 goto cleanup;
138 }
139
140 if (ZBX_IPC_IPMI_SCRIPT_RESULT != message.code)
141 {
142 zbx_snprintf(error, max_error_len, "invalid response code:%u received form IPMI service", message.code);
143 goto cleanup;
144 }
145
146 zbx_ipmi_deserialize_result(message.data, &ts, &ret, &value);
147
148 if (SUCCEED != ret)
149 zbx_strlcpy(error, value, max_error_len);
150 cleanup:
151 zbx_free(value);
152 zbx_free(data);
153 zbx_ipc_message_clean(&message);
154 zbx_ipc_socket_close(&ipmi_socket);
155
156 out:
157 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
158
159 return ret;
160 }
161
162 #endif
163