1 /*****************************************************************************\
2  *  $Id: ipmipower_packet.c,v 1.127 2010-06-11 16:29:34 chu11 Exp $
3  *****************************************************************************
4  *  Copyright (C) 2007-2015 Lawrence Livermore National Security, LLC.
5  *  Copyright (C) 2003-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-155698
9  *
10  *  This file is part of Ipmipower, a remote power control utility.
11  *  For details, see http://www.llnl.gov/linux/.
12  *
13  *  Ipmipower 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  *  Ipmipower 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 Ipmipower.  If not, see <http://www.gnu.org/licenses/>.
25 \*****************************************************************************/
26 
27 #if HAVE_CONFIG_H
28 #include "config.h"
29 #endif /* HAVE_CONFIG_H */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #if STDC_HEADERS
34 #include <string.h>
35 #endif /* STDC_HEADERS */
36 #if HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif /* HAVE_UNISTD_H */
39 #include <errno.h>
40 #include <assert.h>
41 #include <stdint.h>
42 
43 #include "ipmipower_packet.h"
44 #include "ipmipower_error.h"
45 #include "ipmipower_oem.h"
46 #include "ipmipower_util.h"
47 
48 #include "freeipmi-portability.h"
49 #include "debug-util.h"
50 
51 extern struct ipmipower_arguments cmd_args;
52 
53 fiid_field_t *
ipmipower_packet_cmd_template(ipmipower_powercmd_t ip,ipmipower_packet_type_t pkt)54 ipmipower_packet_cmd_template (ipmipower_powercmd_t ip, ipmipower_packet_type_t pkt)
55 {
56   assert (ip);
57   assert (IPMIPOWER_PACKET_TYPE_VALID (pkt));
58 
59   switch (pkt)
60     {
61     case IPMIPOWER_PACKET_TYPE_AUTHENTICATION_CAPABILITIES_RQ:
62       return (&tmpl_cmd_get_channel_authentication_capabilities_rq[0]);
63     case IPMIPOWER_PACKET_TYPE_AUTHENTICATION_CAPABILITIES_RS:
64       return (&tmpl_cmd_get_channel_authentication_capabilities_rs[0]);
65     case IPMIPOWER_PACKET_TYPE_GET_SESSION_CHALLENGE_RQ:
66       return (&tmpl_cmd_get_session_challenge_rq[0]);
67     case IPMIPOWER_PACKET_TYPE_GET_SESSION_CHALLENGE_RS:
68       return (&tmpl_cmd_get_session_challenge_rs[0]);
69     case IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RQ:
70       return (&tmpl_cmd_activate_session_rq[0]);
71     case IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RS:
72       return (&tmpl_cmd_activate_session_rs[0]);
73     case IPMIPOWER_PACKET_TYPE_OPEN_SESSION_REQUEST:
74       return (&tmpl_rmcpplus_open_session_request[0]);
75     case IPMIPOWER_PACKET_TYPE_OPEN_SESSION_RESPONSE:
76       return (&tmpl_rmcpplus_open_session_response[0]);
77     case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_1:
78       return (&tmpl_rmcpplus_rakp_message_1[0]);
79     case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_2:
80       return (&tmpl_rmcpplus_rakp_message_2[0]);
81     case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_3:
82       return (&tmpl_rmcpplus_rakp_message_3[0]);
83     case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_4:
84       return (&tmpl_rmcpplus_rakp_message_4[0]);
85     case IPMIPOWER_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ:
86       return (&tmpl_cmd_set_session_privilege_level_rq[0]);
87     case IPMIPOWER_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS:
88       return (&tmpl_cmd_set_session_privilege_level_rs[0]);
89     case IPMIPOWER_PACKET_TYPE_GET_CHASSIS_STATUS_RQ:
90       return (&tmpl_cmd_get_chassis_status_rq[0]);
91     case IPMIPOWER_PACKET_TYPE_GET_CHASSIS_STATUS_RS:
92       return (&tmpl_cmd_get_chassis_status_rs[0]);
93     case IPMIPOWER_PACKET_TYPE_CHASSIS_CONTROL_RQ:
94       return (&tmpl_cmd_chassis_control_rq[0]);
95     case IPMIPOWER_PACKET_TYPE_CHASSIS_CONTROL_RS:
96       return (&tmpl_cmd_chassis_control_rs[0]);
97     case IPMIPOWER_PACKET_TYPE_CHASSIS_IDENTIFY_RQ:
98       return (&tmpl_cmd_chassis_identify_rq[0]);
99     case IPMIPOWER_PACKET_TYPE_CHASSIS_IDENTIFY_RS:
100       return (&tmpl_cmd_chassis_identify_rs[0]);
101     case IPMIPOWER_PACKET_TYPE_C410X_GET_SENSOR_READING_RQ:
102       return (&tmpl_cmd_get_sensor_reading_rq[0]);
103     case IPMIPOWER_PACKET_TYPE_C410X_GET_SENSOR_READING_RS:
104       return (&tmpl_cmd_get_sensor_reading_rs[0]);
105     case IPMIPOWER_PACKET_TYPE_C410X_SLOT_POWER_CONTROL_RQ:
106       return (&tmpl_cmd_c410x_slot_power_control_rq[0]);
107     case IPMIPOWER_PACKET_TYPE_C410X_SLOT_POWER_CONTROL_RS:
108       return (&tmpl_cmd_c410x_slot_power_control_rs[0]);
109     case IPMIPOWER_PACKET_TYPE_CLOSE_SESSION_RQ:
110       return (&tmpl_cmd_close_session_rq[0]);
111     case IPMIPOWER_PACKET_TYPE_CLOSE_SESSION_RS:
112       return (&tmpl_cmd_close_session_rs[0]);
113     default:
114       IPMIPOWER_ERROR (("ipmipower_packet_cmd_template: invalid packet type: %d", pkt));
115       exit (EXIT_FAILURE);
116     }
117 
118   return (NULL);                  /* NOT REACHED */
119 }
120 
121 fiid_obj_t
ipmipower_packet_cmd_obj(ipmipower_powercmd_t ip,ipmipower_packet_type_t pkt)122 ipmipower_packet_cmd_obj (ipmipower_powercmd_t ip, ipmipower_packet_type_t pkt)
123 {
124   assert (ip);
125   assert (IPMIPOWER_PACKET_TYPE_VALID (pkt));
126 
127   switch (pkt)
128     {
129     case IPMIPOWER_PACKET_TYPE_AUTHENTICATION_CAPABILITIES_RQ:
130       return (ip->obj_authentication_capabilities_rq);
131     case IPMIPOWER_PACKET_TYPE_AUTHENTICATION_CAPABILITIES_RS:
132       return (ip->obj_authentication_capabilities_rs);
133     case IPMIPOWER_PACKET_TYPE_GET_SESSION_CHALLENGE_RQ:
134       return (ip->obj_get_session_challenge_rq);
135     case IPMIPOWER_PACKET_TYPE_GET_SESSION_CHALLENGE_RS:
136       return (ip->obj_get_session_challenge_rs);
137     case IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RQ:
138       return (ip->obj_activate_session_rq);
139     case IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RS:
140       return (ip->obj_activate_session_rs);
141     case IPMIPOWER_PACKET_TYPE_OPEN_SESSION_REQUEST:
142       return (ip->obj_open_session_rq);
143     case IPMIPOWER_PACKET_TYPE_OPEN_SESSION_RESPONSE:
144       return (ip->obj_open_session_rs);
145     case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_1:
146       return (ip->obj_rakp_message_1_rq);
147     case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_2:
148       return (ip->obj_rakp_message_2_rs);
149     case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_3:
150       return (ip->obj_rakp_message_3_rq);
151     case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_4:
152       return (ip->obj_rakp_message_4_rs);
153     case IPMIPOWER_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ:
154       return (ip->obj_set_session_privilege_level_rq);
155     case IPMIPOWER_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS:
156       return (ip->obj_set_session_privilege_level_rs);
157     case IPMIPOWER_PACKET_TYPE_GET_CHASSIS_STATUS_RQ:
158       return (ip->obj_get_chassis_status_rq);
159     case IPMIPOWER_PACKET_TYPE_GET_CHASSIS_STATUS_RS:
160       return (ip->obj_get_chassis_status_rs);
161     case IPMIPOWER_PACKET_TYPE_CHASSIS_CONTROL_RQ:
162       return (ip->obj_chassis_control_rq);
163     case IPMIPOWER_PACKET_TYPE_CHASSIS_CONTROL_RS:
164       return (ip->obj_chassis_control_rs);
165     case IPMIPOWER_PACKET_TYPE_CHASSIS_IDENTIFY_RQ:
166       return (ip->obj_chassis_identify_rq);
167     case IPMIPOWER_PACKET_TYPE_CHASSIS_IDENTIFY_RS:
168       return (ip->obj_chassis_identify_rs);
169     case IPMIPOWER_PACKET_TYPE_C410X_GET_SENSOR_READING_RQ:
170       return (ip->obj_c410x_get_sensor_reading_rq);
171     case IPMIPOWER_PACKET_TYPE_C410X_GET_SENSOR_READING_RS:
172       return (ip->obj_c410x_get_sensor_reading_rs);
173     case IPMIPOWER_PACKET_TYPE_C410X_SLOT_POWER_CONTROL_RQ:
174       return (ip->obj_c410x_slot_power_control_rq);
175     case IPMIPOWER_PACKET_TYPE_C410X_SLOT_POWER_CONTROL_RS:
176       return (ip->obj_c410x_slot_power_control_rs);
177     case IPMIPOWER_PACKET_TYPE_CLOSE_SESSION_RQ:
178       return (ip->obj_close_session_rq);
179     case IPMIPOWER_PACKET_TYPE_CLOSE_SESSION_RS:
180       return (ip->obj_close_session_rs);
181     default:
182       IPMIPOWER_ERROR (("ipmipower_packet_cmd_obj: invalid packet type: %d", pkt));
183       exit (EXIT_FAILURE);
184     }
185 
186   return (NULL);                  /* NOT REACHED */
187 }
188 
189 void
ipmipower_packet_dump(ipmipower_powercmd_t ip,ipmipower_packet_type_t pkt,const void * buf,unsigned int buflen)190 ipmipower_packet_dump (ipmipower_powercmd_t ip,
191                        ipmipower_packet_type_t pkt,
192                        const void *buf,
193                        unsigned int buflen)
194 {
195   assert (ip);
196   assert (IPMIPOWER_PACKET_TYPE_VALID (pkt));
197   assert (buf);
198 
199   if (cmd_args.common_args.debug)
200     {
201       fiid_field_t *tmpl_lan_msg_hdr;
202       char hdrbuf[DEBUG_UTIL_HDR_BUFLEN + 1];
203       uint8_t packet_type;
204       uint8_t packet_direction;
205       const char *str_cmd = NULL;
206 
207       if (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN)
208         packet_type = DEBUG_UTIL_TYPE_IPMI_1_5;
209       else
210         packet_type = DEBUG_UTIL_TYPE_IPMI_2_0;
211 
212       switch (pkt)
213         {
214         case IPMIPOWER_PACKET_TYPE_AUTHENTICATION_CAPABILITIES_RQ:
215         case IPMIPOWER_PACKET_TYPE_AUTHENTICATION_CAPABILITIES_RS:
216           str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES);
217           break;
218         case IPMIPOWER_PACKET_TYPE_GET_SESSION_CHALLENGE_RQ:
219         case IPMIPOWER_PACKET_TYPE_GET_SESSION_CHALLENGE_RS:
220           str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_SESSION_CHALLENGE);
221           break;
222         case IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RQ:
223         case IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RS:
224           str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_ACTIVATE_SESSION);
225           break;
226         case IPMIPOWER_PACKET_TYPE_OPEN_SESSION_REQUEST:
227         case IPMIPOWER_PACKET_TYPE_OPEN_SESSION_RESPONSE:
228           str_cmd = DEBUG_UTIL_OPEN_SESSION_STR;
229           break;
230         case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_1:
231           str_cmd = DEBUG_UTIL_RAKP_1_STR;
232           break;
233         case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_2:
234           str_cmd = DEBUG_UTIL_RAKP_2_STR;
235           break;
236         case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_3:
237           str_cmd = DEBUG_UTIL_RAKP_3_STR;
238           break;
239         case IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_4:
240           str_cmd = DEBUG_UTIL_RAKP_4_STR;
241           break;
242         case IPMIPOWER_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ:
243         case IPMIPOWER_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS:
244           str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_SET_SESSION_PRIVILEGE_LEVEL);
245           break;
246         case IPMIPOWER_PACKET_TYPE_GET_CHASSIS_STATUS_RQ:
247         case IPMIPOWER_PACKET_TYPE_GET_CHASSIS_STATUS_RS:
248           str_cmd = ipmi_cmd_str (IPMI_NET_FN_CHASSIS_RQ, IPMI_CMD_GET_CHASSIS_STATUS);
249           break;
250         case IPMIPOWER_PACKET_TYPE_CHASSIS_CONTROL_RQ:
251         case IPMIPOWER_PACKET_TYPE_CHASSIS_CONTROL_RS:
252           str_cmd = ipmi_cmd_str (IPMI_NET_FN_CHASSIS_RQ, IPMI_CMD_CHASSIS_CONTROL);
253           break;
254         case IPMIPOWER_PACKET_TYPE_CHASSIS_IDENTIFY_RQ:
255         case IPMIPOWER_PACKET_TYPE_CHASSIS_IDENTIFY_RS:
256           str_cmd = ipmi_cmd_str (IPMI_NET_FN_CHASSIS_RQ, IPMI_CMD_CHASSIS_IDENTIFY);
257           break;
258         case IPMIPOWER_PACKET_TYPE_C410X_GET_SENSOR_READING_RQ:
259         case IPMIPOWER_PACKET_TYPE_C410X_GET_SENSOR_READING_RS:
260           str_cmd = ipmi_cmd_str (IPMI_NET_FN_SENSOR_EVENT_RQ, IPMI_CMD_GET_SENSOR_READING);
261           break;
262         case IPMIPOWER_PACKET_TYPE_C410X_SLOT_POWER_CONTROL_RQ:
263         case IPMIPOWER_PACKET_TYPE_C410X_SLOT_POWER_CONTROL_RS:
264           str_cmd = "C410x Slot Power Control";
265           break;
266         case IPMIPOWER_PACKET_TYPE_CLOSE_SESSION_RQ:
267         case IPMIPOWER_PACKET_TYPE_CLOSE_SESSION_RS:
268           str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_CLOSE_SESSION);
269           break;
270         default:
271           IPMIPOWER_ERROR (("ipmipower_packet_dump: invalid packet type: %d", pkt));
272           exit (EXIT_FAILURE);
273         }
274 
275       if (IPMIPOWER_PACKET_TYPE_RQ (pkt))
276         packet_direction = DEBUG_UTIL_DIRECTION_REQUEST;
277       else
278         packet_direction = DEBUG_UTIL_DIRECTION_RESPONSE;
279 
280       memset (hdrbuf, '\0', DEBUG_UTIL_HDR_BUFLEN + 1);
281       debug_hdr_str (packet_type,
282                      packet_direction,
283                      DEBUG_UTIL_FLAGS_DEFAULT,
284                      str_cmd,
285                      hdrbuf,
286                      DEBUG_UTIL_HDR_BUFLEN);
287 
288       if (IPMIPOWER_PACKET_TYPE_RQ (pkt))
289         tmpl_lan_msg_hdr = &tmpl_lan_msg_hdr_rq[0];
290       else
291         tmpl_lan_msg_hdr = &tmpl_lan_msg_hdr_rs[0];
292 
293       if (IPMIPOWER_PACKET_TYPE_IPMI_2_0_SETUP (pkt))
294         {
295           if (ipmi_dump_rmcpplus_packet (STDERR_FILENO,
296                                          ip->ic->hostname,
297                                          hdrbuf,
298                                          NULL,
299                                          IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE,
300                                          IPMI_INTEGRITY_ALGORITHM_NONE,
301                                          IPMI_CONFIDENTIALITY_ALGORITHM_NONE,
302                                          NULL,
303                                          0,
304                                          NULL,
305                                          0,
306                                          buf,
307                                          buflen,
308                                          tmpl_lan_msg_hdr,
309                                          ipmipower_packet_cmd_template (ip, pkt)) < 0)
310             {
311               IPMIPOWER_ERROR (("ipmi_dump_rmcpplus_packet: %s", strerror (errno)));
312               exit (EXIT_FAILURE);
313             }
314         }
315       else if (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN_2_0
316                && IPMIPOWER_PACKET_TYPE_IPMI_SESSION_PACKET (pkt))
317         {
318           if (ipmi_dump_rmcpplus_packet (STDERR_FILENO,
319                                          ip->ic->hostname,
320                                          hdrbuf,
321                                          NULL,
322                                          ip->authentication_algorithm,
323                                          ip->integrity_algorithm,
324                                          ip->confidentiality_algorithm,
325                                          ip->integrity_key_ptr,
326                                          ip->integrity_key_len,
327                                          ip->confidentiality_key_ptr,
328                                          ip->confidentiality_key_len,
329                                          buf,
330                                          buflen,
331                                          tmpl_lan_msg_hdr,
332                                          ipmipower_packet_cmd_template (ip, pkt)) < 0)
333             {
334               IPMIPOWER_ERROR (("ipmi_dump_rmcpplus_packet: %s", strerror (errno)));
335               exit (EXIT_FAILURE);
336             }
337         }
338       else /* cmd_args.common_args.driver_type == IPMI_DEVICE_LAN
339               && IPMIPOWER_PACKET_TYPE_IPMI_SESSION_PACKET (pkt))
340            */
341         {
342           if (ipmi_dump_lan_packet (STDERR_FILENO,
343                                     ip->ic->hostname,
344                                     hdrbuf,
345                                     NULL,
346                                     buf,
347                                     buflen,
348                                     tmpl_lan_msg_hdr,
349                                     ipmipower_packet_cmd_template (ip, pkt)) < 0)
350             {
351               IPMIPOWER_ERROR (("ipmi_dump_lan_packet: %s", strerror (errno)));
352               exit (EXIT_FAILURE);
353             }
354         }
355     }
356 }
357 
358 int
ipmipower_packet_store(ipmipower_powercmd_t ip,ipmipower_packet_type_t pkt,const void * buf,unsigned int buflen)359 ipmipower_packet_store (ipmipower_powercmd_t ip,
360                         ipmipower_packet_type_t pkt,
361                         const void *buf,
362                         unsigned int buflen)
363 {
364   fiid_obj_t obj;
365   int rv = -1;
366 
367   assert (ip);
368   assert (buf);
369   assert (buflen);
370   assert (IPMIPOWER_PACKET_TYPE_RS (pkt));
371 
372   obj = ipmipower_packet_cmd_obj (ip, pkt);
373 
374   if (IPMIPOWER_PACKET_TYPE_IPMI_1_5_SETUP_RS (pkt)
375       || cmd_args.common_args.driver_type == IPMI_DEVICE_LAN)
376     {
377       if ((rv = unassemble_ipmi_lan_pkt (buf,
378                                          buflen,
379                                          ip->obj_rmcp_hdr_rs,
380                                          ip->obj_lan_session_hdr_rs,
381                                          ip->obj_lan_msg_hdr_rs,
382                                          obj,
383                                          ip->obj_lan_msg_trlr_rs,
384                                          IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
385         {
386           IPMIPOWER_ERROR (("unassemble_ipmi_lan_pkt: %s", strerror (errno)));
387           exit (EXIT_FAILURE);
388         }
389     }
390   else
391     {
392       if (IPMIPOWER_PACKET_TYPE_IPMI_2_0_SETUP_RS (pkt))
393         {
394           if ((rv = unassemble_ipmi_rmcpplus_pkt (IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE,
395                                                   IPMI_INTEGRITY_ALGORITHM_NONE,
396                                                   IPMI_CONFIDENTIALITY_ALGORITHM_NONE,
397                                                   NULL,
398                                                   0,
399                                                   NULL,
400                                                   0,
401                                                   buf,
402                                                   buflen,
403                                                   ip->obj_rmcp_hdr_rs,
404                                                   ip->obj_rmcpplus_session_hdr_rs,
405                                                   ip->obj_rmcpplus_payload_rs,
406                                                   ip->obj_lan_msg_hdr_rs,
407                                                   obj,
408                                                   ip->obj_lan_msg_trlr_rs,
409                                                   ip->obj_rmcpplus_session_trlr_rs,
410                                                   IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
411             {
412               IPMIPOWER_ERROR (("unassemble_ipmi_rmcpplus_pkt: %s", strerror (errno)));
413               exit (EXIT_FAILURE);
414             }
415         }
416       else
417         {
418           if ((rv = unassemble_ipmi_rmcpplus_pkt (ip->authentication_algorithm,
419                                                   ip->integrity_algorithm,
420                                                   ip->confidentiality_algorithm,
421                                                   ip->integrity_key_ptr,
422                                                   ip->integrity_key_len,
423                                                   ip->confidentiality_key_ptr,
424                                                   ip->confidentiality_key_len,
425                                                   buf,
426                                                   buflen,
427                                                   ip->obj_rmcp_hdr_rs,
428                                                   ip->obj_rmcpplus_session_hdr_rs,
429                                                   ip->obj_rmcpplus_payload_rs,
430                                                   ip->obj_lan_msg_hdr_rs,
431                                                   obj,
432                                                   ip->obj_lan_msg_trlr_rs,
433                                                   ip->obj_rmcpplus_session_trlr_rs,
434                                                   IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
435             {
436               IPMIPOWER_ERROR (("unassemble_ipmi_rmcpplus_pkt: %s", strerror (errno)));
437               exit (EXIT_FAILURE);
438             }
439         }
440     }
441 
442   return (rv);
443 }
444 
445 static int
_ipmi_1_5_packet_create(ipmipower_powercmd_t ip,ipmipower_packet_type_t pkt,uint8_t authentication_type,uint32_t inbound_sequence_number,uint32_t session_id,void * authentication_code_data,unsigned int authentication_code_data_len,uint8_t net_fn,fiid_obj_t obj_cmd_rq,void * buf,unsigned int buflen)446 _ipmi_1_5_packet_create (ipmipower_powercmd_t ip,
447                          ipmipower_packet_type_t pkt,
448                          uint8_t authentication_type,
449                          uint32_t inbound_sequence_number,
450                          uint32_t session_id,
451                          void *authentication_code_data,
452                          unsigned int authentication_code_data_len,
453                          uint8_t net_fn,
454                          fiid_obj_t obj_cmd_rq,
455                          void *buf,
456                          unsigned int buflen)
457 {
458   int len;
459 
460   assert (ip);
461   assert (IPMIPOWER_PACKET_TYPE_RQ (pkt));
462   assert (fiid_obj_valid (obj_cmd_rq));
463   assert (buf);
464   assert (buflen);
465 
466   if (fill_rmcp_hdr_ipmi (ip->obj_rmcp_hdr_rq) < 0)
467     {
468       IPMIPOWER_ERROR (("fill_rmcp_hdr_ipmi: %s", strerror (errno)));
469       exit (EXIT_FAILURE);
470     }
471 
472   if (fill_lan_session_hdr (authentication_type,
473                             inbound_sequence_number,
474                             session_id,
475                             ip->obj_lan_session_hdr_rq) < 0)
476     {
477       IPMIPOWER_ERROR (("fill_lan_session_hdr: %s", strerror (errno)));
478       exit (EXIT_FAILURE);
479     }
480 
481   if (fill_lan_msg_hdr (IPMI_SLAVE_ADDRESS_BMC,
482                         net_fn,
483                         IPMI_BMC_IPMB_LUN_BMC,
484                         (ip->ic->ipmi_requester_sequence_number_counter % (IPMI_LAN_REQUESTER_SEQUENCE_NUMBER_MAX + 1)),
485                         ip->obj_lan_msg_hdr_rq) < 0)
486     {
487       IPMIPOWER_ERROR (("fill_lan_msg_hdr: %s", strerror (errno)));
488       exit (EXIT_FAILURE);
489     }
490 
491   if ((len = assemble_ipmi_lan_pkt (ip->obj_rmcp_hdr_rq,
492                                     ip->obj_lan_session_hdr_rq,
493                                     ip->obj_lan_msg_hdr_rq,
494                                     obj_cmd_rq,
495                                     authentication_code_data,
496                                     authentication_code_data_len,
497                                     buf,
498                                     buflen,
499                                     IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
500     {
501       IPMIPOWER_ERROR (("assemble_ipmi_lan_pkt: %s", strerror (errno)));
502       exit (EXIT_FAILURE);
503     }
504 
505   return (len);
506 }
507 
508 static int
_ipmi_2_0_packet_create(ipmipower_powercmd_t ip,ipmipower_packet_type_t pkt,uint8_t payload_type,uint8_t payload_authenticated,uint8_t payload_encrypted,uint32_t session_id,uint32_t session_sequence_number,void * authentication_code_data,unsigned int authentication_code_data_len,uint8_t net_fn,uint8_t authentication_algorithm,uint8_t integrity_algorithm,uint8_t confidentiality_algorithm,void * integrity_key,unsigned int integrity_key_len,void * confidentiality_key,unsigned int confidentiality_key_len,fiid_obj_t obj_cmd_rq,void * buf,unsigned int buflen)509 _ipmi_2_0_packet_create (ipmipower_powercmd_t ip,
510                          ipmipower_packet_type_t pkt,
511                          uint8_t payload_type,
512                          uint8_t payload_authenticated,
513                          uint8_t payload_encrypted,
514                          uint32_t session_id,
515                          uint32_t session_sequence_number,
516                          void *authentication_code_data,
517                          unsigned int authentication_code_data_len,
518                          uint8_t net_fn,
519                          uint8_t authentication_algorithm,
520                          uint8_t integrity_algorithm,
521                          uint8_t confidentiality_algorithm,
522                          void *integrity_key,
523                          unsigned int integrity_key_len,
524                          void *confidentiality_key,
525                          unsigned int confidentiality_key_len,
526                          fiid_obj_t obj_cmd_rq,
527                          void *buf,
528                          unsigned int buflen)
529 {
530   int len;
531 
532   assert (ip);
533   assert (IPMIPOWER_PACKET_TYPE_RQ (pkt));
534   assert (fiid_obj_valid (obj_cmd_rq));
535   assert (buf);
536   assert (buflen);
537 
538   if (fill_rmcp_hdr_ipmi (ip->obj_rmcp_hdr_rq) < 0)
539     {
540       IPMIPOWER_ERROR (("fill_rmcp_hdr_ipmi: %s", strerror (errno)));
541       exit (EXIT_FAILURE);
542     }
543 
544   if (fill_rmcpplus_session_hdr (payload_type,
545                                  payload_authenticated,
546                                  payload_encrypted,
547                                  0, /* oem_iana */
548                                  0, /* oem_payload_id */
549                                  session_id,
550                                  session_sequence_number,
551                                  ip->obj_rmcpplus_session_hdr_rq) < 0)
552     {
553       IPMIPOWER_ERROR (("fill_rmcpplus_session_hdr: %s", strerror (errno)));
554       exit (EXIT_FAILURE);
555     }
556 
557   if (fill_lan_msg_hdr (IPMI_SLAVE_ADDRESS_BMC,
558                         net_fn,
559                         IPMI_BMC_IPMB_LUN_BMC,
560                         (ip->ic->ipmi_requester_sequence_number_counter % (IPMI_LAN_REQUESTER_SEQUENCE_NUMBER_MAX + 1)),
561                         ip->obj_lan_msg_hdr_rq) < 0)
562     {
563       IPMIPOWER_ERROR (("fill_lan_msg_hdr: %s", strerror (errno)));
564       exit (EXIT_FAILURE);
565     }
566 
567   if (fill_rmcpplus_session_trlr (ip->obj_rmcpplus_session_trlr_rq) < 0)
568     {
569       IPMIPOWER_ERROR (("fill_rmcpplus_session_trlr: %s", strerror (errno)));
570       exit (EXIT_FAILURE);
571     }
572 
573   if ((len = assemble_ipmi_rmcpplus_pkt (authentication_algorithm,
574                                          integrity_algorithm,
575                                          confidentiality_algorithm,
576                                          integrity_key,
577                                          integrity_key_len,
578                                          confidentiality_key,
579                                          confidentiality_key_len,
580                                          authentication_code_data,
581                                          authentication_code_data_len,
582                                          ip->obj_rmcp_hdr_rq,
583                                          ip->obj_rmcpplus_session_hdr_rq,
584                                          ip->obj_lan_msg_hdr_rq,
585                                          obj_cmd_rq,
586                                          ip->obj_rmcpplus_session_trlr_rq,
587                                          buf,
588                                          buflen,
589                                          IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
590     {
591       IPMIPOWER_ERROR (("assemble_ipmi_rmcpplus_pkt: %s", strerror (errno)));
592       exit (EXIT_FAILURE);
593     }
594 
595   return (len);
596 }
597 
598 int
ipmipower_packet_create(ipmipower_powercmd_t ip,ipmipower_packet_type_t pkt,void * buf,unsigned int buflen)599 ipmipower_packet_create (ipmipower_powercmd_t ip,
600                          ipmipower_packet_type_t pkt,
601                          void *buf,
602                          unsigned int buflen)
603 {
604   char *username = NULL;
605   char *password = NULL;
606   void *integrity_key = NULL;
607   void *confidentiality_key = NULL;
608   char username_buf[IPMI_MAX_USER_NAME_LENGTH+1];
609   unsigned int username_len;
610   uint32_t session_id, managed_system_session_id = 0;
611   uint32_t sequence_number = 0;
612   unsigned int integrity_key_len = 0;
613   unsigned int confidentiality_key_len = 0;
614   uint8_t authentication_type = 0;
615   uint8_t net_fn = 0;
616   uint8_t payload_authenticated = 0;
617   uint8_t payload_encrypted = 0;
618   uint8_t payload_type = 0;
619   uint8_t authentication_algorithm = 0;
620   uint8_t integrity_algorithm = 0;
621   uint8_t confidentiality_algorithm = 0;
622   fiid_obj_t obj_cmd_rq = NULL;
623   uint64_t val;
624   int rv = 0;
625 
626   assert (ip);
627   assert (IPMIPOWER_PACKET_TYPE_RQ (pkt));
628   assert (buf);
629   assert (buflen);
630 
631   if (pkt == IPMIPOWER_PACKET_TYPE_GET_SESSION_CHALLENGE_RQ
632       || pkt == IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_1
633       || pkt == IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_3)
634     {
635       username = cmd_args.common_args.username;
636 
637       /* IPMI Workaround (achu)
638        *
639        * Discovered on SE7520AF2 with Intel Server Management Module
640        * (Professional Edition)
641        *
642        * The username must be padded despite explicitly not being
643        * allowed.  "No Null characters (00h) are allowed in the name".
644        * Table 13-11 in the IPMI 2.0 spec.
645        */
646       if (pkt == IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_1
647           && (cmd_args.common_args.workaround_flags_outofband_2_0 & IPMI_PARSE_WORKAROUND_FLAGS_OUTOFBAND_2_0_INTEL_2_0_SESSION))
648         {
649           memset (username_buf, '\0', IPMI_MAX_USER_NAME_LENGTH+1);
650           if (username)
651             strcpy (username_buf, username);
652           username = username_buf;
653           username_len = IPMI_MAX_USER_NAME_LENGTH;
654         }
655       else
656         username_len = (username) ? strlen (username) : 0;
657     }
658   else
659     {
660       username = NULL;
661       username_len = 0;
662     }
663 
664   /* Calculate Password */
665   if (pkt == IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RQ
666       || IPMIPOWER_PACKET_TYPE_IPMI_2_0_SETUP_RQ (pkt)
667       || IPMIPOWER_PACKET_TYPE_IPMI_SESSION_PACKET_RQ (pkt))
668     password = cmd_args.common_args.password;
669   else
670     password = NULL;
671 
672   /* Calculate Session ID */
673   if (pkt == IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RQ)
674     {
675       if (FIID_OBJ_GET (ip->obj_get_session_challenge_rs,
676                         "temp_session_id",
677                         &val) < 0)
678         {
679           IPMIPOWER_ERROR (("FIID_OBJ_GET: 'temp_session_id': %s",
680                             fiid_obj_errormsg (ip->obj_get_session_challenge_rs)));
681           exit (EXIT_FAILURE);
682         }
683 
684       session_id = val;
685     }
686   else if (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN
687            && IPMIPOWER_PACKET_TYPE_IPMI_SESSION_PACKET_RQ (pkt))
688     {
689       if (FIID_OBJ_GET (ip->obj_activate_session_rs,
690                         "session_id",
691                         &val) < 0)
692         {
693           IPMIPOWER_ERROR (("FIID_OBJ_GET: 'session_id': %s",
694                             fiid_obj_errormsg (ip->obj_activate_session_rs)));
695           exit (EXIT_FAILURE);
696         }
697       session_id = val;
698     }
699   else if (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN_2_0
700            && IPMIPOWER_PACKET_TYPE_IPMI_SESSION_PACKET_RQ (pkt))
701     {
702       if (FIID_OBJ_GET (ip->obj_open_session_rs,
703                         "managed_system_session_id",
704                         &val) < 0)
705         {
706           IPMIPOWER_ERROR (("FIID_OBJ_GET: 'managed_system_session_id': %s",
707                             fiid_obj_errormsg (ip->obj_open_session_rs)));
708           exit (EXIT_FAILURE);
709         }
710       session_id = val;
711     }
712   else
713     session_id = 0;
714 
715   /* Calculate Sequence Number */
716   if (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN
717       && IPMIPOWER_PACKET_TYPE_IPMI_SESSION_PACKET_RQ (pkt))
718     {
719       uint32_t initial_inbound_sequence_number;
720 
721       if (FIID_OBJ_GET (ip->obj_activate_session_rs,
722                         "initial_inbound_sequence_number",
723                         &val) < 0)
724         {
725           IPMIPOWER_ERROR (("FIID_OBJ_GET: 'initial_inbound_sequence_number': %s",
726                             fiid_obj_errormsg (ip->obj_activate_session_rs)));
727           exit (EXIT_FAILURE);
728         }
729       initial_inbound_sequence_number = val;
730 
731       sequence_number = initial_inbound_sequence_number + ip->session_inbound_count;
732     }
733   else if (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN_2_0
734            && IPMIPOWER_PACKET_TYPE_IPMI_SESSION_PACKET_RQ (pkt))
735     sequence_number = ip->session_sequence_number;
736   else
737     sequence_number = 0;
738 
739   /* Calculate Network Function */
740   if (pkt == IPMIPOWER_PACKET_TYPE_GET_CHASSIS_STATUS_RQ
741       || pkt == IPMIPOWER_PACKET_TYPE_CHASSIS_CONTROL_RQ
742       || pkt == IPMIPOWER_PACKET_TYPE_CHASSIS_IDENTIFY_RQ)
743     net_fn = IPMI_NET_FN_CHASSIS_RQ;
744   else if (pkt == IPMIPOWER_PACKET_TYPE_C410X_GET_SENSOR_READING_RQ)
745     net_fn = IPMI_NET_FN_SENSOR_EVENT_RQ;
746   else if (pkt == IPMIPOWER_PACKET_TYPE_C410X_SLOT_POWER_CONTROL_RQ)
747     net_fn = IPMI_NET_FN_OEM_DELL_GENERIC_RQ;
748   else /* pkt == IPMIPOWER_PACKET_TYPE_AUTHENTICATION_CAPABILITIES_RQ
749           || pkt == IPMIPOWER_PACKET_TYPE_GET_SESSION_CHALLENGE_RQ
750           || pkt == IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RQ
751           || pkt == IPMIPOWER_PACKET_TYPE_CLOSE_SESSION_RQ
752        */
753     net_fn = IPMI_NET_FN_APP_RQ;
754 
755   /* Calculate Authentication Type */
756   if (pkt == IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RQ)
757     authentication_type = cmd_args.common_args.authentication_type;
758   else if (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN
759            && IPMIPOWER_PACKET_TYPE_IPMI_SESSION_PACKET_RQ (pkt))
760     {
761       if (!ip->permsgauth_enabled)
762         authentication_type = IPMI_AUTHENTICATION_TYPE_NONE;
763       else
764         authentication_type = cmd_args.common_args.authentication_type;
765 
766       if (authentication_type == IPMI_AUTHENTICATION_TYPE_NONE)
767         password = NULL;
768     }
769   else
770     authentication_type = IPMI_AUTHENTICATION_TYPE_NONE;
771 
772   if (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN_2_0)
773     {
774       /* Calculate Payload Type */
775       if (pkt == IPMIPOWER_PACKET_TYPE_OPEN_SESSION_REQUEST)
776         payload_type = IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST;
777       else if (pkt == IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_1)
778         payload_type = IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1;
779       else if (pkt == IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_3)
780         payload_type = IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3;
781       else
782         payload_type = IPMI_PAYLOAD_TYPE_IPMI;
783 
784       /* achu: "session_id" above is for the session headers.  This is
785        * for the RAKP session setup protocol.  The values will be
786        * different.
787        */
788       if (pkt == IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_1
789           || pkt == IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_3)
790         {
791           if (FIID_OBJ_GET (ip->obj_open_session_rs,
792                             "managed_system_session_id",
793                             &val) < 0)
794             {
795               IPMIPOWER_ERROR (("FIID_OBJ_GET: 'managed_system_session_id': %s",
796                                 fiid_obj_errormsg (ip->obj_open_session_rs)));
797               exit (EXIT_FAILURE);
798             }
799           managed_system_session_id = val;
800         }
801 
802       /* Setup authentication/integrity/confidentiality keys */
803       if (IPMIPOWER_PACKET_TYPE_IPMI_2_0_SETUP_RQ (pkt))
804         {
805           authentication_algorithm = IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE;
806           integrity_algorithm = IPMI_INTEGRITY_ALGORITHM_NONE;
807           confidentiality_algorithm = IPMI_CONFIDENTIALITY_ALGORITHM_NONE;
808           integrity_key = NULL;
809           integrity_key_len = 0;
810           confidentiality_key = NULL;
811           confidentiality_key_len = 0;
812         }
813       else /* IPMIPOWER_PACKET_TYPE_IPMI_SESSION_PACKET_RQ (pkt) */
814         {
815           authentication_algorithm = ip->authentication_algorithm;
816           integrity_algorithm = ip->integrity_algorithm;
817           confidentiality_algorithm = ip->confidentiality_algorithm;
818           integrity_key = ip->integrity_key_ptr;
819           integrity_key_len = ip->integrity_key_len;
820           confidentiality_key = ip->confidentiality_key_ptr;
821           confidentiality_key_len = ip->confidentiality_key_len;
822         }
823 
824       /* Calculate Payload Authenticated */
825       if (IPMIPOWER_PACKET_TYPE_IPMI_2_0_SETUP_RQ (pkt)
826           || integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE)
827         payload_authenticated = IPMI_PAYLOAD_FLAG_UNAUTHENTICATED;
828       else
829         payload_authenticated = IPMI_PAYLOAD_FLAG_AUTHENTICATED;
830 
831       /* Calculate Payload Encrypted */
832       if (IPMIPOWER_PACKET_TYPE_IPMI_2_0_SETUP_RQ (pkt)
833           || confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
834         payload_encrypted = IPMI_PAYLOAD_FLAG_UNENCRYPTED;
835       else
836         payload_encrypted = IPMI_PAYLOAD_FLAG_ENCRYPTED;
837     }
838 
839   /* Calculate/Fill Command Object */
840   if (pkt == IPMIPOWER_PACKET_TYPE_AUTHENTICATION_CAPABILITIES_RQ)
841     {
842       uint8_t get_ipmi_v20_extended_data;
843 
844       if (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN_2_0)
845         get_ipmi_v20_extended_data = IPMI_GET_IPMI_V20_EXTENDED_DATA;
846       else
847         get_ipmi_v20_extended_data = IPMI_GET_IPMI_V15_DATA;
848 
849       if (fill_cmd_get_channel_authentication_capabilities (IPMI_CHANNEL_NUMBER_CURRENT_CHANNEL,
850                                                             cmd_args.common_args.privilege_level,
851                                                             get_ipmi_v20_extended_data,
852                                                             ip->obj_authentication_capabilities_rq) < 0)
853         {
854           IPMIPOWER_ERROR (("fill_cmd_get_channel_authentication_capabilities: %s",
855                             strerror (errno)));
856           exit (EXIT_FAILURE);
857         }
858       obj_cmd_rq = ip->obj_authentication_capabilities_rq;
859     }
860   else if (pkt == IPMIPOWER_PACKET_TYPE_GET_SESSION_CHALLENGE_RQ)
861     {
862       /* Note: The session_authentication_type is none, this authentication type may be different.
863        */
864       if (fill_cmd_get_session_challenge (cmd_args.common_args.authentication_type,
865                                           username,
866                                           username_len,
867                                           ip->obj_get_session_challenge_rq) < 0)
868         {
869           IPMIPOWER_ERROR (("fill_cmd_get_session_challenge: %s", strerror (errno)));
870           exit (EXIT_FAILURE);
871         }
872       obj_cmd_rq = ip->obj_get_session_challenge_rq;
873     }
874   else if (pkt == IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RQ)
875     {
876       uint8_t challenge_string[IPMI_CHALLENGE_STRING_LENGTH];
877       int challenge_string_len;
878 
879       if ((challenge_string_len = fiid_obj_get_data (ip->obj_get_session_challenge_rs,
880                                                      "challenge_string",
881                                                      challenge_string,
882                                                      IPMI_CHALLENGE_STRING_LENGTH)) < 0)
883         {
884           IPMIPOWER_ERROR (("fiid_obj_get_data: 'challenge_string': %s",
885                             fiid_obj_errormsg (ip->obj_get_session_challenge_rs)));
886           exit (EXIT_FAILURE);
887         }
888 
889       if (!challenge_string_len)
890         {
891           IPMIPOWER_ERROR (("host = %s; p = %d; empty challenge string",
892                             ip->ic->hostname, ip->protocol_state));
893           exit (EXIT_FAILURE);
894         }
895 
896       if (fill_cmd_activate_session (authentication_type,
897                                      cmd_args.common_args.privilege_level,
898                                      challenge_string,
899                                      challenge_string_len,
900                                      IPMIPOWER_LAN_INITIAL_OUTBOUND_SEQUENCE_NUMBER,
901                                      ip->obj_activate_session_rq) < 0)
902         {
903           IPMIPOWER_ERROR (("fill_cmd_activate_session: %s", strerror (errno)));
904           exit (EXIT_FAILURE);
905         }
906       obj_cmd_rq = ip->obj_activate_session_rq;
907     }
908   else if (pkt == IPMIPOWER_PACKET_TYPE_OPEN_SESSION_REQUEST)
909     {
910       if (fill_rmcpplus_open_session (ip->initial_message_tag + ip->message_tag_count,
911                                       ip->requested_maximum_privilege_level,
912                                       ip->remote_console_session_id,
913                                       ip->authentication_algorithm,
914                                       ip->integrity_algorithm,
915                                       ip->confidentiality_algorithm,
916                                       ip->obj_open_session_rq) < 0)
917         {
918           IPMIPOWER_ERROR (("fill_rmcpplus_open_session: %s", strerror (errno)));
919           exit (EXIT_FAILURE);
920         }
921       obj_cmd_rq = ip->obj_open_session_rq;
922     }
923   else if (pkt == IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_1)
924     {
925       if (fill_rmcpplus_rakp_message_1 (ip->initial_message_tag + ip->message_tag_count,
926                                         managed_system_session_id,
927                                         ip->remote_console_random_number,
928                                         IPMI_REMOTE_CONSOLE_RANDOM_NUMBER_LENGTH,
929                                         cmd_args.common_args.privilege_level,
930                                         ip->name_only_lookup,
931                                         username,
932                                         username_len,
933                                         ip->obj_rakp_message_1_rq) < 0)
934         {
935           IPMIPOWER_ERROR (("fill_rmcpplus_rakp_message_1: %s", strerror (errno)));
936           exit (EXIT_FAILURE);
937         }
938       obj_cmd_rq = ip->obj_rakp_message_1_rq;
939     }
940   else if (pkt == IPMIPOWER_PACKET_TYPE_RAKP_MESSAGE_3)
941     {
942       uint8_t managed_system_random_number[IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH];
943       int managed_system_random_number_len;
944       uint8_t key_exchange_authentication_code[IPMI_MAX_KEY_EXCHANGE_AUTHENTICATION_CODE_LENGTH];
945       int key_exchange_authentication_code_len;
946       uint8_t name_only_lookup;
947       unsigned int password_len;
948 
949       if ((managed_system_random_number_len = fiid_obj_get_data (ip->obj_rakp_message_2_rs,
950                                                                  "managed_system_random_number",
951                                                                  managed_system_random_number,
952                                                                  IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH)) < 0)
953         {
954           IPMIPOWER_ERROR (("fiid_obj_get_data: 'managed_system_random_number': %s",
955                             fiid_obj_errormsg (ip->obj_rakp_message_2_rs)));
956           exit (EXIT_FAILURE);
957         }
958 
959       /* IPMI Workaround (achu)
960        *
961        * Discovered on SE7520AF2 with Intel Server Management Module
962        * (Professional Edition)
963        *
964        * For some reason we have to create this key with the name only
965        * lookup turned off.  I was skeptical about this actually being
966        * a bug until I saw that the ipmitool folks implemented the
967        * same workaround.
968        */
969 
970       if (cmd_args.common_args.workaround_flags_outofband_2_0 & IPMI_PARSE_WORKAROUND_FLAGS_OUTOFBAND_2_0_INTEL_2_0_SESSION)
971         name_only_lookup = IPMI_USER_NAME_PRIVILEGE_LOOKUP;
972       else
973         name_only_lookup = ip->name_only_lookup;
974 
975       password_len = (password) ? strlen (password) : 0;
976 
977       /* IPMI Workaround (achu)
978        *
979        * Discovered on SE7520AF2 with Intel Server Management Module
980        * (Professional Edition)
981        *
982        * When the authentication algorithm is HMAC-MD5-128 and the
983        * password is greater than 16 bytes, the Intel BMC truncates the
984        * password to 16 bytes when generating keys, hashes, etc.  So we
985        * have to do the same when generating keys, hashes, etc.
986        */
987       if ((cmd_args.common_args.workaround_flags_outofband_2_0 & IPMI_PARSE_WORKAROUND_FLAGS_OUTOFBAND_2_0_INTEL_2_0_SESSION)
988           && ip->authentication_algorithm == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5
989           && password_len > IPMI_1_5_MAX_PASSWORD_LENGTH)
990         password_len = IPMI_1_5_MAX_PASSWORD_LENGTH;
991 
992       if ((key_exchange_authentication_code_len = ipmi_calculate_rakp_3_key_exchange_authentication_code (ip->authentication_algorithm,
993                                                                                                           password,
994                                                                                                           password_len,
995                                                                                                           managed_system_random_number,
996                                                                                                           managed_system_random_number_len,
997                                                                                                           ip->remote_console_session_id,
998                                                                                                           name_only_lookup,
999                                                                                                           cmd_args.common_args.privilege_level,
1000                                                                                                           username,
1001                                                                                                           username_len,
1002                                                                                                           key_exchange_authentication_code,
1003                                                                                                           IPMI_MAX_KEY_EXCHANGE_AUTHENTICATION_CODE_LENGTH)) < 0)
1004         {
1005           IPMIPOWER_ERROR (("ipmi_calculate_rakp_3_key_exchange_authentication_code: %s",
1006                             strerror (errno)));
1007           exit (EXIT_FAILURE);
1008         }
1009 
1010       if (fill_rmcpplus_rakp_message_3 (ip->initial_message_tag + ip->message_tag_count,
1011                                         RMCPPLUS_STATUS_NO_ERRORS,
1012                                         managed_system_session_id,
1013                                         key_exchange_authentication_code,
1014                                         key_exchange_authentication_code_len,
1015                                         ip->obj_rakp_message_3_rq) < 0)
1016         {
1017           IPMIPOWER_ERROR (("fill_rmcpplus_rakp_message_3: %s", strerror (errno)));
1018           exit (EXIT_FAILURE);
1019         }
1020       obj_cmd_rq = ip->obj_rakp_message_3_rq;
1021     }
1022   else if (pkt == IPMIPOWER_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RQ)
1023     {
1024       if (fill_cmd_set_session_privilege_level (cmd_args.common_args.privilege_level,
1025                                                 ip->obj_set_session_privilege_level_rq) < 0)
1026         {
1027           IPMIPOWER_ERROR (("fill_cmd_set_session_privilege_level: %s", strerror (errno)));
1028           exit (EXIT_FAILURE);
1029         }
1030       obj_cmd_rq = ip->obj_set_session_privilege_level_rq;
1031     }
1032   else if (pkt == IPMIPOWER_PACKET_TYPE_GET_CHASSIS_STATUS_RQ)
1033     {
1034       if (fill_cmd_get_chassis_status (ip->obj_get_chassis_status_rq) < 0)
1035         {
1036           IPMIPOWER_ERROR (("fill_cmd_get_chassis_status: %s", strerror (errno)));
1037           exit (EXIT_FAILURE);
1038         }
1039       obj_cmd_rq = ip->obj_get_chassis_status_rq;
1040     }
1041   else if (pkt == IPMIPOWER_PACKET_TYPE_CHASSIS_CONTROL_RQ)
1042     {
1043       uint8_t command = 0;
1044 
1045       assert (ip->cmd == IPMIPOWER_POWER_CMD_POWER_OFF
1046               || ip->cmd == IPMIPOWER_POWER_CMD_POWER_ON
1047               || ip->cmd == IPMIPOWER_POWER_CMD_POWER_CYCLE
1048               || ip->cmd == IPMIPOWER_POWER_CMD_POWER_RESET
1049               || ip->cmd == IPMIPOWER_POWER_CMD_PULSE_DIAGNOSTIC_INTERRUPT
1050               || ip->cmd == IPMIPOWER_POWER_CMD_SOFT_SHUTDOWN_OS);
1051 
1052       if (ip->cmd == IPMIPOWER_POWER_CMD_POWER_OFF)
1053         command = IPMI_CHASSIS_CONTROL_POWER_DOWN;
1054       else if (ip->cmd == IPMIPOWER_POWER_CMD_POWER_ON)
1055         command = IPMI_CHASSIS_CONTROL_POWER_UP;
1056       else if (ip->cmd == IPMIPOWER_POWER_CMD_POWER_CYCLE)
1057         command = IPMI_CHASSIS_CONTROL_POWER_CYCLE;
1058       else if (ip->cmd == IPMIPOWER_POWER_CMD_POWER_RESET)
1059         command = IPMI_CHASSIS_CONTROL_HARD_RESET;
1060       else if (ip->cmd == IPMIPOWER_POWER_CMD_PULSE_DIAGNOSTIC_INTERRUPT)
1061         command = IPMI_CHASSIS_CONTROL_PULSE_DIAGNOSTIC_INTERRUPT;
1062       else if (ip->cmd == IPMIPOWER_POWER_CMD_SOFT_SHUTDOWN_OS)
1063         command = IPMI_CHASSIS_CONTROL_INITIATE_SOFT_SHUTDOWN;
1064 
1065       if (fill_cmd_chassis_control (command, ip->obj_chassis_control_rq) < 0)
1066         {
1067           IPMIPOWER_ERROR (("fill_cmd_chassis_control: %s", strerror (errno)));
1068           exit (EXIT_FAILURE);
1069         }
1070       obj_cmd_rq = ip->obj_chassis_control_rq;
1071     }
1072   else if (pkt == IPMIPOWER_PACKET_TYPE_CHASSIS_IDENTIFY_RQ)
1073     {
1074       uint8_t identify_interval;
1075       uint8_t force_identify;
1076       uint8_t *identify_interval_ptr = NULL;
1077       uint8_t *force_identify_ptr = NULL;
1078 
1079       assert (ip->cmd == IPMIPOWER_POWER_CMD_IDENTIFY_ON
1080               || ip->cmd == IPMIPOWER_POWER_CMD_IDENTIFY_OFF);
1081 
1082       if (ip->cmd == IPMIPOWER_POWER_CMD_IDENTIFY_ON)
1083         {
1084           /* must pass interval for force to be taken */
1085           identify_interval = 0xFF;
1086           identify_interval_ptr = &identify_interval;
1087 
1088           force_identify = IPMI_CHASSIS_FORCE_IDENTIFY_ON;
1089           force_identify_ptr = &force_identify;
1090         }
1091       else
1092         {
1093           identify_interval = 0;
1094           identify_interval_ptr = &identify_interval;
1095         }
1096 
1097       if (fill_cmd_chassis_identify (identify_interval_ptr,
1098                                      force_identify_ptr,
1099                                      ip->obj_chassis_identify_rq) < 0)
1100         {
1101           IPMIPOWER_ERROR (("fill_cmd_chassis_identify: %s", strerror (errno)));
1102           exit (EXIT_FAILURE);
1103         }
1104       obj_cmd_rq = ip->obj_chassis_identify_rq;
1105     }
1106   else if (pkt == IPMIPOWER_PACKET_TYPE_C410X_GET_SENSOR_READING_RQ)
1107     {
1108       char *endptr;
1109       unsigned int slot_number;
1110 
1111       assert (ip->extra_arg);
1112 
1113       errno = 0;
1114       slot_number = strtol (ip->extra_arg, &endptr, 0);
1115 
1116       /* tons of error checks by now, should not error out here */
1117       assert (!errno);
1118       assert (endptr[0] == '\0');
1119       assert (slot_number >= IPMI_OEM_DELL_SLOT_POWER_CONTROL_SLOT_NUMBER_MIN
1120               && slot_number <= IPMI_OEM_DELL_SLOT_POWER_CONTROL_SLOT_NUMBER_MAX);
1121 
1122       if (fill_cmd_get_sensor_reading (IPMI_SENSOR_NUMBER_OEM_DELL_C410X_PCIE_1_WATT + (slot_number - 1),
1123                                        ip->obj_c410x_get_sensor_reading_rq) < 0)
1124         {
1125           IPMIPOWER_ERROR (("fill_cmd_get_sensor_reading: %s", strerror (errno)));
1126           exit (EXIT_FAILURE);
1127         }
1128 
1129       obj_cmd_rq = ip->obj_c410x_get_sensor_reading_rq;
1130     }
1131   else if (pkt == IPMIPOWER_PACKET_TYPE_C410X_SLOT_POWER_CONTROL_RQ)
1132     {
1133       char *endptr;
1134       unsigned int slot_number;
1135       uint16_t slot_number_bitmask;
1136 
1137       assert (ip->extra_arg);
1138 
1139       errno = 0;
1140       slot_number = strtol (ip->extra_arg, &endptr, 0);
1141 
1142       /* tons of error checks by now, should not error out here */
1143       assert (!errno);
1144       assert (endptr[0] == '\0');
1145       assert (slot_number >= IPMI_OEM_DELL_SLOT_POWER_CONTROL_SLOT_NUMBER_MIN
1146               && slot_number <= IPMI_OEM_DELL_SLOT_POWER_CONTROL_SLOT_NUMBER_MAX);
1147 
1148       if (fiid_obj_set (ip->obj_c410x_slot_power_control_rq,
1149                         "cmd",
1150                         IPMI_CMD_OEM_DELL_SLOT_POWER_CONTROL) < 0)
1151         {
1152           IPMIPOWER_ERROR (("fiid_obj_set: 'cmd': %s",
1153                             fiid_obj_errormsg (ip->obj_c410x_slot_power_control_rq)));
1154           exit (EXIT_FAILURE);
1155         }
1156 
1157       slot_number_bitmask = (0x1 << (slot_number - 1));
1158       if (fiid_obj_set (ip->obj_c410x_slot_power_control_rq,
1159                         "slot_number_bitmask",
1160                         slot_number_bitmask) < 0)
1161         {
1162           IPMIPOWER_ERROR (("fiid_obj_set: 'slot_number_bitmask': %s",
1163                             fiid_obj_errormsg (ip->obj_c410x_slot_power_control_rq)));
1164           exit (EXIT_FAILURE);
1165         }
1166 
1167       obj_cmd_rq = ip->obj_c410x_slot_power_control_rq;
1168     }
1169   else if (pkt == IPMIPOWER_PACKET_TYPE_CLOSE_SESSION_RQ)
1170     {
1171       if (fill_cmd_close_session (session_id,
1172                                   NULL,
1173                                   ip->obj_close_session_rq) < 0)
1174         {
1175           IPMIPOWER_ERROR (("fill_cmd_close_session: %s", strerror (errno)));
1176           exit (EXIT_FAILURE);
1177         }
1178       obj_cmd_rq = ip->obj_close_session_rq;
1179     }
1180 
1181   /* Construct packets */
1182   if (IPMIPOWER_PACKET_TYPE_IPMI_1_5_SETUP_RQ (pkt)
1183       || (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN
1184           && IPMIPOWER_PACKET_TYPE_IPMI_SESSION_PACKET_RQ (pkt)))
1185     rv = _ipmi_1_5_packet_create (ip,
1186                                   pkt,
1187                                   authentication_type,
1188                                   sequence_number,
1189                                   session_id,
1190                                   password,
1191                                   (password) ? strlen (password) : 0,
1192                                   net_fn,
1193                                   obj_cmd_rq,
1194                                   buf,
1195                                   buflen);
1196   else if (IPMIPOWER_PACKET_TYPE_IPMI_2_0_SETUP_RQ (pkt)
1197            || (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN_2_0
1198                && IPMIPOWER_PACKET_TYPE_IPMI_SESSION_PACKET_RQ (pkt)))
1199     rv = _ipmi_2_0_packet_create (ip,
1200                                   pkt,
1201                                   payload_type,
1202                                   payload_authenticated,
1203                                   payload_encrypted,
1204                                   session_id,
1205                                   sequence_number,
1206                                   password,
1207                                   (password) ? strlen (password) : 0,
1208                                   net_fn,
1209                                   authentication_algorithm,
1210                                   integrity_algorithm,
1211                                   confidentiality_algorithm,
1212                                   integrity_key,
1213                                   integrity_key_len,
1214                                   confidentiality_key,
1215                                   confidentiality_key_len,
1216                                   obj_cmd_rq,
1217                                   buf,
1218                                   buflen);
1219   else
1220     {
1221       IPMIPOWER_ERROR (("host = %s; p = %d; invalid logic",
1222                         ip->ic->hostname, ip->protocol_state));
1223       exit (EXIT_FAILURE);
1224     }
1225 
1226   return (rv);
1227 }
1228 
1229 ipmipower_msg_type_t
ipmipower_packet_errmsg(ipmipower_powercmd_t ip,ipmipower_packet_type_t pkt)1230 ipmipower_packet_errmsg (ipmipower_powercmd_t ip, ipmipower_packet_type_t pkt)
1231 {
1232   fiid_obj_t obj_cmd;
1233 
1234   assert (ip);
1235   assert (IPMIPOWER_PACKET_TYPE_RS (pkt));
1236 
1237   obj_cmd = ipmipower_packet_cmd_obj (ip, pkt);
1238 
1239   if (IPMIPOWER_PACKET_TYPE_IPMI_2_0_SETUP_RS (pkt))
1240     {
1241       uint8_t rmcpplus_status_code;
1242       uint64_t val;
1243 
1244       if (FIID_OBJ_GET (obj_cmd,
1245                         "rmcpplus_status_code",
1246                         &val) < 0)
1247         {
1248           IPMIPOWER_ERROR (("FIID_OBJ_GET: 'rmcpplus_status_code': %s",
1249                             fiid_obj_errormsg (obj_cmd)));
1250           exit (EXIT_FAILURE);
1251         }
1252       rmcpplus_status_code = val;
1253 
1254       /* achu:
1255 
1256       At this point in time, my belief is that the following RMCPPLUS
1257       Status Codes:
1258 
1259       RMCPPLUS_STATUS_INVALID_AUTHENTICATION_ALGORITHM
1260       RMCPPLUS_STATUS_INVALID_INTEGRITY_ALGORITHM
1261       RMCPPLUS_STATUS_INVALID_CONFIDENTIALITY_ALGORITHM
1262       RMCPPLUS_STATUS_INVALID_ROLE
1263       RMCPPLUS_STATUS_NO_MATCHING_AUTHENTICATION_PAYLOAD
1264       RMCPPLUS_STATUS_NO_MATCHING_INTEGRITY_PAYLOAD
1265 
1266       Imply that an incorrect algorithm/role/payload value was sent.
1267       *NOT* an unsupported algorithm/role/payload.  I assume unsupported algorithm/role/payloads
1268       will get different error codes.
1269 
1270       If my assumption is later proven incorrect, then I need to redo some of this.
1271 
1272       */
1273 
1274       if (rmcpplus_status_code == RMCPPLUS_STATUS_NO_ERRORS)
1275         {
1276           IPMIPOWER_ERROR (("host = %s; p = %d; pkt = %d; called with good rmcpplus_status_code",
1277                             ip->ic->hostname, ip->protocol_state, pkt));
1278           exit (EXIT_FAILURE);
1279         }
1280       else if (rmcpplus_status_code == RMCPPLUS_STATUS_INSUFFICIENT_RESOURCES_TO_CREATE_A_SESSION
1281                || rmcpplus_status_code == RMCPPLUS_STATUS_INSUFFICIENT_RESOURCES_TO_CREATE_A_SESSION_AT_THE_REQUESTED_TIME)
1282         return (IPMIPOWER_MSG_TYPE_BMC_BUSY);
1283       else if (rmcpplus_status_code == RMCPPLUS_STATUS_UNAUTHORIZED_ROLE_OR_PRIVILEGE_LEVEL_REQUESTED
1284                || rmcpplus_status_code == RMCPPLUS_STATUS_INVALID_ROLE)
1285         return (IPMIPOWER_MSG_TYPE_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED);
1286       else if (rmcpplus_status_code == RMCPPLUS_STATUS_UNAUTHORIZED_NAME)
1287         return (IPMIPOWER_MSG_TYPE_USERNAME_INVALID);
1288       else if (rmcpplus_status_code == RMCPPLUS_STATUS_NO_CIPHER_SUITE_MATCH_WITH_PROPOSED_SECURITY_ALGORITHMS)
1289         return (IPMIPOWER_MSG_TYPE_CIPHER_SUITE_ID_UNAVAILABLE);
1290     }
1291   else
1292     {
1293       uint8_t comp_code;
1294       uint64_t val;
1295 
1296       if (FIID_OBJ_GET (obj_cmd,
1297                         "comp_code",
1298                         &val) < 0)
1299         {
1300           IPMIPOWER_ERROR (("FIID_OBJ_GET: 'comp_code': %s",
1301                             fiid_obj_errormsg (obj_cmd)));
1302           exit (EXIT_FAILURE);
1303         }
1304       comp_code = val;
1305 
1306       if (comp_code == IPMI_COMP_CODE_COMMAND_SUCCESS)
1307         {
1308           IPMIPOWER_ERROR (("host = %s; p = %d; pkt = %d; called with good comp_code",
1309                             ip->ic->hostname, ip->protocol_state, pkt));
1310           exit (EXIT_FAILURE);
1311         }
1312       else if (pkt == IPMIPOWER_PACKET_TYPE_AUTHENTICATION_CAPABILITIES_RS
1313                && cmd_args.common_args.driver_type == IPMI_DEVICE_LAN_2_0
1314                && comp_code == IPMI_COMP_CODE_INVALID_DATA_FIELD_IN_REQUEST)
1315         return (IPMIPOWER_MSG_TYPE_IPMI_2_0_UNAVAILABLE);
1316       else if (pkt == IPMIPOWER_PACKET_TYPE_GET_SESSION_CHALLENGE_RS
1317                && (comp_code == IPMI_COMP_CODE_GET_SESSION_CHALLENGE_INVALID_USERNAME
1318                    || comp_code == IPMI_COMP_CODE_GET_SESSION_CHALLENGE_NULL_USERNAME_NOT_ENABLED))
1319         return (IPMIPOWER_MSG_TYPE_USERNAME_INVALID);
1320       else if (pkt == IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RS
1321                && comp_code == IPMI_COMP_CODE_ACTIVATE_SESSION_EXCEEDS_PRIVILEGE_LEVEL)
1322         return (IPMIPOWER_MSG_TYPE_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED);
1323       else if (pkt == IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RS
1324                && (comp_code == IPMI_COMP_CODE_ACTIVATE_SESSION_NO_SESSION_SLOT_AVAILABLE
1325                    || comp_code == IPMI_COMP_CODE_ACTIVATE_SESSION_NO_SLOT_AVAILABLE_FOR_GIVEN_USER
1326                    || comp_code == IPMI_COMP_CODE_ACTIVATE_SESSION_NO_SLOT_AVAILABLE_TO_SUPPORT_USER))
1327         return (IPMIPOWER_MSG_TYPE_BMC_BUSY);
1328       /*
1329        * IPMI Workaround
1330        *
1331        * Discovered on Xyratex HB-F8-SRAY
1332        *
1333        * For some reason on this system, if you do not specify a
1334        * privilege level of Admin, this completion code will always be
1335        * returned.  Reason unknown.  This isn't the best/right error
1336        * to return, but it will atleast point the user to a way to
1337        * work around the problem.
1338        */
1339       else if (pkt == IPMIPOWER_PACKET_TYPE_ACTIVATE_SESSION_RS
1340                && comp_code == IPMI_COMP_CODE_INSUFFICIENT_PRIVILEGE_LEVEL)
1341         return (IPMIPOWER_MSG_TYPE_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED);
1342       else if (pkt == IPMIPOWER_PACKET_TYPE_SET_SESSION_PRIVILEGE_LEVEL_RS
1343                && (comp_code == IPMI_COMP_CODE_SET_SESSION_PRIVILEGE_LEVEL_REQUESTED_LEVEL_NOT_AVAILABLE_FOR_USER
1344                    || comp_code == IPMI_COMP_CODE_SET_SESSION_PRIVILEGE_LEVEL_REQUESTED_LEVEL_EXCEEDS_USER_PRIVILEGE_LIMIT
1345                    || comp_code == IPMI_COMP_CODE_SET_SESSION_PRIVILEGE_LEVEL_CANNOT_DISABLE_USER_LEVEL_AUTHENTICATION))
1346         return (IPMIPOWER_MSG_TYPE_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED);
1347 #if 0
1348       /* Should not reach this point, should be handled by other code */
1349       else if (pkt == IPMIPOWER_PACKET_TYPE_CHASSIS_CONTROL_RS
1350                && comp_code == IPMI_COMP_CODE_INSUFFICIENT_PRIVILEGE_LEVEL)
1351         return (IPMIPOWER_MSG_TYPE_PRIVILEGE_LEVEL_INSUFFICIENT);
1352 #endif
1353       else if (pkt == IPMIPOWER_PACKET_TYPE_CHASSIS_CONTROL_RS
1354                && comp_code == IPMI_COMP_CODE_REQUEST_PARAMETER_NOT_SUPPORTED)
1355         return (IPMIPOWER_MSG_TYPE_OPERATION_INVALID);
1356     }
1357 
1358   return (IPMIPOWER_MSG_TYPE_BMC_ERROR);
1359 }
1360