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