1 /*
2  * Copyright (C) 2003-2015 FreeIPMI Core Team
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18 
19 #ifndef IPMI_API_H
20 #define IPMI_API_H
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 #include <stdint.h>
27 #include <freeipmi/api/ipmi-api.h>
28 #include <freeipmi/fiid/fiid.h>
29 
30 /* ERROR CODE NOTES
31  *
32  * IPMI_ERR_BMC_BUSY vs IPMI_ERR_DRIVER_BUSY
33  *
34  * BMC_BUSY indicates the BMC cannot handle more requests, it is an
35  * error typically from a completion code returned from the BMC.  The
36  * DRIVER_BUSY error indicates a driver is too busy to handle
37  * additional requests, the error does not come from the BMC.
38  *
39  * IPMI_ERR_MESSAGE_TIMEOUT
40  *
41  * message timeout is typical of bridging commands.  The
42  * session/connection has not timed out and is fine, but a
43  * bridging command could not get its bridged response back in a
44  * reasonable timeframe.
45  */
46 
47 /* IPMI COMPLETION CODE / RMCPPLUS CODE MAPPING
48  *
49  * For most users, the high level error codes listed below will
50  * suffice.  However, for those who want/need to see deeper IPMI
51  * completion code or RMCPPlus errors, the following are mappings of
52  * IPMI completion codes and RMCPPlus codes to their respective error
53  * codes.
54  *
55  * Not that other factors outside of completion codes/RMCPPlus codes
56  * could also lead to these IPMI errors.  For example, depending on
57  * motherboard support of username types, a IPMI_ERR_USERNAME_INVALID
58  * could be returned even though no IPMI error occurred.  In addition,
59  * completion codes/RMCPPlus codes could map to different error codes,
60  * depending on when the error occurred (such as during session
61  * authentication vs. after authentication).
62  *
63  * (*) - Completion code is specific to an IPMI command
64  *
65  * IPMI_ERR_USERNAME_INVALID
66  * - IPMI_COMP_CODE_GET_SESSION_CHALLENGE_INVALID_USERNAME (*)
67  * - IPMI_COMP_CODE_GET_SESSION_CHALLENGE_NULL_USERNAME_NOT_ENABLED (*)
68  *
69  * IPMI_ERR_PASSWORD_INVALID
70  * - RMCPPLUS_STATUS_INVALID_INTEGRITY_CHECK_VALUE
71  *
72  * IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT
73  * - IPMI_COMP_CODE_INSUFFICIENT_PRIVILEGE_LEVEL
74  *
75  * IPMI_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED
76  * - IPMI_COMP_CODE_ACTIVATE_SESSION_EXCEEDS_PRIVILEGE_LEVEL (*)
77  * - IPMI_COMP_CODE_INSUFFICIENT_PRIVILEGE_LEVEL
78  * - IPMI_COMP_CODE_SET_SESSION_PRIVILEGE_LEVEL_REQUESTED_LEVEL_NOT_AVAILABLE_FOR_USER (*)
79  * - IPMI_COMP_CODE_SET_SESSION_PRIVILEGE_LEVEL_REQUESTED_LEVEL_EXCEEDS_USER_PRIVILEGE_LIMIT (*)
80  * - RMCPPLUS_STATUS_INVALID_ROLE
81  * - RMCPPLUS_STATUS_UNAUTHORIZED_ROLE_OR_PRIVILEGE_LEVEL_REQUESTED
82  *
83  * IPMI_ERR_CIPHER_SUITE_ID_UNAVAILABLE
84  * - RMCPPLUS_STATUS_NO_CIPHER_SUITE_MATCH_WITH_PROPOSED_SECURITY_ALGORITHMS
85  *
86  * IPMI_ERR_MESSAGE_TIMEOUT
87  * - IPMI_COMP_CODE_COMMAND_TIMEOUT
88  *
89  * IPMI_ERR_COMMAND_INVALID_OR_UNSUPPORTED
90  * - IPMI_COMP_CODE_INVALID_COMMAND
91  * - IPMI_COMP_CODE_COMMAND_INVALID_FOR_LUN
92  * - IPMI_COMP_CODE_REQUEST_DATA_LENGTH_INVALID
93  * - IPMI_COMP_CODE_REQUEST_DATA_LENGTH_LIMIT_EXCEEDED
94  * - IPMI_COMP_CODE_PARAMETER_OUT_OF_RANGE
95  * - IPMI_COMP_CODE_INVALID_DATA_FIELD_IN_REQUEST
96  *
97  * IPMI_ERR_BMC_BUSY
98  * - IPMI_COMP_CODE_NODE_BUSY
99  * - IPMI_COMP_CODE_OUT_OF_SPACE
100  * - IPMI_COMP_CODE_SDR_REPOSITORY_IN_UPDATE_MODE
101  * - IPMI_COMP_CODE_DEVICE_IN_FIRMWARE_UPDATE_MODE
102  * - IPMI_COMP_CODE_BMC_INITIALIZATION_IN_PROGRESS
103  *
104  * All other IPMI completion codes will map to IPMI_ERR_BAD_COMPLETION_CODE.
105  * All other RMCPPlus codes will map to IPMI_ERR_BAD_RMCPPLUS_STATUS_CODE.
106  */
107 
108 enum ipmi_errnum
109   {
110     IPMI_ERR_SUCCESS = 0,
111     IPMI_ERR_CTX_NULL = 1,
112     IPMI_ERR_CTX_INVALID = 2,
113     IPMI_ERR_PERMISSION = 3,
114     IPMI_ERR_USERNAME_INVALID = 4,
115     IPMI_ERR_PASSWORD_INVALID = 5,
116     IPMI_ERR_K_G_INVALID = 6,
117     IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT = 7,
118     IPMI_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED = 8,
119     IPMI_ERR_AUTHENTICATION_TYPE_UNAVAILABLE = 9,
120     IPMI_ERR_CIPHER_SUITE_ID_UNAVAILABLE = 10,
121     IPMI_ERR_PASSWORD_VERIFICATION_TIMEOUT = 11,
122     IPMI_ERR_IPMI_2_0_UNAVAILABLE = 12,
123     IPMI_ERR_CONNECTION_TIMEOUT = 13,
124     IPMI_ERR_SESSION_TIMEOUT = 14,
125     IPMI_ERR_DEVICE_ALREADY_OPEN = 15,
126     IPMI_ERR_DEVICE_NOT_OPEN = 16,
127     IPMI_ERR_DEVICE_NOT_SUPPORTED = 17,
128     IPMI_ERR_DEVICE_NOT_FOUND = 18,
129     IPMI_ERR_DRIVER_BUSY = 19,
130     IPMI_ERR_DRIVER_TIMEOUT = 20,
131     IPMI_ERR_MESSAGE_TIMEOUT = 21,
132     IPMI_ERR_COMMAND_INVALID_FOR_SELECTED_INTERFACE = 22,
133     IPMI_ERR_COMMAND_INVALID_OR_UNSUPPORTED = 23,
134     IPMI_ERR_BAD_COMPLETION_CODE = 24,
135     IPMI_ERR_BAD_RMCPPLUS_STATUS_CODE = 25,
136     IPMI_ERR_NOT_FOUND = 26,
137     IPMI_ERR_BMC_BUSY = 27,
138     IPMI_ERR_OUT_OF_MEMORY = 28,
139     IPMI_ERR_HOSTNAME_INVALID = 29,
140     IPMI_ERR_PARAMETERS = 30,
141     IPMI_ERR_DRIVER_PATH_REQUIRED = 31,
142     IPMI_ERR_IPMI_ERROR = 32,
143     IPMI_ERR_SYSTEM_ERROR = 33,
144     IPMI_ERR_INTERNAL_ERROR = 34,
145     IPMI_ERR_ERRNUMRANGE = 35,
146   };
147 typedef enum ipmi_errnum ipmi_errnum_type_t;
148 
149 enum ipmi_driver_type
150 {
151   IPMI_DEVICE_UNKNOWN = 0,
152   IPMI_DEVICE_LAN = 1,
153   IPMI_DEVICE_LAN_2_0 = 2,
154   IPMI_DEVICE_KCS = 3,
155   IPMI_DEVICE_SMIC = 4,
156   IPMI_DEVICE_BT = 5,
157   IPMI_DEVICE_SSIF = 6,
158   IPMI_DEVICE_OPENIPMI = 7,
159   IPMI_DEVICE_SUNBMC = 8,
160   IPMI_DEVICE_INTELDCMI = 9,
161 };
162 typedef enum ipmi_driver_type ipmi_driver_type_t;
163 
164 #define IPMI_SESSION_TIMEOUT_DEFAULT                                        20000
165 #define IPMI_RETRANSMISSION_TIMEOUT_DEFAULT                                 1000
166 
167 #define IPMI_WORKAROUND_FLAGS_DEFAULT                                       0x00000000
168 
169 /* For use w/ ipmi_ctx_open_outofband() */
170 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_AUTHENTICATION_CAPABILITIES         0x00000001
171 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_ACCEPT_SESSION_ID_ZERO              0x00000002
172 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_FORCE_PERMSG_AUTHENTICATION         0x00000004
173 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_CHECK_UNEXPECTED_AUTHCODE           0x00000008
174 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_BIG_ENDIAN_SEQUENCE_NUMBER          0x00000010
175 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_NO_AUTH_CODE_CHECK                  0x00000020
176 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_NO_CHECKSUM_CHECK                   0x00000040
177 
178 /* For use w/ ipmi_ctx_open_outofband_2_0() */
179 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_2_0_AUTHENTICATION_CAPABILITIES     0x00000001
180 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_2_0_INTEL_2_0_SESSION               0x00000002
181 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_2_0_SUPERMICRO_2_0_SESSION          0x00000004
182 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_2_0_SUN_2_0_SESSION                 0x00000008
183 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_2_0_OPEN_SESSION_PRIVILEGE          0x00000010
184 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_2_0_NON_EMPTY_INTEGRITY_CHECK_VALUE 0x00000020
185 #define IPMI_WORKAROUND_FLAGS_OUTOFBAND_2_0_NO_CHECKSUM_CHECK               0x00000040
186 
187 /* For use w/ ipmi_ctx_open_inband() or ipmi_ctx_find_inband() */
188 #define IPMI_WORKAROUND_FLAGS_INBAND_ASSUME_IO_BASE_ADDRESS                 0x00000001
189 #define IPMI_WORKAROUND_FLAGS_INBAND_SPIN_POLL                              0x00000002
190 
191 /* NONBLOCKING - for inband only, do no block if device busy.
192  *
193  * NOSESSION - for outofband only, do not create an IPMI session.
194  * Useful for the few IPMI payloads that do not require a session for
195  * an IPMI command to be sent (e.g. Get Channel Authentication
196  * Capabilities, Get System GUID, PET Acknowledge).  Can only be set
197  * during opening, not later using ipmi_ctx_set_flags().  If set, you
198  * cannot call most IPMI payload functions, only those few that send
199  * data without a session.
200  *
201  * DEBUG_DUMP - for all interfaces
202  *
203  * NO_VALID_CHECK - do not check if IPMI response payloads are valid
204  * (i.e. all required fields set).  Useful to workaround non-compliant
205  * motherboards.  For example, if an IPMI payload did not return a
206  * required flag in the payload, an error would be returned.  The
207  * error might possibly be a session timeout, as no valid response
208  * packet was ever received.  This flag would skip the checks for
209  * valid fields and return the packet to the user.
210  *
211  * NO_LEGAL_CHECK - do no check if IPMI response payloads have
212  * sufficient data (i.e. completion code fields) to be legal.  Useful
213  * to work around non-compliant motherboards.  This flag is ignores
214  * the legality of IPMI payloads greater than the NO_VALID_CHECK
215  * option.  For example, NO_VALID_CHECK would still return an error if
216  * an IPMI payload did not return a completion code in an IPMI
217  * response.  The NO_LEGAL_CHECK would return such a packet to the
218  * user without an error.  If the payload did not return a completion
219  * code, the completion code will not be checked for.
220  *
221  * IGNORE_AUTHENTICATION_CODE - for IPMI 1.5 packets, do not check the
222  * authentication code on response packets.  Useful to workaround
223  * around non-compliant motherboards implementing invalid code/hashes.
224  * Note that this is different than
225  * IPMI_WORKAROUND_FLAGS_OUTOFBAND_NO_AUTH_CODE_CHECK above.  With the
226  * workaround flag, all authentication codes will be ignored during
227  * the entire IPMI session.  With this flag, specific packets can have
228  * their authentication codes ignored.
229  */
230 
231 #define IPMI_FLAGS_DEFAULT                    0x00000000
232 #define IPMI_FLAGS_NONBLOCKING                0x00000001
233 #define IPMI_FLAGS_NOSESSION                  0x00000002
234 #define IPMI_FLAGS_DEBUG_DUMP                 0x00000010
235 #define IPMI_FLAGS_NO_VALID_CHECK             0x00000100
236 #define IPMI_FLAGS_NO_LEGAL_CHECK             0x00000200
237 #define IPMI_FLAGS_IGNORE_AUTHENTICATION_CODE 0x00000400
238 
239 typedef struct ipmi_ctx *ipmi_ctx_t;
240 
241 ipmi_ctx_t ipmi_ctx_create (void);
242 
243 int ipmi_ctx_errnum (ipmi_ctx_t ctx);
244 
245 char *ipmi_ctx_strerror (int errnum);
246 
247 char *ipmi_ctx_errormsg (ipmi_ctx_t ctx);
248 
249 int ipmi_ctx_get_flags (ipmi_ctx_t ctx, unsigned int *flags);
250 
251 /* for changing flags mid-operation for corner cases */
252 int ipmi_ctx_set_flags (ipmi_ctx_t ctx, unsigned int flags);
253 
254 /* For IPMI 1.5 sessions */
255 /* For session_timeout and retransmission_timeout, specify 0 for default */
256 int ipmi_ctx_open_outofband (ipmi_ctx_t ctx,
257                              const char *hostname,
258                              const char *username,
259                              const char *password,
260                              uint8_t authentication_type,
261                              uint8_t privilege_level,
262                              unsigned int session_timeout,
263                              unsigned int retransmission_timeout,
264                              unsigned int workaround_flags,
265                              unsigned int flags);
266 
267 /* For IPMI 2.0 sessions */
268 /* For session_timeout and retransmission_timeout, specify 0 for default */
269 int ipmi_ctx_open_outofband_2_0 (ipmi_ctx_t ctx,
270                                  const char *hostname,
271                                  const char *username,
272                                  const char *password,
273                                  const unsigned char *k_g,
274                                  unsigned int k_g_len,
275                                  uint8_t privilege_level,
276                                  uint8_t cipher_suite_id,
277                                  unsigned int session_timeout,
278                                  unsigned int retransmission_timeout,
279                                  unsigned int workaround_flags,
280                                  unsigned int flags);
281 
282 /* For inband sessions */
283 int ipmi_ctx_open_inband (ipmi_ctx_t ctx,
284                           ipmi_driver_type_t driver_type,
285                           int disable_auto_probe,
286                           uint16_t driver_address,
287                           uint8_t register_spacing,
288                           const char *driver_device,
289                           unsigned int workaround_flags,
290                           unsigned int flags);
291 
292 /* like ipmi_ctx_open_inband, but finds probes/discovers an inband device */
293 /* returns 1 on driver found, 0 on not found, -1 on error */
294 /* if specified, driver type returned in 'driver_type' */
295 int ipmi_ctx_find_inband (ipmi_ctx_t ctx,
296                           ipmi_driver_type_t *driver_type,
297                           int disable_auto_probe,
298                           uint16_t driver_address,
299                           uint8_t register_spacing,
300                           const char *driver_device,
301                           unsigned int workaround_flags,
302                           unsigned int flags);
303 
304 /* Set target channel and slave address so all ipmi_cmd() calls and
305  * library API calls use ipmb.
306  *
307  * To set only one parameter, pass in NULL for the other parameter.
308  * When only one parameter is passed, the other will be the default
309  * target channel of IPMI_CHANNEL_NUMBER_PRIMARY_IPMB (0x0) or the
310  * default rs_addr of IPMI_SLAVE_ADDRESS_BMC (0x20).
311  *
312  * To reset to defaults, pass in NULL for both parameters.
313  *
314  * Can only be called after device opened.
315  */
316 int ipmi_ctx_set_target (ipmi_ctx_t ctx,
317                          uint8_t *channel_number,
318                          uint8_t *rs_addr);
319 
320 int ipmi_ctx_get_target (ipmi_ctx_t ctx,
321                          uint8_t *channel_number,
322                          uint8_t *rs_addr);
323 
324 int ipmi_cmd (ipmi_ctx_t ctx,
325               uint8_t lun,
326               uint8_t net_fn,
327               fiid_obj_t obj_cmd_rq,
328               fiid_obj_t obj_cmd_rs);
329 
330 /* convenience function to perform a single bridged IPMI command.
331  * Will effectively call ipmi_ctx_set_target(), then ipmi_cmd(), then
332  * will set targets back to prior originals.
333  */
334 int ipmi_cmd_ipmb (ipmi_ctx_t ctx,
335                    uint8_t channel_number,
336                    uint8_t rs_addr,
337                    uint8_t lun,
338                    uint8_t net_fn,
339                    fiid_obj_t obj_cmd_rq,
340                    fiid_obj_t obj_cmd_rs);
341 
342 /* for request/response, byte #1 = cmd */
343 /* for response, byte #2 (typically) = completion code */
344 /* returns length written into buf_fs on success, -1 on error */
345 int ipmi_cmd_raw (ipmi_ctx_t ctx,
346                   uint8_t lun,
347                   uint8_t net_fn,
348                   const void *buf_rq,
349                   unsigned int buf_rq_len,
350                   void *buf_rs,
351                   unsigned int buf_rs_len);
352 
353 /* convenience function to perform a single bridged IPMI raw command.
354  * Will effectively call ipmi_ctx_set_target(), then ipmi_cmd_raw(),
355  * then will set targets back to prior originals.
356  */
357 int ipmi_cmd_raw_ipmb (ipmi_ctx_t ctx,
358                        uint8_t channel_number,
359                        uint8_t rs_addr,
360                        uint8_t lun,
361                        uint8_t net_fn,
362                        const void *buf_rq,
363                        unsigned int buf_rq_len,
364                        void *buf_rs,
365                        unsigned int buf_rs_len);
366 
367 int ipmi_ctx_close (ipmi_ctx_t ctx);
368 
369 void ipmi_ctx_destroy (ipmi_ctx_t ctx);
370 
371 #ifdef __cplusplus
372 }
373 #endif
374 
375 #endif /* IPMI_API_H */
376