1 /*****************************************************************************\
2  *  $Id: ipmiconsole_defs.h,v 1.80 2010-06-10 22:10:12 chu11 Exp $
3  *****************************************************************************
4  *  Copyright (C) 2007-2015 Lawrence Livermore National Security, LLC.
5  *  Copyright (C) 2006-2007 The Regents of the University of California.
6  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
7  *  Written by Albert Chu <chu11@llnl.gov>
8  *  UCRL-CODE-221226
9  *
10  *  This file is part of Ipmiconsole, a set of IPMI 2.0 SOL libraries
11  *  and utilities.  For details, see http://www.llnl.gov/linux/.
12  *
13  *  Ipmiconsole is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by the
15  *  Free Software Foundation; either version 3 of the License, or (at your
16  *  option) any later version.
17  *
18  *  Ipmiconsole is distributed in the hope that it will be useful, but
19  *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20  *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21  *  for more details.
22  *
23  *  You should have received a copy of the GNU General Public License along
24  *  with Ipmiconsole.  If not, see <http://www.gnu.org/licenses/>.
25 \*****************************************************************************/
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif /* HAVE_CONFIG_H */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdint.h>
34 #ifdef HAVE_PTHREAD_H
35 #include <pthread.h>
36 #endif /* HAVE_PTHREAD_H */
37 #if TIME_WITH_SYS_TIME
38 #include <sys/time.h>
39 #include <time.h>
40 #else  /* !TIME_WITH_SYS_TIME */
41 #if HAVE_SYS_TIME_H
42 #include <sys/time.h>
43 #else /* !HAVE_SYS_TIME_H */
44 #include <time.h>
45 #endif  /* !HAVE_SYS_TIME_H */
46 #endif /* !TIME_WITH_SYS_TIME */
47 #include <sys/param.h>
48 #include <netinet/in.h>
49 #include <limits.h>             /* MAXHOSTNAMELEN */
50 #ifdef HAVE_NETDB_H
51 #include <netdb.h>              /* MAXHOSTNAMELEN Solaris */
52 #endif /* HAVE_NETDB_H */
53 #include <freeipmi/freeipmi.h>
54 
55 #include "scbuf.h"
56 
57 #ifndef IPMICONSOLE_DEFS_H
58 #define IPMICONSOLE_DEFS_H
59 
60 #ifndef MAXHOSTNAMELEN
61 #define MAXHOSTNAMELEN 64
62 #endif /* MAXHOSTNAMELEN */
63 
64 #define MAXPORTBUFLEN 16
65 
66 #ifndef MAXPATHLEN
67 #define MAXPATHLEN 4096
68 #endif /* MAXPATHLEN */
69 
70 typedef enum
71   {
72     IPMICONSOLE_PROTOCOL_STATE_START                                    = 0x00,
73     IPMICONSOLE_PROTOCOL_STATE_GET_AUTHENTICATION_CAPABILITIES_SENT     = 0x01,
74     IPMICONSOLE_PROTOCOL_STATE_OPEN_SESSION_REQUEST_SENT                = 0x02,
75     IPMICONSOLE_PROTOCOL_STATE_RAKP_MESSAGE_1_SENT                      = 0x03,
76     IPMICONSOLE_PROTOCOL_STATE_RAKP_MESSAGE_3_SENT                      = 0x04,
77     IPMICONSOLE_PROTOCOL_STATE_SET_SESSION_PRIVILEGE_LEVEL_SENT         = 0x05,
78     IPMICONSOLE_PROTOCOL_STATE_GET_CHANNEL_PAYLOAD_SUPPORT_SENT         = 0x06,
79     IPMICONSOLE_PROTOCOL_STATE_GET_PAYLOAD_ACTIVATION_STATUS_SENT       = 0x07,
80     IPMICONSOLE_PROTOCOL_STATE_ACTIVATE_PAYLOAD_SENT                    = 0x08,
81     IPMICONSOLE_PROTOCOL_STATE_SOL_SESSION                              = 0x09,
82     IPMICONSOLE_PROTOCOL_STATE_DEACTIVATE_PAYLOAD_SENT                  = 0x0A,
83     IPMICONSOLE_PROTOCOL_STATE_CLOSE_SESSION_SENT                       = 0x0B,
84     IPMICONSOLE_PROTOCOL_STATE_END                                      = 0x0C,
85   } ipmiconsole_protocol_state_t;
86 
87 /* Note: Get Channel Payload Version will act as our "ping"
88  * to keep the session state alive.
89  */
90 typedef enum
91   {
92     IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ     = 0x00,
93     IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS     = 0x01,
94     IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST                   = 0x02,
95     IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE                  = 0x03,
px_THROW_ERROR(int err)96     IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1                         = 0x04,
97     IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2                         = 0x05,
98     IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3                         = 0x06,
99     IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4                         = 0x07,
100     IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ         = 0x08,
101     IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS         = 0x09,
102     IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ         = 0x0A,
103     IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS         = 0x0B,
104     IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ       = 0x0C,
105     IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS       = 0x0D,
106     IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ                    = 0x0E,
107     IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS                    = 0x0F,
108     IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ                    = 0x10,
109     IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS                    = 0x11,
110     IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ         = 0x12,
111     IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS         = 0x13,
112     IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ                  = 0x14,
113     IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS                  = 0x15,
114     IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ                       = 0x16,
115     IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS                       = 0x17,
116   } ipmiconsole_packet_type_t;
117 
118 #define IPMICONSOLE_PACKET_TYPE_REQUEST(__p)                                \
119   (((__p) == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ     \
120     || (__p) == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST                \
121     || (__p) == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1                      \
122     || (__p) == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3                      \
123     || (__p) == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ      \
124     || (__p) == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ      \
125     || (__p) == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ    \
px_memset(void * ptr,int c,size_t len)126     || (__p) == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ                 \
127     || (__p) == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ                 \
128     || (__p) == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ      \
129     || (__p) == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ               \
130     || (__p) == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ) ? 1 : 0)
131 
132 #define IPMICONSOLE_PACKET_TYPE_RESPONSE(__p)                               \
133   (((__p) == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS     \
134     || (__p) == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE               \
135     || (__p) == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2                      \
136     || (__p) == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4                      \
137     || (__p) == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS      \
138     || (__p) == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS      \
139     || (__p) == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS    \
140     || (__p) == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS                 \
141     || (__p) == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS                 \
142     || (__p) == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS      \
143     || (__p) == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS               \
144     || (__p) == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS) ? 1 : 0)
145 
146 #define IPMICONSOLE_PACKET_TYPE_VALID(__p)       \
147   ((IPMICONSOLE_PACKET_TYPE_REQUEST (__p)        \
148     || IPMICONSOLE_PACKET_TYPE_RESPONSE (__p)) ? 1 : 0)
149 
150 #define IPMICONSOLE_THREAD_COUNT_DEFAULT                            4
151 
152 #define IPMICONSOLE_SESSION_TIMEOUT_LENGTH_DEFAULT                  60000
153 #define IPMICONSOLE_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT           500
154 #define IPMICONSOLE_RETRANSMISSION_MAX_DEFAULT                      10
155 #define IPMICONSOLE_RETRANSMISSION_BACKOFF_COUNT_DEFAULT            2
156 #define IPMICONSOLE_KEEPALIVE_TIMEOUT_LENGTH_DEFAULT                20000
157 #define IPMICONSOLE_RETRANSMISSION_KEEPALIVE_TIMEOUT_LENGTH_DEFAULT 5000
158 #define IPMICONSOLE_ACCEPTABLE_PACKET_ERRORS_COUNT_DEFAULT          16
159 #define IPMICONSOLE_MAXIMUM_RETRANSMISSION_COUNT_DEFAULT            16
160 #define IPMI_PRIVILEGE_LEVEL_DEFAULT                                IPMI_PRIVILEGE_LEVEL_ADMIN
161 #define IPMI_CIPHER_SUITE_ID_DEFAULT                                3
162 #define IPMI_PAYLOAD_INSTANCE_DEFAULT                               1
163 
164 #define CONSOLE_REMOTE_CONSOLE_TO_BMC_BUF_MIN                 (1024*2)
165 #define CONSOLE_REMOTE_CONSOLE_TO_BMC_BUF_MAX                 (1024*8)
166 
167 #define CONSOLE_BMC_TO_REMOTE_CONSOLE_BUF_MIN                 (1024*4)
168 #define CONSOLE_BMC_TO_REMOTE_CONSOLE_BUF_MAX                 (1024*16)
169 
170 #define IPMI_FROM_BMC_BUF_MIN                                 (1024*4)
171 #define IPMI_FROM_BMC_BUF_MAX                                 (1024*16)
172 
173 #define IPMI_TO_BMC_BUF_MIN                                   (1024*2)
174 #define IPMI_TO_BMC_BUF_MAX                                   (1024*8)
175 
176 /* achu: See IPMI 2.0 spec Section 24.4, Table 24-6.  The Get Payload
177  * Activation Status Command indicates a maximum number of 16
178  * instances are possible.
179  */
180 #define IPMI_INSTANCES_ACTIVATED_LENGTH                       16
181 
182 #define IPMI_MAX_SIK_KEY_LENGTH                               64
183 #define IPMI_MAX_INTEGRITY_KEY_LENGTH                         64
184 #define IPMI_MAX_CONFIDENTIALITY_KEY_LENGTH                   64
185 #define IPMI_MAX_KEY_EXCHANGE_AUTHENTICATION_CODE_LENGTH      64
186 
187 #define IPMI_SESSION_INITIAL_OUTBOUND_SEQUENCE_NUMBER              1
188 #define IPMI_SOL_SESSION_INITIAL_PACKET_SEQUENCE_NUMBER            1
189 
190 /* API magic determines if the context has been destroyed by the user
191  * and can no longer be used.  However, it may not necessarily have
192  * been garbage cleaned up by the libipmiconsole engine library.
193  */
194 #define IPMICONSOLE_CTX_MAGIC                 0x74AB8831
195 #define IPMICONSOLE_CTX_API_MAGIC             0x83FB9202
196 
197 #define IPMICONSOLE_PACKET_BUFLEN             16384
198 
199 #define IPMICONSOLE_MIN_CHARACTER_DATA        1
200 #define IPMICONSOLE_MAX_CHARACTER_DATA        255
201 
202 #define IPMICONSOLE_PIPE_GENERATE_BREAK_CODE  0x01
203 
204 #define IPMICONSOLE_DEBUG_MASK         \
205   (IPMICONSOLE_DEBUG_STDOUT            \
206    | IPMICONSOLE_DEBUG_STDERR          \
207    | IPMICONSOLE_DEBUG_SYSLOG          \
208    | IPMICONSOLE_DEBUG_FILE            \
209    | IPMICONSOLE_DEBUG_IPMI_PACKETS)
210 
211 #define IPMICONSOLE_WORKAROUND_MASK                         \
212   (IPMICONSOLE_WORKAROUND_AUTHENTICATION_CAPABILITIES       \
213    | IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION               \
214    | IPMICONSOLE_WORKAROUND_SUPERMICRO_2_0_SESSION          \
215    | IPMICONSOLE_WORKAROUND_SUN_2_0_SESSION                 \
216    | IPMICONSOLE_WORKAROUND_OPEN_SESSION_PRIVILEGE          \
217    | IPMICONSOLE_WORKAROUND_NON_EMPTY_INTEGRITY_CHECK_VALUE \
218    | IPMICONSOLE_WORKAROUND_NO_CHECKSUM_CHECK               \
219    | IPMICONSOLE_WORKAROUND_SERIAL_ALERTS_DEFERRED          \
220    | IPMICONSOLE_WORKAROUND_INCREMENT_SOL_PACKET_SEQUENCE   \
221    | IPMICONSOLE_WORKAROUND_IGNORE_SOL_PAYLOAD_SIZE         \
222    | IPMICONSOLE_WORKAROUND_IGNORE_SOL_PORT                 \
223    | IPMICONSOLE_WORKAROUND_SKIP_SOL_ACTIVATION_STATUS      \
224    | IPMICONSOLE_WORKAROUND_SKIP_CHANNEL_PAYLOAD_SUPPORT)
225 
226 #define IPMICONSOLE_ENGINE_MASK                    \
227   (IPMICONSOLE_ENGINE_CLOSE_FD                     \
228    | IPMICONSOLE_ENGINE_OUTPUT_ON_SOL_ESTABLISHED  \
229    | IPMICONSOLE_ENGINE_LOCK_MEMORY                \
230    | IPMICONSOLE_ENGINE_SERIAL_KEEPALIVE           \
231    | IPMICONSOLE_ENGINE_SERIAL_KEEPALIVE_EMPTY)
232 
233 #define IPMICONSOLE_BEHAVIOR_MASK           \
234   (IPMICONSOLE_BEHAVIOR_ERROR_ON_SOL_INUSE  \
235    | IPMICONSOLE_BEHAVIOR_DEACTIVATE_ONLY   \
236    | IPMICONSOLE_BEHAVIOR_DEACTIVATE_ALL_INSTANCES)
237 
238 #define IPMICONSOLE_BLOCKING_NOTIFICATION_SOL_SESSION_ESTABLISHED 0x1
239 #define IPMICONSOLE_BLOCKING_NOTIFICATION_SOL_SESSION_ERROR       0x2
240 #define IPMICONSOLE_BLOCKING_NOTIFICATION_SOL_SESSION_DEACTIVATED 0x3
241 
242 /* Protocol/User Config Data */
243 struct ipmiconsole_ctx_config {
244 
245   /* ipmi config */
246   char hostname[MAXHOSTNAMELEN+1];
247   uint16_t port;
248   char username[IPMI_MAX_USER_NAME_LENGTH+1];
249   char password[IPMI_2_0_MAX_PASSWORD_LENGTH+1];
250   uint8_t k_g[IPMI_MAX_K_G_LENGTH+1];
251   unsigned int k_g_len;
252   uint8_t privilege_level;
253   uint8_t cipher_suite_id;
254   unsigned int workaround_flags;
255 
256   /* protocol config */
257   unsigned int session_timeout_len;
258   unsigned int retransmission_timeout_len;
259   unsigned int retransmission_backoff_count;
260   unsigned int keepalive_timeout_len;
261   unsigned int retransmission_keepalive_timeout_len;
262   unsigned int acceptable_packet_errors_count;
263   unsigned int maximum_retransmission_count;
264 
265   /* engine config */
266   unsigned int engine_flags;
267   unsigned int behavior_flags;
268   unsigned int debug_flags;
269 
270   /* advanced config */
271   unsigned int sol_payload_instance;
272 
273   /* Data based on Configuration Parameters */
274   uint8_t authentication_algorithm;
275   uint8_t integrity_algorithm;
276   uint8_t confidentiality_algorithm;
277 };
278 
279 /* Sockets, pipes, objects, etc. used for data in a SOL session */
280 struct ipmiconsole_ctx_connection {
281 
282   /* File Descriptor User Interface */
283   int user_fd;                  /* never touched internally by the library ... */
284   int ipmiconsole_fd;
285   scbuf_t console_remote_console_to_bmc;
286   scbuf_t console_bmc_to_remote_console;
287 
288   /* Connection Data */
289   int ipmi_fd;
290   scbuf_t ipmi_from_bmc;
291   scbuf_t ipmi_to_bmc;
combo_decrypt(PX_Combo * cx,const uint8 * data,unsigned dlen,uint8 * res,unsigned * rlen)292 
293   /* Pipe for non-fd communication: from API to engine */
294   int asynccomm[2];
295 
296   /* Fiid Objects */
297 
298   fiid_obj_t obj_rmcp_hdr_rq;
299   fiid_obj_t obj_rmcp_hdr_rs;
300   fiid_obj_t obj_lan_session_hdr_rq;
301   fiid_obj_t obj_lan_session_hdr_rs;
302   fiid_obj_t obj_rmcpplus_session_hdr_rq;
303   fiid_obj_t obj_rmcpplus_session_hdr_rs;
304   /* fiid_obj_t obj_rmcpplus_payload_rq; */
305   fiid_obj_t obj_rmcpplus_payload_rs;
306   fiid_obj_t obj_lan_msg_hdr_rq;
307   fiid_obj_t obj_lan_msg_hdr_rs;
308 
309   /* fiid_obj_t obj_lan_msg_trlr_rq; */
310   fiid_obj_t obj_lan_msg_trlr_rs;
311   fiid_obj_t obj_rmcpplus_session_trlr_rq;
312   fiid_obj_t obj_rmcpplus_session_trlr_rs;
313 
314   fiid_obj_t obj_authentication_capabilities_rq;
315   fiid_obj_t obj_authentication_capabilities_rs;
316   fiid_obj_t obj_open_session_request;
317   fiid_obj_t obj_open_session_response;
318   fiid_obj_t obj_rakp_message_1;
319   fiid_obj_t obj_rakp_message_2;
320   fiid_obj_t obj_rakp_message_3;
321   fiid_obj_t obj_rakp_message_4;
322   fiid_obj_t obj_set_session_privilege_level_rq;
323   fiid_obj_t obj_set_session_privilege_level_rs;
324   fiid_obj_t obj_get_channel_payload_support_rq;
325   fiid_obj_t obj_get_channel_payload_support_rs;
326   fiid_obj_t obj_get_payload_activation_status_rq;
327   fiid_obj_t obj_get_payload_activation_status_rs;
328   fiid_obj_t obj_activate_payload_rq;
329   fiid_obj_t obj_activate_payload_rs;
330   fiid_obj_t obj_sol_payload_data_rq;
331   fiid_obj_t obj_sol_payload_data_rs;
332   fiid_obj_t obj_get_channel_payload_version_rq;
333   fiid_obj_t obj_get_channel_payload_version_rs;
334   fiid_obj_t obj_deactivate_payload_rq;
335   fiid_obj_t obj_deactivate_payload_rs;
336   fiid_obj_t obj_close_session_rq;
337   fiid_obj_t obj_close_session_rs;
338 };
339 
340 /*
341  * IPMI Session Information - actual data used to keep track of a SOL
342  * session.  Separated from ipmiconsole_ctx_connection above, b/c
343  * everything below will need to be re-initialized if the session is
344  * being reattempted under a different port.
345  */
346 struct ipmiconsole_ctx_session {
347   int16_t console_port;
348 
349   struct sockaddr *addr;
350   socklen_t addr_len;
351   struct sockaddr_in addr4;
combo_free(PX_Combo * cx)352   struct sockaddr_in6 addr6;
353 
354   /* Session timeout, retransmission timeout, keepalive timeout maintenance */
355   struct timeval last_ipmi_packet_sent;
356   struct timeval last_ipmi_packet_received;
357   struct timeval last_keepalive_packet_sent;
358 
359   /* Serial keepalive timeout maintenance */
360   struct timeval last_sol_packet_received;
361 
362   /*
parse_cipher_name(char * full,char ** cipher,char ** pad)363    * Protocol State Machine Variables
364    */
365   ipmiconsole_protocol_state_t protocol_state;
366   int close_session_flag;
367   int try_new_port_flag;
368   int deactivate_payload_instances;
369   /* if deactivate_payload_instances_and_try_again_flag set,
370    * deactivate_payload_instances should always be set, but not vice
371    * versa
372    */
373   int deactivate_payload_instances_and_try_again_flag;
374   int close_timeout_flag;
375   int deactivate_only_succeeded_flag;
376 
377   /*
378    * Protocol Maintenance Variables
379    */
380   unsigned int retransmission_count;
381   unsigned int workaround_retransmission_count; /* For IPMICONSOLE_WORKAROUND_INCREMENT_SOL_PACKET_SEQUENCE */
382   unsigned int errors_count;
383   unsigned int session_sequence_number_errors_count;
384   unsigned int activate_payloads_count;
385   unsigned int deactivate_active_payloads_count;
386   uint32_t highest_received_sequence_number;
387   /* need to also store bytes read from a previous seq num */
388   uint32_t previously_received_list;
389 
390   uint8_t message_tag;
391   uint8_t requester_sequence_number;
392   uint32_t session_sequence_number;
393   uint8_t name_only_lookup;
394   uint32_t remote_console_session_id;
395   uint8_t remote_console_random_number[IPMI_REMOTE_CONSOLE_RANDOM_NUMBER_LENGTH];
396 
397   uint8_t sik_key[IPMI_MAX_SIK_KEY_LENGTH];
398   void *sik_key_ptr;
399   unsigned int sik_key_len;
400   uint8_t integrity_key[IPMI_MAX_INTEGRITY_KEY_LENGTH];
401   void *integrity_key_ptr;
402   unsigned int integrity_key_len;
403   uint8_t confidentiality_key[IPMI_MAX_CONFIDENTIALITY_KEY_LENGTH];
404   void *confidentiality_key_ptr;
px_find_combo(const char * name,PX_Combo ** res)405   unsigned int confidentiality_key_len;
406 
407   uint32_t sol_instance_capacity;
408   uint8_t sol_instances_activated[IPMI_INSTANCES_ACTIVATED_LENGTH];
409   uint32_t sol_instances_activated_count;
410   uint32_t sol_instances_deactivated_count;
411 
412   uint8_t max_sol_character_send_size; /* determine during session setup */
413 
414   /* Serial Break Maintenance */
415   int break_requested;
416   unsigned int console_remote_console_to_bmc_bytes_before_break;
417 
418   /* SOL Input (remote console to BMC) */
419   int sol_input_waiting_for_ack;
420   int sol_input_waiting_for_break_ack;
421   struct timeval last_sol_input_packet_sent;
422   uint8_t sol_input_packet_sequence_number;
423   uint8_t sol_input_character_data[IPMICONSOLE_MAX_CHARACTER_DATA+1];
424   unsigned int sol_input_character_data_len;
425 
426   /* SOL Output (BMC to remote console) */
427   uint8_t last_sol_output_packet_sequence_number;
428   uint8_t last_sol_output_accepted_character_count;
429 
430   /* Flag indicating session info is setup */
431   int session_info_setup;
432 };
433 
434 /* Context debug stuff */
435 struct ipmiconsole_ctx_debug {
436   int debug_fd;
437 };
438 
439 /* Mutexes + flags for signaling between the API and engine */
440 
441 /* state of context
442  * - INIT, user has not submitted it to the engine, user cleans up all
443  *   - can move to ENGINE_SUBMITTED state
444  * - ENGINE_SUBMITTED, in engine being used
445  *   - can move to USER_DESTROYED if user destroys first
446  *   - can move to GARBAGE_COLLECTION_WAIT if engine finished first
447  * - GARBAGE_COLLECTION_WAIT, waiting for user to destroy
448  *   - can move to GARBAGE_COLLECTION_USER_DESTROYED
449  *   - can move to ENGINE_DESTROYED
450  * - GARBAGE_COLLECTION_USER_DESTROYED, user done, garbage collection
451  *   should finish up destruction
452  * - USER_DESTROYED, user destroyed, garbage collector will clean it up
453  * - ENGINE_DESTROYED, engine done with it, user side complete cleanup
454  */
455 typedef enum {
456   IPMICONSOLE_CTX_STATE_INIT,
457   IPMICONSOLE_CTX_STATE_ENGINE_SUBMITTED,
458   IPMICONSOLE_CTX_STATE_GARBAGE_COLLECTION_WAIT,
459   IPMICONSOLE_CTX_STATE_GARBAGE_COLLECTION_USER_DESTROYED,
460   IPMICONSOLE_CTX_STATE_USER_DESTROYED,
461   IPMICONSOLE_CTX_STATE_ENGINE_DESTROYED,
462 } ipmiconsole_ctx_state;
463 
464 struct ipmiconsole_ctx_signal {
465   /* Conceptually there is not a race with the status.  The API initializes
466    * the status, and the engine is the only one that modifies it.
467    *
468    * However, there is a tiny race in
469    * ipmiconsole_engine_submit{_block}().  Conceptually, the status
470    * could be set before we even initialize the status to SUBMITTED.
471    */
472   pthread_mutex_t status_mutex;
473   unsigned int status;
474 
475   /* ctx_state - state and mutex used to determine when the user has
476    * destroyed the context and it is now the responsibility of the
477    * engine/garbage-collector to cleanup, or vice versa.  Need to
478    * mutex to avoid destroy races.
479    */
480   pthread_mutex_t mutex_ctx_state;
481   ipmiconsole_ctx_state ctx_state;
482 };
483 
484 /* non-blocking potential parameters */
485 struct ipmiconsole_ctx_non_blocking {
486   Ipmiconsole_callback callback;
487   void *callback_arg;
488 };
489 
490 /* Info, pipe, and mutex for engine submission blocking */
491 struct ipmiconsole_ctx_blocking {
492   /* Conceptually, it is impossible for both to ever be touched
493    * simultaneously so a mutex may not seem necessary.
494    *
495    * blocking_submit_requested is initialized/set in API land, and
496    * then later read in engine land after the context is submitted.
497    * It is never read again in API land and never written to in engine
498    * land.
499    *
500    * sol_session_established is initialied in API land, afterwards it
501    * is only written/read in the engine after a context is submitted.
502    *
503    * after initialization, the API and Engine only touch their
504    * ends of the pipe.
505    *
506    * However, there is a tiny race that is possible.  After the
507    * session is submitted, the blocking code in _ipmiconsole_block()
508    * could fail, such as in the call to select().  We do not want the
509    * engine and API to race reading/writing under this circumstance.
510    */
511   pthread_mutex_t blocking_mutex;
512   int blocking_submit_requested;
513   int blocking_notification[2];
514   int sol_session_established;
515 };
516 
517 struct ipmiconsole_ctx_fds {
518   /* Copy from ipmiconsole_ctx_session, these file descriptors are
519    * managed exclusively by API level, not the engine.
520    *
521    * The need to manage asynccomm at the API level is b/c users could
522    * access it via ipmiconsole_ctx_generate_break().  If one end of
523    * the asynccomm is closed by the engine, it becomes difficult to
524    * know if we can actually generate a break.
525    *
526    * We could manage this situation through some mutexes, but that would
527    * slow down closing/generate-break code.  We could capture EPIPE in the
528    * API and return a "IS_CLOSING" error to the user, but that would require
529    * the user to set SIGPIPE to SIG_IGN.  Moving it to all be managed in
530    * the API level is best.  We just have to check for POLLNVAL in the
531    * engine poll().
532    *
533    */
534   int user_fd;
535   int user_fd_retrieved;        /* if user ever grabbed it */
536   int asynccomm[2];
537 };
538 
539 struct ipmiconsole_ctx {
540   /* Two magics - first indicates the context is still valid.  Second
541    * is pretty much a flag that indicates the context has been
542    * "destroyed" in API land, and should no longer be used by the API.
543    */
544   uint32_t magic;
545   uint32_t api_magic;
546   pthread_mutex_t errnum_mutex;
547   int errnum;
548   int errnum_retrieved;
549 
550   struct ipmiconsole_ctx_config config;
551 
552   struct ipmiconsole_ctx_debug debug;
553 
554   struct ipmiconsole_ctx_signal signal;
555 
556   struct ipmiconsole_ctx_non_blocking non_blocking;
557 
558   struct ipmiconsole_ctx_blocking blocking;
559 
560   struct ipmiconsole_ctx_session session;
561 
562   struct ipmiconsole_ctx_connection connection;
563 
564   struct ipmiconsole_ctx_fds fds;
565 
566   /* session_submitted - flag indicates context submitted to engine
567    * successfully.  Does not indicate any state of success/failure for
568    * either blocking or non-blocking submissions.  Primary used as a
569    * flag so other functions such as ipmiconsole_ctx_fd() and
570    * ipmiconsole_generate_break() know that they are capable of
571    * moving on.
572    *
573    * Note, does not require a mutex.  Only a flag used in API-land.
574    * Engine threads will never touch this.
575    */
576   unsigned int session_submitted;
577 };
578 
579 #endif /* IPMICONSOLE_DEFS_H */
580