1 /*****************************************************************************\
2  *  $Id: ipmiconsole_packet.c,v 1.64 2010-08-03 00:10:59 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/>.
_crypt_gensalt_traditional_rn(unsigned long count,const char * input,int size,char * output,int output_size)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 #if STDC_HEADERS
35 #include <string.h>
36 #endif /* STDC_HEADERS */
37 #include <assert.h>
38 #include <errno.h>
39 #if HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif /* HAVE_UNISTD_H */
42 
43 #include "ipmiconsole.h"
44 #include "ipmiconsole_defs.h"
45 
46 #include "ipmiconsole_packet.h"
47 #include "ipmiconsole_ctx.h"
48 #include "ipmiconsole_debug.h"
49 
50 #include "freeipmi-portability.h"
51 #include "cbuf.h"
52 #include "debug-util.h"
53 #include "secure.h"
54 
55 #define IPMICONSOLE_MAX_PACKET_DUMP_HDR_LEN 1024
56 
57 fiid_field_t *
58 ipmiconsole_packet_template (ipmiconsole_ctx_t c,
59                              ipmiconsole_packet_type_t p)
60 {
61   assert (c);
62   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
63   assert (IPMICONSOLE_PACKET_TYPE_VALID (p));
64 
65   switch (p)
66     {
67     case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ:
68       return (&tmpl_cmd_get_channel_authentication_capabilities_rq[0]);
69     case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS:
70       return (&tmpl_cmd_get_channel_authentication_capabilities_rs[0]);
71     case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST:
72       return (&tmpl_rmcpplus_open_session_request[0]);
73     case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE:
74       return (&tmpl_rmcpplus_open_session_response[0]);
75     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1:
76       return (&tmpl_rmcpplus_rakp_message_1[0]);
77     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2:
78       return (&tmpl_rmcpplus_rakp_message_2[0]);
79     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3:
80       return (&tmpl_rmcpplus_rakp_message_3[0]);
81     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4:
82       return (&tmpl_rmcpplus_rakp_message_4[0]);
83     case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ:
84       return (&tmpl_cmd_set_session_privilege_level_rq[0]);
85     case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS:
86       return (&tmpl_cmd_set_session_privilege_level_rs[0]);
87     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ:
88       return (&tmpl_cmd_get_channel_payload_support_rq[0]);
89     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS:
90       return (&tmpl_cmd_get_channel_payload_support_rs[0]);
91     case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ:
92       return (&tmpl_cmd_get_payload_activation_status_rq[0]);
93     case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS:
94       return (&tmpl_cmd_get_payload_activation_status_rs[0]);
95     case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ:
96       return (&tmpl_cmd_activate_payload_sol_rq[0]);
97     case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS:
98       return (&tmpl_cmd_activate_payload_sol_rs[0]);
99     case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ:
100       return (&tmpl_sol_payload_data_remote_console_to_bmc[0]);
101     case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS:
102       return (&tmpl_sol_payload_data_bmc_to_remote_console[0]);
103     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ:
104       return (&tmpl_cmd_get_channel_payload_version_rq[0]);
105     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS:
106       return (&tmpl_cmd_get_channel_payload_version_rs[0]);
107     case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ:
108       return (&tmpl_cmd_deactivate_payload_rq[0]);
109     case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS:
110       return (&tmpl_cmd_deactivate_payload_rs[0]);
111     case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ:
112       return (&tmpl_cmd_chassis_control_rq[0]);
113     case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS:
114       return (&tmpl_cmd_chassis_control_rs[0]);
115     default:
116       IPMICONSOLE_CTX_DEBUG (c, ("invalid packet type: %d", p));
117       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
118       return (NULL);
119     }
120 
121   return (NULL);                        /* NOT REACHED */
122 }
123 
BF_encode(char * dst,const BF_word * src,int size)124 fiid_obj_t
125 ipmiconsole_packet_object (ipmiconsole_ctx_t c,
126                            ipmiconsole_packet_type_t p)
127 {
128   assert (c);
129   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
130   assert (IPMICONSOLE_PACKET_TYPE_VALID (p));
131 
132   switch (p)
133     {
134     case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ:
135       return (c->connection.obj_authentication_capabilities_rq);
136     case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS:
137       return (c->connection.obj_authentication_capabilities_rs);
138     case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST:
139       return (c->connection.obj_open_session_request);
140     case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE:
141       return (c->connection.obj_open_session_response);
142     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1:
143       return (c->connection.obj_rakp_message_1);
144     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2:
145       return (c->connection.obj_rakp_message_2);
146     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3:
147       return (c->connection.obj_rakp_message_3);
148     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4:
149       return (c->connection.obj_rakp_message_4);
150     case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ:
151       return (c->connection.obj_set_session_privilege_level_rq);
152     case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS:
153       return (c->connection.obj_set_session_privilege_level_rs);
154     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ:
155       return (c->connection.obj_get_channel_payload_support_rq);
156     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS:
157       return (c->connection.obj_get_channel_payload_support_rs);
158     case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ:
159       return (c->connection.obj_get_payload_activation_status_rq);
160     case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS:
161       return (c->connection.obj_get_payload_activation_status_rs);
162     case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ:
163       return (c->connection.obj_activate_payload_rq);
164     case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS:
165       return (c->connection.obj_activate_payload_rs);
166     case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ:
167       return (c->connection.obj_sol_payload_data_rq);
168     case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS:
169       return (c->connection.obj_sol_payload_data_rs);
170     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ:
171       return (c->connection.obj_get_channel_payload_version_rq);
172     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS:
173       return (c->connection.obj_get_channel_payload_version_rs);
174     case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ:
175       return (c->connection.obj_deactivate_payload_rq);
176     case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS:
177       return (c->connection.obj_deactivate_payload_rs);
178     case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ:
179       return (c->connection.obj_close_session_rq);
180     case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS:
181       return (c->connection.obj_close_session_rs);
182     default:
183       IPMICONSOLE_CTX_DEBUG (c, ("invalid packet type: %d", p));
184       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
185       return (NULL);
186     }
187 
188   return (NULL);                        /* NOT REACHED */
189 }
190 
191 static int
192 _packet_dump_hdr (ipmiconsole_ctx_t c,
193                   ipmiconsole_packet_type_t p,
194                   char *hdr,
195                   unsigned int hdrlen)
196 {
197   uint8_t packet_type;
198   uint8_t packet_direction;
199   const char *str_cmd = NULL;
200 
201   assert (c);
202   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
203   assert (IPMICONSOLE_PACKET_TYPE_VALID (p));
204   assert (hdr);
205   assert (hdrlen);
206 
207   if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ
208       || p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS)
209     packet_type = DEBUG_UTIL_TYPE_IPMI_1_5;
210   else
211     packet_type = DEBUG_UTIL_TYPE_IPMI_2_0;
212 
213   switch (p)
214     {
215     case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ:
216     case IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS:
217       str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES);
218       break;
219     case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST:
220     case IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE:
221       str_cmd = DEBUG_UTIL_OPEN_SESSION_STR;
222       break;
223     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1:
224       str_cmd = DEBUG_UTIL_RAKP_1_STR;
225       break;
226     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2:
227       str_cmd = DEBUG_UTIL_RAKP_2_STR;
228       break;
229     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3:
230       str_cmd = DEBUG_UTIL_RAKP_3_STR;
231       break;
232     case IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4:
233       str_cmd = DEBUG_UTIL_RAKP_4_STR;
234       break;
235     case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ:
236     case IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS:
237       str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_SET_SESSION_PRIVILEGE_LEVEL);
238       break;
239     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ:
240     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS:
241       str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_PAYLOAD_SUPPORT);
242       break;
243     case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ:
244     case IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS:
245       str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_PAYLOAD_ACTIVATION_STATUS);
246       break;
247     case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ:
248     case IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS:
249       str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_ACTIVATE_PAYLOAD);
250       break;
251     case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ:
252       str_cmd = "SOL Remote Console to BMC";
253       break;
254     case IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS:
255       str_cmd = "SOL BMC to Remote Console";
256       break;
257     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ:
258     case IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS:
259       str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_PAYLOAD_VERSION);
260       break;
261     case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ:
262     case IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS:
263       str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_DEACTIVATE_PAYLOAD);
264       break;
265     case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ:
266     case IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS:
267       str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_CLOSE_SESSION);
268       break;
269     default:
270       IPMICONSOLE_CTX_DEBUG (c, ("invalid packet type: %d", p));
271       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
272       return (-1);
273     }
274 
275   /* special case: there is no "Request/Response" with SOL data */
276   if (p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ
277       || p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS)
278     packet_direction = DEBUG_UTIL_DIRECTION_NONE;
279   else if (IPMICONSOLE_PACKET_TYPE_REQUEST (p))
280     packet_direction = DEBUG_UTIL_DIRECTION_REQUEST;
281   else
282     packet_direction = DEBUG_UTIL_DIRECTION_RESPONSE;
283 
284   if (debug_hdr_str (packet_type,
285                      packet_direction,
286                      DEBUG_UTIL_FLAGS_DEFAULT,
287                      str_cmd,
288                      hdr,
289                      hdrlen) < 0)
290     {
291       IPMICONSOLE_CTX_DEBUG (c, ("debug_hdr_str: p = %d", p));
292       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
293       return (-1);
294     }
295 
296   return (0);
297 }
298 
299 int
300 ipmiconsole_packet_dump (ipmiconsole_ctx_t c,
301                          ipmiconsole_packet_type_t p,
302                          const void *buf,
303                          unsigned int buflen)
304 {
305   fiid_field_t *tmpl_lan_msg_hdr;
306   fiid_field_t *tmpl_cmd;
307   char hdr[IPMICONSOLE_MAX_PACKET_DUMP_HDR_LEN];
308   int fd;
309 
310   assert (c);
311   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
312   assert (IPMICONSOLE_PACKET_TYPE_VALID (p));
313   assert (buf);
314   assert (buflen);
315 
316   if (c->config.debug_flags & IPMICONSOLE_DEBUG_STDOUT)
317     fd = STDOUT_FILENO;
318   else if (c->config.debug_flags & IPMICONSOLE_DEBUG_STDERR)
319     fd = STDERR_FILENO;
320   else if (c->config.debug_flags & IPMICONSOLE_DEBUG_FILE)
321     fd = c->debug.debug_fd;
322   else
323     return (0);
324 
325   tmpl_cmd = ipmiconsole_packet_template (c, p);
326 
327   if (IPMICONSOLE_PACKET_TYPE_REQUEST (p))
328     tmpl_lan_msg_hdr = &tmpl_lan_msg_hdr_rq[0];
329   else
330     tmpl_lan_msg_hdr = &tmpl_lan_msg_hdr_rs[0];
331 
332   if (_packet_dump_hdr (c, p, hdr, IPMICONSOLE_MAX_PACKET_DUMP_HDR_LEN) < 0)
333     return (-1);
334 
335   /* IPMI 1.5 Style Packets */
336   if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ
337       || p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS)
338     {
339       if (ipmi_dump_lan_packet (fd,
340                                 c->config.hostname,
341                                 hdr,
342                                 NULL,
343                                 buf,
344                                 buflen,
345                                 tmpl_lan_msg_hdr,
346                                 tmpl_cmd) < 0)
347         {
348           IPMICONSOLE_CTX_DEBUG (c, ("ipmi_dump_lan_packet: p = %d; %s", p, strerror (errno)));
349           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
350           return (-1);
351         }
352     }
353   else /* IPMI 2.0 Style Packets */
354     {
355       /* IPMI 2.0 RAKP Session Setup Packets use no cipher
356        * algorithms
357        */
358       if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
359           || p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE
360           || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
361           || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2
362           || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3
363           || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4)
364         {
365           if (ipmi_dump_rmcpplus_packet (fd,
366                                          c->config.hostname,
367                                          hdr,
368                                          NULL,
369                                          IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE,
370                                          IPMI_INTEGRITY_ALGORITHM_NONE,
371                                          IPMI_CONFIDENTIALITY_ALGORITHM_NONE,
372                                          NULL,
373                                          0,
374                                          NULL,
375                                          0,
376                                          buf,
377                                          buflen,
378                                          tmpl_lan_msg_hdr,
379                                          tmpl_cmd) < 0)
380             {
381               IPMICONSOLE_CTX_DEBUG (c, ("ipmi_dump_rmcpplus_packet: p = %d; %s", p, strerror (errno)));
382               ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
383               return (-1);
384             }
385         }
386       else
387         {
388           if (ipmi_dump_rmcpplus_packet (fd,
389                                          c->config.hostname,
390                                          hdr,
391                                          NULL,
392                                          c->config.authentication_algorithm,
393                                          c->config.integrity_algorithm,
394                                          c->config.confidentiality_algorithm,
395                                          c->session.integrity_key_ptr,
396                                          c->session.integrity_key_len,
397                                          c->session.confidentiality_key_ptr,
398                                          c->session.confidentiality_key_len,
399                                          buf,
400                                          buflen,
401                                          tmpl_lan_msg_hdr,
402                                          tmpl_cmd) < 0)
403             {
404               IPMICONSOLE_CTX_DEBUG (c, ("ipmi_dump_rmcpplus_packet: p = %d; %s", p, strerror (errno)));
405               ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
406               return (-1);
407             }
408 
409         }
410     }
411 
412   return (0);
413 }
414 
415 static int
416 _packet_dump_unknown_hdr (ipmiconsole_ctx_t c,
417                           const void *buf,
418                           unsigned int buflen,
419                           char *hdr,
420                           unsigned int hdrlen)
421 {
422   char *fmt =
423     "================================================\n"
424     "%s\n"
425     "================================================";
426   char *str;
427   int ret;
428   int len;
429 
430   assert (c);
431   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
432   assert (buf);
433   assert (buflen);
434   assert (hdr);
435   assert (hdrlen);
436 
437   if ((ret = ipmi_is_ipmi_1_5_packet (buf, buflen)) < 0)
438     {
439       IPMICONSOLE_CTX_DEBUG (c, ("ipmi_is_ipmi_1_5_packet: %s", strerror (errno)));
440       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
441       return (-1);
442     }
443 
444   if (ret)
445     str = "= Unexpected IPMI 1.5 Packet                   =";
446   else
447     {
448       uint8_t payload_type;
449 
450       if (ipmi_rmcpplus_calculate_payload_type (buf, buflen, &payload_type) < 0)
451         {
452           IPMICONSOLE_CTX_DEBUG (c, ("ipmi_rmcpplus_calculate_payload_type: %s", strerror (errno)));
453           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
454           return (-1);
455         }
456 
457       switch (payload_type)
458         {
459         case IPMI_PAYLOAD_TYPE_SOL:
460           str = "= Unexpected SOL Packet                        =";
461           break;
462         case IPMI_PAYLOAD_TYPE_IPMI:
463           str = "= Unexpected IPMI 2.0 Packet                   =";
464           break;
465         case IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST:
466           str = "= Unexpected Open Session Request              =";
467           break;
468         case IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE:
469           str = "= Unexpected Open Session Response             =";
470           break;
471         case IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1:
472           str = "= Unexpected RAKP Message 1                    =";
473           break;
474         case IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2:
475           str = "= Unexpected RAKP Message 2                    =";
476           break;
477         case IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3:
478           str = "= Unexpected RAKP Message 3                    =";
479           break;
480         case IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4:
481           str = "= Unexpected RAKP Message 4                    =";
482           break;
483         default:
484           str = "= Unexpected Packet                            =";
485         }
486     }
487 
488   if ((len = snprintf (hdr, hdrlen, fmt, str)) < 0)
489     {
490       IPMICONSOLE_CTX_DEBUG (c, ("snprintf"));
491       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
492       return (-1);
493     }
494 
495   if (len >= hdrlen)
496     {
497       IPMICONSOLE_CTX_DEBUG (c, ("snprintf truncation: len = %d", len));
498       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
499       return (-1);
500     }
501 
502   return (len);
503 }
504 
505 int
506 ipmiconsole_packet_dump_unknown (ipmiconsole_ctx_t c,
507                                  const void *buf,
508                                  unsigned int buflen)
509 {
510   char hdr[IPMICONSOLE_MAX_PACKET_DUMP_HDR_LEN];
511   int fd;
512   int ret;
513 
514   assert (c);
515   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
516   assert (buf);
517   assert (buflen);
518 
519   if (c->config.debug_flags & IPMICONSOLE_DEBUG_STDOUT)
520     fd = STDOUT_FILENO;
521   else if (c->config.debug_flags & IPMICONSOLE_DEBUG_STDERR)
522     fd = STDERR_FILENO;
523   else if (c->config.debug_flags & IPMICONSOLE_DEBUG_FILE)
524     fd = c->debug.debug_fd;
525   else
526     return (0);
527 
528   if (_packet_dump_unknown_hdr (c, buf, buflen, hdr, IPMICONSOLE_MAX_PACKET_DUMP_HDR_LEN) < 0)
529     return (-1);
530 
531   if ((ret = ipmi_is_ipmi_1_5_packet (buf, buflen)) < 0)
532     {
533       IPMICONSOLE_CTX_DEBUG (c, ("ipmi_is_ipmi_1_5_packet: %s", strerror (errno)));
534       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
535       return (-1);
536     }
537 
538   if (ret)
539     {
540       if (ipmi_dump_lan_packet (fd,
541                                 c->config.hostname,
542                                 hdr,
543                                 NULL,
544                                 buf,
545                                 buflen,
546                                 tmpl_lan_msg_hdr_rs,
547                                 tmpl_unexpected_data) < 0)
548         {
549           IPMICONSOLE_CTX_DEBUG (c, ("ipmi_dump_lan_packet: %s", strerror (errno)));
550           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
551           return (-1);
552         }
553     }
554   else
555     {
556       if (ipmi_dump_rmcpplus_packet (fd,
557                                      c->config.hostname,
558                                      hdr,
559                                      NULL,
560                                      c->config.authentication_algorithm,
561                                      c->config.integrity_algorithm,
562                                      c->config.confidentiality_algorithm,
563                                      c->session.integrity_key_ptr,
564                                      c->session.integrity_key_len,
565                                      c->session.confidentiality_key_ptr,
566                                      c->session.confidentiality_key_len,
567                                      buf,
568                                      buflen,
569                                      tmpl_lan_msg_hdr_rs,
570                                      tmpl_unexpected_data) < 0)
571         {
572           IPMICONSOLE_CTX_DEBUG (c, ("ipmi_dump_rmcpplus_packet: %s", strerror (errno)));
573           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
574           return (-1);
575         }
576     }
577 
578   return (0);
579 }
580 
581 
582 static int
583 _ipmi_1_5_packet_assemble (ipmiconsole_ctx_t c,
584                            ipmiconsole_packet_type_t p,
585                            uint8_t authentication_type,
586                            uint32_t inbound_sequence_number,
587                            uint32_t session_id,
588                            void *authentication_code_data,
589                            unsigned int authentication_code_data_len,
590                            uint8_t net_fn,
591                            fiid_obj_t obj_cmd_rq,
592                            void *buf,
593                            unsigned int buflen)
594 {
595   int pkt_len;
596 
597   assert (c);
598   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
599   assert (IPMICONSOLE_PACKET_TYPE_REQUEST (p));
600   assert (buf);
601   assert (buflen);
602 
603   if (fill_rmcp_hdr_ipmi (c->connection.obj_rmcp_hdr_rq) < 0)
604     {
605       IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcp_hdr_ipmi: p = %d; %s", p, strerror (errno)));
606       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
607       return (-1);
608     }
609 
610   if (fill_lan_session_hdr (authentication_type,
611                             inbound_sequence_number,
612                             session_id,
613                             c->connection.obj_lan_session_hdr_rq) < 0)
614     {
615       IPMICONSOLE_CTX_DEBUG (c, ("fill_lan_session_hdr: p = %d; %s", p, strerror (errno)));
616       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
617       return (-1);
618     }
619 
620   if (fill_lan_msg_hdr (IPMI_SLAVE_ADDRESS_BMC,
621                         net_fn,
622                         IPMI_BMC_IPMB_LUN_BMC,
623                         c->session.requester_sequence_number,
624                         c->connection.obj_lan_msg_hdr_rq) < 0)
625     {
626       IPMICONSOLE_CTX_DEBUG (c, ("fill_lan_msg_hdr: p = %d; %s", p, strerror (errno)));
627       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
628       return (-1);
629     }
630 
631   if ((pkt_len = assemble_ipmi_lan_pkt (c->connection.obj_rmcp_hdr_rq,
632                                         c->connection.obj_lan_session_hdr_rq,
633                                         c->connection.obj_lan_msg_hdr_rq,
634                                         obj_cmd_rq,
635                                         authentication_code_data,
636                                         authentication_code_data_len,
637                                         buf,
638                                         buflen,
639                                         IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
640     {
641       IPMICONSOLE_CTX_DEBUG (c, ("assemble_ipmi_lan_pkt: p = %d; %s", p, strerror (errno)));
642       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
643       return (-1);
644     }
645 
646   return (pkt_len);
647 }
648 
649 static int
650 _ipmi_2_0_packet_assemble (ipmiconsole_ctx_t c,
651                            ipmiconsole_packet_type_t p,
652                            uint8_t payload_type,
653                            uint8_t payload_authenticated,
654                            uint8_t payload_encrypted,
655                            uint32_t session_id,
656                            uint32_t session_sequence_number,
657                            void *authentication_code_data,
658                            unsigned int authentication_code_data_len,
659                            uint8_t net_fn,
660                            uint8_t authentication_algorithm,
661                            uint8_t integrity_algorithm,
662                            uint8_t confidentiality_algorithm,
663                            void *integrity_key,
664                            unsigned int integrity_key_len,
665                            void *confidentiality_key,
666                            unsigned int confidentiality_key_len,
667                            fiid_obj_t obj_cmd_rq,
668                            void *buf,
669                            unsigned int buflen)
670 {
671   int pkt_len;
672 
673   assert (c);
674   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
675   assert (IPMICONSOLE_PACKET_TYPE_REQUEST (p));
676   assert (buf);
677   assert (buflen);
678 
679   if (fill_rmcp_hdr_ipmi (c->connection.obj_rmcp_hdr_rq) < 0)
680     {
681       IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcp_hdr_ipmi: p = %d; %s", p, strerror (errno)));
682       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
683       return (-1);
684     }
685 
686   if (fill_rmcpplus_session_hdr (payload_type,
687                                  payload_authenticated,
688                                  payload_encrypted,
689                                  0, /* oem_iana */
690                                  0, /* oem_payload_id */
691                                  session_id,
692                                  session_sequence_number,
693                                  c->connection.obj_rmcpplus_session_hdr_rq) < 0)
694     {
695       IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcpplus_session_hdr: p = %d; %s", p, strerror (errno)));
696       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
697       return (-1);
698     }
699 
700   if (fill_lan_msg_hdr (IPMI_SLAVE_ADDRESS_BMC,
701                         net_fn,
702                         IPMI_BMC_IPMB_LUN_BMC,
703                         c->session.requester_sequence_number,
704                         c->connection.obj_lan_msg_hdr_rq) < 0)
705     {
706       IPMICONSOLE_CTX_DEBUG (c, ("fill_lan_msg_hdr: p = %d; %s", p, strerror (errno)));
707       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
708       return (-1);
709     }
710 
711   if (fill_rmcpplus_session_trlr (c->connection.obj_rmcpplus_session_trlr_rq) < 0)
712     {
713       IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcpplus_session_trlr: p = %d; %s", p, strerror (errno)));
714       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
715       return (-1);
716     }
717 
718   if ((pkt_len = assemble_ipmi_rmcpplus_pkt (authentication_algorithm,
719                                              integrity_algorithm,
720                                              confidentiality_algorithm,
721                                              integrity_key,
722                                              integrity_key_len,
723                                              confidentiality_key,
724                                              confidentiality_key_len,
725                                              authentication_code_data,
726                                              authentication_code_data_len,
727                                              c->connection.obj_rmcp_hdr_rq,
728                                              c->connection.obj_rmcpplus_session_hdr_rq,
729                                              c->connection.obj_lan_msg_hdr_rq,
730                                              obj_cmd_rq,
731                                              c->connection.obj_rmcpplus_session_trlr_rq,
732                                              buf,
733                                              buflen,
734                                              IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
735     {
736       IPMICONSOLE_CTX_DEBUG (c, ("assemble_ipmi_rmcpplus_pkt: p = %d; %s", p, strerror (errno)));
737       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
738       return (-1);
739     }
740 
741   return (pkt_len);
742 }
743 
744 
745 int
746 ipmiconsole_ipmi_packet_assemble (ipmiconsole_ctx_t c,
747                                   ipmiconsole_packet_type_t p,
748                                   void *buf,
749                                   unsigned int buflen)
750 {
751   char username_buf[IPMI_MAX_USER_NAME_LENGTH+1];
752   char *username = NULL;
753   unsigned int username_len;
754   char *password = NULL;
755   unsigned int password_len;
756   uint8_t authentication_type = 0;
757   uint32_t session_id = 0;
758   uint32_t managed_system_session_id = 0;
759   uint32_t session_sequence_number = 0;
760   uint8_t net_fn = 0;
761   uint8_t payload_type = 0;
762   uint8_t authentication_algorithm = 0;
763   uint8_t integrity_algorithm = 0;
764   void *integrity_key = NULL;
765   unsigned int integrity_key_len = 0;
766   uint8_t confidentiality_algorithm = 0;
767   void *confidentiality_key = NULL;
768   unsigned int confidentiality_key_len = 0;
769   uint8_t payload_authenticated = 0;
770   uint8_t payload_encrypted = 0;
771   fiid_obj_t obj_cmd_rq = NULL;
772   int pkt_len;
773   uint64_t val;
774 
775   assert (c);
776   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
777   assert (IPMICONSOLE_PACKET_TYPE_REQUEST (p));
778   assert (p != IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ);
779   assert (buf);
780   assert (buflen);
781 
782   /* Determine Username */
783   /* IPMI Workaround
784    *
785    * Intel IPMI 2.0 implementations pad their usernames.
786    */
787   if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION
788       && p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1)
789     {
790       memset (username_buf, '\0', IPMI_MAX_USER_NAME_LENGTH+1);
791       if (strlen (c->config.username))
792         strcpy (username_buf, c->config.username);
793       username = username_buf;
794       username_len = IPMI_MAX_USER_NAME_LENGTH;
795     }
796   else
797     {
798       if (strlen (c->config.username))
799         username = c->config.username;
800       else
801         username = NULL;
802       username_len = (username) ? strlen (username) : 0;
803     }
804 
805   /* Determine Password */
806   if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ)
807     password = NULL;
808   else
809     {
810       if (strlen (c->config.password))
811         password = c->config.password;
812       else
813         password = NULL;
814     }
815 
816   password_len = (password) ? strlen (password) : 0;
817 
818   /* IPMI Workaround
819    *
820    * Intel IPMI 2.0 implementations improperly calculate HMAC-MD5-128 hashes
821    * when the passwords are > 16 bytes long.  The BMCs probably assume
822    * all keys are <= 16 bytes in length.  So we have to adjust.
823    */
824   if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION
825       && c->config.authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5
826       && password_len > IPMI_1_5_MAX_PASSWORD_LENGTH)
827     password_len = IPMI_1_5_MAX_PASSWORD_LENGTH;
828 
829   /* Determine Authentication Type */
830   if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ)
831     authentication_type = IPMI_AUTHENTICATION_TYPE_NONE;
832 
833   /* Determine Session ID */
834   if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ
835       || p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
836       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
837       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
838     session_id = 0;
839   else
840     {
841       if (FIID_OBJ_GET (c->connection.obj_open_session_response,
842                         "managed_system_session_id",
843                         &val) < 0)
844         {
845           IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get: 'managed_system_session_id': %s",
846                                      fiid_obj_errormsg (c->connection.obj_open_session_response)));
847           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
848           return (-1);
849         }
850       session_id = val;
851     }
852 
853   /* Determine Managed System Session ID */
854   if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
855       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
856     {
857       if (FIID_OBJ_GET (c->connection.obj_open_session_response,
858                         "managed_system_session_id",
859                         &val) < 0)
860         {
861           IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get: 'managed_system_session_id': %s",
862                                      fiid_obj_errormsg (c->connection.obj_open_session_response)));
863           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
864           return (-1);
865         }
866       managed_system_session_id = val;
867     }
868 
869   /* Determine Sequence Number */
870   if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ
871       || p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
872       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
873       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
874     session_sequence_number = 0;
875   else
876     session_sequence_number = c->session.session_sequence_number;
877 
878   /* Determine Network Function */
879   if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ
880       || p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ
881       || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ
882       || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ
883       || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ
884       || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ
885       || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ
886       || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ)
887     net_fn = IPMI_NET_FN_APP_RQ;
888 
889   /* Determine Payload Type */
890   if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST)
891     payload_type = IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST;
892   else if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1)
893     payload_type = IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1;
894   else if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
895     payload_type = IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3;
896   else if (p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ
897            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ
898            || p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ
899            || p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ
900            || p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ
901            || p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ
902            || p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ)
903     payload_type = IPMI_PAYLOAD_TYPE_IPMI;
904   else if (p == IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ)
905     payload_type = IPMI_PAYLOAD_TYPE_SOL;
906 
907   /* Determine Authentication/Integrity/Confidentiality Keys */
908   if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
909       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
910       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
911     {
912       authentication_algorithm = IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE;
913       integrity_algorithm = IPMI_INTEGRITY_ALGORITHM_NONE;
914       confidentiality_algorithm = IPMI_CONFIDENTIALITY_ALGORITHM_NONE;
915       integrity_key = NULL;
916       integrity_key_len = 0;
917       confidentiality_key = NULL;
918       confidentiality_key_len = 0;
919     }
920   else
921     {
922       authentication_algorithm = c->config.authentication_algorithm;
923       integrity_algorithm = c->config.integrity_algorithm;
924       confidentiality_algorithm = c->config.confidentiality_algorithm;
925       integrity_key = c->session.integrity_key_ptr;
926       integrity_key_len = c->session.integrity_key_len;
927       confidentiality_key = c->session.confidentiality_key_ptr;
928       confidentiality_key_len = c->session.confidentiality_key_len;
929     }
930 
931   /* Determine Payload Authenticated Flag */
932   if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
933       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
934       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3
935       || integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE)
936     payload_authenticated = IPMI_PAYLOAD_FLAG_UNAUTHENTICATED;
937   else
938     payload_authenticated = IPMI_PAYLOAD_FLAG_AUTHENTICATED;
939 
940   /* Determine Payload Encrypted Flag */
941   if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST
942       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1
943       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3
944       || confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
945     payload_encrypted = IPMI_PAYLOAD_FLAG_UNENCRYPTED;
946   else
947     payload_encrypted = IPMI_PAYLOAD_FLAG_ENCRYPTED;
948 
949   /* Fill/Determine Object */
950 
951   if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ)
952     {
953       if (fill_cmd_get_channel_authentication_capabilities (IPMI_CHANNEL_NUMBER_CURRENT_CHANNEL,
954                                                             c->config.privilege_level,
955                                                             IPMI_GET_IPMI_V20_EXTENDED_DATA,
956                                                             c->connection.obj_authentication_capabilities_rq) < 0)
957         {
958           IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_get_channel_authentication_capabilities: p = %d; %s", p, strerror (errno)));
959           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
960           return (-1);
961         }
962       obj_cmd_rq = c->connection.obj_authentication_capabilities_rq;
963     }
964   else if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_REQUEST)
965     {
966       uint8_t privilege_level;
967 
968       /*
969        * IPMI Workaround (achu)
970        *
971        * Forgotten Motherboard
972        *
973        * Cipher suite IDs are attached to specific privilege levels
974        * rather than a maximum privilege level limit.  So you can only
975        * authenticate at the configured privilege level rather than a
976        * privilege level <= to it.
977        *
978        * To deal with this situation.  We send the "request highest
979        * privilege" flag in the open session request.  This should be
980        * enough to work around this issue but still work with other
981        * motherboards.
982        */
983 
984       /* IPMI Workaround (achu)
985        *
986        * Discovered on SE7520AF2 with Intel Server Management Module
987        * (Professional Edition)
988        *
989        * The Intel's return IPMI_PRIVILEGE_LEVEL_HIGHEST_LEVEL instead
990        * of an actual privilege, so have to pass the actual privilege
991        * we want to use.
992        */
993 
994       /* IPMI Workaround (achu)
995        *
996        * Discovered on Sun Fire 4100, Inventec 5441/Dell Xanadu II,
997        * Supermicro X8DTH, Supermicro X8DTG, Supermicro X8DTU, Intel
998        * S5500WBV/Penguin Relion 700
999        *
1000        * The remote BMC incorrectly calculates keys using the privilege
1001        * specified in the open session stage rather than the privilege
1002        * used during the RAKP1 stage.  This can be problematic if you
1003        * specify IPMI_PRIVILEGE_LEVEL_HIGHEST_LEVEL during that stage
1004        * instead of a real privilege level.  So we must pass the actual
1005        * privilege we want to use.
1006        */
1007       if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION
1008           || c->config.workaround_flags & IPMICONSOLE_WORKAROUND_SUN_2_0_SESSION
1009           || c->config.workaround_flags & IPMICONSOLE_WORKAROUND_OPEN_SESSION_PRIVILEGE)
1010         privilege_level = c->config.privilege_level;
1011       else
1012         privilege_level = IPMI_PRIVILEGE_LEVEL_HIGHEST_LEVEL;
1013 
1014       if (fill_rmcpplus_open_session (c->session.message_tag,
1015                                       privilege_level,
1016                                       c->session.remote_console_session_id,
1017                                       c->config.authentication_algorithm,
1018                                       c->config.integrity_algorithm,
1019                                       c->config.confidentiality_algorithm,
1020                                       c->connection.obj_open_session_request) < 0)
1021         {
1022           IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcpplus_open_session: p = %d; %s", p, strerror (errno)));
1023           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1024           return (-1);
1025         }
1026       obj_cmd_rq = c->connection.obj_open_session_request;
1027     }
1028   else if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_1)
1029     {
1030       if (fill_rmcpplus_rakp_message_1 (c->session.message_tag,
1031                                         managed_system_session_id,
1032                                         c->session.remote_console_random_number,
1033                                         IPMI_REMOTE_CONSOLE_RANDOM_NUMBER_LENGTH,
1034                                         c->config.privilege_level,
1035                                         c->session.name_only_lookup,
1036                                         username,
1037                                         username_len,
1038                                         c->connection.obj_rakp_message_1) < 0)
1039         {
1040           IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcpplus_rakp_message_1: p = %d; %s", p, strerror (errno)));
1041           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1042           return (-1);
1043         }
1044       obj_cmd_rq = c->connection.obj_rakp_message_1;
1045     }
1046   else if (p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_3)
1047     {
1048       uint8_t managed_system_random_number[IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH];
1049       int managed_system_random_number_len;
1050       uint8_t key_exchange_authentication_code[IPMI_MAX_KEY_EXCHANGE_AUTHENTICATION_CODE_LENGTH];
1051       int key_exchange_authentication_code_len;
1052       uint8_t name_only_lookup;
1053 
1054       /* IPMI Workaround
1055        *
1056        * Intel IPMI 2.0 implementations use this flag incorrectly.
1057        */
1058       if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION)
1059         name_only_lookup = IPMI_USER_NAME_PRIVILEGE_LOOKUP;
1060       else
1061         name_only_lookup = c->session.name_only_lookup;
1062 
1063       if ((managed_system_random_number_len = fiid_obj_get_data (c->connection.obj_rakp_message_2,
1064                                                                  "managed_system_random_number",
1065                                                                  managed_system_random_number,
1066                                                                  IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH)) < 0)
1067         {
1068           IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: 'managed_system_random_number': %s",
1069                                      fiid_obj_errormsg (c->connection.obj_rakp_message_2)));
1070           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1071           return (-1);
1072         }
1073 
1074       if (managed_system_random_number_len != IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH)
1075         {
1076           IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get_data: invalid managed system random number length: %d", managed_system_random_number_len));
1077           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1078           return (-1);
1079         }
1080 
1081       if ((key_exchange_authentication_code_len = ipmi_calculate_rakp_3_key_exchange_authentication_code (c->config.authentication_algorithm,
1082                                                                                                           password,
1083                                                                                                           password_len,
1084                                                                                                           managed_system_random_number,
1085                                                                                                           managed_system_random_number_len,
1086                                                                                                           c->session.remote_console_session_id,
1087                                                                                                           name_only_lookup,
1088                                                                                                           c->config.privilege_level,
1089                                                                                                           username,
1090                                                                                                           username_len,
1091                                                                                                           key_exchange_authentication_code,
1092                                                                                                           IPMI_MAX_KEY_EXCHANGE_AUTHENTICATION_CODE_LENGTH)) < 0)
1093         {
1094           IPMICONSOLE_CTX_DEBUG (c, ("ipmi_calculate_rakp_3_key_exchange_authentication_code: p = %d; %s", p, strerror (errno)));
1095           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1096           return (-1);
1097         }
1098 
1099       if (fill_rmcpplus_rakp_message_3 (c->session.message_tag,
1100                                         RMCPPLUS_STATUS_NO_ERRORS,
1101                                         managed_system_session_id,
1102                                         key_exchange_authentication_code,
1103                                         key_exchange_authentication_code_len,
1104                                         c->connection.obj_rakp_message_3) < 0)
1105         {
1106           IPMICONSOLE_CTX_DEBUG (c, ("fill_rmcpplus_rakp_message_3: p = %d; %s", p, strerror (errno)));
1107           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1108           return (-1);
1109         }
1110       obj_cmd_rq = c->connection.obj_rakp_message_3;
1111     }
1112   else if (p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ)
1113     {
1114       if (fill_cmd_set_session_privilege_level (c->config.privilege_level,
1115                                                 c->connection.obj_set_session_privilege_level_rq) < 0)
1116         {
1117           IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_set_session_privilege_level: p = %d; %s", p, strerror (errno)));
1118           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1119           return (-1);
1120         }
1121       obj_cmd_rq = c->connection.obj_set_session_privilege_level_rq;
1122     }
1123   else if (p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RQ)
1124     {
1125       if (fill_cmd_get_channel_payload_support (IPMI_CHANNEL_NUMBER_CURRENT_CHANNEL,
1126                                                 c->connection.obj_get_channel_payload_support_rq) < 0)
1127         {
1128           IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_get_channel_payload_support: p = %d; %s", p, strerror (errno)));
1129           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1130           return (-1);
1131         }
1132       obj_cmd_rq = c->connection.obj_get_channel_payload_support_rq;
1133     }
1134   else if (p == IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RQ)
1135     {
1136       if (fill_cmd_get_payload_activation_status (IPMI_PAYLOAD_TYPE_SOL,
1137                                                   c->connection.obj_get_payload_activation_status_rq) < 0)
1138         {
1139           IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_get_payload_activation_status: p = %d; %s", p, strerror (errno)));
1140           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1141           return (-1);
1142         }
1143       obj_cmd_rq = c->connection.obj_get_payload_activation_status_rq;
1144     }
1145   else if (p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RQ)
1146     {
1147       uint8_t sol_startup_handshake;
1148       uint8_t authentication_activation;
1149       uint8_t encryption_activation;
1150       uint8_t shared_serial_alert_behavior;
1151 
1152       /* IPMI Workaround
1153        *
1154        * Intel IPMI 2.0 specific issue.  I have no idea why this is.
1155        * I took it from ipmiutil.  Ipmiutil author Andrew Cress cannot
1156        * remember why this is the case either.
1157        */
1158       if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_INTEL_2_0_SESSION)
1159         sol_startup_handshake = IPMI_SOL_STARTUP_HANDSHAKE_CTS_AND_DCD_SDR_ASSERTED;
1160       else
1161         sol_startup_handshake = IPMI_SOL_STARTUP_HANDSHAKE_CTS_AND_DCD_SDR_DEASSERTED;
1162 
1163       if (c->config.integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE)
1164         authentication_activation = IPMI_ACTIVATE_PAYLOAD_WITHOUT_AUTHENTICATION;
1165       else
1166         authentication_activation = IPMI_ACTIVATE_PAYLOAD_WITH_AUTHENTICATION;
1167 
1168       if (c->config.confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
1169         encryption_activation = IPMI_ACTIVATE_PAYLOAD_WITHOUT_ENCRYPTION;
1170       else
1171         encryption_activation = IPMI_ACTIVATE_PAYLOAD_WITH_ENCRYPTION;
1172 
1173       /* Workaround
1174        *
1175        * Discovered on Intel Windmill/Quanta Winterfell/Wiwynn Windmill
1176        *
1177        * Nodes like this to be set, I have no idea why.  The boards
1178        * don't even have serial ports.
1179        */
1180       if (c->config.workaround_flags & IPMICONSOLE_WORKAROUND_SERIAL_ALERTS_DEFERRED)
1181         shared_serial_alert_behavior = IPMI_SERIAL_MODEM_ALERTS_DEFERRED_WHILE_SOL_ACTIVE;
1182       else
1183         shared_serial_alert_behavior = IPMI_SERIAL_MODEM_ALERTS_FAIL_WHILE_SOL_ACTIVE;
1184 
1185       if (fill_cmd_activate_payload_sol (IPMI_PAYLOAD_TYPE_SOL,
1186                                          (uint8_t)c->config.sol_payload_instance,
1187                                          sol_startup_handshake,
1188                                          shared_serial_alert_behavior,
1189                                          IPMI_TEST_MODE_DEACTIVATED,
1190                                          authentication_activation,
1191                                          encryption_activation,
1192                                          c->connection.obj_activate_payload_rq) < 0)
1193         {
1194           IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_activate_payload_sol: p = %d; %s", p, strerror (errno)));
1195           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1196           return (-1);
1197         }
1198       obj_cmd_rq = c->connection.obj_activate_payload_rq;
1199     }
1200   else if (p == IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RQ)
1201     {
1202       assert (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_SOL_SESSION);
1203 
1204       if (fill_cmd_get_channel_payload_version (IPMI_CHANNEL_NUMBER_CURRENT_CHANNEL,
1205                                                 IPMI_PAYLOAD_TYPE_SOL,
1206                                                 c->connection.obj_get_channel_payload_version_rq) < 0)
1207         {
1208           IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_get_channel_payload_version: p = %d; %s", p, strerror (errno)));
1209           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1210           return (-1);
1211         }
1212       obj_cmd_rq = c->connection.obj_get_channel_payload_version_rq;
1213     }
1214   else if (p == IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RQ)
1215     {
1216       uint8_t payload_instance;
1217 
1218       if (c->session.deactivate_payload_instances)
1219         payload_instance = c->session.sol_instances_activated[c->session.sol_instances_deactivated_count];
1220       else
1221         payload_instance = (uint8_t)c->config.sol_payload_instance;
1222 
1223       if (fill_cmd_deactivate_payload (IPMI_PAYLOAD_TYPE_SOL,
1224                                        payload_instance,
1225                                        0, /* achu: IPMI SPEC says: 0h for SOL */
1226                                        c->connection.obj_deactivate_payload_rq) < 0)
1227         {
1228           IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_deactivate_payload: p = %d; %s", p, strerror (errno)));
1229           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1230           return (-1);
1231         }
1232       obj_cmd_rq = c->connection.obj_deactivate_payload_rq;
1233     }
1234   else /* p == IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RQ */
1235     {
1236       if (fill_cmd_close_session (session_id,
1237                                   NULL,
1238                                   c->connection.obj_close_session_rq) < 0)
1239         {
1240           IPMICONSOLE_CTX_DEBUG (c, ("fill_cmd_close_session: p = %d; %s", p, strerror (errno)));
1241           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1242           return (-1);
1243         }
1244       obj_cmd_rq = c->connection.obj_close_session_rq;
1245     }
1246 
1247   /* IPMI 1.5 Style Packets */
1248   if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RQ)
1249     {
1250       if ((pkt_len = _ipmi_1_5_packet_assemble (c,
1251                                                 p,
1252                                                 authentication_type,
1253                                                 session_sequence_number,
1254                                                 session_id,
1255                                                 password,
1256                                                 password_len,
1257                                                 net_fn,
1258                                                 obj_cmd_rq,
1259                                                 buf,
1260                                                 buflen)) < 0)
1261         return (-1);
1262     }
1263   else /* IPMI 2.0 Style Packets */
1264     {
1265       if ((pkt_len = _ipmi_2_0_packet_assemble (c,
1266                                                 p,
1267                                                 payload_type,
1268                                                 payload_authenticated,
1269                                                 payload_encrypted,
1270                                                 session_id,
1271                                                 session_sequence_number,
1272                                                 password,
1273                                                 password_len,
1274                                                 net_fn,
1275                                                 authentication_algorithm,
1276                                                 integrity_algorithm,
1277                                                 confidentiality_algorithm,
1278                                                 integrity_key,
1279                                                 integrity_key_len,
1280                                                 confidentiality_key,
1281                                                 confidentiality_key_len,
1282                                                 obj_cmd_rq,
1283                                                 buf,
1284                                                 buflen)) < 0)
1285         return (-1);
1286     }
1287 
1288   return (pkt_len);
1289 }
1290 
1291 int
1292 ipmiconsole_sol_packet_assemble (ipmiconsole_ctx_t c,
1293                                  uint8_t packet_sequence_number,
1294                                  uint8_t packet_ack_nack_sequence_number,
1295                                  uint8_t accepted_character_count,
1296                                  uint8_t generate_break,
1297                                  void *character_data,
1298                                  unsigned int character_data_len,
1299                                  void *buf,
1300                                  unsigned int buflen)
1301 {
1302   char *password = NULL;
1303   uint32_t session_id = 0;
1304   uint8_t payload_authenticated = 0;
1305   uint8_t payload_encrypted = 0;
1306   uint8_t ack;
1307   int pkt_len;
1308   uint64_t val;
1309   int rv = -1;
1310 
1311   assert (c);
1312   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
1313   assert (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_SOL_SESSION);
1314   assert (character_data_len <= c->session.max_sol_character_send_size);
1315 
1316   /* If the packet sequence number is 0, that means this is an ACK
1317    * only packet.  So the ack_nack sequence number should be non-zero
1318    * and no character data should be sent.  The accepted character
1319    * count can be 0 to indicate a NACK instead of an ACK.
1320    */
1321   assert (packet_sequence_number
1322           || (!packet_sequence_number
1323               && packet_ack_nack_sequence_number
1324               && !character_data_len));
1325   assert (buf);
1326   assert (buflen);
1327 
1328   if (strlen (c->config.password))
1329     password = c->config.password;
1330   else
1331     password = NULL;
1332 
1333   if (FIID_OBJ_GET (c->connection.obj_open_session_response,
1334                     "managed_system_session_id",
1335                     &val) < 0)
1336     {
1337       IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get: 'managed_system_session_id': %s",
1338                                  fiid_obj_errormsg (c->connection.obj_open_session_response)));
1339       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1340       goto cleanup;
1341     }
1342   session_id = val;
1343 
1344   /* Determine Payload Authenticated Flag */
1345   if (c->config.integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE)
1346     payload_authenticated = IPMI_PAYLOAD_FLAG_UNAUTHENTICATED;
1347   else
1348     payload_authenticated = IPMI_PAYLOAD_FLAG_AUTHENTICATED;
1349 
1350   /* Determine Payload Encrypted Flag */
1351   if (c->config.confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
1352     payload_encrypted = IPMI_PAYLOAD_FLAG_UNENCRYPTED;
1353   else
1354     payload_encrypted = IPMI_PAYLOAD_FLAG_ENCRYPTED;
1355 
1356   /* Determine ACK flag */
1357   if (!packet_sequence_number)
1358     {
1359       if (accepted_character_count)
1360         ack = IPMI_SOL_ACK;
1361       else
1362         ack = IPMI_SOL_NACK;
1363     }
1364   else
1365     /* XXX: Hopefully this is right. Specification is unclear */
1366     ack = 0;
1367 
1368   /* Fill/Determine Object */
1369   if (fill_sol_payload_data_remote_console_to_bmc (packet_sequence_number,
1370                                                    packet_ack_nack_sequence_number,
1371                                                    accepted_character_count,
1372                                                    0,
1373                                                    0,
1374                                                    0,
1375                                                    0,
1376                                                    generate_break,
1377                                                    0,
1378                                                    ack,
1379                                                    character_data,
1380                                                    character_data_len,
1381                                                    c->connection.obj_sol_payload_data_rq) < 0)
1382     {
1383       IPMICONSOLE_CTX_DEBUG (c, ("fill_sol_payload_data_remote_console_to_bmc: %s", strerror (errno)));
1384       ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1385       goto cleanup;
1386     }
1387 
1388   if ((pkt_len = _ipmi_2_0_packet_assemble (c,
1389                                             IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RQ,
1390                                             IPMI_PAYLOAD_TYPE_SOL,
1391                                             payload_authenticated,
1392                                             payload_encrypted,
1393                                             session_id,
1394                                             c->session.session_sequence_number,
1395                                             password,
1396                                             (password) ? strlen (password) : 0,
1397                                             0,
1398                                             c->config.authentication_algorithm,
1399                                             c->config.integrity_algorithm,
1400                                             c->config.confidentiality_algorithm,
1401                                             c->session.integrity_key_ptr,
1402                                             c->session.integrity_key_len,
1403                                             c->session.confidentiality_key_ptr,
1404                                             c->session.confidentiality_key_len,
1405                                             c->connection.obj_sol_payload_data_rq,
1406                                             buf,
1407                                             buflen)) < 0)
1408     goto cleanup;
1409 
1410   rv = pkt_len;
1411  cleanup:
1412   return (rv);
1413 }
1414 
1415 
1416 int
1417 ipmiconsole_packet_unassemble (ipmiconsole_ctx_t c,
1418                                ipmiconsole_packet_type_t *p,
1419                                const void *buf,
1420                                unsigned int buflen)
1421 {
1422   ipmiconsole_packet_type_t pkt;
1423   fiid_obj_t obj_cmd = NULL;
1424   int ret, pkt_ret = 0;
1425 
1426   assert (c);
1427   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
1428   assert (p);
1429   assert (buf);
1430   assert (buflen);
1431 
1432   /* Calculate packet type */
1433 
1434   if ((ret = ipmi_is_ipmi_1_5_packet (buf, buflen)) < 0)
1435     {
1436       IPMICONSOLE_CTX_DEBUG (c, ("ipmi_is_ipmi_1_5_packet: %s", strerror (errno)));
1437       /* Assume malformed packet */
1438       pkt_ret = 0;
1439       goto out;
1440     }
1441 
1442   if (ret)
1443     {
1444       if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_GET_AUTHENTICATION_CAPABILITIES_SENT)
1445         pkt = IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS;
1446       else
1447         {
1448           /* Unexpected packet, throw it away */
1449           IPMICONSOLE_CTX_DEBUG (c, ("Unexpected IPMI 1.5 Packet: protocol_state = %d", c->session.protocol_state));
1450           pkt_ret = 0;
1451           goto out;
1452         }
1453 
1454       obj_cmd =  ipmiconsole_packet_object (c, pkt);
1455 
1456       if ((pkt_ret = unassemble_ipmi_lan_pkt (buf,
1457                                               buflen,
1458                                               c->connection.obj_rmcp_hdr_rs,
1459                                               c->connection.obj_lan_session_hdr_rs,
1460                                               c->connection.obj_lan_msg_hdr_rs,
1461                                               obj_cmd,
1462                                               c->connection.obj_lan_msg_trlr_rs,
1463                                               IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
1464         {
1465           IPMICONSOLE_CTX_DEBUG (c, ("unassemble_ipmi_lan_pkt: %s", strerror (errno)));
1466           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1467           return (-1);
1468         }
1469       *p = pkt;
1470     }
1471   else
1472     {
1473       uint8_t payload_type;
1474 
1475       if (ipmi_rmcpplus_calculate_payload_type (buf, buflen, &payload_type) < 0)
1476         {
1477           IPMICONSOLE_CTX_DEBUG (c, ("ipmi_rmcpplus_calculate_payload_type: %s", strerror (errno)));
1478           /* Assume malformed packet */
1479           pkt_ret = 0;
1480           goto out;
1481         }
1482 
1483       if (payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE
1484           || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2
1485           || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4)
1486         {
1487           if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_OPEN_SESSION_REQUEST_SENT)
1488             pkt = IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE;
1489           else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_RAKP_MESSAGE_1_SENT)
1490             pkt = IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2;
1491           else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_RAKP_MESSAGE_3_SENT)
1492             pkt = IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4;
1493           else
1494             {
1495               IPMICONSOLE_CTX_DEBUG (c, ("Unexpected IPMI 2.0 Session Setup Packet: protocol_state = %d", c->session.protocol_state));
1496               pkt_ret = 0;
1497               goto out;
1498             }
1499 
1500           obj_cmd =  ipmiconsole_packet_object (c, pkt);
1501 
1502           /* IPMI 2.0 Pre-Session Establishment Packets */
1503           if ((pkt_ret = unassemble_ipmi_rmcpplus_pkt (IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE,
1504                                                        IPMI_INTEGRITY_ALGORITHM_NONE,
1505                                                        IPMI_CONFIDENTIALITY_ALGORITHM_NONE,
1506                                                        NULL,
1507                                                        0,
1508                                                        NULL,
1509                                                        0,
1510                                                        buf,
1511                                                        buflen,
1512                                                        c->connection.obj_rmcp_hdr_rs,
1513                                                        c->connection.obj_rmcpplus_session_hdr_rs,
1514                                                        c->connection.obj_rmcpplus_payload_rs,
1515                                                        c->connection.obj_lan_msg_hdr_rs,
1516                                                        obj_cmd,
1517                                                        c->connection.obj_lan_msg_trlr_rs,
1518                                                        c->connection.obj_rmcpplus_session_trlr_rs,
1519                                                        IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
1520             {
1521               IPMICONSOLE_CTX_DEBUG (c, ("unassemble_ipmi_rmcpplus_pkt: %s", strerror (errno)));
1522               ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1523               return (-1);
1524             }
1525           *p = pkt;
1526         }
1527       else if (payload_type == IPMI_PAYLOAD_TYPE_IPMI
1528                || payload_type == IPMI_PAYLOAD_TYPE_SOL)
1529         {
1530           if (payload_type == IPMI_PAYLOAD_TYPE_IPMI)
1531             {
1532               if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_SET_SESSION_PRIVILEGE_LEVEL_SENT)
1533                 pkt = IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS;
1534               else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_GET_CHANNEL_PAYLOAD_SUPPORT_SENT)
1535                 pkt = IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_SUPPORT_RS;
1536               else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_GET_PAYLOAD_ACTIVATION_STATUS_SENT)
1537                 pkt = IPMICONSOLE_PACKET_TYPE_GET_PAYLOAD_ACTIVATION_STATUS_RS;
1538               else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_ACTIVATE_PAYLOAD_SENT)
1539                 pkt = IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS;
1540               else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_SOL_SESSION)
1541                 pkt = IPMICONSOLE_PACKET_TYPE_GET_CHANNEL_PAYLOAD_VERSION_RS;
1542               else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_DEACTIVATE_PAYLOAD_SENT)
1543                 pkt = IPMICONSOLE_PACKET_TYPE_DEACTIVATE_PAYLOAD_RS;
1544               else if (c->session.protocol_state == IPMICONSOLE_PROTOCOL_STATE_CLOSE_SESSION_SENT)
1545                 pkt = IPMICONSOLE_PACKET_TYPE_CLOSE_SESSION_RS;
1546               else
1547                 {
1548                   IPMICONSOLE_CTX_DEBUG (c, ("Unexpected IPMI 2.0 IPMI Packet: protocol_state = %d", c->session.protocol_state));
1549                   pkt_ret = 0;
1550                   goto out;
1551                 }
1552             }
1553           else
1554             {
1555               if (c->session.protocol_state != IPMICONSOLE_PROTOCOL_STATE_SOL_SESSION)
1556                 {
1557                   IPMICONSOLE_CTX_DEBUG (c, ("Unexpected IPMI 2.0 SOL Packet: protocol_state = %d", c->session.protocol_state));
1558                   pkt_ret = 0;
1559                   goto out;
1560                 }
1561               pkt = IPMICONSOLE_PACKET_TYPE_SOL_PAYLOAD_DATA_RS;
1562             }
1563 
1564           obj_cmd =  ipmiconsole_packet_object (c, pkt);
1565 
1566           /* IPMI 2.0 Session Packets */
1567           if ((pkt_ret = unassemble_ipmi_rmcpplus_pkt (c->config.authentication_algorithm,
1568                                                        c->config.integrity_algorithm,
1569                                                        c->config.confidentiality_algorithm,
1570                                                        c->session.integrity_key_ptr,
1571                                                        c->session.integrity_key_len,
1572                                                        c->session.confidentiality_key_ptr,
1573                                                        c->session.confidentiality_key_len,
1574                                                        buf,
1575                                                        buflen,
1576                                                        c->connection.obj_rmcp_hdr_rs,
1577                                                        c->connection.obj_rmcpplus_session_hdr_rs,
1578                                                        c->connection.obj_rmcpplus_payload_rs,
1579                                                        c->connection.obj_lan_msg_hdr_rs,
1580                                                        obj_cmd,
1581                                                        c->connection.obj_lan_msg_trlr_rs,
1582                                                        c->connection.obj_rmcpplus_session_trlr_rs,
1583                                                        IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
1584             {
1585               IPMICONSOLE_CTX_DEBUG (c, ("unassemble_ipmi_rmcpplus_pkt: %s", strerror (errno)));
1586               ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1587               return (-1);
1588             }
1589           *p = pkt;
1590         }
1591       else
1592         {
1593           IPMICONSOLE_CTX_DEBUG (c, ("Unexpected payload_type: payload_type = %u", payload_type));
1594           pkt_ret = 0;
1595           goto out;
1596         }
1597     }
1598 
1599  out:
1600   return (pkt_ret);
1601 }
1602 
1603 int
1604 ipmiconsole_calculate_errnum (ipmiconsole_ctx_t c,
1605                               ipmiconsole_packet_type_t p)
1606 {
1607   fiid_obj_t obj_cmd;
1608   uint64_t val;
1609 
1610   assert (c);
1611   assert (c->magic == IPMICONSOLE_CTX_MAGIC);
1612   assert (IPMICONSOLE_PACKET_TYPE_RESPONSE (p));
1613 
1614   if (!(obj_cmd = ipmiconsole_packet_object (c, p)))
1615     return (-1);
1616 
1617   if (p == IPMICONSOLE_PACKET_TYPE_OPEN_SESSION_RESPONSE
1618       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_2
1619       || p == IPMICONSOLE_PACKET_TYPE_RAKP_MESSAGE_4)
1620     {
1621       uint8_t rmcpplus_status_code;
1622 
1623       if (FIID_OBJ_GET (obj_cmd, "rmcpplus_status_code", &val) < 0)
1624         {
1625           IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get: 'rmcpplus_status_code': %s",
1626                                      fiid_obj_errormsg (obj_cmd)));
1627           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1628           return (-1);
1629         }
1630       rmcpplus_status_code = val;
1631 
1632       if (rmcpplus_status_code == RMCPPLUS_STATUS_NO_ERRORS)
1633         {
1634           IPMICONSOLE_CTX_DEBUG (c, ("called with valid success code; p = %d", p));
1635           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1636           return (-1);
1637         }
1638       else if (rmcpplus_status_code == RMCPPLUS_STATUS_INSUFFICIENT_RESOURCES_TO_CREATE_A_SESSION
1639                || rmcpplus_status_code == RMCPPLUS_STATUS_INSUFFICIENT_RESOURCES_TO_CREATE_A_SESSION_AT_THE_REQUESTED_TIME)
1640         {
1641           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_BMC_BUSY);
1642           return (0);
1643         }
1644       else if (rmcpplus_status_code == RMCPPLUS_STATUS_UNAUTHORIZED_ROLE_OR_PRIVILEGE_LEVEL_REQUESTED
1645                || rmcpplus_status_code == RMCPPLUS_STATUS_INVALID_ROLE)
1646         {
1647           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED);
1648           return (0);
1649         }
1650       else if (rmcpplus_status_code == RMCPPLUS_STATUS_UNAUTHORIZED_NAME)
1651         {
1652           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_USERNAME_INVALID);
1653           return (0);
1654         }
1655       else if (rmcpplus_status_code == RMCPPLUS_STATUS_NO_CIPHER_SUITE_MATCH_WITH_PROPOSED_SECURITY_ALGORITHMS)
1656         {
1657           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_CIPHER_SUITE_ID_UNAVAILABLE);
1658           return (0);
1659         }
1660       else if (rmcpplus_status_code == RMCPPLUS_STATUS_INVALID_INTEGRITY_CHECK_VALUE)
1661         {
1662           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_PASSWORD_INVALID);
1663           return (0);
1664         }
1665     }
1666   else
1667     {
1668       uint8_t comp_code;
1669 
1670       if (FIID_OBJ_GET (obj_cmd, "comp_code", &val) < 0)
1671         {
1672           IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_get: 'comp_code': %s",
1673                                      fiid_obj_errormsg (obj_cmd)));
1674           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1675           return (-1);
1676         }
1677       comp_code = val;
1678 
1679       if (comp_code == IPMI_COMP_CODE_COMMAND_SUCCESS)
1680         {
1681           IPMICONSOLE_CTX_DEBUG (c, ("called with valid success code; p = %d", p));
1682           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
1683           return (-1);
1684         }
1685 
1686       if (p == IPMICONSOLE_PACKET_TYPE_GET_AUTHENTICATION_CAPABILITIES_RS
1687           && comp_code == IPMI_COMP_CODE_INVALID_DATA_FIELD_IN_REQUEST)
1688         {
1689           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_IPMI_2_0_UNAVAILABLE);
1690           return (0);
1691         }
1692       else if (p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
1693                && (comp_code == IPMI_COMP_CODE_ACTIVATE_PAYLOAD_PAYLOAD_ALREADY_ACTIVE_ON_ANOTHER_SESSION
1694                    || comp_code == IPMI_COMP_CODE_ACTIVATE_PAYLOAD_PAYLOAD_ACTIVATION_LIMIT_REACHED))
1695         {
1696           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SOL_INUSE);
1697           return (0);
1698         }
1699       else if (p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
1700                && comp_code == IPMI_COMP_CODE_ACTIVATE_PAYLOAD_CANNOT_ACTIVATE_PAYLOAD_WITH_ENCRYPTION)
1701         {
1702           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SOL_REQUIRES_NO_ENCRYPTION);
1703           return (0);
1704         }
1705       /* Workaround
1706        *
1707        * Inventec 5441/Dell Xanadu II returns
1708        * IPMI_COMP_CODE_PARAMETER_OUT_OF_RANGE, so we'll assume that
1709        * return code always means we need encryption.
1710        */
1711       else if (p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
1712                && (comp_code == IPMI_COMP_CODE_ACTIVATE_PAYLOAD_CANNOT_ACTIVATE_PAYLOAD_WITHOUT_ENCRYPTION
1713                    || comp_code == IPMI_COMP_CODE_PARAMETER_OUT_OF_RANGE))
1714         {
1715           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SOL_REQUIRES_ENCRYPTION);
1716           return (0);
1717         }
1718       else if (p == IPMICONSOLE_PACKET_TYPE_ACTIVATE_PAYLOAD_RS
1719                && comp_code == IPMI_COMP_CODE_ACTIVATE_PAYLOAD_PAYLOAD_TYPE_IS_DISABLED)
1720         {
1721           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SOL_UNAVAILABLE);
1722           return (0);
1723         }
1724       else if (p == IPMICONSOLE_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
1725                && (comp_code == IPMI_COMP_CODE_SET_SESSION_PRIVILEGE_LEVEL_REQUESTED_LEVEL_NOT_AVAILABLE_FOR_USER
1726                    || comp_code == IPMI_COMP_CODE_SET_SESSION_PRIVILEGE_LEVEL_REQUESTED_LEVEL_EXCEEDS_USER_PRIVILEGE_LIMIT))
1727         {
1728           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED);
1729           return (0);
1730         }
1731 
1732       if (comp_code == IPMI_COMP_CODE_INSUFFICIENT_PRIVILEGE_LEVEL)
1733         {
1734           ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_PRIVILEGE_LEVEL_INSUFFICIENT);
1735           return (0);
1736         }
1737 
1738     }
1739 
1740   ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_BMC_ERROR);
1741   return (0);
1742 }
1743