1c18ec02fSPetter Reinholdtsen /* 2c18ec02fSPetter Reinholdtsen * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. 3c18ec02fSPetter Reinholdtsen * 4c18ec02fSPetter Reinholdtsen * Redistribution and use in source and binary forms, with or without 5c18ec02fSPetter Reinholdtsen * modification, are permitted provided that the following conditions 6c18ec02fSPetter Reinholdtsen * are met: 7c18ec02fSPetter Reinholdtsen * 8c18ec02fSPetter Reinholdtsen * Redistribution of source code must retain the above copyright 9c18ec02fSPetter Reinholdtsen * notice, this list of conditions and the following disclaimer. 10c18ec02fSPetter Reinholdtsen * 11c18ec02fSPetter Reinholdtsen * Redistribution in binary form must reproduce the above copyright 12c18ec02fSPetter Reinholdtsen * notice, this list of conditions and the following disclaimer in the 13c18ec02fSPetter Reinholdtsen * documentation and/or other materials provided with the distribution. 14c18ec02fSPetter Reinholdtsen * 15c18ec02fSPetter Reinholdtsen * Neither the name of Sun Microsystems, Inc. or the names of 16c18ec02fSPetter Reinholdtsen * contributors may be used to endorse or promote products derived 17c18ec02fSPetter Reinholdtsen * from this software without specific prior written permission. 18c18ec02fSPetter Reinholdtsen * 19c18ec02fSPetter Reinholdtsen * This software is provided "AS IS," without a warranty of any kind. 20c18ec02fSPetter Reinholdtsen * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 21c18ec02fSPetter Reinholdtsen * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 22c18ec02fSPetter Reinholdtsen * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 23c18ec02fSPetter Reinholdtsen * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE 24c18ec02fSPetter Reinholdtsen * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING 25c18ec02fSPetter Reinholdtsen * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL 26c18ec02fSPetter Reinholdtsen * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, 27c18ec02fSPetter Reinholdtsen * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR 28c18ec02fSPetter Reinholdtsen * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF 29c18ec02fSPetter Reinholdtsen * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 30c18ec02fSPetter Reinholdtsen * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 31c18ec02fSPetter Reinholdtsen */ 32c18ec02fSPetter Reinholdtsen 33c18ec02fSPetter Reinholdtsen #include <stdlib.h> 34c18ec02fSPetter Reinholdtsen #include <stdio.h> 35c18ec02fSPetter Reinholdtsen #include <inttypes.h> 36c18ec02fSPetter Reinholdtsen #include <string.h> 37c18ec02fSPetter Reinholdtsen #include <sys/types.h> 38c18ec02fSPetter Reinholdtsen #include <sys/socket.h> 39c18ec02fSPetter Reinholdtsen #include <netinet/in.h> 40c18ec02fSPetter Reinholdtsen #include <arpa/inet.h> 41c18ec02fSPetter Reinholdtsen #include <errno.h> 42c18ec02fSPetter Reinholdtsen #include <unistd.h> 43c18ec02fSPetter Reinholdtsen #include <netdb.h> 44c18ec02fSPetter Reinholdtsen #include <time.h> 45c18ec02fSPetter Reinholdtsen #include <fcntl.h> 46c18ec02fSPetter Reinholdtsen #include <assert.h> 47c18ec02fSPetter Reinholdtsen 48c18ec02fSPetter Reinholdtsen #ifdef HAVE_CONFIG_H 49c18ec02fSPetter Reinholdtsen # include <config.h> 50c18ec02fSPetter Reinholdtsen #endif 51c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h> 52c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h> 53c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h> 54c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_lanp.h> 55c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_channel.h> 56c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h> 57c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_strings.h> 5823e9340bSZdenek Styblik #include <ipmitool/hpm2.h> 59c18ec02fSPetter Reinholdtsen #include <ipmitool/bswap.h> 60c18ec02fSPetter Reinholdtsen #include <openssl/rand.h> 61c18ec02fSPetter Reinholdtsen 62c18ec02fSPetter Reinholdtsen #include "lanplus.h" 63c18ec02fSPetter Reinholdtsen #include "lanplus_crypt.h" 64c18ec02fSPetter Reinholdtsen #include "lanplus_crypt_impl.h" 65c18ec02fSPetter Reinholdtsen #include "lanplus_dump.h" 66c18ec02fSPetter Reinholdtsen #include "rmcp.h" 67c18ec02fSPetter Reinholdtsen #include "asf.h" 68c18ec02fSPetter Reinholdtsen 6923e9340bSZdenek Styblik /* 7023e9340bSZdenek Styblik * LAN interface is required to support 45 byte request transactions and 7123e9340bSZdenek Styblik * 42 byte response transactions. 7223e9340bSZdenek Styblik */ 7323e9340bSZdenek Styblik #define IPMI_LAN_MAX_REQUEST_SIZE 38 /* 45 - 7 */ 7423e9340bSZdenek Styblik #define IPMI_LAN_MAX_RESPONSE_SIZE 34 /* 42 - 8 */ 7523e9340bSZdenek Styblik 76c18ec02fSPetter Reinholdtsen extern const struct valstr ipmi_rakp_return_codes[]; 77c18ec02fSPetter Reinholdtsen extern const struct valstr ipmi_priv_levels[]; 78c18ec02fSPetter Reinholdtsen extern const struct valstr ipmi_auth_algorithms[]; 79c18ec02fSPetter Reinholdtsen extern const struct valstr ipmi_integrity_algorithms[]; 80c18ec02fSPetter Reinholdtsen extern const struct valstr ipmi_encryption_algorithms[]; 81c18ec02fSPetter Reinholdtsen 82c18ec02fSPetter Reinholdtsen static struct ipmi_rq_entry * ipmi_req_entries; 83c18ec02fSPetter Reinholdtsen static struct ipmi_rq_entry * ipmi_req_entries_tail; 84c18ec02fSPetter Reinholdtsen 85c18ec02fSPetter Reinholdtsen 86c18ec02fSPetter Reinholdtsen static int ipmi_lanplus_setup(struct ipmi_intf * intf); 87c18ec02fSPetter Reinholdtsen static int ipmi_lanplus_keepalive(struct ipmi_intf * intf); 88c18ec02fSPetter Reinholdtsen static int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len); 89c18ec02fSPetter Reinholdtsen static struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf); 90c18ec02fSPetter Reinholdtsen static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf); 91c18ec02fSPetter Reinholdtsen static struct ipmi_rs * ipmi_lanplus_send_ipmi_cmd(struct ipmi_intf * intf, struct ipmi_rq * req); 92c18ec02fSPetter Reinholdtsen static struct ipmi_rs * ipmi_lanplus_send_payload(struct ipmi_intf * intf, 93c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * payload); 94c18ec02fSPetter Reinholdtsen static void getIpmiPayloadWireRep( 95c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 96c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * payload, /* in */ 97c18ec02fSPetter Reinholdtsen uint8_t * out, 98c18ec02fSPetter Reinholdtsen struct ipmi_rq * req, 99c18ec02fSPetter Reinholdtsen uint8_t rq_seq, 100c18ec02fSPetter Reinholdtsen uint8_t curr_seq); 101c18ec02fSPetter Reinholdtsen static void getSolPayloadWireRep( 102c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 103c18ec02fSPetter Reinholdtsen uint8_t * msg, 104c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * payload); 105c18ec02fSPetter Reinholdtsen static void read_open_session_response(struct ipmi_rs * rsp, int offset); 106c18ec02fSPetter Reinholdtsen static void read_rakp2_message(struct ipmi_rs * rsp, int offset, uint8_t alg); 107c18ec02fSPetter Reinholdtsen static void read_rakp4_message(struct ipmi_rs * rsp, int offset, uint8_t alg); 108c18ec02fSPetter Reinholdtsen static void read_session_data(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s); 109c18ec02fSPetter Reinholdtsen static void read_session_data_v15(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s); 110c18ec02fSPetter Reinholdtsen static void read_session_data_v2x(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s); 111c18ec02fSPetter Reinholdtsen static void read_ipmi_response(struct ipmi_rs * rsp, int * offset); 112c18ec02fSPetter Reinholdtsen static void read_sol_packet(struct ipmi_rs * rsp, int * offset); 113c18ec02fSPetter Reinholdtsen static struct ipmi_rs * ipmi_lanplus_recv_sol(struct ipmi_intf * intf); 114c18ec02fSPetter Reinholdtsen static struct ipmi_rs * ipmi_lanplus_send_sol( 115c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 116c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * payload); 117c18ec02fSPetter Reinholdtsen static int check_sol_packet_for_new_data( 118c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 119c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp); 120c18ec02fSPetter Reinholdtsen static void ack_sol_packet( 121c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 122c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp); 12323e9340bSZdenek Styblik static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size); 12423e9340bSZdenek Styblik static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size); 125c18ec02fSPetter Reinholdtsen 126c18ec02fSPetter Reinholdtsen static uint8_t bridgePossible = 0; 127c18ec02fSPetter Reinholdtsen 128c18ec02fSPetter Reinholdtsen struct ipmi_intf ipmi_lanplus_intf = { 129c18ec02fSPetter Reinholdtsen name: "lanplus", 130c18ec02fSPetter Reinholdtsen desc: "IPMI v2.0 RMCP+ LAN Interface", 131c18ec02fSPetter Reinholdtsen setup: ipmi_lanplus_setup, 132c18ec02fSPetter Reinholdtsen open: ipmi_lanplus_open, 133c18ec02fSPetter Reinholdtsen close: ipmi_lanplus_close, 134c18ec02fSPetter Reinholdtsen sendrecv: ipmi_lanplus_send_ipmi_cmd, 135c18ec02fSPetter Reinholdtsen recv_sol: ipmi_lanplus_recv_sol, 136c18ec02fSPetter Reinholdtsen send_sol: ipmi_lanplus_send_sol, 137c18ec02fSPetter Reinholdtsen keepalive: ipmi_lanplus_keepalive, 13823e9340bSZdenek Styblik set_max_request_data_size: ipmi_lanp_set_max_rq_data_size, 13923e9340bSZdenek Styblik set_max_response_data_size: ipmi_lanp_set_max_rp_data_size, 140c18ec02fSPetter Reinholdtsen target_addr: IPMI_BMC_SLAVE_ADDR, 141c18ec02fSPetter Reinholdtsen }; 142c18ec02fSPetter Reinholdtsen 143c18ec02fSPetter Reinholdtsen 144c18ec02fSPetter Reinholdtsen extern int verbose; 145c18ec02fSPetter Reinholdtsen 146c18ec02fSPetter Reinholdtsen 147c18ec02fSPetter Reinholdtsen 148c18ec02fSPetter Reinholdtsen /* 149c18ec02fSPetter Reinholdtsen * lanplus_get_requested_ciphers 150c18ec02fSPetter Reinholdtsen * 151c18ec02fSPetter Reinholdtsen * Set the authentication, integrity and encryption algorithms based 152c18ec02fSPetter Reinholdtsen * on the cipher suite ID. See table 22-19 in the IPMIv2 spec for the 153c18ec02fSPetter Reinholdtsen * source of this information. 154c18ec02fSPetter Reinholdtsen * 155c18ec02fSPetter Reinholdtsen * param cipher_suite_id [in] 156c18ec02fSPetter Reinholdtsen * param auth_alg [out] 157c18ec02fSPetter Reinholdtsen * param integrity_alg [out] 158c18ec02fSPetter Reinholdtsen * param crypt_alg [out] 159c18ec02fSPetter Reinholdtsen * 160c18ec02fSPetter Reinholdtsen * returns 0 on success 161c18ec02fSPetter Reinholdtsen * 1 on failure 162c18ec02fSPetter Reinholdtsen */ 163c18ec02fSPetter Reinholdtsen int lanplus_get_requested_ciphers(int cipher_suite_id, 164c18ec02fSPetter Reinholdtsen uint8_t * auth_alg, 165c18ec02fSPetter Reinholdtsen uint8_t * integrity_alg, 166c18ec02fSPetter Reinholdtsen uint8_t * crypt_alg) 167c18ec02fSPetter Reinholdtsen { 168c18ec02fSPetter Reinholdtsen if ((cipher_suite_id < 0) || (cipher_suite_id > 14)) 169c18ec02fSPetter Reinholdtsen return 1; 170c18ec02fSPetter Reinholdtsen 171c18ec02fSPetter Reinholdtsen /* See table 22-19 for the source of the statement */ 172c18ec02fSPetter Reinholdtsen switch (cipher_suite_id) 173c18ec02fSPetter Reinholdtsen { 174c18ec02fSPetter Reinholdtsen case 0: 175c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_NONE; 176c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_NONE; 177c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_NONE; 178c18ec02fSPetter Reinholdtsen break; 179c18ec02fSPetter Reinholdtsen case 1: 180c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1; 181c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_NONE; 182c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_NONE; 183c18ec02fSPetter Reinholdtsen break; 184c18ec02fSPetter Reinholdtsen case 2: 185c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1; 186c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96; 187c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_NONE; 188c18ec02fSPetter Reinholdtsen break; 189c18ec02fSPetter Reinholdtsen case 3: 190c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1; 191c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96; 192c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_AES_CBC_128; 193c18ec02fSPetter Reinholdtsen break; 194c18ec02fSPetter Reinholdtsen case 4: 195c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1; 196c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96; 197c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_XRC4_128; 198c18ec02fSPetter Reinholdtsen break; 199c18ec02fSPetter Reinholdtsen case 5: 200c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1; 201c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96; 202c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_XRC4_40; 203c18ec02fSPetter Reinholdtsen break; 204c18ec02fSPetter Reinholdtsen case 6: 205c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 206c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_NONE; 207c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_NONE; 208c18ec02fSPetter Reinholdtsen break; 209c18ec02fSPetter Reinholdtsen case 7: 210c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 211c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128; 212c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_NONE; 213c18ec02fSPetter Reinholdtsen break; 214c18ec02fSPetter Reinholdtsen case 8: 215c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 216c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128; 217c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_AES_CBC_128; 218c18ec02fSPetter Reinholdtsen break; 219c18ec02fSPetter Reinholdtsen case 9: 220c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 221c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128; 222c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_XRC4_128; 223c18ec02fSPetter Reinholdtsen break; 224c18ec02fSPetter Reinholdtsen case 10: 225c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 226c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128; 227c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_XRC4_40; 228c18ec02fSPetter Reinholdtsen break; 229c18ec02fSPetter Reinholdtsen case 11: 230c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 231c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_MD5_128; 232c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_NONE; 233c18ec02fSPetter Reinholdtsen break; 234c18ec02fSPetter Reinholdtsen case 12: 235c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 236c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_MD5_128; 237c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_AES_CBC_128; 238c18ec02fSPetter Reinholdtsen break; 239c18ec02fSPetter Reinholdtsen case 13: 240c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 241c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_MD5_128; 242c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_XRC4_128; 243c18ec02fSPetter Reinholdtsen break; 244c18ec02fSPetter Reinholdtsen case 14: 245c18ec02fSPetter Reinholdtsen *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5; 246c18ec02fSPetter Reinholdtsen *integrity_alg = IPMI_INTEGRITY_MD5_128; 247c18ec02fSPetter Reinholdtsen *crypt_alg = IPMI_CRYPT_XRC4_40; 248c18ec02fSPetter Reinholdtsen break; 249c18ec02fSPetter Reinholdtsen } 250c18ec02fSPetter Reinholdtsen 251c18ec02fSPetter Reinholdtsen return 0; 252c18ec02fSPetter Reinholdtsen } 253c18ec02fSPetter Reinholdtsen 254c18ec02fSPetter Reinholdtsen 255c18ec02fSPetter Reinholdtsen 256c18ec02fSPetter Reinholdtsen /* 257c18ec02fSPetter Reinholdtsen * Reverse the order of arbitrarily long strings of bytes 258c18ec02fSPetter Reinholdtsen */ 259c18ec02fSPetter Reinholdtsen void lanplus_swap( 260c18ec02fSPetter Reinholdtsen uint8_t * buffer, 261c18ec02fSPetter Reinholdtsen int length) 262c18ec02fSPetter Reinholdtsen { 263c18ec02fSPetter Reinholdtsen int i; 264c18ec02fSPetter Reinholdtsen uint8_t temp; 265c18ec02fSPetter Reinholdtsen 266c18ec02fSPetter Reinholdtsen for (i =0; i < length/2; ++i) 267c18ec02fSPetter Reinholdtsen { 268c18ec02fSPetter Reinholdtsen temp = buffer[i]; 269c18ec02fSPetter Reinholdtsen buffer[i] = buffer[length - 1 - i]; 270c18ec02fSPetter Reinholdtsen buffer[length - 1 - i] = temp; 271c18ec02fSPetter Reinholdtsen } 272c18ec02fSPetter Reinholdtsen } 273c18ec02fSPetter Reinholdtsen 274c18ec02fSPetter Reinholdtsen 275c18ec02fSPetter Reinholdtsen 276c18ec02fSPetter Reinholdtsen static const struct valstr plus_payload_types_vals[] = { 277c18ec02fSPetter Reinholdtsen { IPMI_PAYLOAD_TYPE_IPMI, "IPMI (0)" }, // IPMI Message 278c18ec02fSPetter Reinholdtsen { IPMI_PAYLOAD_TYPE_SOL, "SOL (1)" }, // SOL (Serial over LAN) 279c18ec02fSPetter Reinholdtsen { IPMI_PAYLOAD_TYPE_OEM, "OEM (2)" }, // OEM Explicid 280c18ec02fSPetter Reinholdtsen 281c18ec02fSPetter Reinholdtsen { IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST, "OpenSession Req (0x10)" }, 282c18ec02fSPetter Reinholdtsen { IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE,"OpenSession Resp (0x11)" }, 283c18ec02fSPetter Reinholdtsen { IPMI_PAYLOAD_TYPE_RAKP_1, "RAKP1 (0x12)" }, 284c18ec02fSPetter Reinholdtsen { IPMI_PAYLOAD_TYPE_RAKP_2, "RAKP2 (0x13)" }, 285c18ec02fSPetter Reinholdtsen { IPMI_PAYLOAD_TYPE_RAKP_3, "RAKP3 (0x14)" }, 286c18ec02fSPetter Reinholdtsen { IPMI_PAYLOAD_TYPE_RAKP_4, "RAKP4 (0x15)" }, 287c18ec02fSPetter Reinholdtsen { 0x00, NULL }, 288c18ec02fSPetter Reinholdtsen }; 289c18ec02fSPetter Reinholdtsen 290c18ec02fSPetter Reinholdtsen 291c18ec02fSPetter Reinholdtsen static struct ipmi_rq_entry * 292c18ec02fSPetter Reinholdtsen ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req, uint8_t req_seq) 293c18ec02fSPetter Reinholdtsen { 294c18ec02fSPetter Reinholdtsen struct ipmi_rq_entry * e; 295c18ec02fSPetter Reinholdtsen 296c18ec02fSPetter Reinholdtsen e = malloc(sizeof(struct ipmi_rq_entry)); 297c18ec02fSPetter Reinholdtsen if (e == NULL) { 298c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure"); 299c18ec02fSPetter Reinholdtsen return NULL; 300c18ec02fSPetter Reinholdtsen } 301c18ec02fSPetter Reinholdtsen 302c18ec02fSPetter Reinholdtsen memset(e, 0, sizeof(struct ipmi_rq_entry)); 303c18ec02fSPetter Reinholdtsen memcpy(&e->req, req, sizeof(struct ipmi_rq)); 304c18ec02fSPetter Reinholdtsen 305c18ec02fSPetter Reinholdtsen e->intf = intf; 306c18ec02fSPetter Reinholdtsen e->rq_seq = req_seq; 307c18ec02fSPetter Reinholdtsen 308c18ec02fSPetter Reinholdtsen if (ipmi_req_entries == NULL) 309c18ec02fSPetter Reinholdtsen ipmi_req_entries = e; 310c18ec02fSPetter Reinholdtsen else 311c18ec02fSPetter Reinholdtsen ipmi_req_entries_tail->next = e; 312c18ec02fSPetter Reinholdtsen 313c18ec02fSPetter Reinholdtsen ipmi_req_entries_tail = e; 314c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+3, "added list entry seq=0x%02x cmd=0x%02x", 315c18ec02fSPetter Reinholdtsen e->rq_seq, e->req.msg.cmd); 316c18ec02fSPetter Reinholdtsen return e; 317c18ec02fSPetter Reinholdtsen } 318c18ec02fSPetter Reinholdtsen 319c18ec02fSPetter Reinholdtsen 320c18ec02fSPetter Reinholdtsen static struct ipmi_rq_entry * 321c18ec02fSPetter Reinholdtsen ipmi_req_lookup_entry(uint8_t seq, uint8_t cmd) 322c18ec02fSPetter Reinholdtsen { 323c18ec02fSPetter Reinholdtsen struct ipmi_rq_entry * e = ipmi_req_entries; 324c18ec02fSPetter Reinholdtsen 325c18ec02fSPetter Reinholdtsen while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) { 326c18ec02fSPetter Reinholdtsen if (e == e->next) 327c18ec02fSPetter Reinholdtsen return NULL; 328c18ec02fSPetter Reinholdtsen e = e->next; 329c18ec02fSPetter Reinholdtsen } 330c18ec02fSPetter Reinholdtsen return e; 331c18ec02fSPetter Reinholdtsen } 332c18ec02fSPetter Reinholdtsen 333c18ec02fSPetter Reinholdtsen static void 334c18ec02fSPetter Reinholdtsen ipmi_req_remove_entry(uint8_t seq, uint8_t cmd) 335c18ec02fSPetter Reinholdtsen { 336c18ec02fSPetter Reinholdtsen struct ipmi_rq_entry * p, * e, * saved_next_entry; 337c18ec02fSPetter Reinholdtsen 338c18ec02fSPetter Reinholdtsen e = p = ipmi_req_entries; 339c18ec02fSPetter Reinholdtsen 340c18ec02fSPetter Reinholdtsen while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) { 341c18ec02fSPetter Reinholdtsen p = e; 342c18ec02fSPetter Reinholdtsen e = e->next; 343c18ec02fSPetter Reinholdtsen } 344c18ec02fSPetter Reinholdtsen if (e) { 345c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+3, "removed list entry seq=0x%02x cmd=0x%02x", 346c18ec02fSPetter Reinholdtsen seq, cmd); 347c18ec02fSPetter Reinholdtsen saved_next_entry = e->next; 348c18ec02fSPetter Reinholdtsen p->next = (p->next == e->next) ? NULL : e->next; 349c18ec02fSPetter Reinholdtsen /* If entry being removed is first in list, fix up list head */ 350c18ec02fSPetter Reinholdtsen if (ipmi_req_entries == e) { 351c18ec02fSPetter Reinholdtsen if (ipmi_req_entries != p) 352c18ec02fSPetter Reinholdtsen ipmi_req_entries = p; 353c18ec02fSPetter Reinholdtsen else 354c18ec02fSPetter Reinholdtsen ipmi_req_entries = saved_next_entry; 355c18ec02fSPetter Reinholdtsen } 356c18ec02fSPetter Reinholdtsen /* If entry being removed is last in list, fix up list tail */ 357c18ec02fSPetter Reinholdtsen if (ipmi_req_entries_tail == e) { 358c18ec02fSPetter Reinholdtsen if (ipmi_req_entries_tail != p) 359c18ec02fSPetter Reinholdtsen ipmi_req_entries_tail = p; 360c18ec02fSPetter Reinholdtsen else 361c18ec02fSPetter Reinholdtsen ipmi_req_entries_tail = NULL; 362c18ec02fSPetter Reinholdtsen } 363c18ec02fSPetter Reinholdtsen 364c18ec02fSPetter Reinholdtsen if (e->msg_data) { 365c18ec02fSPetter Reinholdtsen free(e->msg_data); 366c18ec02fSPetter Reinholdtsen e->msg_data = NULL; 367c18ec02fSPetter Reinholdtsen } 368c18ec02fSPetter Reinholdtsen free(e); 369c18ec02fSPetter Reinholdtsen e = NULL; 370c18ec02fSPetter Reinholdtsen } 371c18ec02fSPetter Reinholdtsen } 372c18ec02fSPetter Reinholdtsen 373c18ec02fSPetter Reinholdtsen static void 374c18ec02fSPetter Reinholdtsen ipmi_req_clear_entries(void) 375c18ec02fSPetter Reinholdtsen { 376c18ec02fSPetter Reinholdtsen struct ipmi_rq_entry * p, * e; 377c18ec02fSPetter Reinholdtsen 378c18ec02fSPetter Reinholdtsen e = ipmi_req_entries; 379c18ec02fSPetter Reinholdtsen while (e) { 380c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+3, "cleared list entry seq=0x%02x cmd=0x%02x", 381c18ec02fSPetter Reinholdtsen e->rq_seq, e->req.msg.cmd); 382c18ec02fSPetter Reinholdtsen p = e->next; 383c18ec02fSPetter Reinholdtsen free(e); 384c18ec02fSPetter Reinholdtsen e = p; 385c18ec02fSPetter Reinholdtsen } 386c18ec02fSPetter Reinholdtsen } 387c18ec02fSPetter Reinholdtsen 388c18ec02fSPetter Reinholdtsen 389c18ec02fSPetter Reinholdtsen int 390c18ec02fSPetter Reinholdtsen ipmi_lan_send_packet( 391c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 392c18ec02fSPetter Reinholdtsen uint8_t * data, int 393c18ec02fSPetter Reinholdtsen data_len) 394c18ec02fSPetter Reinholdtsen { 395c18ec02fSPetter Reinholdtsen if (verbose >= 5) 396c18ec02fSPetter Reinholdtsen printbuf(data, data_len, ">> sending packet"); 397c18ec02fSPetter Reinholdtsen 398c18ec02fSPetter Reinholdtsen return send(intf->fd, data, data_len, 0); 399c18ec02fSPetter Reinholdtsen } 400c18ec02fSPetter Reinholdtsen 401c18ec02fSPetter Reinholdtsen 402c18ec02fSPetter Reinholdtsen 403c18ec02fSPetter Reinholdtsen struct ipmi_rs * 404c18ec02fSPetter Reinholdtsen ipmi_lan_recv_packet(struct ipmi_intf * intf) 405c18ec02fSPetter Reinholdtsen { 406c18ec02fSPetter Reinholdtsen static struct ipmi_rs rsp; 407c18ec02fSPetter Reinholdtsen fd_set read_set, err_set; 408c18ec02fSPetter Reinholdtsen struct timeval tmout; 409c18ec02fSPetter Reinholdtsen int ret; 410c18ec02fSPetter Reinholdtsen 411c18ec02fSPetter Reinholdtsen FD_ZERO(&read_set); 412c18ec02fSPetter Reinholdtsen FD_SET(intf->fd, &read_set); 413c18ec02fSPetter Reinholdtsen 414c18ec02fSPetter Reinholdtsen FD_ZERO(&err_set); 415c18ec02fSPetter Reinholdtsen FD_SET(intf->fd, &err_set); 416c18ec02fSPetter Reinholdtsen 417c18ec02fSPetter Reinholdtsen tmout.tv_sec = intf->session->timeout; 418c18ec02fSPetter Reinholdtsen tmout.tv_usec = 0; 419c18ec02fSPetter Reinholdtsen 420c18ec02fSPetter Reinholdtsen ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout); 421c18ec02fSPetter Reinholdtsen if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set)) 422c18ec02fSPetter Reinholdtsen return NULL; 423c18ec02fSPetter Reinholdtsen 424c18ec02fSPetter Reinholdtsen /* the first read may return ECONNREFUSED because the rmcp ping 425c18ec02fSPetter Reinholdtsen * packet--sent to UDP port 623--will be processed by both the 426c18ec02fSPetter Reinholdtsen * BMC and the OS. 427c18ec02fSPetter Reinholdtsen * 428c18ec02fSPetter Reinholdtsen * The problem with this is that the ECONNREFUSED takes 429c18ec02fSPetter Reinholdtsen * priority over any other received datagram; that means that 430c18ec02fSPetter Reinholdtsen * the Connection Refused shows up _before_ the response packet, 431c18ec02fSPetter Reinholdtsen * regardless of the order they were sent out. (unless the 432c18ec02fSPetter Reinholdtsen * response is read before the connection refused is returned) 433c18ec02fSPetter Reinholdtsen */ 434c18ec02fSPetter Reinholdtsen ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0); 435c18ec02fSPetter Reinholdtsen 436c18ec02fSPetter Reinholdtsen if (ret < 0) { 437c18ec02fSPetter Reinholdtsen FD_ZERO(&read_set); 438c18ec02fSPetter Reinholdtsen FD_SET(intf->fd, &read_set); 439c18ec02fSPetter Reinholdtsen 440c18ec02fSPetter Reinholdtsen FD_ZERO(&err_set); 441c18ec02fSPetter Reinholdtsen FD_SET(intf->fd, &err_set); 442c18ec02fSPetter Reinholdtsen 443c18ec02fSPetter Reinholdtsen tmout.tv_sec = intf->session->timeout; 444c18ec02fSPetter Reinholdtsen tmout.tv_usec = 0; 445c18ec02fSPetter Reinholdtsen 446c18ec02fSPetter Reinholdtsen ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout); 447c18ec02fSPetter Reinholdtsen if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set)) 448c18ec02fSPetter Reinholdtsen return NULL; 449c18ec02fSPetter Reinholdtsen 450c18ec02fSPetter Reinholdtsen ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0); 451c18ec02fSPetter Reinholdtsen if (ret < 0) 452c18ec02fSPetter Reinholdtsen return NULL; 453c18ec02fSPetter Reinholdtsen } 454c18ec02fSPetter Reinholdtsen 455c18ec02fSPetter Reinholdtsen if (ret == 0) 456c18ec02fSPetter Reinholdtsen return NULL; 457c18ec02fSPetter Reinholdtsen 458c18ec02fSPetter Reinholdtsen rsp.data[ret] = '\0'; 459c18ec02fSPetter Reinholdtsen rsp.data_len = ret; 460c18ec02fSPetter Reinholdtsen 461c18ec02fSPetter Reinholdtsen if (verbose >= 5) 462c18ec02fSPetter Reinholdtsen printbuf(rsp.data, rsp.data_len, "<< received packet"); 463c18ec02fSPetter Reinholdtsen 464c18ec02fSPetter Reinholdtsen return &rsp; 465c18ec02fSPetter Reinholdtsen } 466c18ec02fSPetter Reinholdtsen 467c18ec02fSPetter Reinholdtsen 468c18ec02fSPetter Reinholdtsen 469c18ec02fSPetter Reinholdtsen /* 470c18ec02fSPetter Reinholdtsen * parse response RMCP "pong" packet 471c18ec02fSPetter Reinholdtsen * 472c18ec02fSPetter Reinholdtsen * return -1 if ping response not received 473c18ec02fSPetter Reinholdtsen * returns 0 if IPMI is NOT supported 474c18ec02fSPetter Reinholdtsen * returns 1 if IPMI is supported 475c18ec02fSPetter Reinholdtsen * 476c18ec02fSPetter Reinholdtsen * udp.source = 0x026f // RMCP_UDP_PORT 477c18ec02fSPetter Reinholdtsen * udp.dest = ? // udp.source from rmcp-ping 478c18ec02fSPetter Reinholdtsen * udp.len = ? 479c18ec02fSPetter Reinholdtsen * udp.check = ? 480c18ec02fSPetter Reinholdtsen * rmcp.ver = 0x06 // RMCP Version 1.0 481c18ec02fSPetter Reinholdtsen * rmcp.__res = 0x00 // RESERVED 482c18ec02fSPetter Reinholdtsen * rmcp.seq = 0xff // no RMCP ACK 483c18ec02fSPetter Reinholdtsen * rmcp.class = 0x06 // RMCP_CLASS_ASF 484c18ec02fSPetter Reinholdtsen * asf.iana = 0x000011be // ASF_RMCP_IANA 485c18ec02fSPetter Reinholdtsen * asf.type = 0x40 // ASF_TYPE_PONG 486c18ec02fSPetter Reinholdtsen * asf.tag = ? // asf.tag from rmcp-ping 487c18ec02fSPetter Reinholdtsen * asf.__res = 0x00 // RESERVED 488c18ec02fSPetter Reinholdtsen * asf.len = 0x10 // 16 bytes 489c18ec02fSPetter Reinholdtsen * asf.data[3:0]= 0x000011be // IANA# = RMCP_ASF_IANA if no OEM 490c18ec02fSPetter Reinholdtsen * asf.data[7:4]= 0x00000000 // OEM-defined (not for IPMI) 491c18ec02fSPetter Reinholdtsen * asf.data[8] = 0x81 // supported entities 492c18ec02fSPetter Reinholdtsen * // [7]=IPMI [6:4]=RES [3:0]=ASF_1.0 493c18ec02fSPetter Reinholdtsen * asf.data[9] = 0x00 // supported interactions (reserved) 494c18ec02fSPetter Reinholdtsen * asf.data[f:a]= 0x000000000000 495c18ec02fSPetter Reinholdtsen */ 496c18ec02fSPetter Reinholdtsen static int 497c18ec02fSPetter Reinholdtsen ipmi_handle_pong(struct ipmi_intf * intf, struct ipmi_rs * rsp) 498c18ec02fSPetter Reinholdtsen { 499c18ec02fSPetter Reinholdtsen struct rmcp_pong { 500c18ec02fSPetter Reinholdtsen struct rmcp_hdr rmcp; 501c18ec02fSPetter Reinholdtsen struct asf_hdr asf; 502c18ec02fSPetter Reinholdtsen uint32_t iana; 503c18ec02fSPetter Reinholdtsen uint32_t oem; 504c18ec02fSPetter Reinholdtsen uint8_t sup_entities; 505c18ec02fSPetter Reinholdtsen uint8_t sup_interact; 506c18ec02fSPetter Reinholdtsen uint8_t reserved[6]; 507c18ec02fSPetter Reinholdtsen } * pong; 508c18ec02fSPetter Reinholdtsen 509c18ec02fSPetter Reinholdtsen if (!rsp) 510c18ec02fSPetter Reinholdtsen return -1; 511c18ec02fSPetter Reinholdtsen 512c18ec02fSPetter Reinholdtsen pong = (struct rmcp_pong *)rsp->data; 513c18ec02fSPetter Reinholdtsen 514c18ec02fSPetter Reinholdtsen if (verbose) 515c18ec02fSPetter Reinholdtsen printf("Received IPMI/RMCP response packet: " 516c18ec02fSPetter Reinholdtsen "IPMI%s Supported\n", 517c18ec02fSPetter Reinholdtsen (pong->sup_entities & 0x80) ? "" : " NOT"); 518c18ec02fSPetter Reinholdtsen 519c18ec02fSPetter Reinholdtsen if (verbose > 1) 520c18ec02fSPetter Reinholdtsen printf(" ASF Version %s\n" 521c18ec02fSPetter Reinholdtsen " RMCP Version %s\n" 522c18ec02fSPetter Reinholdtsen " RMCP Sequence %d\n" 523c18ec02fSPetter Reinholdtsen " IANA Enterprise %lu\n\n", 524c18ec02fSPetter Reinholdtsen (pong->sup_entities & 0x01) ? "1.0" : "unknown", 525c18ec02fSPetter Reinholdtsen (pong->rmcp.ver == 6) ? "1.0" : "unknown", 526c18ec02fSPetter Reinholdtsen pong->rmcp.seq, 527c18ec02fSPetter Reinholdtsen (unsigned long)ntohl(pong->iana)); 528c18ec02fSPetter Reinholdtsen 529c18ec02fSPetter Reinholdtsen return (pong->sup_entities & 0x80) ? 1 : 0; 530c18ec02fSPetter Reinholdtsen } 531c18ec02fSPetter Reinholdtsen 532c18ec02fSPetter Reinholdtsen 533c18ec02fSPetter Reinholdtsen /* build and send RMCP presence ping packet 534c18ec02fSPetter Reinholdtsen * 535c18ec02fSPetter Reinholdtsen * RMCP ping 536c18ec02fSPetter Reinholdtsen * 537c18ec02fSPetter Reinholdtsen * udp.source = ? 538c18ec02fSPetter Reinholdtsen * udp.dest = 0x026f // RMCP_UDP_PORT 539c18ec02fSPetter Reinholdtsen * udp.len = ? 540c18ec02fSPetter Reinholdtsen * udp.check = ? 541c18ec02fSPetter Reinholdtsen * rmcp.ver = 0x06 // RMCP Version 1.0 542c18ec02fSPetter Reinholdtsen * rmcp.__res = 0x00 // RESERVED 543c18ec02fSPetter Reinholdtsen * rmcp.seq = 0xff // no RMCP ACK 544c18ec02fSPetter Reinholdtsen * rmcp.class = 0x06 // RMCP_CLASS_ASF 545c18ec02fSPetter Reinholdtsen * asf.iana = 0x000011be // ASF_RMCP_IANA 546c18ec02fSPetter Reinholdtsen * asf.type = 0x80 // ASF_TYPE_PING 547c18ec02fSPetter Reinholdtsen * asf.tag = ? // ASF sequence number 548c18ec02fSPetter Reinholdtsen * asf.__res = 0x00 // RESERVED 549c18ec02fSPetter Reinholdtsen * asf.len = 0x00 550c18ec02fSPetter Reinholdtsen * 551c18ec02fSPetter Reinholdtsen */ 552c18ec02fSPetter Reinholdtsen int 553c18ec02fSPetter Reinholdtsen ipmiv2_lan_ping(struct ipmi_intf * intf) 554c18ec02fSPetter Reinholdtsen { 555c18ec02fSPetter Reinholdtsen struct asf_hdr asf_ping = { 556c18ec02fSPetter Reinholdtsen .iana = htonl(ASF_RMCP_IANA), 557c18ec02fSPetter Reinholdtsen .type = ASF_TYPE_PING, 558c18ec02fSPetter Reinholdtsen }; 559c18ec02fSPetter Reinholdtsen struct rmcp_hdr rmcp_ping = { 560c18ec02fSPetter Reinholdtsen .ver = RMCP_VERSION_1, 561c18ec02fSPetter Reinholdtsen .class = RMCP_CLASS_ASF, 562c18ec02fSPetter Reinholdtsen .seq = 0xff, 563c18ec02fSPetter Reinholdtsen }; 564c18ec02fSPetter Reinholdtsen uint8_t * data; 565c18ec02fSPetter Reinholdtsen int len = sizeof(rmcp_ping) + sizeof(asf_ping); 566c18ec02fSPetter Reinholdtsen int rv; 567c18ec02fSPetter Reinholdtsen 568c18ec02fSPetter Reinholdtsen data = malloc(len); 569c18ec02fSPetter Reinholdtsen if (data == NULL) { 570c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure"); 571c18ec02fSPetter Reinholdtsen return -1; 572c18ec02fSPetter Reinholdtsen } 573c18ec02fSPetter Reinholdtsen memset(data, 0, len); 574c18ec02fSPetter Reinholdtsen memcpy(data, &rmcp_ping, sizeof(rmcp_ping)); 575c18ec02fSPetter Reinholdtsen memcpy(data+sizeof(rmcp_ping), &asf_ping, sizeof(asf_ping)); 576c18ec02fSPetter Reinholdtsen 577c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Sending IPMI/RMCP presence ping packet"); 578c18ec02fSPetter Reinholdtsen 579c18ec02fSPetter Reinholdtsen rv = ipmi_lan_send_packet(intf, data, len); 580c18ec02fSPetter Reinholdtsen 581c18ec02fSPetter Reinholdtsen free(data); 582c18ec02fSPetter Reinholdtsen data = NULL; 583c18ec02fSPetter Reinholdtsen 584c18ec02fSPetter Reinholdtsen if (rv < 0) { 585c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Unable to send IPMI presence ping packet"); 586c18ec02fSPetter Reinholdtsen return -1; 587c18ec02fSPetter Reinholdtsen } 588c18ec02fSPetter Reinholdtsen 589c18ec02fSPetter Reinholdtsen if (ipmi_lan_poll_recv(intf) == 0) 590c18ec02fSPetter Reinholdtsen return 0; 591c18ec02fSPetter Reinholdtsen 592c18ec02fSPetter Reinholdtsen return 1; 593c18ec02fSPetter Reinholdtsen } 594c18ec02fSPetter Reinholdtsen 595c18ec02fSPetter Reinholdtsen 596c18ec02fSPetter Reinholdtsen /** 597c18ec02fSPetter Reinholdtsen * 598c18ec02fSPetter Reinholdtsen * ipmi_lan_poll_recv 599c18ec02fSPetter Reinholdtsen * 600c18ec02fSPetter Reinholdtsen * Receive whatever comes back. Ignore received packets that don't correspond 601c18ec02fSPetter Reinholdtsen * to a request we've sent. 602c18ec02fSPetter Reinholdtsen * 603c18ec02fSPetter Reinholdtsen * Returns: the ipmi_rs packet describing the/a reponse we expect. 604c18ec02fSPetter Reinholdtsen */ 605c18ec02fSPetter Reinholdtsen static struct ipmi_rs * 606c18ec02fSPetter Reinholdtsen ipmi_lan_poll_recv(struct ipmi_intf * intf) 607c18ec02fSPetter Reinholdtsen { 608c18ec02fSPetter Reinholdtsen struct rmcp_hdr rmcp_rsp; 609c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp; 610c18ec02fSPetter Reinholdtsen struct ipmi_session * session = intf->session; 611c18ec02fSPetter Reinholdtsen int offset, rv; 612c18ec02fSPetter Reinholdtsen uint16_t payload_size; 613c18ec02fSPetter Reinholdtsen uint8_t ourAddress = intf->my_addr; 614c18ec02fSPetter Reinholdtsen 615c18ec02fSPetter Reinholdtsen if (ourAddress == 0) { 616c18ec02fSPetter Reinholdtsen ourAddress = IPMI_BMC_SLAVE_ADDR; 617c18ec02fSPetter Reinholdtsen } 618c18ec02fSPetter Reinholdtsen 619c18ec02fSPetter Reinholdtsen rsp = ipmi_lan_recv_packet(intf); 620c18ec02fSPetter Reinholdtsen 621c18ec02fSPetter Reinholdtsen /* 622c18ec02fSPetter Reinholdtsen * Not positive why we're looping. Do we sometimes get stuff we don't 623c18ec02fSPetter Reinholdtsen * expect? 624c18ec02fSPetter Reinholdtsen */ 625c18ec02fSPetter Reinholdtsen while (rsp != NULL) { 626c18ec02fSPetter Reinholdtsen 627c18ec02fSPetter Reinholdtsen /* parse response headers */ 628c18ec02fSPetter Reinholdtsen memcpy(&rmcp_rsp, rsp->data, 4); 629c18ec02fSPetter Reinholdtsen 630c18ec02fSPetter Reinholdtsen if (rmcp_rsp.class == RMCP_CLASS_ASF) { 631c18ec02fSPetter Reinholdtsen /* might be ping response packet */ 632c18ec02fSPetter Reinholdtsen rv = ipmi_handle_pong(intf, rsp); 633c18ec02fSPetter Reinholdtsen return (rv <= 0) ? NULL : rsp; 634c18ec02fSPetter Reinholdtsen } 635c18ec02fSPetter Reinholdtsen 636c18ec02fSPetter Reinholdtsen if (rmcp_rsp.class != RMCP_CLASS_IPMI) { 637c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Invalid RMCP class: %x", 638c18ec02fSPetter Reinholdtsen rmcp_rsp.class); 639c18ec02fSPetter Reinholdtsen rsp = ipmi_lan_recv_packet(intf); 640c18ec02fSPetter Reinholdtsen continue; 641c18ec02fSPetter Reinholdtsen } 642c18ec02fSPetter Reinholdtsen 643c18ec02fSPetter Reinholdtsen 644c18ec02fSPetter Reinholdtsen /* 645c18ec02fSPetter Reinholdtsen * The authtype / payload type determines what we are receiving 646c18ec02fSPetter Reinholdtsen */ 647c18ec02fSPetter Reinholdtsen offset = 4; 648c18ec02fSPetter Reinholdtsen 649c18ec02fSPetter Reinholdtsen 650c18ec02fSPetter Reinholdtsen /*-------------------------------------------------------------------- 651c18ec02fSPetter Reinholdtsen * 652c18ec02fSPetter Reinholdtsen * The current packet could be one of several things: 653c18ec02fSPetter Reinholdtsen * 654c18ec02fSPetter Reinholdtsen * 1) An IPMI 1.5 packet (the response to our GET CHANNEL 655c18ec02fSPetter Reinholdtsen * AUTHENTICATION CAPABILITIES request) 656c18ec02fSPetter Reinholdtsen * 2) An RMCP+ message with an IPMI reponse payload 657c18ec02fSPetter Reinholdtsen * 3) AN RMCP+ open session response 658c18ec02fSPetter Reinholdtsen * 4) An RAKP-2 message (response to an RAKP 1 message) 659c18ec02fSPetter Reinholdtsen * 5) An RAKP-4 message (response to an RAKP 3 message) 660c18ec02fSPetter Reinholdtsen * 6) A Serial Over LAN packet 661c18ec02fSPetter Reinholdtsen * 7) An Invalid packet (one that doesn't match a request) 662c18ec02fSPetter Reinholdtsen * ------------------------------------------------------------------- 663c18ec02fSPetter Reinholdtsen */ 664c18ec02fSPetter Reinholdtsen 665c18ec02fSPetter Reinholdtsen read_session_data(rsp, &offset, intf->session); 666c18ec02fSPetter Reinholdtsen 667c18ec02fSPetter Reinholdtsen if (lanplus_has_valid_auth_code(rsp, intf->session) == 0) 668c18ec02fSPetter Reinholdtsen { 669c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ERROR: Received message with invalid authcode!"); 670c18ec02fSPetter Reinholdtsen rsp = ipmi_lan_recv_packet(intf); 671c18ec02fSPetter Reinholdtsen assert(0); 672c18ec02fSPetter Reinholdtsen //continue; 673c18ec02fSPetter Reinholdtsen } 674c18ec02fSPetter Reinholdtsen 675c18ec02fSPetter Reinholdtsen if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) && 676c18ec02fSPetter Reinholdtsen (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) && 677c18ec02fSPetter Reinholdtsen (rsp->session.bEncrypted)) 678c18ec02fSPetter Reinholdtsen 679c18ec02fSPetter Reinholdtsen { 680c18ec02fSPetter Reinholdtsen lanplus_decrypt_payload(session->v2_data.crypt_alg, 681c18ec02fSPetter Reinholdtsen session->v2_data.k2, 682c18ec02fSPetter Reinholdtsen rsp->data + offset, 683c18ec02fSPetter Reinholdtsen rsp->session.msglen, 684c18ec02fSPetter Reinholdtsen rsp->data + offset, 685c18ec02fSPetter Reinholdtsen &payload_size); 686c18ec02fSPetter Reinholdtsen } 687c18ec02fSPetter Reinholdtsen else 688c18ec02fSPetter Reinholdtsen payload_size = rsp->session.msglen; 689c18ec02fSPetter Reinholdtsen 690c18ec02fSPetter Reinholdtsen 691c18ec02fSPetter Reinholdtsen /* 692c18ec02fSPetter Reinholdtsen * Handle IPMI responses (case #1 and #2) -- all IPMI reponses 693c18ec02fSPetter Reinholdtsen */ 694c18ec02fSPetter Reinholdtsen if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI) 695c18ec02fSPetter Reinholdtsen { 696c18ec02fSPetter Reinholdtsen struct ipmi_rq_entry * entry; 697c18ec02fSPetter Reinholdtsen int payload_start = offset; 698c18ec02fSPetter Reinholdtsen int extra_data_length; 699c18ec02fSPetter Reinholdtsen read_ipmi_response(rsp, &offset); 700c18ec02fSPetter Reinholdtsen 701c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header"); 702c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< Authtype : %s", 703c18ec02fSPetter Reinholdtsen val2str(rsp->session.authtype, ipmi_authtype_session_vals)); 704c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< Payload type : %s", 705c18ec02fSPetter Reinholdtsen val2str(rsp->session.payloadtype, plus_payload_types_vals)); 706c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< Session ID : 0x%08lx", 707c18ec02fSPetter Reinholdtsen (long)rsp->session.id); 708c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< Sequence : 0x%08lx", 709c18ec02fSPetter Reinholdtsen (long)rsp->session.seq); 710c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< IPMI Msg/Payload Length : %d", 711c18ec02fSPetter Reinholdtsen rsp->session.msglen); 712c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header"); 713c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< Rq Addr : %02x", 714c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rq_addr); 715c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< NetFn : %02x", 716c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.netfn); 717c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< Rq LUN : %01x", 718c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rq_lun); 719c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< Rs Addr : %02x", 720c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rs_addr); 721c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< Rq Seq : %02x", 722c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rq_seq); 723c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< Rs Lun : %01x", 724c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rs_lun); 725c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< Command : %02x", 726c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.cmd); 727c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "<< Compl Code : 0x%02x", 728c18ec02fSPetter Reinholdtsen rsp->ccode); 729c18ec02fSPetter Reinholdtsen 730c18ec02fSPetter Reinholdtsen /* Are we expecting this packet? */ 731c18ec02fSPetter Reinholdtsen entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq, 732c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.cmd); 733c18ec02fSPetter Reinholdtsen 734c18ec02fSPetter Reinholdtsen if (entry != NULL) { 735c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+2, "IPMI Request Match found"); 736c18ec02fSPetter Reinholdtsen if ( intf->target_addr != intf->my_addr && 737c18ec02fSPetter Reinholdtsen bridgePossible && 738c18ec02fSPetter Reinholdtsen rsp->data_len && 739c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.cmd == 0x34 && 740c18ec02fSPetter Reinholdtsen (rsp->payload.ipmi_response.netfn == 0x06 || 741c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.netfn == 0x07) && 742c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rs_lun == 0 ) 743c18ec02fSPetter Reinholdtsen { 744c18ec02fSPetter Reinholdtsen /* Check completion code */ 745c18ec02fSPetter Reinholdtsen if (rsp->data[offset-1] == 0) 746c18ec02fSPetter Reinholdtsen { 747c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Bridged command answer," 748c18ec02fSPetter Reinholdtsen " waiting for next answer... "); 749c18ec02fSPetter Reinholdtsen ipmi_req_remove_entry( 750c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rq_seq, 751c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.cmd); 752c18ec02fSPetter Reinholdtsen return ipmi_lan_poll_recv(intf); 753c18ec02fSPetter Reinholdtsen } 754c18ec02fSPetter Reinholdtsen else 755c18ec02fSPetter Reinholdtsen { 756c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "WARNING: Bridged " 757c18ec02fSPetter Reinholdtsen "cmd ccode = 0x%02x", 758c18ec02fSPetter Reinholdtsen rsp->data[offset-1]); 759c18ec02fSPetter Reinholdtsen } 760c18ec02fSPetter Reinholdtsen 761c18ec02fSPetter Reinholdtsen if (rsp->data_len && 762c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.cmd == 0x34) { 763c18ec02fSPetter Reinholdtsen memcpy(rsp->data, &rsp->data[offset], 764c18ec02fSPetter Reinholdtsen (rsp->data_len-offset)); 765c18ec02fSPetter Reinholdtsen if (verbose > 2) 766c18ec02fSPetter Reinholdtsen printbuf( &rsp->data[offset], 767c18ec02fSPetter Reinholdtsen (rsp->data_len-offset), 768c18ec02fSPetter Reinholdtsen "bridge command response"); 769c18ec02fSPetter Reinholdtsen } 770c18ec02fSPetter Reinholdtsen } 771c18ec02fSPetter Reinholdtsen 772c18ec02fSPetter Reinholdtsen ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq, 773c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.cmd); 774c18ec02fSPetter Reinholdtsen } else { 775c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "IPMI Request Match NOT FOUND"); 776c18ec02fSPetter Reinholdtsen rsp = ipmi_lan_recv_packet(intf); 777c18ec02fSPetter Reinholdtsen continue; 778c18ec02fSPetter Reinholdtsen } 779c18ec02fSPetter Reinholdtsen 780c18ec02fSPetter Reinholdtsen /* 781c18ec02fSPetter Reinholdtsen * Good packet. Shift response data to start of array. 782c18ec02fSPetter Reinholdtsen * rsp->data becomes the variable length IPMI response data 783c18ec02fSPetter Reinholdtsen * rsp->data_len becomes the length of that data 784c18ec02fSPetter Reinholdtsen */ 785c18ec02fSPetter Reinholdtsen extra_data_length = payload_size - (offset - payload_start) - 1; 786c18ec02fSPetter Reinholdtsen if (rsp != NULL && extra_data_length) 787c18ec02fSPetter Reinholdtsen { 788c18ec02fSPetter Reinholdtsen rsp->data_len = extra_data_length; 789c18ec02fSPetter Reinholdtsen memmove(rsp->data, rsp->data + offset, extra_data_length); 790c18ec02fSPetter Reinholdtsen } 791c18ec02fSPetter Reinholdtsen else 792c18ec02fSPetter Reinholdtsen rsp->data_len = 0; 793c18ec02fSPetter Reinholdtsen 794c18ec02fSPetter Reinholdtsen break; 795c18ec02fSPetter Reinholdtsen } 796c18ec02fSPetter Reinholdtsen 797c18ec02fSPetter Reinholdtsen 798c18ec02fSPetter Reinholdtsen /* 799c18ec02fSPetter Reinholdtsen * Open Response 800c18ec02fSPetter Reinholdtsen */ 801c18ec02fSPetter Reinholdtsen else if (rsp->session.payloadtype == 802c18ec02fSPetter Reinholdtsen IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE) 803c18ec02fSPetter Reinholdtsen { 804c18ec02fSPetter Reinholdtsen if (session->v2_data.session_state != 805c18ec02fSPetter Reinholdtsen LANPLUS_STATE_OPEN_SESSION_SENT) 806c18ec02fSPetter Reinholdtsen { 807c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error: Received an Unexpected Open Session " 808c18ec02fSPetter Reinholdtsen "Response"); 809c18ec02fSPetter Reinholdtsen rsp = ipmi_lan_recv_packet(intf); 810c18ec02fSPetter Reinholdtsen continue; 811c18ec02fSPetter Reinholdtsen } 812c18ec02fSPetter Reinholdtsen 813c18ec02fSPetter Reinholdtsen read_open_session_response(rsp, offset); 814c18ec02fSPetter Reinholdtsen break; 815c18ec02fSPetter Reinholdtsen } 816c18ec02fSPetter Reinholdtsen 817c18ec02fSPetter Reinholdtsen 818c18ec02fSPetter Reinholdtsen /* 819c18ec02fSPetter Reinholdtsen * RAKP 2 820c18ec02fSPetter Reinholdtsen */ 821c18ec02fSPetter Reinholdtsen else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_2) 822c18ec02fSPetter Reinholdtsen { 823c18ec02fSPetter Reinholdtsen if (session->v2_data.session_state != LANPLUS_STATE_RAKP_1_SENT) 824c18ec02fSPetter Reinholdtsen { 825c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 2 message"); 826c18ec02fSPetter Reinholdtsen rsp = ipmi_lan_recv_packet(intf); 827c18ec02fSPetter Reinholdtsen continue; 828c18ec02fSPetter Reinholdtsen } 829c18ec02fSPetter Reinholdtsen 830c18ec02fSPetter Reinholdtsen read_rakp2_message(rsp, offset, session->v2_data.auth_alg); 831c18ec02fSPetter Reinholdtsen break; 832c18ec02fSPetter Reinholdtsen } 833c18ec02fSPetter Reinholdtsen 834c18ec02fSPetter Reinholdtsen 835c18ec02fSPetter Reinholdtsen /* 836c18ec02fSPetter Reinholdtsen * RAKP 4 837c18ec02fSPetter Reinholdtsen */ 838c18ec02fSPetter Reinholdtsen else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_4) 839c18ec02fSPetter Reinholdtsen { 840c18ec02fSPetter Reinholdtsen if (session->v2_data.session_state != LANPLUS_STATE_RAKP_3_SENT) 841c18ec02fSPetter Reinholdtsen { 842c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 4 message"); 843c18ec02fSPetter Reinholdtsen rsp = ipmi_lan_recv_packet(intf); 844c18ec02fSPetter Reinholdtsen continue; 845c18ec02fSPetter Reinholdtsen } 846c18ec02fSPetter Reinholdtsen 847c18ec02fSPetter Reinholdtsen read_rakp4_message(rsp, offset, session->v2_data.auth_alg); 848c18ec02fSPetter Reinholdtsen break; 849c18ec02fSPetter Reinholdtsen } 850c18ec02fSPetter Reinholdtsen 851c18ec02fSPetter Reinholdtsen 852c18ec02fSPetter Reinholdtsen /* 853c18ec02fSPetter Reinholdtsen * SOL 854c18ec02fSPetter Reinholdtsen */ 855c18ec02fSPetter Reinholdtsen else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) 856c18ec02fSPetter Reinholdtsen { 857c18ec02fSPetter Reinholdtsen int payload_start = offset; 858c18ec02fSPetter Reinholdtsen int extra_data_length; 859c18ec02fSPetter Reinholdtsen 860c18ec02fSPetter Reinholdtsen if (session->v2_data.session_state != LANPLUS_STATE_ACTIVE) 861c18ec02fSPetter Reinholdtsen { 862c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error: Received an Unexpected SOL packet"); 863c18ec02fSPetter Reinholdtsen rsp = ipmi_lan_recv_packet(intf); 864c18ec02fSPetter Reinholdtsen continue; 865c18ec02fSPetter Reinholdtsen } 866c18ec02fSPetter Reinholdtsen 867c18ec02fSPetter Reinholdtsen read_sol_packet(rsp, &offset); 868c18ec02fSPetter Reinholdtsen extra_data_length = payload_size - (offset - payload_start); 869c18ec02fSPetter Reinholdtsen if (rsp && extra_data_length) 870c18ec02fSPetter Reinholdtsen { 871c18ec02fSPetter Reinholdtsen rsp->data_len = extra_data_length; 872c18ec02fSPetter Reinholdtsen memmove(rsp->data, rsp->data + offset, extra_data_length); 873c18ec02fSPetter Reinholdtsen } 874c18ec02fSPetter Reinholdtsen else 875c18ec02fSPetter Reinholdtsen rsp->data_len = 0; 876c18ec02fSPetter Reinholdtsen 877c18ec02fSPetter Reinholdtsen break; 878c18ec02fSPetter Reinholdtsen } 879c18ec02fSPetter Reinholdtsen 880c18ec02fSPetter Reinholdtsen else 881c18ec02fSPetter Reinholdtsen { 882c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Invalid RMCP+ payload type : 0x%x", 883c18ec02fSPetter Reinholdtsen rsp->session.payloadtype); 884c18ec02fSPetter Reinholdtsen assert(0); 885c18ec02fSPetter Reinholdtsen } 886c18ec02fSPetter Reinholdtsen } 887c18ec02fSPetter Reinholdtsen 888c18ec02fSPetter Reinholdtsen return rsp; 889c18ec02fSPetter Reinholdtsen } 890c18ec02fSPetter Reinholdtsen 891c18ec02fSPetter Reinholdtsen 892c18ec02fSPetter Reinholdtsen 893c18ec02fSPetter Reinholdtsen /* 894c18ec02fSPetter Reinholdtsen * read_open_session_reponse 895c18ec02fSPetter Reinholdtsen * 896c18ec02fSPetter Reinholdtsen * Initialize the ipmi_rs from the IPMI 2.x open session response data. 897c18ec02fSPetter Reinholdtsen * 898c18ec02fSPetter Reinholdtsen * The offset should point to the first byte of the the Open Session Response 899c18ec02fSPetter Reinholdtsen * payload when this function is called. 900c18ec02fSPetter Reinholdtsen * 901c18ec02fSPetter Reinholdtsen * param rsp [in/out] reading from the data and writing to the open_session_response 902c18ec02fSPetter Reinholdtsen * section 903c18ec02fSPetter Reinholdtsen * param offset [in] tells us where the Open Session Response payload starts 904c18ec02fSPetter Reinholdtsen * 905c18ec02fSPetter Reinholdtsen * returns 0 on success, 1 on error 906c18ec02fSPetter Reinholdtsen */ 907c18ec02fSPetter Reinholdtsen void 908c18ec02fSPetter Reinholdtsen read_open_session_response(struct ipmi_rs * rsp, int offset) 909c18ec02fSPetter Reinholdtsen { 910c18ec02fSPetter Reinholdtsen memset(&rsp->payload.open_session_response, 0, 911c18ec02fSPetter Reinholdtsen sizeof(rsp->payload.open_session_response)); 912c18ec02fSPetter Reinholdtsen 913c18ec02fSPetter Reinholdtsen /* Message tag */ 914c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.message_tag = rsp->data[offset]; 915c18ec02fSPetter Reinholdtsen 916c18ec02fSPetter Reinholdtsen /* RAKP reponse code */ 917c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.rakp_return_code = rsp->data[offset + 1]; 918c18ec02fSPetter Reinholdtsen 919c18ec02fSPetter Reinholdtsen /* Maximum privilege level */ 920c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.max_priv_level = rsp->data[offset + 2]; 921c18ec02fSPetter Reinholdtsen 922c18ec02fSPetter Reinholdtsen /*** offset + 3 is reserved ***/ 923c18ec02fSPetter Reinholdtsen 924c18ec02fSPetter Reinholdtsen /* Remote console session ID */ 925c18ec02fSPetter Reinholdtsen memcpy(&(rsp->payload.open_session_response.console_id), 926c18ec02fSPetter Reinholdtsen rsp->data + offset + 4, 927c18ec02fSPetter Reinholdtsen 4); 928c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN 929c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.console_id = 930c18ec02fSPetter Reinholdtsen BSWAP_32(rsp->payload.open_session_response.console_id); 931c18ec02fSPetter Reinholdtsen #endif 932c18ec02fSPetter Reinholdtsen 933c18ec02fSPetter Reinholdtsen /* only tag, status, privlvl, and console id are returned if error */ 934c18ec02fSPetter Reinholdtsen if (rsp->payload.open_session_response.rakp_return_code != 935c18ec02fSPetter Reinholdtsen IPMI_RAKP_STATUS_NO_ERRORS) 936c18ec02fSPetter Reinholdtsen return; 937c18ec02fSPetter Reinholdtsen 938c18ec02fSPetter Reinholdtsen /* BMC session ID */ 939c18ec02fSPetter Reinholdtsen memcpy(&(rsp->payload.open_session_response.bmc_id), 940c18ec02fSPetter Reinholdtsen rsp->data + offset + 8, 941c18ec02fSPetter Reinholdtsen 4); 942c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN 943c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.bmc_id = 944c18ec02fSPetter Reinholdtsen BSWAP_32(rsp->payload.open_session_response.bmc_id); 945c18ec02fSPetter Reinholdtsen #endif 946c18ec02fSPetter Reinholdtsen 947c18ec02fSPetter Reinholdtsen /* And of course, our negotiated algorithms */ 948c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.auth_alg = rsp->data[offset + 16]; 949c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.integrity_alg = rsp->data[offset + 24]; 950c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.crypt_alg = rsp->data[offset + 32]; 951c18ec02fSPetter Reinholdtsen } 952c18ec02fSPetter Reinholdtsen 953c18ec02fSPetter Reinholdtsen 954c18ec02fSPetter Reinholdtsen 955c18ec02fSPetter Reinholdtsen /* 956c18ec02fSPetter Reinholdtsen * read_rakp2_message 957c18ec02fSPetter Reinholdtsen * 958c18ec02fSPetter Reinholdtsen * Initialize the ipmi_rs from the IPMI 2.x RAKP 2 message 959c18ec02fSPetter Reinholdtsen * 960c18ec02fSPetter Reinholdtsen * The offset should point the first byte of the the RAKP 2 payload when this 961c18ec02fSPetter Reinholdtsen * function is called. 962c18ec02fSPetter Reinholdtsen * 963c18ec02fSPetter Reinholdtsen * param rsp [in/out] reading from the data variable and writing to the rakp 2 964c18ec02fSPetter Reinholdtsen * section 965c18ec02fSPetter Reinholdtsen * param offset [in] tells us where hte rakp2 payload starts 966c18ec02fSPetter Reinholdtsen * param auth_alg [in] describes the authentication algorithm was agreed upon in 967c18ec02fSPetter Reinholdtsen * the open session request/response phase. We need to know that here so 968c18ec02fSPetter Reinholdtsen * that we know how many bytes (if any) to read fromt the packet. 969c18ec02fSPetter Reinholdtsen * 970c18ec02fSPetter Reinholdtsen * returns 0 on success, 1 on error 971c18ec02fSPetter Reinholdtsen */ 972c18ec02fSPetter Reinholdtsen void 973c18ec02fSPetter Reinholdtsen read_rakp2_message( 974c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp, 975c18ec02fSPetter Reinholdtsen int offset, 976c18ec02fSPetter Reinholdtsen uint8_t auth_alg) 977c18ec02fSPetter Reinholdtsen { 978c18ec02fSPetter Reinholdtsen int i; 979c18ec02fSPetter Reinholdtsen 980c18ec02fSPetter Reinholdtsen /* Message tag */ 981c18ec02fSPetter Reinholdtsen rsp->payload.rakp2_message.message_tag = rsp->data[offset]; 982c18ec02fSPetter Reinholdtsen 983c18ec02fSPetter Reinholdtsen /* RAKP reponse code */ 984c18ec02fSPetter Reinholdtsen rsp->payload.rakp2_message.rakp_return_code = rsp->data[offset + 1]; 985c18ec02fSPetter Reinholdtsen 986c18ec02fSPetter Reinholdtsen /* Console session ID */ 987c18ec02fSPetter Reinholdtsen memcpy(&(rsp->payload.rakp2_message.console_id), 988c18ec02fSPetter Reinholdtsen rsp->data + offset + 4, 989c18ec02fSPetter Reinholdtsen 4); 990c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN 991c18ec02fSPetter Reinholdtsen rsp->payload.rakp2_message.console_id = 992c18ec02fSPetter Reinholdtsen BSWAP_32(rsp->payload.rakp2_message.console_id); 993c18ec02fSPetter Reinholdtsen #endif 994c18ec02fSPetter Reinholdtsen 995c18ec02fSPetter Reinholdtsen /* BMC random number */ 996c18ec02fSPetter Reinholdtsen memcpy(&(rsp->payload.rakp2_message.bmc_rand), 997c18ec02fSPetter Reinholdtsen rsp->data + offset + 8, 998c18ec02fSPetter Reinholdtsen 16); 999c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN 1000c18ec02fSPetter Reinholdtsen lanplus_swap(rsp->payload.rakp2_message.bmc_rand, 16); 1001c18ec02fSPetter Reinholdtsen #endif 1002c18ec02fSPetter Reinholdtsen 1003c18ec02fSPetter Reinholdtsen /* BMC GUID */ 1004c18ec02fSPetter Reinholdtsen memcpy(&(rsp->payload.rakp2_message.bmc_guid), 1005c18ec02fSPetter Reinholdtsen rsp->data + offset + 24, 1006c18ec02fSPetter Reinholdtsen 16); 1007c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN 1008c18ec02fSPetter Reinholdtsen lanplus_swap(rsp->payload.rakp2_message.bmc_guid, 16); 1009c18ec02fSPetter Reinholdtsen #endif 1010c18ec02fSPetter Reinholdtsen 1011c18ec02fSPetter Reinholdtsen /* Key exchange authentication code */ 1012c18ec02fSPetter Reinholdtsen switch (auth_alg) 1013c18ec02fSPetter Reinholdtsen { 1014c18ec02fSPetter Reinholdtsen case IPMI_AUTH_RAKP_NONE: 1015c18ec02fSPetter Reinholdtsen /* Nothing to do here */ 1016c18ec02fSPetter Reinholdtsen break; 1017c18ec02fSPetter Reinholdtsen 1018c18ec02fSPetter Reinholdtsen case IPMI_AUTH_RAKP_HMAC_SHA1: 1019c18ec02fSPetter Reinholdtsen /* We need to copy 20 bytes */ 1020c18ec02fSPetter Reinholdtsen for (i = 0; i < 20; ++i) 1021c18ec02fSPetter Reinholdtsen rsp->payload.rakp2_message.key_exchange_auth_code[i] = 1022c18ec02fSPetter Reinholdtsen rsp->data[offset + 40 + i]; 1023c18ec02fSPetter Reinholdtsen break; 1024c18ec02fSPetter Reinholdtsen 1025c18ec02fSPetter Reinholdtsen case IPMI_AUTH_RAKP_HMAC_MD5: 1026c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "read_rakp2_message: no support for " 1027c18ec02fSPetter Reinholdtsen "IPMI_AUTH_RAKP_HMAC_MD5"); 1028c18ec02fSPetter Reinholdtsen assert(0); 1029c18ec02fSPetter Reinholdtsen break; 1030c18ec02fSPetter Reinholdtsen } 1031c18ec02fSPetter Reinholdtsen } 1032c18ec02fSPetter Reinholdtsen 1033c18ec02fSPetter Reinholdtsen 1034c18ec02fSPetter Reinholdtsen 1035c18ec02fSPetter Reinholdtsen /* 1036c18ec02fSPetter Reinholdtsen * read_rakp4_message 1037c18ec02fSPetter Reinholdtsen * 1038c18ec02fSPetter Reinholdtsen * Initialize the ipmi_rs from the IPMI 2.x RAKP 4 message 1039c18ec02fSPetter Reinholdtsen * 1040c18ec02fSPetter Reinholdtsen * The offset should point the first byte of the the RAKP 4 payload when this 1041c18ec02fSPetter Reinholdtsen * function is called. 1042c18ec02fSPetter Reinholdtsen * 1043c18ec02fSPetter Reinholdtsen * param rsp [in/out] reading from the data variable and writing to the rakp 1044c18ec02fSPetter Reinholdtsen * 4 section 1045c18ec02fSPetter Reinholdtsen * param offset [in] tells us where hte rakp4 payload starts 1046c18ec02fSPetter Reinholdtsen * param integrity_alg [in] describes the authentication algorithm was 1047c18ec02fSPetter Reinholdtsen * agreed upon in the open session request/response phase. We need 1048c18ec02fSPetter Reinholdtsen * to know that here so that we know how many bytes (if any) to read 1049c18ec02fSPetter Reinholdtsen * from the packet. 1050c18ec02fSPetter Reinholdtsen * 1051c18ec02fSPetter Reinholdtsen * returns 0 on success, 1 on error 1052c18ec02fSPetter Reinholdtsen */ 1053c18ec02fSPetter Reinholdtsen void 1054c18ec02fSPetter Reinholdtsen read_rakp4_message( 1055c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp, 1056c18ec02fSPetter Reinholdtsen int offset, 1057c18ec02fSPetter Reinholdtsen uint8_t auth_alg) 1058c18ec02fSPetter Reinholdtsen { 1059c18ec02fSPetter Reinholdtsen int i; 1060c18ec02fSPetter Reinholdtsen 1061c18ec02fSPetter Reinholdtsen /* Message tag */ 1062c18ec02fSPetter Reinholdtsen rsp->payload.rakp4_message.message_tag = rsp->data[offset]; 1063c18ec02fSPetter Reinholdtsen 1064c18ec02fSPetter Reinholdtsen /* RAKP reponse code */ 1065c18ec02fSPetter Reinholdtsen rsp->payload.rakp4_message.rakp_return_code = rsp->data[offset + 1]; 1066c18ec02fSPetter Reinholdtsen 1067c18ec02fSPetter Reinholdtsen /* Console session ID */ 1068c18ec02fSPetter Reinholdtsen memcpy(&(rsp->payload.rakp4_message.console_id), 1069c18ec02fSPetter Reinholdtsen rsp->data + offset + 4, 1070c18ec02fSPetter Reinholdtsen 4); 1071c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN 1072c18ec02fSPetter Reinholdtsen rsp->payload.rakp4_message.console_id = 1073c18ec02fSPetter Reinholdtsen BSWAP_32(rsp->payload.rakp4_message.console_id); 1074c18ec02fSPetter Reinholdtsen #endif 1075c18ec02fSPetter Reinholdtsen 1076c18ec02fSPetter Reinholdtsen 1077c18ec02fSPetter Reinholdtsen /* Integrity check value */ 1078c18ec02fSPetter Reinholdtsen switch (auth_alg) 1079c18ec02fSPetter Reinholdtsen { 1080c18ec02fSPetter Reinholdtsen case IPMI_AUTH_RAKP_NONE: 1081c18ec02fSPetter Reinholdtsen /* Nothing to do here */ 1082c18ec02fSPetter Reinholdtsen break; 1083c18ec02fSPetter Reinholdtsen 1084c18ec02fSPetter Reinholdtsen case IPMI_AUTH_RAKP_HMAC_SHA1: 1085c18ec02fSPetter Reinholdtsen /* We need to copy 12 bytes */ 1086c18ec02fSPetter Reinholdtsen for (i = 0; i < 12; ++i) 1087c18ec02fSPetter Reinholdtsen rsp->payload.rakp4_message.integrity_check_value[i] = 1088c18ec02fSPetter Reinholdtsen rsp->data[offset + 8 + i]; 1089c18ec02fSPetter Reinholdtsen break; 1090c18ec02fSPetter Reinholdtsen 1091c18ec02fSPetter Reinholdtsen case IPMI_AUTH_RAKP_HMAC_MD5: 1092c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "read_rakp4_message: no support " 1093c18ec02fSPetter Reinholdtsen "for authentication algorithm 0x%x", auth_alg); 1094c18ec02fSPetter Reinholdtsen assert(0); 1095c18ec02fSPetter Reinholdtsen break; 1096c18ec02fSPetter Reinholdtsen } 1097c18ec02fSPetter Reinholdtsen } 1098c18ec02fSPetter Reinholdtsen 1099c18ec02fSPetter Reinholdtsen 1100c18ec02fSPetter Reinholdtsen 1101c18ec02fSPetter Reinholdtsen 1102c18ec02fSPetter Reinholdtsen /* 1103c18ec02fSPetter Reinholdtsen * read_session_data 1104c18ec02fSPetter Reinholdtsen * 1105c18ec02fSPetter Reinholdtsen * Initialize the ipmi_rsp from the session data in the packet 1106c18ec02fSPetter Reinholdtsen * 1107c18ec02fSPetter Reinholdtsen * The offset should point the first byte of the the IPMI session when this 1108c18ec02fSPetter Reinholdtsen * function is called. 1109c18ec02fSPetter Reinholdtsen * 1110c18ec02fSPetter Reinholdtsen * param rsp [in/out] we read from the data buffer and populate the session 1111c18ec02fSPetter Reinholdtsen * specific fields. 1112c18ec02fSPetter Reinholdtsen * param offset [in/out] should point to the beginning of the session when 1113c18ec02fSPetter Reinholdtsen * this function is called. The offset will be adjusted to 1114c18ec02fSPetter Reinholdtsen * point to the end of the session when this function exits. 1115c18ec02fSPetter Reinholdtsen * param session holds our session state 1116c18ec02fSPetter Reinholdtsen */ 1117c18ec02fSPetter Reinholdtsen void 1118c18ec02fSPetter Reinholdtsen read_session_data( 1119c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp, 1120c18ec02fSPetter Reinholdtsen int * offset, 1121c18ec02fSPetter Reinholdtsen struct ipmi_session * s) 1122c18ec02fSPetter Reinholdtsen { 1123c18ec02fSPetter Reinholdtsen /* We expect to read different stuff depending on the authtype */ 1124c18ec02fSPetter Reinholdtsen rsp->session.authtype = rsp->data[*offset]; 1125c18ec02fSPetter Reinholdtsen 1126c18ec02fSPetter Reinholdtsen if (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) 1127c18ec02fSPetter Reinholdtsen read_session_data_v2x(rsp, offset, s); 1128c18ec02fSPetter Reinholdtsen else 1129c18ec02fSPetter Reinholdtsen read_session_data_v15(rsp, offset, s); 1130c18ec02fSPetter Reinholdtsen } 1131c18ec02fSPetter Reinholdtsen 1132c18ec02fSPetter Reinholdtsen 1133c18ec02fSPetter Reinholdtsen 1134c18ec02fSPetter Reinholdtsen /* 1135c18ec02fSPetter Reinholdtsen * read_session_data_v2x 1136c18ec02fSPetter Reinholdtsen * 1137c18ec02fSPetter Reinholdtsen * Initialize the ipmi_rsp from the v2.x session header of the packet. 1138c18ec02fSPetter Reinholdtsen * 1139c18ec02fSPetter Reinholdtsen * The offset should point to the first byte of the the IPMI session when this 1140c18ec02fSPetter Reinholdtsen * function is called. When this function exits, offset will point to the 1141c18ec02fSPetter Reinholdtsen * start of payload. 1142c18ec02fSPetter Reinholdtsen * 1143c18ec02fSPetter Reinholdtsen * Should decrypt and perform integrity checking here? 1144c18ec02fSPetter Reinholdtsen * 1145c18ec02fSPetter Reinholdtsen * param rsp [in/out] we read from the data buffer and populate the session 1146c18ec02fSPetter Reinholdtsen * specific fields. 1147c18ec02fSPetter Reinholdtsen * param offset [in/out] should point to the beginning of the session when this 1148c18ec02fSPetter Reinholdtsen * function is called. The offset will be adjusted to point to 1149c18ec02fSPetter Reinholdtsen * the end of the session when this function exits. 1150c18ec02fSPetter Reinholdtsen * param s holds our session state 1151c18ec02fSPetter Reinholdtsen */ 1152c18ec02fSPetter Reinholdtsen void 1153c18ec02fSPetter Reinholdtsen read_session_data_v2x( 1154c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp, 1155c18ec02fSPetter Reinholdtsen int * offset, 1156c18ec02fSPetter Reinholdtsen struct ipmi_session * s) 1157c18ec02fSPetter Reinholdtsen { 1158c18ec02fSPetter Reinholdtsen rsp->session.authtype = rsp->data[(*offset)++]; 1159c18ec02fSPetter Reinholdtsen 1160c18ec02fSPetter Reinholdtsen rsp->session.bEncrypted = (rsp->data[*offset] & 0x80 ? 1 : 0); 1161c18ec02fSPetter Reinholdtsen rsp->session.bAuthenticated = (rsp->data[*offset] & 0x40 ? 1 : 0); 1162c18ec02fSPetter Reinholdtsen 1163c18ec02fSPetter Reinholdtsen 1164c18ec02fSPetter Reinholdtsen /* Payload type */ 1165c18ec02fSPetter Reinholdtsen rsp->session.payloadtype = rsp->data[(*offset)++] & 0x3F; 1166c18ec02fSPetter Reinholdtsen 1167c18ec02fSPetter Reinholdtsen /* Session ID */ 1168c18ec02fSPetter Reinholdtsen memcpy(&rsp->session.id, rsp->data + *offset, 4); 1169c18ec02fSPetter Reinholdtsen *offset += 4; 1170c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN 1171c18ec02fSPetter Reinholdtsen rsp->session.id = BSWAP_32(rsp->session.id); 1172c18ec02fSPetter Reinholdtsen #endif 1173c18ec02fSPetter Reinholdtsen 1174c18ec02fSPetter Reinholdtsen 1175c18ec02fSPetter Reinholdtsen /* 1176c18ec02fSPetter Reinholdtsen * Verify that the session ID is what we think it should be 1177c18ec02fSPetter Reinholdtsen */ 1178c18ec02fSPetter Reinholdtsen if ((s->v2_data.session_state == LANPLUS_STATE_ACTIVE) && 1179c18ec02fSPetter Reinholdtsen (rsp->session.id != s->v2_data.console_id)) 1180c18ec02fSPetter Reinholdtsen { 1181c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "packet session id 0x%x does not " 1182c18ec02fSPetter Reinholdtsen "match active session 0x%0x", 1183c18ec02fSPetter Reinholdtsen rsp->session.id, s->v2_data.console_id); 1184c18ec02fSPetter Reinholdtsen assert(0); 1185c18ec02fSPetter Reinholdtsen } 1186c18ec02fSPetter Reinholdtsen 1187c18ec02fSPetter Reinholdtsen 1188c18ec02fSPetter Reinholdtsen /* Ignored, so far */ 1189c18ec02fSPetter Reinholdtsen memcpy(&rsp->session.seq, rsp->data + *offset, 4); 1190c18ec02fSPetter Reinholdtsen *offset += 4; 1191c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN 1192c18ec02fSPetter Reinholdtsen rsp->session.seq = BSWAP_32(rsp->session.seq); 1193c18ec02fSPetter Reinholdtsen #endif 1194c18ec02fSPetter Reinholdtsen 1195c18ec02fSPetter Reinholdtsen memcpy(&rsp->session.msglen, rsp->data + *offset, 2); 1196c18ec02fSPetter Reinholdtsen *offset += 2; 1197c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN 1198c18ec02fSPetter Reinholdtsen rsp->session.msglen = BSWAP_16(rsp->session.msglen); 1199c18ec02fSPetter Reinholdtsen #endif 1200c18ec02fSPetter Reinholdtsen } 1201c18ec02fSPetter Reinholdtsen 1202c18ec02fSPetter Reinholdtsen 1203c18ec02fSPetter Reinholdtsen 1204c18ec02fSPetter Reinholdtsen /* 1205c18ec02fSPetter Reinholdtsen * read_session_data_v15 1206c18ec02fSPetter Reinholdtsen * 1207c18ec02fSPetter Reinholdtsen * Initialize the ipmi_rsp from the session header of the packet. 1208c18ec02fSPetter Reinholdtsen * 1209c18ec02fSPetter Reinholdtsen * The offset should point the first byte of the the IPMI session when this 1210c18ec02fSPetter Reinholdtsen * function is called. When this function exits, the offset will point to 1211c18ec02fSPetter Reinholdtsen * the start of the IPMI message. 1212c18ec02fSPetter Reinholdtsen * 1213c18ec02fSPetter Reinholdtsen * param rsp [in/out] we read from the data buffer and populate the session 1214c18ec02fSPetter Reinholdtsen * specific fields. 1215c18ec02fSPetter Reinholdtsen * param offset [in/out] should point to the beginning of the session when this 1216c18ec02fSPetter Reinholdtsen * function is called. The offset will be adjusted to point to the 1217c18ec02fSPetter Reinholdtsen * end of the session when this function exits. 1218c18ec02fSPetter Reinholdtsen * param s holds our session state 1219c18ec02fSPetter Reinholdtsen */ 1220c18ec02fSPetter Reinholdtsen void read_session_data_v15( 1221c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp, 1222c18ec02fSPetter Reinholdtsen int * offset, 1223c18ec02fSPetter Reinholdtsen struct ipmi_session * s) 1224c18ec02fSPetter Reinholdtsen { 1225c18ec02fSPetter Reinholdtsen /* All v15 messages are IPMI messages */ 1226c18ec02fSPetter Reinholdtsen rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_IPMI; 1227c18ec02fSPetter Reinholdtsen 1228c18ec02fSPetter Reinholdtsen rsp->session.authtype = rsp->data[(*offset)++]; 1229c18ec02fSPetter Reinholdtsen 1230c18ec02fSPetter Reinholdtsen /* All v15 messages that we will receive are unencrypted/unauthenticated */ 1231c18ec02fSPetter Reinholdtsen rsp->session.bEncrypted = 0; 1232c18ec02fSPetter Reinholdtsen rsp->session.bAuthenticated = 0; 1233c18ec02fSPetter Reinholdtsen 1234c18ec02fSPetter Reinholdtsen /* skip the session id and sequence number fields */ 1235c18ec02fSPetter Reinholdtsen *offset += 8; 1236c18ec02fSPetter Reinholdtsen 1237c18ec02fSPetter Reinholdtsen /* This is the size of the whole payload */ 1238c18ec02fSPetter Reinholdtsen rsp->session.msglen = rsp->data[(*offset)++]; 1239c18ec02fSPetter Reinholdtsen } 1240c18ec02fSPetter Reinholdtsen 1241c18ec02fSPetter Reinholdtsen 1242c18ec02fSPetter Reinholdtsen 1243c18ec02fSPetter Reinholdtsen /* 1244c18ec02fSPetter Reinholdtsen * read_ipmi_response 1245c18ec02fSPetter Reinholdtsen * 1246c18ec02fSPetter Reinholdtsen * Initialize the ipmi_rs from with the IPMI response specific data 1247c18ec02fSPetter Reinholdtsen * 1248c18ec02fSPetter Reinholdtsen * The offset should point the first byte of the the IPMI payload when this 1249c18ec02fSPetter Reinholdtsen * function is called. 1250c18ec02fSPetter Reinholdtsen * 1251c18ec02fSPetter Reinholdtsen * param rsp [in/out] we read from the data buffer and populate the IPMI 1252c18ec02fSPetter Reinholdtsen * specific fields. 1253c18ec02fSPetter Reinholdtsen * param offset [in/out] should point to the beginning of the IPMI payload when 1254c18ec02fSPetter Reinholdtsen * this function is called. 1255c18ec02fSPetter Reinholdtsen */ 1256c18ec02fSPetter Reinholdtsen void read_ipmi_response(struct ipmi_rs * rsp, int * offset) 1257c18ec02fSPetter Reinholdtsen { 1258c18ec02fSPetter Reinholdtsen /* 1259c18ec02fSPetter Reinholdtsen * The data here should be decrypted by now. 1260c18ec02fSPetter Reinholdtsen */ 1261c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rq_addr = rsp->data[(*offset)++]; 1262c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.netfn = rsp->data[*offset] >> 2; 1263c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rq_lun = rsp->data[(*offset)++] & 0x3; 1264c18ec02fSPetter Reinholdtsen (*offset)++; /* checksum */ 1265c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rs_addr = rsp->data[(*offset)++]; 1266c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rq_seq = rsp->data[*offset] >> 2; 1267c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.rs_lun = rsp->data[(*offset)++] & 0x3; 1268c18ec02fSPetter Reinholdtsen rsp->payload.ipmi_response.cmd = rsp->data[(*offset)++]; 1269c18ec02fSPetter Reinholdtsen rsp->ccode = rsp->data[(*offset)++]; 1270c18ec02fSPetter Reinholdtsen 1271c18ec02fSPetter Reinholdtsen } 1272c18ec02fSPetter Reinholdtsen 1273c18ec02fSPetter Reinholdtsen 1274c18ec02fSPetter Reinholdtsen 1275c18ec02fSPetter Reinholdtsen /* 1276c18ec02fSPetter Reinholdtsen * read_sol_packet 1277c18ec02fSPetter Reinholdtsen * 1278c18ec02fSPetter Reinholdtsen * Initialize the ipmi_rs with the SOL response data 1279c18ec02fSPetter Reinholdtsen * 1280c18ec02fSPetter Reinholdtsen * The offset should point the first byte of the the SOL payload when this 1281c18ec02fSPetter Reinholdtsen * function is called. 1282c18ec02fSPetter Reinholdtsen * 1283c18ec02fSPetter Reinholdtsen * param rsp [in/out] we read from the data buffer and populate the 1284c18ec02fSPetter Reinholdtsen * SOL specific fields. 1285c18ec02fSPetter Reinholdtsen * param offset [in/out] should point to the beginning of the SOL payload 1286c18ec02fSPetter Reinholdtsen * when this function is called. 1287c18ec02fSPetter Reinholdtsen */ 1288c18ec02fSPetter Reinholdtsen void read_sol_packet(struct ipmi_rs * rsp, int * offset) 1289c18ec02fSPetter Reinholdtsen { 1290c18ec02fSPetter Reinholdtsen 1291c18ec02fSPetter Reinholdtsen /* 1292c18ec02fSPetter Reinholdtsen * The data here should be decrypted by now. 1293c18ec02fSPetter Reinholdtsen */ 1294c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.packet_sequence_number = 1295c18ec02fSPetter Reinholdtsen rsp->data[(*offset)++] & 0x0F; 1296c18ec02fSPetter Reinholdtsen 1297c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.acked_packet_number = 1298c18ec02fSPetter Reinholdtsen rsp->data[(*offset)++] & 0x0F; 1299c18ec02fSPetter Reinholdtsen 1300c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.accepted_character_count = 1301c18ec02fSPetter Reinholdtsen rsp->data[(*offset)++]; 1302c18ec02fSPetter Reinholdtsen 1303c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.is_nack = 1304c18ec02fSPetter Reinholdtsen rsp->data[*offset] & 0x40; 1305c18ec02fSPetter Reinholdtsen 1306c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.transfer_unavailable = 1307c18ec02fSPetter Reinholdtsen rsp->data[*offset] & 0x20; 1308c18ec02fSPetter Reinholdtsen 1309c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.sol_inactive = 1310c18ec02fSPetter Reinholdtsen rsp->data[*offset] & 0x10; 1311c18ec02fSPetter Reinholdtsen 1312c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.transmit_overrun = 1313c18ec02fSPetter Reinholdtsen rsp->data[*offset] & 0x08; 1314c18ec02fSPetter Reinholdtsen 1315c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.break_detected = 1316c18ec02fSPetter Reinholdtsen rsp->data[(*offset)++] & 0x04; 1317c18ec02fSPetter Reinholdtsen 1318c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "<<<<<<<<<< RECV FROM BMC <<<<<<<<<<<"); 1319c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "< SOL sequence number : 0x%02x", 1320c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.packet_sequence_number); 1321c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "< SOL acked packet : 0x%02x", 1322c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.acked_packet_number); 1323c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "< SOL accepted char count : 0x%02x", 1324c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.accepted_character_count); 1325c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "< SOL is nack : %s", 1326c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.is_nack? "true" : "false"); 1327c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "< SOL xfer unavailable : %s", 1328c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.transfer_unavailable? "true" : "false"); 1329c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "< SOL inactive : %s", 1330c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.sol_inactive? "true" : "false"); 1331c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "< SOL transmit overrun : %s", 1332c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.transmit_overrun? "true" : "false"); 1333c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "< SOL break detected : %s", 1334c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.break_detected? "true" : "false"); 1335c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); 1336c18ec02fSPetter Reinholdtsen 1337c18ec02fSPetter Reinholdtsen if (verbose >= 5) 1338c18ec02fSPetter Reinholdtsen printbuf(rsp->data + *offset - 4, 4, "SOL MSG FROM BMC"); 1339c18ec02fSPetter Reinholdtsen } 1340c18ec02fSPetter Reinholdtsen 1341c18ec02fSPetter Reinholdtsen 1342c18ec02fSPetter Reinholdtsen 1343c18ec02fSPetter Reinholdtsen /* 1344c18ec02fSPetter Reinholdtsen * getIpmiPayloadWireRep 1345c18ec02fSPetter Reinholdtsen * 1346c18ec02fSPetter Reinholdtsen * param out [out] will contain our wire representation 1347c18ec02fSPetter Reinholdtsen * param req [in] is the IPMI request to be written 1348c18ec02fSPetter Reinholdtsen * param crypt_alg [in] specifies the encryption to use 1349c18ec02fSPetter Reinholdtsen * param rq_seq [in] is the IPMI command sequence number. 1350c18ec02fSPetter Reinholdtsen */ 1351c18ec02fSPetter Reinholdtsen void getIpmiPayloadWireRep( 1352c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, /* in out */ 1353c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * payload, /* in */ 1354c18ec02fSPetter Reinholdtsen uint8_t * msg, 1355c18ec02fSPetter Reinholdtsen struct ipmi_rq * req, 1356c18ec02fSPetter Reinholdtsen uint8_t rq_seq, 1357c18ec02fSPetter Reinholdtsen uint8_t curr_seq) 1358c18ec02fSPetter Reinholdtsen { 1359c18ec02fSPetter Reinholdtsen int cs, tmp, len; 1360c18ec02fSPetter Reinholdtsen int cs2 = 0; 1361c18ec02fSPetter Reinholdtsen int cs3 = 0; 1362c18ec02fSPetter Reinholdtsen uint8_t ourAddress = intf->my_addr; 1363c18ec02fSPetter Reinholdtsen uint8_t bridgedRequest = 0; 1364c18ec02fSPetter Reinholdtsen 1365c18ec02fSPetter Reinholdtsen if (ourAddress == 0) 1366c18ec02fSPetter Reinholdtsen ourAddress = IPMI_BMC_SLAVE_ADDR; 1367c18ec02fSPetter Reinholdtsen 1368c18ec02fSPetter Reinholdtsen len = 0; 1369c18ec02fSPetter Reinholdtsen 1370c18ec02fSPetter Reinholdtsen /* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */ 1371c18ec02fSPetter Reinholdtsen if ((intf->target_addr == ourAddress) || (!bridgePossible)) { 1372c18ec02fSPetter Reinholdtsen cs = len; 1373c18ec02fSPetter Reinholdtsen } else { 1374c18ec02fSPetter Reinholdtsen bridgedRequest = 1; 1375c18ec02fSPetter Reinholdtsen 1376c18ec02fSPetter Reinholdtsen if(intf->transit_addr != ourAddress && intf->transit_addr != 0) 1377c18ec02fSPetter Reinholdtsen { 1378c18ec02fSPetter Reinholdtsen bridgedRequest++; 1379c18ec02fSPetter Reinholdtsen } 1380c18ec02fSPetter Reinholdtsen /* bridged request: encapsulate w/in Send Message */ 1381c18ec02fSPetter Reinholdtsen cs = len; 1382c18ec02fSPetter Reinholdtsen msg[len++] = IPMI_BMC_SLAVE_ADDR; 1383c18ec02fSPetter Reinholdtsen msg[len++] = IPMI_NETFN_APP << 2; 1384c18ec02fSPetter Reinholdtsen tmp = len - cs; 1385c18ec02fSPetter Reinholdtsen msg[len++] = ipmi_csum(msg+cs, tmp); 1386c18ec02fSPetter Reinholdtsen cs2 = len; 1387c18ec02fSPetter Reinholdtsen msg[len++] = IPMI_REMOTE_SWID; 1388c18ec02fSPetter Reinholdtsen msg[len++] = curr_seq << 2; 1389c18ec02fSPetter Reinholdtsen 1390c18ec02fSPetter Reinholdtsen 1391c18ec02fSPetter Reinholdtsen msg[len++] = 0x34; /* Send Message rqst */ 1392c18ec02fSPetter Reinholdtsen if(bridgedRequest == 2) 1393c18ec02fSPetter Reinholdtsen msg[len++] = (0x40|intf->transit_channel); /* Track request*/ 1394c18ec02fSPetter Reinholdtsen else 1395c18ec02fSPetter Reinholdtsen msg[len++] = (0x40|intf->target_channel); /* Track request*/ 1396c18ec02fSPetter Reinholdtsen 1397c18ec02fSPetter Reinholdtsen payload->payload_length += 7; 1398c18ec02fSPetter Reinholdtsen cs = len; 1399c18ec02fSPetter Reinholdtsen 1400c18ec02fSPetter Reinholdtsen if(bridgedRequest == 2) 1401c18ec02fSPetter Reinholdtsen { 1402c18ec02fSPetter Reinholdtsen /* bridged request: encapsulate w/in Send Message */ 1403c18ec02fSPetter Reinholdtsen cs = len; 1404c18ec02fSPetter Reinholdtsen msg[len++] = intf->transit_addr; 1405c18ec02fSPetter Reinholdtsen msg[len++] = IPMI_NETFN_APP << 2; 1406c18ec02fSPetter Reinholdtsen tmp = len - cs; 1407c18ec02fSPetter Reinholdtsen msg[len++] = ipmi_csum(msg+cs, tmp); 1408c18ec02fSPetter Reinholdtsen cs3 = len; 1409c18ec02fSPetter Reinholdtsen msg[len++] = intf->my_addr; 1410c18ec02fSPetter Reinholdtsen msg[len++] = curr_seq << 2; 1411c18ec02fSPetter Reinholdtsen msg[len++] = 0x34; /* Send Message rqst */ 1412c18ec02fSPetter Reinholdtsen #if 0 /* From lan.c example */ 1413c18ec02fSPetter Reinholdtsen entry->req.msg.target_cmd = entry->req.msg.cmd; /* Save target command */ 1414c18ec02fSPetter Reinholdtsen entry->req.msg.cmd = 0x34; /* (fixup request entry) */ 1415c18ec02fSPetter Reinholdtsen #endif 1416c18ec02fSPetter Reinholdtsen msg[len++] = (0x40|intf->target_channel); /* Track request*/ 1417c18ec02fSPetter Reinholdtsen 1418c18ec02fSPetter Reinholdtsen payload->payload_length += 7; 1419c18ec02fSPetter Reinholdtsen 1420c18ec02fSPetter Reinholdtsen cs = len; 1421c18ec02fSPetter Reinholdtsen } 1422c18ec02fSPetter Reinholdtsen } 1423c18ec02fSPetter Reinholdtsen 1424c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG,"%s RqAddr %#x transit %#x:%#x target %#x:%#x " 1425c18ec02fSPetter Reinholdtsen "bridgePossible %d", 1426c18ec02fSPetter Reinholdtsen bridgedRequest ? "Bridging" : "Local", 1427c18ec02fSPetter Reinholdtsen intf->my_addr, intf->transit_addr, intf->transit_channel, 1428c18ec02fSPetter Reinholdtsen intf->target_addr, intf->target_channel, 1429c18ec02fSPetter Reinholdtsen bridgePossible); 1430c18ec02fSPetter Reinholdtsen 1431c18ec02fSPetter Reinholdtsen /* rsAddr */ 1432c18ec02fSPetter Reinholdtsen msg[len++] = intf->target_addr; /* IPMI_BMC_SLAVE_ADDR; */ 1433c18ec02fSPetter Reinholdtsen 1434c18ec02fSPetter Reinholdtsen /* net Fn */ 1435c18ec02fSPetter Reinholdtsen msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3); 1436c18ec02fSPetter Reinholdtsen tmp = len - cs; 1437c18ec02fSPetter Reinholdtsen 1438c18ec02fSPetter Reinholdtsen /* checkSum */ 1439c18ec02fSPetter Reinholdtsen msg[len++] = ipmi_csum(msg+cs, tmp); 1440c18ec02fSPetter Reinholdtsen cs = len; 1441c18ec02fSPetter Reinholdtsen 1442c18ec02fSPetter Reinholdtsen /* rqAddr */ 1443c18ec02fSPetter Reinholdtsen if (!bridgedRequest) 1444c18ec02fSPetter Reinholdtsen msg[len++] = IPMI_REMOTE_SWID; 1445c18ec02fSPetter Reinholdtsen else /* Bridged message */ 1446c18ec02fSPetter Reinholdtsen msg[len++] = intf->my_addr; 1447c18ec02fSPetter Reinholdtsen 1448c18ec02fSPetter Reinholdtsen /* rqSeq / rqLUN */ 1449c18ec02fSPetter Reinholdtsen msg[len++] = rq_seq << 2; 1450c18ec02fSPetter Reinholdtsen 1451c18ec02fSPetter Reinholdtsen /* cmd */ 1452c18ec02fSPetter Reinholdtsen msg[len++] = req->msg.cmd; 1453c18ec02fSPetter Reinholdtsen 1454c18ec02fSPetter Reinholdtsen /* message data */ 1455c18ec02fSPetter Reinholdtsen if (req->msg.data_len) { 1456c18ec02fSPetter Reinholdtsen memcpy(msg + len, req->msg.data, req->msg.data_len); 1457c18ec02fSPetter Reinholdtsen len += req->msg.data_len; 1458c18ec02fSPetter Reinholdtsen } 1459c18ec02fSPetter Reinholdtsen 1460c18ec02fSPetter Reinholdtsen /* second checksum */ 1461c18ec02fSPetter Reinholdtsen tmp = len - cs; 1462c18ec02fSPetter Reinholdtsen msg[len++] = ipmi_csum(msg+cs, tmp); 1463c18ec02fSPetter Reinholdtsen 1464c18ec02fSPetter Reinholdtsen /* Dual bridged request: 2nd checksum */ 1465c18ec02fSPetter Reinholdtsen if (bridgedRequest == 2) { 1466c18ec02fSPetter Reinholdtsen tmp = len - cs3; 1467c18ec02fSPetter Reinholdtsen msg[len++] = ipmi_csum(msg+cs3, tmp); 1468c18ec02fSPetter Reinholdtsen payload->payload_length += 1; 1469c18ec02fSPetter Reinholdtsen } 1470c18ec02fSPetter Reinholdtsen 1471c18ec02fSPetter Reinholdtsen /* bridged request: 2nd checksum */ 1472c18ec02fSPetter Reinholdtsen if (bridgedRequest) { 1473c18ec02fSPetter Reinholdtsen tmp = len - cs2; 1474c18ec02fSPetter Reinholdtsen msg[len++] = ipmi_csum(msg+cs2, tmp); 1475c18ec02fSPetter Reinholdtsen payload->payload_length += 1; 1476c18ec02fSPetter Reinholdtsen } 1477c18ec02fSPetter Reinholdtsen } 1478c18ec02fSPetter Reinholdtsen 1479c18ec02fSPetter Reinholdtsen 1480c18ec02fSPetter Reinholdtsen 1481c18ec02fSPetter Reinholdtsen /* 1482c18ec02fSPetter Reinholdtsen * getSolPayloadWireRep 1483c18ec02fSPetter Reinholdtsen * 1484c18ec02fSPetter Reinholdtsen * param msg [out] will contain our wire representation 1485c18ec02fSPetter Reinholdtsen * param payload [in] holds the v2 payload with our SOL data 1486c18ec02fSPetter Reinholdtsen */ 1487c18ec02fSPetter Reinholdtsen void getSolPayloadWireRep( 1488c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, /* in out */ 1489c18ec02fSPetter Reinholdtsen uint8_t * msg, /* output */ 1490c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * payload) /* input */ 1491c18ec02fSPetter Reinholdtsen { 1492c18ec02fSPetter Reinholdtsen int i = 0; 1493c18ec02fSPetter Reinholdtsen 1494c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, ">>>>>>>>>> SENDING TO BMC >>>>>>>>>>"); 1495c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "> SOL sequence number : 0x%02x", 1496c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.packet_sequence_number); 1497c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "> SOL acked packet : 0x%02x", 1498c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.acked_packet_number); 1499c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "> SOL accepted char count : 0x%02x", 1500c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.accepted_character_count); 1501c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "> SOL is nack : %s", 1502c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.is_nack ? "true" : "false"); 1503c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "> SOL assert ring wor : %s", 1504c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.assert_ring_wor ? "true" : "false"); 1505c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "> SOL generate break : %s", 1506c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.generate_break ? "true" : "false"); 1507c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "> SOL deassert cts : %s", 1508c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.deassert_cts ? "true" : "false"); 1509c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "> SOL deassert dcd dsr : %s", 1510c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.deassert_dcd_dsr ? "true" : "false"); 1511c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "> SOL flush inbound : %s", 1512c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.flush_inbound ? "true" : "false"); 1513c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "> SOL flush outbound : %s", 1514c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.flush_outbound ? "true" : "false"); 1515c18ec02fSPetter Reinholdtsen 1516c18ec02fSPetter Reinholdtsen msg[i++] = payload->payload.sol_packet.packet_sequence_number; 1517c18ec02fSPetter Reinholdtsen msg[i++] = payload->payload.sol_packet.acked_packet_number; 1518c18ec02fSPetter Reinholdtsen msg[i++] = payload->payload.sol_packet.accepted_character_count; 1519c18ec02fSPetter Reinholdtsen 1520c18ec02fSPetter Reinholdtsen msg[i] = payload->payload.sol_packet.is_nack ? 0x40 : 0; 1521c18ec02fSPetter Reinholdtsen msg[i] |= payload->payload.sol_packet.assert_ring_wor ? 0x20 : 0; 1522c18ec02fSPetter Reinholdtsen msg[i] |= payload->payload.sol_packet.generate_break ? 0x10 : 0; 1523c18ec02fSPetter Reinholdtsen msg[i] |= payload->payload.sol_packet.deassert_cts ? 0x08 : 0; 1524c18ec02fSPetter Reinholdtsen msg[i] |= payload->payload.sol_packet.deassert_dcd_dsr ? 0x04 : 0; 1525c18ec02fSPetter Reinholdtsen msg[i] |= payload->payload.sol_packet.flush_inbound ? 0x02 : 0; 1526c18ec02fSPetter Reinholdtsen msg[i++] |= payload->payload.sol_packet.flush_outbound ? 0x01 : 0; 1527c18ec02fSPetter Reinholdtsen 1528c18ec02fSPetter Reinholdtsen /* We may have data to add */ 1529c18ec02fSPetter Reinholdtsen memcpy(msg + i, 1530c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.data, 1531c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.character_count); 1532c18ec02fSPetter Reinholdtsen 1533c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "> SOL character count : %d", 1534c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.character_count); 1535c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); 1536c18ec02fSPetter Reinholdtsen 1537c18ec02fSPetter Reinholdtsen if (verbose >= 5 && payload->payload.sol_packet.character_count) 1538c18ec02fSPetter Reinholdtsen printbuf(payload->payload.sol_packet.data, payload->payload.sol_packet.character_count, "SOL SEND DATA"); 1539c18ec02fSPetter Reinholdtsen 1540c18ec02fSPetter Reinholdtsen /* 1541c18ec02fSPetter Reinholdtsen * At this point, the payload length becomes the whole payload 1542c18ec02fSPetter Reinholdtsen * length, including the 4 bytes at the beginning of the SOL 1543c18ec02fSPetter Reinholdtsen * packet 1544c18ec02fSPetter Reinholdtsen */ 1545c18ec02fSPetter Reinholdtsen payload->payload_length = payload->payload.sol_packet.character_count + 4; 1546c18ec02fSPetter Reinholdtsen } 1547c18ec02fSPetter Reinholdtsen 1548c18ec02fSPetter Reinholdtsen 1549c18ec02fSPetter Reinholdtsen 1550c18ec02fSPetter Reinholdtsen /* 1551c18ec02fSPetter Reinholdtsen * ipmi_lanplus_build_v2x_msg 1552c18ec02fSPetter Reinholdtsen * 1553c18ec02fSPetter Reinholdtsen * Encapsulates the payload data to create the IPMI v2.0 / RMCP+ packet. 1554c18ec02fSPetter Reinholdtsen * 1555c18ec02fSPetter Reinholdtsen * 1556c18ec02fSPetter Reinholdtsen * IPMI v2.0 LAN Request Message Format 1557c18ec02fSPetter Reinholdtsen * +----------------------+ 1558c18ec02fSPetter Reinholdtsen * | rmcp.ver | 4 bytes 1559c18ec02fSPetter Reinholdtsen * | rmcp.__reserved | 1560c18ec02fSPetter Reinholdtsen * | rmcp.seq | 1561c18ec02fSPetter Reinholdtsen * | rmcp.class | 1562c18ec02fSPetter Reinholdtsen * +----------------------+ 1563c18ec02fSPetter Reinholdtsen * | session.authtype | 10 bytes 1564c18ec02fSPetter Reinholdtsen * | session.payloadtype | 1565c18ec02fSPetter Reinholdtsen * | session.id | 1566c18ec02fSPetter Reinholdtsen * | session.seq | 1567c18ec02fSPetter Reinholdtsen * +----------------------+ 1568c18ec02fSPetter Reinholdtsen * | message length | 2 bytes 1569c18ec02fSPetter Reinholdtsen * +----------------------+ 1570c18ec02fSPetter Reinholdtsen * | Confidentiality Hdr | var (possibly absent) 1571c18ec02fSPetter Reinholdtsen * +----------------------+ 1572c18ec02fSPetter Reinholdtsen * | Paylod | var Payload 1573c18ec02fSPetter Reinholdtsen * +----------------------+ 1574c18ec02fSPetter Reinholdtsen * | Confidentiality Trlr | var (possibly absent) 1575c18ec02fSPetter Reinholdtsen * +----------------------+ 1576c18ec02fSPetter Reinholdtsen * | Integrity pad | var (possibly absent) 1577c18ec02fSPetter Reinholdtsen * +----------------------+ 1578c18ec02fSPetter Reinholdtsen * | Pad length | 1 byte (WTF?) 1579c18ec02fSPetter Reinholdtsen * +----------------------+ 1580c18ec02fSPetter Reinholdtsen * | Next Header | 1 byte (WTF?) 1581c18ec02fSPetter Reinholdtsen * +----------------------+ 1582c18ec02fSPetter Reinholdtsen * | Authcode | var (possibly absent) 1583c18ec02fSPetter Reinholdtsen * +----------------------+ 1584c18ec02fSPetter Reinholdtsen */ 1585c18ec02fSPetter Reinholdtsen void 1586c18ec02fSPetter Reinholdtsen ipmi_lanplus_build_v2x_msg( 1587c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, /* in */ 1588c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * payload, /* in */ 1589c18ec02fSPetter Reinholdtsen int * msg_len, /* out */ 1590c18ec02fSPetter Reinholdtsen uint8_t ** msg_data, /* out */ 1591c18ec02fSPetter Reinholdtsen uint8_t curr_seq) 1592c18ec02fSPetter Reinholdtsen { 1593c18ec02fSPetter Reinholdtsen uint32_t session_trailer_length = 0; 1594c18ec02fSPetter Reinholdtsen struct ipmi_session * session = intf->session; 1595c18ec02fSPetter Reinholdtsen struct rmcp_hdr rmcp = { 1596c18ec02fSPetter Reinholdtsen .ver = RMCP_VERSION_1, 1597c18ec02fSPetter Reinholdtsen .class = RMCP_CLASS_IPMI, 1598c18ec02fSPetter Reinholdtsen .seq = 0xff, 1599c18ec02fSPetter Reinholdtsen }; 1600c18ec02fSPetter Reinholdtsen 1601c18ec02fSPetter Reinholdtsen /* msg will hold the entire message to be sent */ 1602c18ec02fSPetter Reinholdtsen uint8_t * msg; 1603c18ec02fSPetter Reinholdtsen int len = 0; 1604c18ec02fSPetter Reinholdtsen 1605c18ec02fSPetter Reinholdtsen 1606c18ec02fSPetter Reinholdtsen len = 1607c18ec02fSPetter Reinholdtsen sizeof(rmcp) + // RMCP Header (4) 1608c18ec02fSPetter Reinholdtsen 10 + // IPMI Session Header 1609c18ec02fSPetter Reinholdtsen 2 + // Message length 1610c18ec02fSPetter Reinholdtsen payload->payload_length + // The actual payload 1611c18ec02fSPetter Reinholdtsen IPMI_MAX_INTEGRITY_PAD_SIZE + // Integrity Pad 1612c18ec02fSPetter Reinholdtsen 1 + // Pad Length 1613c18ec02fSPetter Reinholdtsen 1 + // Next Header 1614c18ec02fSPetter Reinholdtsen IPMI_MAX_AUTH_CODE_SIZE; // Authcode 1615c18ec02fSPetter Reinholdtsen 1616c18ec02fSPetter Reinholdtsen 1617c18ec02fSPetter Reinholdtsen msg = malloc(len); 1618c18ec02fSPetter Reinholdtsen if (msg == NULL) { 1619c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure"); 1620c18ec02fSPetter Reinholdtsen return; 1621c18ec02fSPetter Reinholdtsen } 1622c18ec02fSPetter Reinholdtsen memset(msg, 0, len); 1623c18ec02fSPetter Reinholdtsen 1624c18ec02fSPetter Reinholdtsen /* 1625c18ec02fSPetter Reinholdtsen *------------------------------------------ 1626c18ec02fSPetter Reinholdtsen * RMCP HEADER 1627c18ec02fSPetter Reinholdtsen *------------------------------------------ 1628c18ec02fSPetter Reinholdtsen */ 1629c18ec02fSPetter Reinholdtsen memcpy(msg, &rmcp, sizeof(rmcp)); 1630c18ec02fSPetter Reinholdtsen len = sizeof(rmcp); 1631c18ec02fSPetter Reinholdtsen 1632c18ec02fSPetter Reinholdtsen 1633c18ec02fSPetter Reinholdtsen /* 1634c18ec02fSPetter Reinholdtsen *------------------------------------------ 1635c18ec02fSPetter Reinholdtsen * IPMI SESSION HEADER 1636c18ec02fSPetter Reinholdtsen *------------------------------------------ 1637c18ec02fSPetter Reinholdtsen */ 1638c18ec02fSPetter Reinholdtsen /* ipmi session Auth Type / Format is always 0x06 for IPMI v2 */ 1639c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_AUTHTYPE] = 0x06; 1640c18ec02fSPetter Reinholdtsen 1641c18ec02fSPetter Reinholdtsen /* Payload Type -- also specifies whether were authenticated/encyrpted */ 1642c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] = payload->payload_type; 1643c18ec02fSPetter Reinholdtsen 1644c18ec02fSPetter Reinholdtsen if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE) 1645c18ec02fSPetter Reinholdtsen { 1646c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] |= 1647c18ec02fSPetter Reinholdtsen ((session->v2_data.crypt_alg != IPMI_CRYPT_NONE )? 0x80 : 0x00); 1648c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] |= 1649c18ec02fSPetter Reinholdtsen ((session->v2_data.integrity_alg != IPMI_INTEGRITY_NONE)? 0x40 : 0x00); 1650c18ec02fSPetter Reinholdtsen } 1651c18ec02fSPetter Reinholdtsen 1652c18ec02fSPetter Reinholdtsen if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE) 1653c18ec02fSPetter Reinholdtsen { 1654c18ec02fSPetter Reinholdtsen /* Session ID -- making it LSB */ 1655c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_SESSION_ID ] = session->v2_data.bmc_id & 0xff; 1656c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 1] = (session->v2_data.bmc_id >> 8) & 0xff; 1657c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 2] = (session->v2_data.bmc_id >> 16) & 0xff; 1658c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 3] = (session->v2_data.bmc_id >> 24) & 0xff; 1659c18ec02fSPetter Reinholdtsen 1660c18ec02fSPetter Reinholdtsen /* Sequence Number -- making it LSB */ 1661c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM ] = session->out_seq & 0xff; 1662c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 1] = (session->out_seq >> 8) & 0xff; 1663c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 2] = (session->out_seq >> 16) & 0xff; 1664c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 3] = (session->out_seq >> 24) & 0xff; 1665c18ec02fSPetter Reinholdtsen } 1666c18ec02fSPetter Reinholdtsen 1667c18ec02fSPetter Reinholdtsen /* 1668c18ec02fSPetter Reinholdtsen * Payload Length is set below (we don't know how big the payload is until after 1669c18ec02fSPetter Reinholdtsen * encryption). 1670c18ec02fSPetter Reinholdtsen */ 1671c18ec02fSPetter Reinholdtsen 1672c18ec02fSPetter Reinholdtsen /* 1673c18ec02fSPetter Reinholdtsen * Payload 1674c18ec02fSPetter Reinholdtsen * 1675c18ec02fSPetter Reinholdtsen * At this point we are ready to slam the payload in. 1676c18ec02fSPetter Reinholdtsen * This includes: 1677c18ec02fSPetter Reinholdtsen * 1) The confidentiality header 1678c18ec02fSPetter Reinholdtsen * 2) The payload proper (possibly encrypted) 1679c18ec02fSPetter Reinholdtsen * 3) The confidentiality trailer 1680c18ec02fSPetter Reinholdtsen * 1681c18ec02fSPetter Reinholdtsen */ 1682c18ec02fSPetter Reinholdtsen switch (payload->payload_type) 1683c18ec02fSPetter Reinholdtsen { 1684c18ec02fSPetter Reinholdtsen case IPMI_PAYLOAD_TYPE_IPMI: 1685c18ec02fSPetter Reinholdtsen getIpmiPayloadWireRep(intf, 1686c18ec02fSPetter Reinholdtsen payload, /* in */ 1687c18ec02fSPetter Reinholdtsen msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 1688c18ec02fSPetter Reinholdtsen payload->payload.ipmi_request.request, 1689c18ec02fSPetter Reinholdtsen payload->payload.ipmi_request.rq_seq, 1690c18ec02fSPetter Reinholdtsen curr_seq); 1691c18ec02fSPetter Reinholdtsen break; 1692c18ec02fSPetter Reinholdtsen 1693c18ec02fSPetter Reinholdtsen case IPMI_PAYLOAD_TYPE_SOL: 1694c18ec02fSPetter Reinholdtsen getSolPayloadWireRep(intf, 1695c18ec02fSPetter Reinholdtsen msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 1696c18ec02fSPetter Reinholdtsen payload); 1697c18ec02fSPetter Reinholdtsen 1698c18ec02fSPetter Reinholdtsen if (verbose >= 5) 1699c18ec02fSPetter Reinholdtsen printbuf(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 4, "SOL MSG TO BMC"); 1700c18ec02fSPetter Reinholdtsen 1701c18ec02fSPetter Reinholdtsen len += payload->payload_length; 1702c18ec02fSPetter Reinholdtsen 1703c18ec02fSPetter Reinholdtsen break; 1704c18ec02fSPetter Reinholdtsen 1705c18ec02fSPetter Reinholdtsen case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST: 1706c18ec02fSPetter Reinholdtsen /* never encrypted, so our job is easy */ 1707c18ec02fSPetter Reinholdtsen memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 1708c18ec02fSPetter Reinholdtsen payload->payload.open_session_request.request, 1709c18ec02fSPetter Reinholdtsen payload->payload_length); 1710c18ec02fSPetter Reinholdtsen len += payload->payload_length; 1711c18ec02fSPetter Reinholdtsen break; 1712c18ec02fSPetter Reinholdtsen 1713c18ec02fSPetter Reinholdtsen case IPMI_PAYLOAD_TYPE_RAKP_1: 1714c18ec02fSPetter Reinholdtsen /* never encrypted, so our job is easy */ 1715c18ec02fSPetter Reinholdtsen memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 1716c18ec02fSPetter Reinholdtsen payload->payload.rakp_1_message.message, 1717c18ec02fSPetter Reinholdtsen payload->payload_length); 1718c18ec02fSPetter Reinholdtsen len += payload->payload_length; 1719c18ec02fSPetter Reinholdtsen break; 1720c18ec02fSPetter Reinholdtsen 1721c18ec02fSPetter Reinholdtsen case IPMI_PAYLOAD_TYPE_RAKP_3: 1722c18ec02fSPetter Reinholdtsen /* never encrypted, so our job is easy */ 1723c18ec02fSPetter Reinholdtsen memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 1724c18ec02fSPetter Reinholdtsen payload->payload.rakp_3_message.message, 1725c18ec02fSPetter Reinholdtsen payload->payload_length); 1726c18ec02fSPetter Reinholdtsen len += payload->payload_length; 1727c18ec02fSPetter Reinholdtsen break; 1728c18ec02fSPetter Reinholdtsen 1729c18ec02fSPetter Reinholdtsen default: 1730c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "unsupported payload type 0x%x", 1731c18ec02fSPetter Reinholdtsen payload->payload_type); 1732c18ec02fSPetter Reinholdtsen free(msg); 1733c18ec02fSPetter Reinholdtsen msg = NULL; 1734c18ec02fSPetter Reinholdtsen assert(0); 1735c18ec02fSPetter Reinholdtsen break; 1736c18ec02fSPetter Reinholdtsen } 1737c18ec02fSPetter Reinholdtsen 1738c18ec02fSPetter Reinholdtsen 1739c18ec02fSPetter Reinholdtsen /* 1740c18ec02fSPetter Reinholdtsen *------------------------------------------ 1741c18ec02fSPetter Reinholdtsen * ENCRYPT THE PAYLOAD IF NECESSARY 1742c18ec02fSPetter Reinholdtsen *------------------------------------------ 1743c18ec02fSPetter Reinholdtsen */ 1744c18ec02fSPetter Reinholdtsen if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE) 1745c18ec02fSPetter Reinholdtsen { 1746c18ec02fSPetter Reinholdtsen /* Payload len is adjusted as necessary by lanplus_encrypt_payload */ 1747c18ec02fSPetter Reinholdtsen lanplus_encrypt_payload(session->v2_data.crypt_alg, /* input */ 1748c18ec02fSPetter Reinholdtsen session->v2_data.k2, /* input */ 1749c18ec02fSPetter Reinholdtsen msg + IPMI_LANPLUS_OFFSET_PAYLOAD, /* input */ 1750c18ec02fSPetter Reinholdtsen payload->payload_length, /* input */ 1751c18ec02fSPetter Reinholdtsen msg + IPMI_LANPLUS_OFFSET_PAYLOAD, /* output */ 1752c18ec02fSPetter Reinholdtsen &(payload->payload_length)); /* output */ 1753c18ec02fSPetter Reinholdtsen 1754c18ec02fSPetter Reinholdtsen } 1755c18ec02fSPetter Reinholdtsen 1756c18ec02fSPetter Reinholdtsen /* Now we know the payload length */ 1757c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE ] = 1758c18ec02fSPetter Reinholdtsen payload->payload_length & 0xff; 1759c18ec02fSPetter Reinholdtsen msg[IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE + 1] = 1760c18ec02fSPetter Reinholdtsen (payload->payload_length >> 8) & 0xff; 1761c18ec02fSPetter Reinholdtsen 1762c18ec02fSPetter Reinholdtsen 1763c18ec02fSPetter Reinholdtsen /* 1764c18ec02fSPetter Reinholdtsen *------------------------------------------ 1765c18ec02fSPetter Reinholdtsen * SESSION TRAILER 1766c18ec02fSPetter Reinholdtsen *------------------------------------------ 1767c18ec02fSPetter Reinholdtsen */ 1768c18ec02fSPetter Reinholdtsen if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) && 1769c18ec02fSPetter Reinholdtsen (session->v2_data.integrity_alg != IPMI_INTEGRITY_NONE)) 1770c18ec02fSPetter Reinholdtsen { 1771c18ec02fSPetter Reinholdtsen uint32_t i, hmac_length, integrity_pad_size = 0, hmac_input_size; 1772c18ec02fSPetter Reinholdtsen uint8_t * hmac_output; 1773c18ec02fSPetter Reinholdtsen uint32_t start_of_session_trailer = 1774c18ec02fSPetter Reinholdtsen IPMI_LANPLUS_OFFSET_PAYLOAD + 1775c18ec02fSPetter Reinholdtsen payload->payload_length; 1776c18ec02fSPetter Reinholdtsen 1777c18ec02fSPetter Reinholdtsen 1778c18ec02fSPetter Reinholdtsen /* 1779c18ec02fSPetter Reinholdtsen * Determine the required integrity pad length. We have to make the 1780c18ec02fSPetter Reinholdtsen * data range covered by the authcode a multiple of 4. 1781c18ec02fSPetter Reinholdtsen */ 1782c18ec02fSPetter Reinholdtsen uint32_t length_before_authcode; 1783c18ec02fSPetter Reinholdtsen 1784c18ec02fSPetter Reinholdtsen if (ipmi_oem_active(intf, "icts")) { 1785c18ec02fSPetter Reinholdtsen length_before_authcode = 1786c18ec02fSPetter Reinholdtsen 12 + /* the stuff before the payload */ 1787c18ec02fSPetter Reinholdtsen payload->payload_length; 1788c18ec02fSPetter Reinholdtsen } else { 1789c18ec02fSPetter Reinholdtsen length_before_authcode = 1790c18ec02fSPetter Reinholdtsen 12 + /* the stuff before the payload */ 1791c18ec02fSPetter Reinholdtsen payload->payload_length + 1792c18ec02fSPetter Reinholdtsen 1 + /* pad length field */ 1793c18ec02fSPetter Reinholdtsen 1; /* next header field */ 1794c18ec02fSPetter Reinholdtsen } 1795c18ec02fSPetter Reinholdtsen 1796c18ec02fSPetter Reinholdtsen if (length_before_authcode % 4) 1797c18ec02fSPetter Reinholdtsen integrity_pad_size = 4 - (length_before_authcode % 4); 1798c18ec02fSPetter Reinholdtsen 1799c18ec02fSPetter Reinholdtsen for (i = 0; i < integrity_pad_size; ++i) 1800c18ec02fSPetter Reinholdtsen msg[start_of_session_trailer + i] = 0xFF; 1801c18ec02fSPetter Reinholdtsen 1802c18ec02fSPetter Reinholdtsen /* Pad length */ 1803c18ec02fSPetter Reinholdtsen msg[start_of_session_trailer + integrity_pad_size] = integrity_pad_size; 1804c18ec02fSPetter Reinholdtsen 1805c18ec02fSPetter Reinholdtsen /* Next Header */ 1806c18ec02fSPetter Reinholdtsen msg[start_of_session_trailer + integrity_pad_size + 1] = 1807c18ec02fSPetter Reinholdtsen 0x07; /* Hardcoded per the spec, table 13-8 */ 1808c18ec02fSPetter Reinholdtsen 1809c18ec02fSPetter Reinholdtsen hmac_input_size = 1810c18ec02fSPetter Reinholdtsen 12 + 1811c18ec02fSPetter Reinholdtsen payload->payload_length + 1812c18ec02fSPetter Reinholdtsen integrity_pad_size + 1813c18ec02fSPetter Reinholdtsen 2; 1814c18ec02fSPetter Reinholdtsen 1815c18ec02fSPetter Reinholdtsen hmac_output = 1816c18ec02fSPetter Reinholdtsen msg + 1817c18ec02fSPetter Reinholdtsen IPMI_LANPLUS_OFFSET_PAYLOAD + 1818c18ec02fSPetter Reinholdtsen payload->payload_length + 1819c18ec02fSPetter Reinholdtsen integrity_pad_size + 1820c18ec02fSPetter Reinholdtsen 2; 1821c18ec02fSPetter Reinholdtsen 1822c18ec02fSPetter Reinholdtsen if (verbose > 2) 1823c18ec02fSPetter Reinholdtsen printbuf(msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, hmac_input_size, "authcode input"); 1824c18ec02fSPetter Reinholdtsen 1825c18ec02fSPetter Reinholdtsen 1826c18ec02fSPetter Reinholdtsen /* Auth Code */ 1827c18ec02fSPetter Reinholdtsen lanplus_HMAC(session->v2_data.integrity_alg, 1828c18ec02fSPetter Reinholdtsen session->v2_data.k1, /* key */ 1829c18ec02fSPetter Reinholdtsen 20, /* key length */ 1830c18ec02fSPetter Reinholdtsen msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, /* hmac input */ 1831c18ec02fSPetter Reinholdtsen hmac_input_size, 1832c18ec02fSPetter Reinholdtsen hmac_output, 1833c18ec02fSPetter Reinholdtsen &hmac_length); 1834c18ec02fSPetter Reinholdtsen 1835c18ec02fSPetter Reinholdtsen assert(hmac_length == 20); 1836c18ec02fSPetter Reinholdtsen 1837c18ec02fSPetter Reinholdtsen if (verbose > 2) 1838c18ec02fSPetter Reinholdtsen printbuf(hmac_output, 12, "authcode output"); 1839c18ec02fSPetter Reinholdtsen 1840c18ec02fSPetter Reinholdtsen /* Set session_trailer_length appropriately */ 1841c18ec02fSPetter Reinholdtsen session_trailer_length = 1842c18ec02fSPetter Reinholdtsen integrity_pad_size + 1843c18ec02fSPetter Reinholdtsen 2 + /* pad length + next header */ 1844c18ec02fSPetter Reinholdtsen 12; /* Size of the authcode (we only use the first 12 bytes) */ 1845c18ec02fSPetter Reinholdtsen } 1846c18ec02fSPetter Reinholdtsen 1847c18ec02fSPetter Reinholdtsen 1848c18ec02fSPetter Reinholdtsen ++(session->out_seq); 1849c18ec02fSPetter Reinholdtsen if (!session->out_seq) 1850c18ec02fSPetter Reinholdtsen ++(session->out_seq); 1851c18ec02fSPetter Reinholdtsen 1852c18ec02fSPetter Reinholdtsen *msg_len = 1853c18ec02fSPetter Reinholdtsen IPMI_LANPLUS_OFFSET_PAYLOAD + 1854c18ec02fSPetter Reinholdtsen payload->payload_length + 1855c18ec02fSPetter Reinholdtsen session_trailer_length; 1856c18ec02fSPetter Reinholdtsen *msg_data = msg; 1857c18ec02fSPetter Reinholdtsen } 1858c18ec02fSPetter Reinholdtsen 1859c18ec02fSPetter Reinholdtsen 1860c18ec02fSPetter Reinholdtsen 1861c18ec02fSPetter Reinholdtsen /* 1862c18ec02fSPetter Reinholdtsen * ipmi_lanplus_build_v2x_ipmi_cmd 1863c18ec02fSPetter Reinholdtsen * 1864c18ec02fSPetter Reinholdtsen * Wraps ipmi_lanplus_build_v2x_msg and returns a new entry object for the 1865c18ec02fSPetter Reinholdtsen * command 1866c18ec02fSPetter Reinholdtsen * 1867c18ec02fSPetter Reinholdtsen */ 1868c18ec02fSPetter Reinholdtsen static struct ipmi_rq_entry * 1869c18ec02fSPetter Reinholdtsen ipmi_lanplus_build_v2x_ipmi_cmd( 1870c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 1871c18ec02fSPetter Reinholdtsen struct ipmi_rq * req, 1872c18ec02fSPetter Reinholdtsen int isRetry) 1873c18ec02fSPetter Reinholdtsen { 1874c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload v2_payload; 1875c18ec02fSPetter Reinholdtsen struct ipmi_rq_entry * entry; 1876c18ec02fSPetter Reinholdtsen 1877c18ec02fSPetter Reinholdtsen /* 1878c18ec02fSPetter Reinholdtsen * We have a problem. we need to know the sequence number here, 1879c18ec02fSPetter Reinholdtsen * because we use it in our stored entry. But we also need to 1880c18ec02fSPetter Reinholdtsen * know the sequence number when we generate our IPMI 1881c18ec02fSPetter Reinholdtsen * representation far below. 1882c18ec02fSPetter Reinholdtsen */ 1883c18ec02fSPetter Reinholdtsen static uint8_t curr_seq = 0; 1884c18ec02fSPetter Reinholdtsen 1885c18ec02fSPetter Reinholdtsen if( isRetry == 0 ) 1886c18ec02fSPetter Reinholdtsen curr_seq += 1; 1887c18ec02fSPetter Reinholdtsen 1888c18ec02fSPetter Reinholdtsen if (curr_seq >= 64) 1889c18ec02fSPetter Reinholdtsen curr_seq = 0; 1890c18ec02fSPetter Reinholdtsen 1891c18ec02fSPetter Reinholdtsen 1892c18ec02fSPetter Reinholdtsen /* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */ 1893c18ec02fSPetter Reinholdtsen if ((intf->target_addr == intf->my_addr) || (!bridgePossible)) 1894c18ec02fSPetter Reinholdtsen { 1895c18ec02fSPetter Reinholdtsen entry = ipmi_req_add_entry(intf, req, curr_seq); 1896c18ec02fSPetter Reinholdtsen } 1897c18ec02fSPetter Reinholdtsen else /* it's a bridge command */ 1898c18ec02fSPetter Reinholdtsen { 1899c18ec02fSPetter Reinholdtsen unsigned char backup_cmd; 1900c18ec02fSPetter Reinholdtsen 1901c18ec02fSPetter Reinholdtsen /* Add entry for cmd */ 1902c18ec02fSPetter Reinholdtsen entry = ipmi_req_add_entry(intf, req, curr_seq); 1903c18ec02fSPetter Reinholdtsen 1904c18ec02fSPetter Reinholdtsen if(entry) 1905c18ec02fSPetter Reinholdtsen { 1906c18ec02fSPetter Reinholdtsen /* Add entry for bridge cmd */ 1907c18ec02fSPetter Reinholdtsen backup_cmd = req->msg.cmd; 1908c18ec02fSPetter Reinholdtsen req->msg.cmd = 0x34; 1909c18ec02fSPetter Reinholdtsen entry = ipmi_req_add_entry(intf, req, curr_seq); 1910c18ec02fSPetter Reinholdtsen req->msg.cmd = backup_cmd; 1911c18ec02fSPetter Reinholdtsen } 1912c18ec02fSPetter Reinholdtsen } 1913c18ec02fSPetter Reinholdtsen 1914c18ec02fSPetter Reinholdtsen if (entry == NULL) 1915c18ec02fSPetter Reinholdtsen return NULL; 1916c18ec02fSPetter Reinholdtsen 1917c18ec02fSPetter Reinholdtsen // Build our payload 1918c18ec02fSPetter Reinholdtsen v2_payload.payload_type = IPMI_PAYLOAD_TYPE_IPMI; 1919c18ec02fSPetter Reinholdtsen v2_payload.payload_length = req->msg.data_len + 7; 1920c18ec02fSPetter Reinholdtsen v2_payload.payload.ipmi_request.request = req; 1921c18ec02fSPetter Reinholdtsen v2_payload.payload.ipmi_request.rq_seq = curr_seq; 1922c18ec02fSPetter Reinholdtsen 1923c18ec02fSPetter Reinholdtsen ipmi_lanplus_build_v2x_msg(intf, // in 1924c18ec02fSPetter Reinholdtsen &v2_payload, // in 1925c18ec02fSPetter Reinholdtsen &(entry->msg_len), // out 1926c18ec02fSPetter Reinholdtsen &(entry->msg_data), // out 1927c18ec02fSPetter Reinholdtsen curr_seq); // in 1928c18ec02fSPetter Reinholdtsen 1929c18ec02fSPetter Reinholdtsen return entry; 1930c18ec02fSPetter Reinholdtsen } 1931c18ec02fSPetter Reinholdtsen 1932c18ec02fSPetter Reinholdtsen 1933c18ec02fSPetter Reinholdtsen 1934c18ec02fSPetter Reinholdtsen 1935c18ec02fSPetter Reinholdtsen 1936c18ec02fSPetter Reinholdtsen /* 1937c18ec02fSPetter Reinholdtsen * IPMI LAN Request Message Format 1938c18ec02fSPetter Reinholdtsen * +--------------------+ 1939c18ec02fSPetter Reinholdtsen * | rmcp.ver | 4 bytes 1940c18ec02fSPetter Reinholdtsen * | rmcp.__reserved | 1941c18ec02fSPetter Reinholdtsen * | rmcp.seq | 1942c18ec02fSPetter Reinholdtsen * | rmcp.class | 1943c18ec02fSPetter Reinholdtsen * +--------------------+ 1944c18ec02fSPetter Reinholdtsen * | session.authtype | 9 bytes 1945c18ec02fSPetter Reinholdtsen * | session.seq | 1946c18ec02fSPetter Reinholdtsen * | session.id | 1947c18ec02fSPetter Reinholdtsen * +--------------------+ 1948c18ec02fSPetter Reinholdtsen * | [session.authcode] | 16 bytes (AUTHTYPE != none) 1949c18ec02fSPetter Reinholdtsen * +--------------------+ 1950c18ec02fSPetter Reinholdtsen * | message length | 1 byte 1951c18ec02fSPetter Reinholdtsen * +--------------------+ 1952c18ec02fSPetter Reinholdtsen * | message.rs_addr | 6 bytes 1953c18ec02fSPetter Reinholdtsen * | message.netfn_lun | 1954c18ec02fSPetter Reinholdtsen * | message.checksum | 1955c18ec02fSPetter Reinholdtsen * | message.rq_addr | 1956c18ec02fSPetter Reinholdtsen * | message.rq_seq | 1957c18ec02fSPetter Reinholdtsen * | message.cmd | 1958c18ec02fSPetter Reinholdtsen * +--------------------+ 1959c18ec02fSPetter Reinholdtsen * | [request data] | data_len bytes 1960c18ec02fSPetter Reinholdtsen * +--------------------+ 1961c18ec02fSPetter Reinholdtsen * | checksum | 1 byte 1962c18ec02fSPetter Reinholdtsen * +--------------------+ 1963c18ec02fSPetter Reinholdtsen */ 1964c18ec02fSPetter Reinholdtsen static struct ipmi_rq_entry * 1965c18ec02fSPetter Reinholdtsen ipmi_lanplus_build_v15_ipmi_cmd( 1966c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 1967c18ec02fSPetter Reinholdtsen struct ipmi_rq * req) 1968c18ec02fSPetter Reinholdtsen { 1969c18ec02fSPetter Reinholdtsen struct rmcp_hdr rmcp = { 1970c18ec02fSPetter Reinholdtsen .ver = RMCP_VERSION_1, 1971c18ec02fSPetter Reinholdtsen .class = RMCP_CLASS_IPMI, 1972c18ec02fSPetter Reinholdtsen .seq = 0xff, 1973c18ec02fSPetter Reinholdtsen }; 1974c18ec02fSPetter Reinholdtsen uint8_t * msg; 1975c18ec02fSPetter Reinholdtsen int cs, mp, len = 0, tmp; 1976c18ec02fSPetter Reinholdtsen struct ipmi_session * session = intf->session; 1977c18ec02fSPetter Reinholdtsen struct ipmi_rq_entry * entry; 1978c18ec02fSPetter Reinholdtsen 1979c18ec02fSPetter Reinholdtsen entry = ipmi_req_add_entry(intf, req, 0); 1980c18ec02fSPetter Reinholdtsen if (entry == NULL) 1981c18ec02fSPetter Reinholdtsen return NULL; 1982c18ec02fSPetter Reinholdtsen 1983c18ec02fSPetter Reinholdtsen len = req->msg.data_len + 21; 1984c18ec02fSPetter Reinholdtsen 1985c18ec02fSPetter Reinholdtsen msg = malloc(len); 1986c18ec02fSPetter Reinholdtsen if (msg == NULL) { 1987c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure"); 1988c18ec02fSPetter Reinholdtsen return NULL; 1989c18ec02fSPetter Reinholdtsen } 1990c18ec02fSPetter Reinholdtsen memset(msg, 0, len); 1991c18ec02fSPetter Reinholdtsen 1992c18ec02fSPetter Reinholdtsen /* rmcp header */ 1993c18ec02fSPetter Reinholdtsen memcpy(msg, &rmcp, sizeof(rmcp)); 1994c18ec02fSPetter Reinholdtsen len = sizeof(rmcp); 1995c18ec02fSPetter Reinholdtsen 1996c18ec02fSPetter Reinholdtsen /* 1997c18ec02fSPetter Reinholdtsen * ipmi session header 1998c18ec02fSPetter Reinholdtsen */ 1999c18ec02fSPetter Reinholdtsen /* Authtype should always be none for 1.5 packets sent from this 2000c18ec02fSPetter Reinholdtsen * interface 2001c18ec02fSPetter Reinholdtsen */ 2002c18ec02fSPetter Reinholdtsen msg[len++] = IPMI_SESSION_AUTHTYPE_NONE; 2003c18ec02fSPetter Reinholdtsen 2004c18ec02fSPetter Reinholdtsen msg[len++] = session->out_seq & 0xff; 2005c18ec02fSPetter Reinholdtsen msg[len++] = (session->out_seq >> 8) & 0xff; 2006c18ec02fSPetter Reinholdtsen msg[len++] = (session->out_seq >> 16) & 0xff; 2007c18ec02fSPetter Reinholdtsen msg[len++] = (session->out_seq >> 24) & 0xff; 2008c18ec02fSPetter Reinholdtsen 2009c18ec02fSPetter Reinholdtsen /* 2010c18ec02fSPetter Reinholdtsen * The session ID should be all zeroes for pre-session commands. We 2011c18ec02fSPetter Reinholdtsen * should only be using the 1.5 interface for the pre-session Get 2012c18ec02fSPetter Reinholdtsen * Channel Authentication Capabilities command 2013c18ec02fSPetter Reinholdtsen */ 2014c18ec02fSPetter Reinholdtsen msg[len++] = 0; 2015c18ec02fSPetter Reinholdtsen msg[len++] = 0; 2016c18ec02fSPetter Reinholdtsen msg[len++] = 0; 2017c18ec02fSPetter Reinholdtsen msg[len++] = 0; 2018c18ec02fSPetter Reinholdtsen 2019c18ec02fSPetter Reinholdtsen /* message length */ 2020c18ec02fSPetter Reinholdtsen msg[len++] = req->msg.data_len + 7; 2021c18ec02fSPetter Reinholdtsen 2022c18ec02fSPetter Reinholdtsen /* ipmi message header */ 2023c18ec02fSPetter Reinholdtsen cs = mp = len; 2024c18ec02fSPetter Reinholdtsen msg[len++] = IPMI_BMC_SLAVE_ADDR; 2025c18ec02fSPetter Reinholdtsen msg[len++] = req->msg.netfn << 2; 2026c18ec02fSPetter Reinholdtsen tmp = len - cs; 2027c18ec02fSPetter Reinholdtsen msg[len++] = ipmi_csum(msg+cs, tmp); 2028c18ec02fSPetter Reinholdtsen cs = len; 2029c18ec02fSPetter Reinholdtsen msg[len++] = IPMI_REMOTE_SWID; 2030c18ec02fSPetter Reinholdtsen 2031c18ec02fSPetter Reinholdtsen entry->rq_seq = 0; 2032c18ec02fSPetter Reinholdtsen 2033c18ec02fSPetter Reinholdtsen msg[len++] = entry->rq_seq << 2; 2034c18ec02fSPetter Reinholdtsen msg[len++] = req->msg.cmd; 2035c18ec02fSPetter Reinholdtsen 2036c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> IPMI Request Session Header"); 2037c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> Authtype : %s", 2038c18ec02fSPetter Reinholdtsen val2str(IPMI_SESSION_AUTHTYPE_NONE, ipmi_authtype_session_vals)); 2039c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> Sequence : 0x%08lx", 2040c18ec02fSPetter Reinholdtsen (long)session->out_seq); 2041c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> Session ID : 0x%08lx", 2042c18ec02fSPetter Reinholdtsen (long)0); 2043c18ec02fSPetter Reinholdtsen 2044c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> IPMI Request Message Header"); 2045c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> Rs Addr : %02x", IPMI_BMC_SLAVE_ADDR); 2046c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> NetFn : %02x", req->msg.netfn); 2047c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> Rs LUN : %01x", 0); 2048c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> Rq Addr : %02x", IPMI_REMOTE_SWID); 2049c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> Rq Seq : %02x", entry->rq_seq); 2050c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> Rq Lun : %01x", 0); 2051c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, ">> Command : %02x", req->msg.cmd); 2052c18ec02fSPetter Reinholdtsen 2053c18ec02fSPetter Reinholdtsen /* message data */ 2054c18ec02fSPetter Reinholdtsen if (req->msg.data_len) { 2055c18ec02fSPetter Reinholdtsen memcpy(msg+len, req->msg.data, req->msg.data_len); 2056c18ec02fSPetter Reinholdtsen len += req->msg.data_len; 2057c18ec02fSPetter Reinholdtsen } 2058c18ec02fSPetter Reinholdtsen 2059c18ec02fSPetter Reinholdtsen /* second checksum */ 2060c18ec02fSPetter Reinholdtsen tmp = len - cs; 2061c18ec02fSPetter Reinholdtsen msg[len++] = ipmi_csum(msg+cs, tmp); 2062c18ec02fSPetter Reinholdtsen 2063c18ec02fSPetter Reinholdtsen entry->msg_len = len; 2064c18ec02fSPetter Reinholdtsen entry->msg_data = msg; 2065c18ec02fSPetter Reinholdtsen 2066c18ec02fSPetter Reinholdtsen return entry; 2067c18ec02fSPetter Reinholdtsen } 2068c18ec02fSPetter Reinholdtsen 2069c18ec02fSPetter Reinholdtsen 2070c18ec02fSPetter Reinholdtsen 2071c18ec02fSPetter Reinholdtsen /* 2072c18ec02fSPetter Reinholdtsen * is_sol_packet 2073c18ec02fSPetter Reinholdtsen */ 2074c18ec02fSPetter Reinholdtsen static int 2075c18ec02fSPetter Reinholdtsen is_sol_packet(struct ipmi_rs * rsp) 2076c18ec02fSPetter Reinholdtsen { 2077c18ec02fSPetter Reinholdtsen return (rsp && 2078c18ec02fSPetter Reinholdtsen (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) && 2079c18ec02fSPetter Reinholdtsen (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)); 2080c18ec02fSPetter Reinholdtsen } 2081c18ec02fSPetter Reinholdtsen 2082c18ec02fSPetter Reinholdtsen 2083c18ec02fSPetter Reinholdtsen 2084c18ec02fSPetter Reinholdtsen /* 2085c18ec02fSPetter Reinholdtsen * sol_response_acks_packet 2086c18ec02fSPetter Reinholdtsen */ 2087c18ec02fSPetter Reinholdtsen static int 2088c18ec02fSPetter Reinholdtsen sol_response_acks_packet( 2089c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp, 2090c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * payload) 2091c18ec02fSPetter Reinholdtsen { 2092c18ec02fSPetter Reinholdtsen return (is_sol_packet(rsp) && 2093c18ec02fSPetter Reinholdtsen payload && 2094c18ec02fSPetter Reinholdtsen (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL) && 2095c18ec02fSPetter Reinholdtsen (rsp->payload.sol_packet.acked_packet_number == 2096c18ec02fSPetter Reinholdtsen payload->payload.sol_packet.packet_sequence_number)); 2097c18ec02fSPetter Reinholdtsen } 2098c18ec02fSPetter Reinholdtsen 2099c18ec02fSPetter Reinholdtsen 2100c18ec02fSPetter Reinholdtsen 2101c18ec02fSPetter Reinholdtsen /* 2102c18ec02fSPetter Reinholdtsen * ipmi_lanplus_send_payload 2103c18ec02fSPetter Reinholdtsen * 2104c18ec02fSPetter Reinholdtsen */ 2105c18ec02fSPetter Reinholdtsen struct ipmi_rs * 2106c18ec02fSPetter Reinholdtsen ipmi_lanplus_send_payload( 2107c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 2108c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * payload) 2109c18ec02fSPetter Reinholdtsen { 2110c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp = NULL; 2111c18ec02fSPetter Reinholdtsen uint8_t * msg_data; 2112c18ec02fSPetter Reinholdtsen int msg_length; 2113c18ec02fSPetter Reinholdtsen struct ipmi_session * session = intf->session; 2114176774cfSZdenek Styblik struct ipmi_rq_entry * entry = NULL; 2115c18ec02fSPetter Reinholdtsen int try = 0; 2116c18ec02fSPetter Reinholdtsen int xmit = 1; 2117c18ec02fSPetter Reinholdtsen time_t ltime; 2118c18ec02fSPetter Reinholdtsen uint32_t saved_timeout; 2119c18ec02fSPetter Reinholdtsen 2120c18ec02fSPetter Reinholdtsen if (!intf->opened && intf->open && intf->open(intf) < 0) 2121c18ec02fSPetter Reinholdtsen return NULL; 2122c18ec02fSPetter Reinholdtsen 2123c18ec02fSPetter Reinholdtsen /* 2124c18ec02fSPetter Reinholdtsen * The session timeout is initialized in the above interface open, 2125c18ec02fSPetter Reinholdtsen * so it will only be valid after the open completes. 2126c18ec02fSPetter Reinholdtsen */ 2127c18ec02fSPetter Reinholdtsen saved_timeout = session->timeout; 2128c18ec02fSPetter Reinholdtsen while (try < session->retry) { 2129c18ec02fSPetter Reinholdtsen //ltime = time(NULL); 2130c18ec02fSPetter Reinholdtsen 2131c18ec02fSPetter Reinholdtsen if (xmit) { 2132c18ec02fSPetter Reinholdtsen ltime = time(NULL); 2133c18ec02fSPetter Reinholdtsen 2134c18ec02fSPetter Reinholdtsen if (payload->payload_type == IPMI_PAYLOAD_TYPE_IPMI) 2135c18ec02fSPetter Reinholdtsen { 2136c18ec02fSPetter Reinholdtsen /* 2137c18ec02fSPetter Reinholdtsen * Build an IPMI v1.5 or v2 command 2138c18ec02fSPetter Reinholdtsen */ 2139c18ec02fSPetter Reinholdtsen struct ipmi_rq * ipmi_request = payload->payload.ipmi_request.request; 2140c18ec02fSPetter Reinholdtsen 2141c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, ""); 2142c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, ">> Sending IPMI command payload"); 2143c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, ">> netfn : 0x%02x", ipmi_request->msg.netfn); 2144c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, ">> command : 0x%02x", ipmi_request->msg.cmd); 2145c18ec02fSPetter Reinholdtsen 2146c18ec02fSPetter Reinholdtsen if (verbose > 1) 2147c18ec02fSPetter Reinholdtsen { 2148c18ec02fSPetter Reinholdtsen uint16_t i; 2149c18ec02fSPetter Reinholdtsen fprintf(stderr, ">> data : "); 2150c18ec02fSPetter Reinholdtsen for (i = 0; i < ipmi_request->msg.data_len; ++i) 2151c18ec02fSPetter Reinholdtsen fprintf(stderr, "0x%02x ", ipmi_request->msg.data[i]); 2152c18ec02fSPetter Reinholdtsen fprintf(stderr, "\n\n"); 2153c18ec02fSPetter Reinholdtsen } 2154c18ec02fSPetter Reinholdtsen 2155c18ec02fSPetter Reinholdtsen 2156c18ec02fSPetter Reinholdtsen /* 2157c18ec02fSPetter Reinholdtsen * If we are presession, and the command is GET CHANNEL AUTHENTICATION 2158c18ec02fSPetter Reinholdtsen * CAPABILITIES, we will build the command in v1.5 format. This is so 2159c18ec02fSPetter Reinholdtsen * that we can ask any server whether it supports IPMI v2 / RMCP+ 2160c18ec02fSPetter Reinholdtsen * before we attempt to open a v2.x session. 2161c18ec02fSPetter Reinholdtsen */ 2162c18ec02fSPetter Reinholdtsen if ((ipmi_request->msg.netfn == IPMI_NETFN_APP) && 2163c18ec02fSPetter Reinholdtsen (ipmi_request->msg.cmd == IPMI_GET_CHANNEL_AUTH_CAP) && 2164c18ec02fSPetter Reinholdtsen (session->v2_data.bmc_id == 0)) // jme - check 2165c18ec02fSPetter Reinholdtsen { 2166c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "BUILDING A v1.5 COMMAND"); 2167c18ec02fSPetter Reinholdtsen entry = ipmi_lanplus_build_v15_ipmi_cmd(intf, ipmi_request); 2168c18ec02fSPetter Reinholdtsen } 2169c18ec02fSPetter Reinholdtsen else 2170c18ec02fSPetter Reinholdtsen { 2171c18ec02fSPetter Reinholdtsen int isRetry = ( try > 0 ? 1 : 0 ); 2172c18ec02fSPetter Reinholdtsen 2173c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG+1, "BUILDING A v2 COMMAND"); 2174c18ec02fSPetter Reinholdtsen entry = ipmi_lanplus_build_v2x_ipmi_cmd(intf, ipmi_request, isRetry); 2175c18ec02fSPetter Reinholdtsen } 2176c18ec02fSPetter Reinholdtsen 2177c18ec02fSPetter Reinholdtsen if (entry == NULL) { 2178c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Aborting send command, unable to build"); 2179c18ec02fSPetter Reinholdtsen return NULL; 2180c18ec02fSPetter Reinholdtsen } 2181c18ec02fSPetter Reinholdtsen 2182c18ec02fSPetter Reinholdtsen msg_data = entry->msg_data; 2183c18ec02fSPetter Reinholdtsen msg_length = entry->msg_len; 2184c18ec02fSPetter Reinholdtsen } 2185c18ec02fSPetter Reinholdtsen 2186c18ec02fSPetter Reinholdtsen else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST) 2187c18ec02fSPetter Reinholdtsen { 2188c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, ">> SENDING AN OPEN SESSION REQUEST\n"); 2189c18ec02fSPetter Reinholdtsen assert(session->v2_data.session_state == LANPLUS_STATE_PRESESSION 2190c18ec02fSPetter Reinholdtsen || session->v2_data.session_state == LANPLUS_STATE_OPEN_SESSION_SENT); 2191c18ec02fSPetter Reinholdtsen 2192c18ec02fSPetter Reinholdtsen ipmi_lanplus_build_v2x_msg(intf, /* in */ 2193c18ec02fSPetter Reinholdtsen payload, /* in */ 2194c18ec02fSPetter Reinholdtsen &msg_length, /* out */ 2195c18ec02fSPetter Reinholdtsen &msg_data, /* out */ 2196c18ec02fSPetter Reinholdtsen 0); /* irrelevant for this msg*/ 2197c18ec02fSPetter Reinholdtsen 2198c18ec02fSPetter Reinholdtsen } 2199c18ec02fSPetter Reinholdtsen 2200c18ec02fSPetter Reinholdtsen else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_1) 2201c18ec02fSPetter Reinholdtsen { 2202c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, ">> SENDING A RAKP 1 MESSAGE\n"); 2203c18ec02fSPetter Reinholdtsen assert(session->v2_data.session_state == 2204c18ec02fSPetter Reinholdtsen LANPLUS_STATE_OPEN_SESSION_RECEIEVED); 2205c18ec02fSPetter Reinholdtsen 2206c18ec02fSPetter Reinholdtsen ipmi_lanplus_build_v2x_msg(intf, /* in */ 2207c18ec02fSPetter Reinholdtsen payload, /* in */ 2208c18ec02fSPetter Reinholdtsen &msg_length, /* out */ 2209c18ec02fSPetter Reinholdtsen &msg_data, /* out */ 2210c18ec02fSPetter Reinholdtsen 0); /* irrelevant for this msg*/ 2211c18ec02fSPetter Reinholdtsen 2212c18ec02fSPetter Reinholdtsen } 2213c18ec02fSPetter Reinholdtsen 2214c18ec02fSPetter Reinholdtsen else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_3) 2215c18ec02fSPetter Reinholdtsen { 2216c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, ">> SENDING A RAKP 3 MESSAGE\n"); 2217c18ec02fSPetter Reinholdtsen assert(session->v2_data.session_state == 2218c18ec02fSPetter Reinholdtsen LANPLUS_STATE_RAKP_2_RECEIVED); 2219c18ec02fSPetter Reinholdtsen 2220c18ec02fSPetter Reinholdtsen ipmi_lanplus_build_v2x_msg(intf, /* in */ 2221c18ec02fSPetter Reinholdtsen payload, /* in */ 2222c18ec02fSPetter Reinholdtsen &msg_length, /* out */ 2223c18ec02fSPetter Reinholdtsen &msg_data, /* out */ 2224c18ec02fSPetter Reinholdtsen 0); /* irrelevant for this msg*/ 2225c18ec02fSPetter Reinholdtsen 2226c18ec02fSPetter Reinholdtsen } 2227c18ec02fSPetter Reinholdtsen 2228c18ec02fSPetter Reinholdtsen else if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL) 2229c18ec02fSPetter Reinholdtsen { 2230c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, ">> SENDING A SOL MESSAGE\n"); 2231c18ec02fSPetter Reinholdtsen assert(session->v2_data.session_state == LANPLUS_STATE_ACTIVE); 2232c18ec02fSPetter Reinholdtsen 2233c18ec02fSPetter Reinholdtsen ipmi_lanplus_build_v2x_msg(intf, /* in */ 2234c18ec02fSPetter Reinholdtsen payload, /* in */ 2235c18ec02fSPetter Reinholdtsen &msg_length, /* out */ 2236c18ec02fSPetter Reinholdtsen &msg_data, /* out */ 2237c18ec02fSPetter Reinholdtsen 0); /* irrelevant for this msg*/ 2238c18ec02fSPetter Reinholdtsen } 2239c18ec02fSPetter Reinholdtsen 2240c18ec02fSPetter Reinholdtsen else 2241c18ec02fSPetter Reinholdtsen { 2242c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Payload type 0x%0x is unsupported!", 2243c18ec02fSPetter Reinholdtsen payload->payload_type); 2244c18ec02fSPetter Reinholdtsen assert(0); 2245c18ec02fSPetter Reinholdtsen } 2246c18ec02fSPetter Reinholdtsen 2247c18ec02fSPetter Reinholdtsen 2248c18ec02fSPetter Reinholdtsen if (ipmi_lan_send_packet(intf, msg_data, msg_length) < 0) { 2249c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "IPMI LAN send command failed"); 2250c18ec02fSPetter Reinholdtsen return NULL; 2251c18ec02fSPetter Reinholdtsen } 2252c18ec02fSPetter Reinholdtsen } 2253c18ec02fSPetter Reinholdtsen 2254c18ec02fSPetter Reinholdtsen /* if we are set to noanswer we do not expect response */ 2255c18ec02fSPetter Reinholdtsen if (intf->noanswer) 2256c18ec02fSPetter Reinholdtsen break; 2257c18ec02fSPetter Reinholdtsen 2258c18ec02fSPetter Reinholdtsen usleep(100); /* Not sure what this is for */ 2259c18ec02fSPetter Reinholdtsen 2260c18ec02fSPetter Reinholdtsen /* Remember our connection state */ 2261c18ec02fSPetter Reinholdtsen switch (payload->payload_type) 2262c18ec02fSPetter Reinholdtsen { 2263c18ec02fSPetter Reinholdtsen case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST: 2264c18ec02fSPetter Reinholdtsen session->v2_data.session_state = LANPLUS_STATE_OPEN_SESSION_SENT; 2265176774cfSZdenek Styblik /* not retryable for timeouts, force no retry */ 2266176774cfSZdenek Styblik try = session->retry; 2267c18ec02fSPetter Reinholdtsen break; 2268c18ec02fSPetter Reinholdtsen case IPMI_PAYLOAD_TYPE_RAKP_1: 2269c18ec02fSPetter Reinholdtsen session->v2_data.session_state = LANPLUS_STATE_RAKP_1_SENT; 2270176774cfSZdenek Styblik /* not retryable for timeouts, force no retry */ 2271176774cfSZdenek Styblik try = session->retry; 2272c18ec02fSPetter Reinholdtsen break; 2273c18ec02fSPetter Reinholdtsen case IPMI_PAYLOAD_TYPE_RAKP_3: 2274176774cfSZdenek Styblik /* not retryable for timeouts, force no retry */ 2275176774cfSZdenek Styblik try = session->retry; 2276c18ec02fSPetter Reinholdtsen session->v2_data.session_state = LANPLUS_STATE_RAKP_3_SENT; 2277c18ec02fSPetter Reinholdtsen break; 2278c18ec02fSPetter Reinholdtsen } 2279c18ec02fSPetter Reinholdtsen 2280c18ec02fSPetter Reinholdtsen 2281c18ec02fSPetter Reinholdtsen /* 2282c18ec02fSPetter Reinholdtsen * Special case for SOL outbound packets. 2283c18ec02fSPetter Reinholdtsen */ 2284c18ec02fSPetter Reinholdtsen if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL) 2285c18ec02fSPetter Reinholdtsen { 2286c18ec02fSPetter Reinholdtsen if (! payload->payload.sol_packet.packet_sequence_number) 2287c18ec02fSPetter Reinholdtsen { 2288c18ec02fSPetter Reinholdtsen /* We're just sending an ACK. No need to retry. */ 2289c18ec02fSPetter Reinholdtsen break; 2290c18ec02fSPetter Reinholdtsen } 2291c18ec02fSPetter Reinholdtsen 2292c18ec02fSPetter Reinholdtsen 2293c18ec02fSPetter Reinholdtsen rsp = ipmi_lanplus_recv_sol(intf); /* Grab the next packet */ 2294c18ec02fSPetter Reinholdtsen 2295c18ec02fSPetter Reinholdtsen if (sol_response_acks_packet(rsp, payload)) 2296c18ec02fSPetter Reinholdtsen break; 2297c18ec02fSPetter Reinholdtsen 2298c18ec02fSPetter Reinholdtsen else if (is_sol_packet(rsp) && rsp->data_len) 2299c18ec02fSPetter Reinholdtsen { 2300c18ec02fSPetter Reinholdtsen /* 2301c18ec02fSPetter Reinholdtsen * We're still waiting for our ACK, but we more data from 2302c18ec02fSPetter Reinholdtsen * the BMC 2303c18ec02fSPetter Reinholdtsen */ 2304c18ec02fSPetter Reinholdtsen intf->session->sol_data.sol_input_handler(rsp); 2305c18ec02fSPetter Reinholdtsen /* In order to avoid duplicate output, just set data_len to 0 */ 2306c18ec02fSPetter Reinholdtsen rsp->data_len = 0; 2307c18ec02fSPetter Reinholdtsen } 2308c18ec02fSPetter Reinholdtsen } 2309c18ec02fSPetter Reinholdtsen 2310c18ec02fSPetter Reinholdtsen 2311c18ec02fSPetter Reinholdtsen /* Non-SOL processing */ 2312c18ec02fSPetter Reinholdtsen else 2313c18ec02fSPetter Reinholdtsen { 2314c18ec02fSPetter Reinholdtsen rsp = ipmi_lan_poll_recv(intf); 2315c18ec02fSPetter Reinholdtsen 2316c18ec02fSPetter Reinholdtsen /* Duplicate Request ccode most likely indicates a response to 2317c18ec02fSPetter Reinholdtsen a previous retry. Ignore and keep polling. */ 2318c18ec02fSPetter Reinholdtsen while ((rsp != NULL) && (rsp->ccode == 0xcf)) 2319c18ec02fSPetter Reinholdtsen { 2320c18ec02fSPetter Reinholdtsen rsp = NULL; 2321c18ec02fSPetter Reinholdtsen rsp = ipmi_lan_poll_recv(intf); 2322c18ec02fSPetter Reinholdtsen } 2323c18ec02fSPetter Reinholdtsen 2324c18ec02fSPetter Reinholdtsen if (rsp) 2325c18ec02fSPetter Reinholdtsen break; 2326176774cfSZdenek Styblik /* This payload type is retryable for timeouts. */ 2327176774cfSZdenek Styblik if ((payload->payload_type == IPMI_PAYLOAD_TYPE_IPMI) && entry) { 2328176774cfSZdenek Styblik ipmi_req_remove_entry( entry->rq_seq, entry->req.msg.cmd); 2329176774cfSZdenek Styblik } 2330c18ec02fSPetter Reinholdtsen } 2331c18ec02fSPetter Reinholdtsen 2332c18ec02fSPetter Reinholdtsen /* only timeout if time exceeds the timeout value */ 2333c18ec02fSPetter Reinholdtsen xmit = ((time(NULL) - ltime) >= session->timeout); 2334c18ec02fSPetter Reinholdtsen 2335c18ec02fSPetter Reinholdtsen usleep(5000); 2336c18ec02fSPetter Reinholdtsen 2337c18ec02fSPetter Reinholdtsen if (xmit) { 2338c18ec02fSPetter Reinholdtsen /* increment session timeout by 1 second each retry */ 2339c18ec02fSPetter Reinholdtsen session->timeout++; 2340c18ec02fSPetter Reinholdtsen } 2341c18ec02fSPetter Reinholdtsen 2342c18ec02fSPetter Reinholdtsen try++; 2343c18ec02fSPetter Reinholdtsen } 2344c18ec02fSPetter Reinholdtsen session->timeout = saved_timeout; 2345c18ec02fSPetter Reinholdtsen 2346c18ec02fSPetter Reinholdtsen /* IPMI messages are deleted under ipmi_lan_poll_recv() */ 2347c18ec02fSPetter Reinholdtsen switch (payload->payload_type) { 2348c18ec02fSPetter Reinholdtsen case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST: 2349c18ec02fSPetter Reinholdtsen case IPMI_PAYLOAD_TYPE_RAKP_1: 2350c18ec02fSPetter Reinholdtsen case IPMI_PAYLOAD_TYPE_RAKP_3: 2351c18ec02fSPetter Reinholdtsen free(msg_data); 2352c18ec02fSPetter Reinholdtsen msg_data = NULL; 2353c18ec02fSPetter Reinholdtsen break; 2354c18ec02fSPetter Reinholdtsen } 2355c18ec02fSPetter Reinholdtsen 2356c18ec02fSPetter Reinholdtsen return rsp; 2357c18ec02fSPetter Reinholdtsen } 2358c18ec02fSPetter Reinholdtsen 2359c18ec02fSPetter Reinholdtsen 2360c18ec02fSPetter Reinholdtsen 2361c18ec02fSPetter Reinholdtsen /* 2362c18ec02fSPetter Reinholdtsen * is_sol_partial_ack 2363c18ec02fSPetter Reinholdtsen * 2364c18ec02fSPetter Reinholdtsen * Determine if the response is a partial ACK/NACK that indicates 2365c18ec02fSPetter Reinholdtsen * we need to resend part of our packet. 2366c18ec02fSPetter Reinholdtsen * 2367c18ec02fSPetter Reinholdtsen * returns the number of characters we need to resend, or 2368c18ec02fSPetter Reinholdtsen * 0 if this isn't an ACK or we don't need to resend anything 2369c18ec02fSPetter Reinholdtsen */ 2370c18ec02fSPetter Reinholdtsen int is_sol_partial_ack( 2371c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 2372c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * v2_payload, 2373c18ec02fSPetter Reinholdtsen struct ipmi_rs * rs) 2374c18ec02fSPetter Reinholdtsen { 2375c18ec02fSPetter Reinholdtsen int chars_to_resend = 0; 2376c18ec02fSPetter Reinholdtsen 2377c18ec02fSPetter Reinholdtsen if (v2_payload && 2378c18ec02fSPetter Reinholdtsen rs && 2379c18ec02fSPetter Reinholdtsen is_sol_packet(rs) && 2380c18ec02fSPetter Reinholdtsen sol_response_acks_packet(rs, v2_payload) && 2381c18ec02fSPetter Reinholdtsen (rs->payload.sol_packet.accepted_character_count < 2382c18ec02fSPetter Reinholdtsen v2_payload->payload.sol_packet.character_count)) 2383c18ec02fSPetter Reinholdtsen { 2384c18ec02fSPetter Reinholdtsen if (ipmi_oem_active(intf, "intelplus") && 2385c18ec02fSPetter Reinholdtsen rs->payload.sol_packet.accepted_character_count == 0) 2386c18ec02fSPetter Reinholdtsen return 0; 2387c18ec02fSPetter Reinholdtsen 2388c18ec02fSPetter Reinholdtsen chars_to_resend = 2389c18ec02fSPetter Reinholdtsen v2_payload->payload.sol_packet.character_count - 2390c18ec02fSPetter Reinholdtsen rs->payload.sol_packet.accepted_character_count; 2391c18ec02fSPetter Reinholdtsen } 2392c18ec02fSPetter Reinholdtsen 2393c18ec02fSPetter Reinholdtsen return chars_to_resend; 2394c18ec02fSPetter Reinholdtsen } 2395c18ec02fSPetter Reinholdtsen 2396c18ec02fSPetter Reinholdtsen 2397c18ec02fSPetter Reinholdtsen 2398c18ec02fSPetter Reinholdtsen /* 2399c18ec02fSPetter Reinholdtsen * set_sol_packet_sequence_number 2400c18ec02fSPetter Reinholdtsen */ 2401c18ec02fSPetter Reinholdtsen static void set_sol_packet_sequence_number( 2402c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 2403c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * v2_payload) 2404c18ec02fSPetter Reinholdtsen { 2405c18ec02fSPetter Reinholdtsen /* Keep our sequence number sane */ 2406c18ec02fSPetter Reinholdtsen if (intf->session->sol_data.sequence_number > 0x0F) 2407c18ec02fSPetter Reinholdtsen intf->session->sol_data.sequence_number = 1; 2408c18ec02fSPetter Reinholdtsen 2409c18ec02fSPetter Reinholdtsen v2_payload->payload.sol_packet.packet_sequence_number = 2410c18ec02fSPetter Reinholdtsen intf->session->sol_data.sequence_number++; 2411c18ec02fSPetter Reinholdtsen } 2412c18ec02fSPetter Reinholdtsen 2413c18ec02fSPetter Reinholdtsen 2414c18ec02fSPetter Reinholdtsen 2415c18ec02fSPetter Reinholdtsen /* 2416c18ec02fSPetter Reinholdtsen * ipmi_lanplus_send_sol 2417c18ec02fSPetter Reinholdtsen * 2418c18ec02fSPetter Reinholdtsen * Sends a SOL packet.. We handle partial ACK/NACKs from the BMC here. 2419c18ec02fSPetter Reinholdtsen * 2420c18ec02fSPetter Reinholdtsen * Returns a pointer to the SOL ACK we received, or 2421c18ec02fSPetter Reinholdtsen * 0 on failure 2422c18ec02fSPetter Reinholdtsen * 2423c18ec02fSPetter Reinholdtsen */ 2424c18ec02fSPetter Reinholdtsen struct ipmi_rs * 2425c18ec02fSPetter Reinholdtsen ipmi_lanplus_send_sol( 2426c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 2427c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload * v2_payload) 2428c18ec02fSPetter Reinholdtsen { 2429c18ec02fSPetter Reinholdtsen struct ipmi_rs * rs; 2430c18ec02fSPetter Reinholdtsen 2431c18ec02fSPetter Reinholdtsen /* 2432c18ec02fSPetter Reinholdtsen * chars_to_resend indicates either that we got a NACK telling us 2433c18ec02fSPetter Reinholdtsen * that we need to resend some part of our data. 2434c18ec02fSPetter Reinholdtsen */ 2435c18ec02fSPetter Reinholdtsen int chars_to_resend = 0; 2436c18ec02fSPetter Reinholdtsen 2437c18ec02fSPetter Reinholdtsen v2_payload->payload_type = IPMI_PAYLOAD_TYPE_SOL; 2438c18ec02fSPetter Reinholdtsen 2439c18ec02fSPetter Reinholdtsen /* 2440c18ec02fSPetter Reinholdtsen * Payload length is just the length of the character 2441c18ec02fSPetter Reinholdtsen * data here. 2442c18ec02fSPetter Reinholdtsen */ 2443c18ec02fSPetter Reinholdtsen v2_payload->payload_length = v2_payload->payload.sol_packet.character_count; 2444c18ec02fSPetter Reinholdtsen 2445c18ec02fSPetter Reinholdtsen v2_payload->payload.sol_packet.acked_packet_number = 0; /* NA */ 2446c18ec02fSPetter Reinholdtsen 2447c18ec02fSPetter Reinholdtsen set_sol_packet_sequence_number(intf, v2_payload); 2448c18ec02fSPetter Reinholdtsen 2449c18ec02fSPetter Reinholdtsen v2_payload->payload.sol_packet.accepted_character_count = 0; /* NA */ 2450c18ec02fSPetter Reinholdtsen 2451c18ec02fSPetter Reinholdtsen rs = ipmi_lanplus_send_payload(intf, v2_payload); 2452c18ec02fSPetter Reinholdtsen 2453c18ec02fSPetter Reinholdtsen /* Determine if we need to resend some of our data */ 2454c18ec02fSPetter Reinholdtsen chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs); 2455c18ec02fSPetter Reinholdtsen 2456c18ec02fSPetter Reinholdtsen while (rs && !rs->payload.sol_packet.transfer_unavailable && 2457c18ec02fSPetter Reinholdtsen !rs->payload.sol_packet.is_nack && 2458c18ec02fSPetter Reinholdtsen chars_to_resend) 2459c18ec02fSPetter Reinholdtsen { 2460c18ec02fSPetter Reinholdtsen /* 2461c18ec02fSPetter Reinholdtsen * We first need to handle any new data we might have 2462c18ec02fSPetter Reinholdtsen * received in our NACK 2463c18ec02fSPetter Reinholdtsen */ 2464c18ec02fSPetter Reinholdtsen if (rs->data_len) 2465c18ec02fSPetter Reinholdtsen intf->session->sol_data.sol_input_handler(rs); 2466c18ec02fSPetter Reinholdtsen 2467c18ec02fSPetter Reinholdtsen set_sol_packet_sequence_number(intf, v2_payload); 2468c18ec02fSPetter Reinholdtsen 2469c18ec02fSPetter Reinholdtsen /* Just send the required data */ 2470c18ec02fSPetter Reinholdtsen memmove(v2_payload->payload.sol_packet.data, 2471c18ec02fSPetter Reinholdtsen v2_payload->payload.sol_packet.data + 2472c18ec02fSPetter Reinholdtsen rs->payload.sol_packet.accepted_character_count, 2473c18ec02fSPetter Reinholdtsen chars_to_resend); 2474c18ec02fSPetter Reinholdtsen 2475c18ec02fSPetter Reinholdtsen v2_payload->payload.sol_packet.character_count = chars_to_resend; 2476c18ec02fSPetter Reinholdtsen 2477c18ec02fSPetter Reinholdtsen v2_payload->payload_length = v2_payload->payload.sol_packet.character_count; 2478c18ec02fSPetter Reinholdtsen 2479c18ec02fSPetter Reinholdtsen rs = ipmi_lanplus_send_payload(intf, v2_payload); 2480c18ec02fSPetter Reinholdtsen 2481c18ec02fSPetter Reinholdtsen chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs); 2482c18ec02fSPetter Reinholdtsen } 2483c18ec02fSPetter Reinholdtsen 2484c18ec02fSPetter Reinholdtsen return rs; 2485c18ec02fSPetter Reinholdtsen } 2486c18ec02fSPetter Reinholdtsen 2487c18ec02fSPetter Reinholdtsen 2488c18ec02fSPetter Reinholdtsen 2489c18ec02fSPetter Reinholdtsen /* 2490c18ec02fSPetter Reinholdtsen * check_sol_packet_for_new_data 2491c18ec02fSPetter Reinholdtsen * 2492c18ec02fSPetter Reinholdtsen * Determine whether the SOL packet has already been seen 2493c18ec02fSPetter Reinholdtsen * and whether the packet has new data for us. 2494c18ec02fSPetter Reinholdtsen * 2495c18ec02fSPetter Reinholdtsen * This function has the side effect of removing an previously 2496c18ec02fSPetter Reinholdtsen * seen data, and moving new data to the front. 2497c18ec02fSPetter Reinholdtsen * 2498c18ec02fSPetter Reinholdtsen * It also "Remembers" the data so we don't get repeats. 2499c18ec02fSPetter Reinholdtsen * 2500c18ec02fSPetter Reinholdtsen * returns the number of new bytes in the SOL packet 2501c18ec02fSPetter Reinholdtsen */ 2502c18ec02fSPetter Reinholdtsen static int 2503c18ec02fSPetter Reinholdtsen check_sol_packet_for_new_data( 2504c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 2505c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp) 2506c18ec02fSPetter Reinholdtsen { 2507c18ec02fSPetter Reinholdtsen static uint8_t last_received_sequence_number = 0; 2508c18ec02fSPetter Reinholdtsen static uint8_t last_received_byte_count = 0; 2509c18ec02fSPetter Reinholdtsen int new_data_size = 0; 2510c18ec02fSPetter Reinholdtsen 2511c18ec02fSPetter Reinholdtsen 2512c18ec02fSPetter Reinholdtsen if (rsp && 2513c18ec02fSPetter Reinholdtsen (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) && 2514c18ec02fSPetter Reinholdtsen (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)) 2515c18ec02fSPetter Reinholdtsen { 2516c18ec02fSPetter Reinholdtsen /* Store the data length before we mod it */ 2517c18ec02fSPetter Reinholdtsen uint8_t unaltered_data_len = rsp->data_len; 2518c18ec02fSPetter Reinholdtsen 2519c18ec02fSPetter Reinholdtsen if (rsp->payload.sol_packet.packet_sequence_number == 2520c18ec02fSPetter Reinholdtsen last_received_sequence_number) 2521c18ec02fSPetter Reinholdtsen { 2522c18ec02fSPetter Reinholdtsen 2523c18ec02fSPetter Reinholdtsen /* 2524c18ec02fSPetter Reinholdtsen * This is the same as the last packet, but may include 2525c18ec02fSPetter Reinholdtsen * extra data 2526c18ec02fSPetter Reinholdtsen */ 2527c18ec02fSPetter Reinholdtsen new_data_size = rsp->data_len - last_received_byte_count; 2528c18ec02fSPetter Reinholdtsen 2529c18ec02fSPetter Reinholdtsen if (new_data_size > 0) 2530c18ec02fSPetter Reinholdtsen { 2531c18ec02fSPetter Reinholdtsen /* We have more data to process */ 2532c18ec02fSPetter Reinholdtsen memmove(rsp->data, 2533c18ec02fSPetter Reinholdtsen rsp->data + 2534c18ec02fSPetter Reinholdtsen rsp->data_len - new_data_size, 2535c18ec02fSPetter Reinholdtsen new_data_size); 2536c18ec02fSPetter Reinholdtsen } 2537c18ec02fSPetter Reinholdtsen 2538c18ec02fSPetter Reinholdtsen rsp->data_len = new_data_size; 2539c18ec02fSPetter Reinholdtsen } 2540c18ec02fSPetter Reinholdtsen 2541c18ec02fSPetter Reinholdtsen 2542c18ec02fSPetter Reinholdtsen /* 2543c18ec02fSPetter Reinholdtsen *Rember the data for next round 2544c18ec02fSPetter Reinholdtsen */ 2545c18ec02fSPetter Reinholdtsen if (rsp->payload.sol_packet.packet_sequence_number) 2546c18ec02fSPetter Reinholdtsen { 2547c18ec02fSPetter Reinholdtsen last_received_sequence_number = 2548c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.packet_sequence_number; 2549c18ec02fSPetter Reinholdtsen 2550c18ec02fSPetter Reinholdtsen last_received_byte_count = unaltered_data_len; 2551c18ec02fSPetter Reinholdtsen } 2552c18ec02fSPetter Reinholdtsen } 2553c18ec02fSPetter Reinholdtsen 2554c18ec02fSPetter Reinholdtsen 2555c18ec02fSPetter Reinholdtsen return new_data_size; 2556c18ec02fSPetter Reinholdtsen } 2557c18ec02fSPetter Reinholdtsen 2558c18ec02fSPetter Reinholdtsen 2559c18ec02fSPetter Reinholdtsen 2560c18ec02fSPetter Reinholdtsen /* 2561c18ec02fSPetter Reinholdtsen * ack_sol_packet 2562c18ec02fSPetter Reinholdtsen * 2563c18ec02fSPetter Reinholdtsen * Provided the specified packet looks reasonable, ACK it. 2564c18ec02fSPetter Reinholdtsen */ 2565c18ec02fSPetter Reinholdtsen static void 2566c18ec02fSPetter Reinholdtsen ack_sol_packet( 2567c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 2568c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp) 2569c18ec02fSPetter Reinholdtsen { 2570c18ec02fSPetter Reinholdtsen if (rsp && 2571c18ec02fSPetter Reinholdtsen (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) && 2572c18ec02fSPetter Reinholdtsen (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) && 2573c18ec02fSPetter Reinholdtsen (rsp->payload.sol_packet.packet_sequence_number)) 2574c18ec02fSPetter Reinholdtsen { 2575c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload ack; 2576c18ec02fSPetter Reinholdtsen 2577*d9f89a8dSZdenek Styblik memset(&ack, 0, sizeof(struct ipmi_v2_payload)); 2578c18ec02fSPetter Reinholdtsen 2579c18ec02fSPetter Reinholdtsen ack.payload_type = IPMI_PAYLOAD_TYPE_SOL; 2580c18ec02fSPetter Reinholdtsen 2581c18ec02fSPetter Reinholdtsen /* 2582c18ec02fSPetter Reinholdtsen * Payload length is just the length of the character 2583c18ec02fSPetter Reinholdtsen * data here. 2584c18ec02fSPetter Reinholdtsen */ 2585c18ec02fSPetter Reinholdtsen ack.payload_length = 0; 2586c18ec02fSPetter Reinholdtsen 2587c18ec02fSPetter Reinholdtsen /* ACK packets have sequence numbers of 0 */ 2588c18ec02fSPetter Reinholdtsen ack.payload.sol_packet.packet_sequence_number = 0; 2589c18ec02fSPetter Reinholdtsen 2590c18ec02fSPetter Reinholdtsen ack.payload.sol_packet.acked_packet_number = 2591c18ec02fSPetter Reinholdtsen rsp->payload.sol_packet.packet_sequence_number; 2592c18ec02fSPetter Reinholdtsen 2593c18ec02fSPetter Reinholdtsen ack.payload.sol_packet.accepted_character_count = rsp->data_len; 2594c18ec02fSPetter Reinholdtsen 2595c18ec02fSPetter Reinholdtsen ipmi_lanplus_send_payload(intf, &ack); 2596c18ec02fSPetter Reinholdtsen } 2597c18ec02fSPetter Reinholdtsen } 2598c18ec02fSPetter Reinholdtsen 2599c18ec02fSPetter Reinholdtsen 2600c18ec02fSPetter Reinholdtsen 2601c18ec02fSPetter Reinholdtsen /* 2602c18ec02fSPetter Reinholdtsen * ipmi_lanplus_recv_sol 2603c18ec02fSPetter Reinholdtsen * 2604c18ec02fSPetter Reinholdtsen * Receive a SOL packet and send an ACK in response. 2605c18ec02fSPetter Reinholdtsen * 2606c18ec02fSPetter Reinholdtsen */ 2607c18ec02fSPetter Reinholdtsen struct ipmi_rs * 2608c18ec02fSPetter Reinholdtsen ipmi_lanplus_recv_sol(struct ipmi_intf * intf) 2609c18ec02fSPetter Reinholdtsen { 2610c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp = ipmi_lan_poll_recv(intf); 2611c18ec02fSPetter Reinholdtsen 2612c18ec02fSPetter Reinholdtsen if (rsp && rsp->session.authtype != 0) 2613c18ec02fSPetter Reinholdtsen { 2614c18ec02fSPetter Reinholdtsen ack_sol_packet(intf, rsp); 2615c18ec02fSPetter Reinholdtsen 2616c18ec02fSPetter Reinholdtsen /* 2617c18ec02fSPetter Reinholdtsen * Remembers the data sent, and alters the data to just 2618c18ec02fSPetter Reinholdtsen * include the new stuff. 2619c18ec02fSPetter Reinholdtsen */ 2620c18ec02fSPetter Reinholdtsen check_sol_packet_for_new_data(intf, rsp); 2621c18ec02fSPetter Reinholdtsen } 2622c18ec02fSPetter Reinholdtsen return rsp; 2623c18ec02fSPetter Reinholdtsen } 2624c18ec02fSPetter Reinholdtsen 2625c18ec02fSPetter Reinholdtsen 2626c18ec02fSPetter Reinholdtsen 2627c18ec02fSPetter Reinholdtsen /** 2628c18ec02fSPetter Reinholdtsen * ipmi_lanplus_send_ipmi_cmd 2629c18ec02fSPetter Reinholdtsen * 2630c18ec02fSPetter Reinholdtsen * Build a payload request and dispatch it. 2631c18ec02fSPetter Reinholdtsen */ 2632c18ec02fSPetter Reinholdtsen struct ipmi_rs * 2633c18ec02fSPetter Reinholdtsen ipmi_lanplus_send_ipmi_cmd( 2634c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 2635c18ec02fSPetter Reinholdtsen struct ipmi_rq * req) 2636c18ec02fSPetter Reinholdtsen { 2637c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload v2_payload; 2638c18ec02fSPetter Reinholdtsen 2639c18ec02fSPetter Reinholdtsen v2_payload.payload_type = IPMI_PAYLOAD_TYPE_IPMI; 2640c18ec02fSPetter Reinholdtsen v2_payload.payload.ipmi_request.request = req; 2641c18ec02fSPetter Reinholdtsen 2642c18ec02fSPetter Reinholdtsen return ipmi_lanplus_send_payload(intf, &v2_payload); 2643c18ec02fSPetter Reinholdtsen } 2644c18ec02fSPetter Reinholdtsen 2645c18ec02fSPetter Reinholdtsen 2646c18ec02fSPetter Reinholdtsen /* 2647c18ec02fSPetter Reinholdtsen * ipmi_get_auth_capabilities_cmd 2648c18ec02fSPetter Reinholdtsen * 2649c18ec02fSPetter Reinholdtsen * This command may have to be sent twice. We first ask for the 2650c18ec02fSPetter Reinholdtsen * authentication capabilities with the "request IPMI v2 data bit" 2651c18ec02fSPetter Reinholdtsen * set. If this fails, we send the same command without that bit 2652c18ec02fSPetter Reinholdtsen * set. 2653c18ec02fSPetter Reinholdtsen * 2654c18ec02fSPetter Reinholdtsen * param intf is the initialized (but possibly) pre-session interface 2655c18ec02fSPetter Reinholdtsen * on which we will send the command 2656c18ec02fSPetter Reinholdtsen * param auth_cap [out] will be initialized to hold the Get Channel 2657c18ec02fSPetter Reinholdtsen * Authentication Capabilities return data on success. Its 2658c18ec02fSPetter Reinholdtsen * contents will be undefined on error. 2659c18ec02fSPetter Reinholdtsen * 2660c18ec02fSPetter Reinholdtsen * returns 0 on success 2661c18ec02fSPetter Reinholdtsen * non-zero if we were unable to contact the BMC, or we cannot 2662c18ec02fSPetter Reinholdtsen * get a successful response 2663c18ec02fSPetter Reinholdtsen * 2664c18ec02fSPetter Reinholdtsen */ 2665c18ec02fSPetter Reinholdtsen static int 2666c18ec02fSPetter Reinholdtsen ipmi_get_auth_capabilities_cmd( 2667c18ec02fSPetter Reinholdtsen struct ipmi_intf * intf, 2668c18ec02fSPetter Reinholdtsen struct get_channel_auth_cap_rsp * auth_cap) 2669c18ec02fSPetter Reinholdtsen { 2670c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp; 2671c18ec02fSPetter Reinholdtsen struct ipmi_rq req; 2672c18ec02fSPetter Reinholdtsen uint8_t msg_data[2]; 2673c18ec02fSPetter Reinholdtsen uint8_t backupBridgePossible; 2674c18ec02fSPetter Reinholdtsen 2675c18ec02fSPetter Reinholdtsen backupBridgePossible = bridgePossible; 2676c18ec02fSPetter Reinholdtsen 2677c18ec02fSPetter Reinholdtsen bridgePossible = 0; 2678c18ec02fSPetter Reinholdtsen 2679c18ec02fSPetter Reinholdtsen msg_data[0] = IPMI_LAN_CHANNEL_E | 0x80; // Ask for IPMI v2 data as well 2680c18ec02fSPetter Reinholdtsen msg_data[1] = intf->session->privlvl; 2681c18ec02fSPetter Reinholdtsen 2682c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req)); 2683c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_APP; // 0x06 2684c18ec02fSPetter Reinholdtsen req.msg.cmd = IPMI_GET_CHANNEL_AUTH_CAP; // 0x38 2685c18ec02fSPetter Reinholdtsen req.msg.data = msg_data; 2686c18ec02fSPetter Reinholdtsen req.msg.data_len = 2; 2687c18ec02fSPetter Reinholdtsen 2688c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req); 2689c18ec02fSPetter Reinholdtsen 2690c18ec02fSPetter Reinholdtsen if (rsp == NULL || rsp->ccode > 0) { 2691c18ec02fSPetter Reinholdtsen /* 2692c18ec02fSPetter Reinholdtsen * It's very possible that this failed because we asked for IPMI 2693c18ec02fSPetter Reinholdtsen * v2 data. Ask again, without requesting IPMI v2 data. 2694c18ec02fSPetter Reinholdtsen */ 2695c18ec02fSPetter Reinholdtsen msg_data[0] &= 0x7F; 2696c18ec02fSPetter Reinholdtsen 2697c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req); 2698c18ec02fSPetter Reinholdtsen 2699c18ec02fSPetter Reinholdtsen if (rsp == NULL) { 2700c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "Get Auth Capabilities error"); 2701c18ec02fSPetter Reinholdtsen return 1; 2702c18ec02fSPetter Reinholdtsen } 2703c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) { 2704c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "Get Auth Capabilities error: %s", 2705c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals)); 2706c18ec02fSPetter Reinholdtsen return 1; 2707c18ec02fSPetter Reinholdtsen } 2708c18ec02fSPetter Reinholdtsen } 2709c18ec02fSPetter Reinholdtsen 2710c18ec02fSPetter Reinholdtsen 2711c18ec02fSPetter Reinholdtsen memcpy(auth_cap, 2712c18ec02fSPetter Reinholdtsen rsp->data, 2713c18ec02fSPetter Reinholdtsen sizeof(struct get_channel_auth_cap_rsp)); 2714c18ec02fSPetter Reinholdtsen 2715c18ec02fSPetter Reinholdtsen bridgePossible = backupBridgePossible; 2716c18ec02fSPetter Reinholdtsen 2717c18ec02fSPetter Reinholdtsen return 0; 2718c18ec02fSPetter Reinholdtsen } 2719c18ec02fSPetter Reinholdtsen 2720c18ec02fSPetter Reinholdtsen 2721c18ec02fSPetter Reinholdtsen 2722c18ec02fSPetter Reinholdtsen static int 2723c18ec02fSPetter Reinholdtsen ipmi_close_session_cmd(struct ipmi_intf * intf) 2724c18ec02fSPetter Reinholdtsen { 2725c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp; 2726c18ec02fSPetter Reinholdtsen struct ipmi_rq req; 2727c18ec02fSPetter Reinholdtsen uint8_t msg_data[4]; 2728c18ec02fSPetter Reinholdtsen uint32_t bmc_session_lsbf; 2729c18ec02fSPetter Reinholdtsen uint8_t backupBridgePossible; 2730c18ec02fSPetter Reinholdtsen 2731c18ec02fSPetter Reinholdtsen if (intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE) 2732c18ec02fSPetter Reinholdtsen return -1; 2733c18ec02fSPetter Reinholdtsen 2734c18ec02fSPetter Reinholdtsen backupBridgePossible = bridgePossible; 2735c18ec02fSPetter Reinholdtsen 2736c18ec02fSPetter Reinholdtsen intf->target_addr = IPMI_BMC_SLAVE_ADDR; 2737c18ec02fSPetter Reinholdtsen bridgePossible = 0; 2738c18ec02fSPetter Reinholdtsen 2739c18ec02fSPetter Reinholdtsen bmc_session_lsbf = intf->session->v2_data.bmc_id; 2740c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN 2741c18ec02fSPetter Reinholdtsen bmc_session_lsbf = BSWAP_32(bmc_session_lsbf); 2742c18ec02fSPetter Reinholdtsen #endif 2743c18ec02fSPetter Reinholdtsen 2744c18ec02fSPetter Reinholdtsen memcpy(&msg_data, &bmc_session_lsbf, 4); 2745c18ec02fSPetter Reinholdtsen 2746c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req)); 2747c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_APP; 2748c18ec02fSPetter Reinholdtsen req.msg.cmd = 0x3c; 2749c18ec02fSPetter Reinholdtsen req.msg.data = msg_data; 2750c18ec02fSPetter Reinholdtsen req.msg.data_len = 4; 2751c18ec02fSPetter Reinholdtsen 2752c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req); 2753c18ec02fSPetter Reinholdtsen if (rsp == NULL) { 2754c18ec02fSPetter Reinholdtsen /* Looks like the session was closed */ 2755c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Close Session command failed"); 2756c18ec02fSPetter Reinholdtsen return -1; 2757c18ec02fSPetter Reinholdtsen } 2758c18ec02fSPetter Reinholdtsen if (verbose > 2) 2759c18ec02fSPetter Reinholdtsen printbuf(rsp->data, rsp->data_len, "close_session"); 2760c18ec02fSPetter Reinholdtsen 2761c18ec02fSPetter Reinholdtsen if (rsp->ccode == 0x87) { 2762c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Failed to Close Session: invalid " 2763c18ec02fSPetter Reinholdtsen "session ID %08lx", 2764c18ec02fSPetter Reinholdtsen (long)intf->session->v2_data.bmc_id); 2765c18ec02fSPetter Reinholdtsen return -1; 2766c18ec02fSPetter Reinholdtsen } 2767c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) { 2768c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Close Session command failed: %s", 2769c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals)); 2770c18ec02fSPetter Reinholdtsen return -1; 2771c18ec02fSPetter Reinholdtsen } 2772c18ec02fSPetter Reinholdtsen 2773c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Closed Session %08lx\n", 2774c18ec02fSPetter Reinholdtsen (long)intf->session->v2_data.bmc_id); 2775c18ec02fSPetter Reinholdtsen 2776c18ec02fSPetter Reinholdtsen bridgePossible = backupBridgePossible; 2777c18ec02fSPetter Reinholdtsen 2778c18ec02fSPetter Reinholdtsen return 0; 2779c18ec02fSPetter Reinholdtsen } 2780c18ec02fSPetter Reinholdtsen 2781c18ec02fSPetter Reinholdtsen 2782c18ec02fSPetter Reinholdtsen 2783c18ec02fSPetter Reinholdtsen /* 2784c18ec02fSPetter Reinholdtsen * ipmi_lanplus_open_session 2785c18ec02fSPetter Reinholdtsen * 2786c18ec02fSPetter Reinholdtsen * Build and send the open session command. See section 13.17 of the IPMI 2787c18ec02fSPetter Reinholdtsen * v2 specification for details. 2788c18ec02fSPetter Reinholdtsen */ 2789c18ec02fSPetter Reinholdtsen static int 2790c18ec02fSPetter Reinholdtsen ipmi_lanplus_open_session(struct ipmi_intf * intf) 2791c18ec02fSPetter Reinholdtsen { 2792c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload v2_payload; 2793c18ec02fSPetter Reinholdtsen struct ipmi_session * session = intf->session; 2794c18ec02fSPetter Reinholdtsen uint8_t * msg; 2795c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp; 2796176774cfSZdenek Styblik /* 0 = success, 1 = error, 2 = timeout */ 2797c18ec02fSPetter Reinholdtsen int rc = 0; 2798c18ec02fSPetter Reinholdtsen 2799c18ec02fSPetter Reinholdtsen 2800c18ec02fSPetter Reinholdtsen /* 2801c18ec02fSPetter Reinholdtsen * Build an Open Session Request Payload 2802c18ec02fSPetter Reinholdtsen */ 2803c18ec02fSPetter Reinholdtsen msg = (uint8_t*)malloc(IPMI_OPEN_SESSION_REQUEST_SIZE); 2804c18ec02fSPetter Reinholdtsen if (msg == NULL) { 2805c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure"); 2806176774cfSZdenek Styblik return 1; 2807c18ec02fSPetter Reinholdtsen } 2808c18ec02fSPetter Reinholdtsen 2809c18ec02fSPetter Reinholdtsen memset(msg, 0, IPMI_OPEN_SESSION_REQUEST_SIZE); 2810c18ec02fSPetter Reinholdtsen 2811c18ec02fSPetter Reinholdtsen msg[0] = 0; /* Message tag */ 2812c18ec02fSPetter Reinholdtsen if (ipmi_oem_active(intf, "intelplus") || session->privlvl != IPMI_SESSION_PRIV_ADMIN) 2813c18ec02fSPetter Reinholdtsen msg[1] = session->privlvl; 2814c18ec02fSPetter Reinholdtsen else 2815c18ec02fSPetter Reinholdtsen msg[1] = 0; /* Give us highest privlg level based on supported algorithms */ 2816c18ec02fSPetter Reinholdtsen msg[2] = 0; /* reserved */ 2817c18ec02fSPetter Reinholdtsen msg[3] = 0; /* reserved */ 2818c18ec02fSPetter Reinholdtsen 2819c18ec02fSPetter Reinholdtsen /* Choose our session ID for easy recognition in the packet dump */ 2820c18ec02fSPetter Reinholdtsen session->v2_data.console_id = 0xA0A2A3A4; 2821c18ec02fSPetter Reinholdtsen msg[4] = session->v2_data.console_id & 0xff; 2822c18ec02fSPetter Reinholdtsen msg[5] = (session->v2_data.console_id >> 8) & 0xff; 2823c18ec02fSPetter Reinholdtsen msg[6] = (session->v2_data.console_id >> 16) & 0xff; 2824c18ec02fSPetter Reinholdtsen msg[7] = (session->v2_data.console_id >> 24) & 0xff; 2825c18ec02fSPetter Reinholdtsen 2826c18ec02fSPetter Reinholdtsen 2827c18ec02fSPetter Reinholdtsen if (lanplus_get_requested_ciphers(session->cipher_suite_id, 2828c18ec02fSPetter Reinholdtsen &(session->v2_data.requested_auth_alg), 2829c18ec02fSPetter Reinholdtsen &(session->v2_data.requested_integrity_alg), 2830c18ec02fSPetter Reinholdtsen &(session->v2_data.requested_crypt_alg))) 2831c18ec02fSPetter Reinholdtsen { 2832c18ec02fSPetter Reinholdtsen lprintf(LOG_WARNING, "Unsupported cipher suite ID : %d\n", 2833c18ec02fSPetter Reinholdtsen session->cipher_suite_id); 2834c18ec02fSPetter Reinholdtsen free(msg); 2835c18ec02fSPetter Reinholdtsen msg = NULL; 2836176774cfSZdenek Styblik return 1; 2837c18ec02fSPetter Reinholdtsen } 2838c18ec02fSPetter Reinholdtsen 2839c18ec02fSPetter Reinholdtsen 2840c18ec02fSPetter Reinholdtsen /* 2841c18ec02fSPetter Reinholdtsen * Authentication payload 2842c18ec02fSPetter Reinholdtsen */ 2843c18ec02fSPetter Reinholdtsen msg[8] = 0; /* specifies authentication payload */ 2844c18ec02fSPetter Reinholdtsen msg[9] = 0; /* reserved */ 2845c18ec02fSPetter Reinholdtsen msg[10] = 0; /* reserved */ 2846c18ec02fSPetter Reinholdtsen msg[11] = 8; /* payload length */ 2847c18ec02fSPetter Reinholdtsen msg[12] = session->v2_data.requested_auth_alg; 2848c18ec02fSPetter Reinholdtsen msg[13] = 0; /* reserved */ 2849c18ec02fSPetter Reinholdtsen msg[14] = 0; /* reserved */ 2850c18ec02fSPetter Reinholdtsen msg[15] = 0; /* reserved */ 2851c18ec02fSPetter Reinholdtsen 2852c18ec02fSPetter Reinholdtsen /* 2853c18ec02fSPetter Reinholdtsen * Integrity payload 2854c18ec02fSPetter Reinholdtsen */ 2855c18ec02fSPetter Reinholdtsen msg[16] = 1; /* specifies integrity payload */ 2856c18ec02fSPetter Reinholdtsen msg[17] = 0; /* reserved */ 2857c18ec02fSPetter Reinholdtsen msg[18] = 0; /* reserved */ 2858c18ec02fSPetter Reinholdtsen msg[19] = 8; /* payload length */ 2859c18ec02fSPetter Reinholdtsen msg[20] = session->v2_data.requested_integrity_alg; 2860c18ec02fSPetter Reinholdtsen msg[21] = 0; /* reserved */ 2861c18ec02fSPetter Reinholdtsen msg[22] = 0; /* reserved */ 2862c18ec02fSPetter Reinholdtsen msg[23] = 0; /* reserved */ 2863c18ec02fSPetter Reinholdtsen 2864c18ec02fSPetter Reinholdtsen /* 2865c18ec02fSPetter Reinholdtsen * Confidentiality/Encryption payload 2866c18ec02fSPetter Reinholdtsen */ 2867c18ec02fSPetter Reinholdtsen msg[24] = 2; /* specifies confidentiality payload */ 2868c18ec02fSPetter Reinholdtsen msg[25] = 0; /* reserved */ 2869c18ec02fSPetter Reinholdtsen msg[26] = 0; /* reserved */ 2870c18ec02fSPetter Reinholdtsen msg[27] = 8; /* payload length */ 2871c18ec02fSPetter Reinholdtsen msg[28] = session->v2_data.requested_crypt_alg; 2872c18ec02fSPetter Reinholdtsen msg[29] = 0; /* reserved */ 2873c18ec02fSPetter Reinholdtsen msg[30] = 0; /* reserved */ 2874c18ec02fSPetter Reinholdtsen msg[31] = 0; /* reserved */ 2875c18ec02fSPetter Reinholdtsen 2876c18ec02fSPetter Reinholdtsen 2877c18ec02fSPetter Reinholdtsen v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST; 2878c18ec02fSPetter Reinholdtsen v2_payload.payload_length = IPMI_OPEN_SESSION_REQUEST_SIZE; 2879c18ec02fSPetter Reinholdtsen v2_payload.payload.open_session_request.request = msg; 2880c18ec02fSPetter Reinholdtsen 2881c18ec02fSPetter Reinholdtsen rsp = ipmi_lanplus_send_payload(intf, &v2_payload); 2882c18ec02fSPetter Reinholdtsen 2883c18ec02fSPetter Reinholdtsen free(msg); 2884c18ec02fSPetter Reinholdtsen msg = NULL; 2885176774cfSZdenek Styblik if (rsp == NULL ) { 2886176774cfSZdenek Styblik lprintf(LOG_DEBUG, "Timeout in open session response message."); 2887176774cfSZdenek Styblik return 2; 2888176774cfSZdenek Styblik } 28894f096777SZdenek Styblik if (verbose) 28904f096777SZdenek Styblik lanplus_dump_open_session_response(rsp); 28914f096777SZdenek Styblik 2892c18ec02fSPetter Reinholdtsen if (rsp->payload.open_session_response.rakp_return_code != 2893c18ec02fSPetter Reinholdtsen IPMI_RAKP_STATUS_NO_ERRORS) 2894c18ec02fSPetter Reinholdtsen { 2895c18ec02fSPetter Reinholdtsen lprintf(LOG_WARNING, "Error in open session response message : %s\n", 2896c18ec02fSPetter Reinholdtsen val2str(rsp->payload.open_session_response.rakp_return_code, 2897c18ec02fSPetter Reinholdtsen ipmi_rakp_return_codes)); 2898176774cfSZdenek Styblik return 1; 2899c18ec02fSPetter Reinholdtsen } 2900c18ec02fSPetter Reinholdtsen else 2901c18ec02fSPetter Reinholdtsen { 2902c18ec02fSPetter Reinholdtsen if (rsp->payload.open_session_response.console_id != 2903c18ec02fSPetter Reinholdtsen session->v2_data.console_id) { 2904c18ec02fSPetter Reinholdtsen lprintf(LOG_WARNING, "Warning: Console session ID is not " 2905c18ec02fSPetter Reinholdtsen "what we requested"); 2906c18ec02fSPetter Reinholdtsen } 2907c18ec02fSPetter Reinholdtsen 2908c18ec02fSPetter Reinholdtsen session->v2_data.max_priv_level = 2909c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.max_priv_level; 2910c18ec02fSPetter Reinholdtsen session->v2_data.bmc_id = 2911c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.bmc_id; 2912c18ec02fSPetter Reinholdtsen session->v2_data.auth_alg = 2913c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.auth_alg; 2914c18ec02fSPetter Reinholdtsen session->v2_data.integrity_alg = 2915c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.integrity_alg; 2916c18ec02fSPetter Reinholdtsen session->v2_data.crypt_alg = 2917c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.crypt_alg; 2918c18ec02fSPetter Reinholdtsen session->v2_data.session_state = 2919c18ec02fSPetter Reinholdtsen LANPLUS_STATE_OPEN_SESSION_RECEIEVED; 2920c18ec02fSPetter Reinholdtsen 2921c18ec02fSPetter Reinholdtsen 2922c18ec02fSPetter Reinholdtsen /* 2923c18ec02fSPetter Reinholdtsen * Verify that we have agreed on a cipher suite 2924c18ec02fSPetter Reinholdtsen */ 2925c18ec02fSPetter Reinholdtsen if (rsp->payload.open_session_response.auth_alg != 2926c18ec02fSPetter Reinholdtsen session->v2_data.requested_auth_alg) 2927c18ec02fSPetter Reinholdtsen { 2928c18ec02fSPetter Reinholdtsen lprintf(LOG_WARNING, "Authentication algorithm 0x%02x is " 2929c18ec02fSPetter Reinholdtsen "not what we requested 0x%02x\n", 2930c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.auth_alg, 2931c18ec02fSPetter Reinholdtsen session->v2_data.requested_auth_alg); 2932176774cfSZdenek Styblik rc = 1; 2933c18ec02fSPetter Reinholdtsen } 2934c18ec02fSPetter Reinholdtsen else if (rsp->payload.open_session_response.integrity_alg != 2935c18ec02fSPetter Reinholdtsen session->v2_data.requested_integrity_alg) 2936c18ec02fSPetter Reinholdtsen { 2937c18ec02fSPetter Reinholdtsen lprintf(LOG_WARNING, "Integrity algorithm 0x%02x is " 2938c18ec02fSPetter Reinholdtsen "not what we requested 0x%02x\n", 2939c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.integrity_alg, 2940c18ec02fSPetter Reinholdtsen session->v2_data.requested_integrity_alg); 2941176774cfSZdenek Styblik rc = 1; 2942c18ec02fSPetter Reinholdtsen } 2943c18ec02fSPetter Reinholdtsen else if (rsp->payload.open_session_response.crypt_alg != 2944c18ec02fSPetter Reinholdtsen session->v2_data.requested_crypt_alg) 2945c18ec02fSPetter Reinholdtsen { 2946c18ec02fSPetter Reinholdtsen lprintf(LOG_WARNING, "Encryption algorithm 0x%02x is " 2947c18ec02fSPetter Reinholdtsen "not what we requested 0x%02x\n", 2948c18ec02fSPetter Reinholdtsen rsp->payload.open_session_response.crypt_alg, 2949c18ec02fSPetter Reinholdtsen session->v2_data.requested_crypt_alg); 2950176774cfSZdenek Styblik rc = 1; 2951c18ec02fSPetter Reinholdtsen } 2952c18ec02fSPetter Reinholdtsen 2953c18ec02fSPetter Reinholdtsen } 2954c18ec02fSPetter Reinholdtsen 2955c18ec02fSPetter Reinholdtsen return rc; 2956c18ec02fSPetter Reinholdtsen } 2957c18ec02fSPetter Reinholdtsen 2958c18ec02fSPetter Reinholdtsen 2959c18ec02fSPetter Reinholdtsen 2960c18ec02fSPetter Reinholdtsen /* 2961c18ec02fSPetter Reinholdtsen * ipmi_lanplus_rakp1 2962c18ec02fSPetter Reinholdtsen * 2963c18ec02fSPetter Reinholdtsen * Build and send the RAKP 1 message as part of the IPMI v2 / RMCP+ session 2964c18ec02fSPetter Reinholdtsen * negotiation protocol. We also read and validate the RAKP 2 message received 2965c18ec02fSPetter Reinholdtsen * from the BMC, here. See section 13.20 of the IPMI v2 specification for 2966c18ec02fSPetter Reinholdtsen * details. 2967c18ec02fSPetter Reinholdtsen * 2968c18ec02fSPetter Reinholdtsen * returns 0 on success 2969c18ec02fSPetter Reinholdtsen * 1 on failure 2970c18ec02fSPetter Reinholdtsen * 2971c18ec02fSPetter Reinholdtsen * Note that failure is only indicated if we have an internal error of 2972c18ec02fSPetter Reinholdtsen * some kind. If we actually get a RAKP 2 message in response to our 2973c18ec02fSPetter Reinholdtsen * RAKP 1 message, any errors will be stored in 2974c18ec02fSPetter Reinholdtsen * session->v2_data.rakp2_return_code and sent to the BMC in the RAKP 2975c18ec02fSPetter Reinholdtsen * 3 message. 2976c18ec02fSPetter Reinholdtsen */ 2977c18ec02fSPetter Reinholdtsen static int 2978c18ec02fSPetter Reinholdtsen ipmi_lanplus_rakp1(struct ipmi_intf * intf) 2979c18ec02fSPetter Reinholdtsen { 2980c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload v2_payload; 2981c18ec02fSPetter Reinholdtsen struct ipmi_session * session = intf->session; 2982c18ec02fSPetter Reinholdtsen uint8_t * msg; 2983c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp; 2984176774cfSZdenek Styblik int rc = 0; /* 0 = success, 1 = error, 2 = timeout */ 2985c18ec02fSPetter Reinholdtsen 2986c18ec02fSPetter Reinholdtsen /* 2987c18ec02fSPetter Reinholdtsen * Build a RAKP 1 message 2988c18ec02fSPetter Reinholdtsen */ 2989c18ec02fSPetter Reinholdtsen msg = (uint8_t*)malloc(IPMI_RAKP1_MESSAGE_SIZE); 2990c18ec02fSPetter Reinholdtsen if (msg == NULL) { 2991c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure"); 2992c18ec02fSPetter Reinholdtsen return 1; 2993c18ec02fSPetter Reinholdtsen } 2994c18ec02fSPetter Reinholdtsen memset(msg, 0, IPMI_RAKP1_MESSAGE_SIZE); 2995c18ec02fSPetter Reinholdtsen 2996c18ec02fSPetter Reinholdtsen 2997c18ec02fSPetter Reinholdtsen msg[0] = 0; /* Message tag */ 2998c18ec02fSPetter Reinholdtsen 2999c18ec02fSPetter Reinholdtsen msg[1] = 0; /* reserved */ 3000c18ec02fSPetter Reinholdtsen msg[2] = 0; /* reserved */ 3001c18ec02fSPetter Reinholdtsen msg[3] = 0; /* reserved */ 3002c18ec02fSPetter Reinholdtsen 3003c18ec02fSPetter Reinholdtsen /* BMC session ID */ 3004c18ec02fSPetter Reinholdtsen msg[4] = session->v2_data.bmc_id & 0xff; 3005c18ec02fSPetter Reinholdtsen msg[5] = (session->v2_data.bmc_id >> 8) & 0xff; 3006c18ec02fSPetter Reinholdtsen msg[6] = (session->v2_data.bmc_id >> 16) & 0xff; 3007c18ec02fSPetter Reinholdtsen msg[7] = (session->v2_data.bmc_id >> 24) & 0xff; 3008c18ec02fSPetter Reinholdtsen 3009c18ec02fSPetter Reinholdtsen 3010c18ec02fSPetter Reinholdtsen /* We need a 16 byte random number */ 3011c18ec02fSPetter Reinholdtsen if (lanplus_rand(session->v2_data.console_rand, 16)) 3012c18ec02fSPetter Reinholdtsen { 3013c18ec02fSPetter Reinholdtsen // ERROR; 3014c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ERROR generating random number " 3015c18ec02fSPetter Reinholdtsen "in ipmi_lanplus_rakp1"); 3016c18ec02fSPetter Reinholdtsen free(msg); 3017c18ec02fSPetter Reinholdtsen msg = NULL; 3018c18ec02fSPetter Reinholdtsen return 1; 3019c18ec02fSPetter Reinholdtsen } 3020c18ec02fSPetter Reinholdtsen memcpy(msg + 8, session->v2_data.console_rand, 16); 3021c18ec02fSPetter Reinholdtsen #if WORDS_BIGENDIAN 3022c18ec02fSPetter Reinholdtsen lanplus_swap(msg + 8, 16); 3023c18ec02fSPetter Reinholdtsen #endif 3024c18ec02fSPetter Reinholdtsen 3025c18ec02fSPetter Reinholdtsen if (verbose > 1) 3026c18ec02fSPetter Reinholdtsen printbuf(session->v2_data.console_rand, 16, 3027c18ec02fSPetter Reinholdtsen ">> Console generated random number"); 3028c18ec02fSPetter Reinholdtsen 3029c18ec02fSPetter Reinholdtsen 3030c18ec02fSPetter Reinholdtsen /* 3031c18ec02fSPetter Reinholdtsen * Requested maximum privilege level. 3032c18ec02fSPetter Reinholdtsen */ 3033c18ec02fSPetter Reinholdtsen msg[24] = session->privlvl | session->v2_data.lookupbit; 3034c18ec02fSPetter Reinholdtsen session->v2_data.requested_role = msg[24]; 3035c18ec02fSPetter Reinholdtsen msg[25] = 0; /* reserved */ 3036c18ec02fSPetter Reinholdtsen msg[26] = 0; /* reserved */ 3037c18ec02fSPetter Reinholdtsen 3038c18ec02fSPetter Reinholdtsen 3039c18ec02fSPetter Reinholdtsen /* Username specification */ 3040c18ec02fSPetter Reinholdtsen msg[27] = strlen((const char *)session->username); 3041c18ec02fSPetter Reinholdtsen if (msg[27] > IPMI_MAX_USER_NAME_LENGTH) 3042c18ec02fSPetter Reinholdtsen { 3043c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ERROR: user name too long. " 3044c18ec02fSPetter Reinholdtsen "(Exceeds %d characters)", 3045c18ec02fSPetter Reinholdtsen IPMI_MAX_USER_NAME_LENGTH); 3046c18ec02fSPetter Reinholdtsen free(msg); 3047c18ec02fSPetter Reinholdtsen msg = NULL; 3048c18ec02fSPetter Reinholdtsen return 1; 3049c18ec02fSPetter Reinholdtsen } 3050c18ec02fSPetter Reinholdtsen memcpy(msg + 28, session->username, msg[27]); 3051c18ec02fSPetter Reinholdtsen 3052c18ec02fSPetter Reinholdtsen v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_1; 3053f56d740dSZdenek Styblik if (ipmi_oem_active(intf, "i82571spt")) { 3054f56d740dSZdenek Styblik /* 3055f56d740dSZdenek Styblik * The IPMI v2.0 spec hints on that all user name bytes 3056f56d740dSZdenek Styblik * must be occupied (29:44). The Intel 82571 GbE refuses 3057f56d740dSZdenek Styblik * to establish a session if this field is shorter. 3058f56d740dSZdenek Styblik */ 3059f56d740dSZdenek Styblik v2_payload.payload_length = IPMI_RAKP1_MESSAGE_SIZE; 3060f56d740dSZdenek Styblik } else { 3061c18ec02fSPetter Reinholdtsen v2_payload.payload_length = 3062c18ec02fSPetter Reinholdtsen IPMI_RAKP1_MESSAGE_SIZE - (16 - msg[27]); 3063f56d740dSZdenek Styblik } 3064c18ec02fSPetter Reinholdtsen v2_payload.payload.rakp_1_message.message = msg; 3065c18ec02fSPetter Reinholdtsen 3066c18ec02fSPetter Reinholdtsen rsp = ipmi_lanplus_send_payload(intf, &v2_payload); 3067c18ec02fSPetter Reinholdtsen 3068c18ec02fSPetter Reinholdtsen free(msg); 3069c18ec02fSPetter Reinholdtsen msg = NULL; 3070c18ec02fSPetter Reinholdtsen 3071c18ec02fSPetter Reinholdtsen if (rsp == NULL) 3072c18ec02fSPetter Reinholdtsen { 3073176774cfSZdenek Styblik lprintf(LOG_WARNING, "> Error: no response from RAKP 1 message"); 3074176774cfSZdenek Styblik return 2; 3075c18ec02fSPetter Reinholdtsen } 3076c18ec02fSPetter Reinholdtsen 3077c18ec02fSPetter Reinholdtsen session->v2_data.session_state = LANPLUS_STATE_RAKP_2_RECEIVED; 3078c18ec02fSPetter Reinholdtsen 3079c18ec02fSPetter Reinholdtsen if (verbose) 3080c18ec02fSPetter Reinholdtsen lanplus_dump_rakp2_message(rsp, session->v2_data.auth_alg); 3081c18ec02fSPetter Reinholdtsen 3082c18ec02fSPetter Reinholdtsen 3083c18ec02fSPetter Reinholdtsen 3084c18ec02fSPetter Reinholdtsen if (rsp->payload.rakp2_message.rakp_return_code != IPMI_RAKP_STATUS_NO_ERRORS) 3085c18ec02fSPetter Reinholdtsen { 3086c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "RAKP 2 message indicates an error : %s", 3087c18ec02fSPetter Reinholdtsen val2str(rsp->payload.rakp2_message.rakp_return_code, 3088c18ec02fSPetter Reinholdtsen ipmi_rakp_return_codes)); 3089c18ec02fSPetter Reinholdtsen rc = 1; 3090c18ec02fSPetter Reinholdtsen } 3091c18ec02fSPetter Reinholdtsen 3092c18ec02fSPetter Reinholdtsen else 3093c18ec02fSPetter Reinholdtsen { 3094c18ec02fSPetter Reinholdtsen memcpy(session->v2_data.bmc_rand, rsp->payload.rakp2_message.bmc_rand, 16); 3095c18ec02fSPetter Reinholdtsen memcpy(session->v2_data.bmc_guid, rsp->payload.rakp2_message.bmc_guid, 16); 3096c18ec02fSPetter Reinholdtsen 3097c18ec02fSPetter Reinholdtsen if (verbose > 2) 3098c18ec02fSPetter Reinholdtsen printbuf(session->v2_data.bmc_rand, 16, "bmc_rand"); 3099c18ec02fSPetter Reinholdtsen 3100c18ec02fSPetter Reinholdtsen /* 3101c18ec02fSPetter Reinholdtsen * It is at this point that we have to decode the random number and determine 3102c18ec02fSPetter Reinholdtsen * whether the BMC has authenticated. 3103c18ec02fSPetter Reinholdtsen */ 3104c18ec02fSPetter Reinholdtsen if (! lanplus_rakp2_hmac_matches(session, 3105c18ec02fSPetter Reinholdtsen rsp->payload.rakp2_message.key_exchange_auth_code, 3106c18ec02fSPetter Reinholdtsen intf)) 3107c18ec02fSPetter Reinholdtsen { 3108c18ec02fSPetter Reinholdtsen /* Error */ 3109c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "> RAKP 2 HMAC is invalid"); 3110c18ec02fSPetter Reinholdtsen session->v2_data.rakp2_return_code = IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE; 3111c18ec02fSPetter Reinholdtsen rc = 1; 3112c18ec02fSPetter Reinholdtsen } 3113c18ec02fSPetter Reinholdtsen else 3114c18ec02fSPetter Reinholdtsen { 3115c18ec02fSPetter Reinholdtsen /* Success */ 3116c18ec02fSPetter Reinholdtsen session->v2_data.rakp2_return_code = IPMI_RAKP_STATUS_NO_ERRORS; 3117c18ec02fSPetter Reinholdtsen } 3118c18ec02fSPetter Reinholdtsen } 3119c18ec02fSPetter Reinholdtsen 3120c18ec02fSPetter Reinholdtsen return rc; 3121c18ec02fSPetter Reinholdtsen } 3122c18ec02fSPetter Reinholdtsen 3123c18ec02fSPetter Reinholdtsen 3124c18ec02fSPetter Reinholdtsen 3125c18ec02fSPetter Reinholdtsen /* 3126c18ec02fSPetter Reinholdtsen * ipmi_lanplus_rakp3 3127c18ec02fSPetter Reinholdtsen * 3128c18ec02fSPetter Reinholdtsen * Build and send the RAKP 3 message as part of the IPMI v2 / RMCP+ session 3129c18ec02fSPetter Reinholdtsen * negotiation protocol. We also read and validate the RAKP 4 message received 3130c18ec02fSPetter Reinholdtsen * from the BMC, here. See section 13.20 of the IPMI v2 specification for 3131c18ec02fSPetter Reinholdtsen * details. 3132c18ec02fSPetter Reinholdtsen * 3133c18ec02fSPetter Reinholdtsen * If the RAKP 2 return code is not IPMI_RAKP_STATUS_NO_ERRORS, we will 3134c18ec02fSPetter Reinholdtsen * exit with an error code immediately after sendint the RAKP 3 message. 3135c18ec02fSPetter Reinholdtsen * 3136c18ec02fSPetter Reinholdtsen * param intf is the intf that holds all the state we are concerned with 3137c18ec02fSPetter Reinholdtsen * 3138c18ec02fSPetter Reinholdtsen * returns 0 on success 3139c18ec02fSPetter Reinholdtsen * 1 on failure 3140c18ec02fSPetter Reinholdtsen */ 3141c18ec02fSPetter Reinholdtsen static int 3142c18ec02fSPetter Reinholdtsen ipmi_lanplus_rakp3(struct ipmi_intf * intf) 3143c18ec02fSPetter Reinholdtsen { 3144c18ec02fSPetter Reinholdtsen struct ipmi_v2_payload v2_payload; 3145c18ec02fSPetter Reinholdtsen struct ipmi_session * session = intf->session; 3146c18ec02fSPetter Reinholdtsen uint8_t * msg; 3147c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp; 3148c18ec02fSPetter Reinholdtsen 3149c18ec02fSPetter Reinholdtsen assert(session->v2_data.session_state == LANPLUS_STATE_RAKP_2_RECEIVED); 3150c18ec02fSPetter Reinholdtsen 3151c18ec02fSPetter Reinholdtsen /* 3152c18ec02fSPetter Reinholdtsen * Build a RAKP 3 message 3153c18ec02fSPetter Reinholdtsen */ 3154c18ec02fSPetter Reinholdtsen msg = (uint8_t*)malloc(IPMI_RAKP3_MESSAGE_MAX_SIZE); 3155c18ec02fSPetter Reinholdtsen if (msg == NULL) { 3156c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure"); 3157c18ec02fSPetter Reinholdtsen return 1; 3158c18ec02fSPetter Reinholdtsen } 3159c18ec02fSPetter Reinholdtsen memset(msg, 0, IPMI_RAKP3_MESSAGE_MAX_SIZE); 3160c18ec02fSPetter Reinholdtsen 3161c18ec02fSPetter Reinholdtsen 3162c18ec02fSPetter Reinholdtsen msg[0] = 0; /* Message tag */ 3163c18ec02fSPetter Reinholdtsen msg[1] = session->v2_data.rakp2_return_code; 3164c18ec02fSPetter Reinholdtsen 3165c18ec02fSPetter Reinholdtsen msg[2] = 0; /* reserved */ 3166c18ec02fSPetter Reinholdtsen msg[3] = 0; /* reserved */ 3167c18ec02fSPetter Reinholdtsen 3168c18ec02fSPetter Reinholdtsen /* BMC session ID */ 3169c18ec02fSPetter Reinholdtsen msg[4] = session->v2_data.bmc_id & 0xff; 3170c18ec02fSPetter Reinholdtsen msg[5] = (session->v2_data.bmc_id >> 8) & 0xff; 3171c18ec02fSPetter Reinholdtsen msg[6] = (session->v2_data.bmc_id >> 16) & 0xff; 3172c18ec02fSPetter Reinholdtsen msg[7] = (session->v2_data.bmc_id >> 24) & 0xff; 3173c18ec02fSPetter Reinholdtsen 3174c18ec02fSPetter Reinholdtsen v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_3; 3175c18ec02fSPetter Reinholdtsen v2_payload.payload_length = 8; 3176c18ec02fSPetter Reinholdtsen v2_payload.payload.rakp_3_message.message = msg; 3177c18ec02fSPetter Reinholdtsen 3178c18ec02fSPetter Reinholdtsen /* 3179c18ec02fSPetter Reinholdtsen * If the rakp2 return code indicates and error, we don't have to 3180c18ec02fSPetter Reinholdtsen * generate an authcode or session integrity key. In that case, we 3181c18ec02fSPetter Reinholdtsen * are simply sending a RAKP 3 message to indicate to the BMC that the 3182c18ec02fSPetter Reinholdtsen * RAKP 2 message caused an error. 3183c18ec02fSPetter Reinholdtsen */ 3184c18ec02fSPetter Reinholdtsen if (session->v2_data.rakp2_return_code == IPMI_RAKP_STATUS_NO_ERRORS) 3185c18ec02fSPetter Reinholdtsen { 3186c18ec02fSPetter Reinholdtsen uint32_t auth_length; 3187c18ec02fSPetter Reinholdtsen 3188c18ec02fSPetter Reinholdtsen if (lanplus_generate_rakp3_authcode(msg + 8, session, &auth_length, intf)) 3189c18ec02fSPetter Reinholdtsen { 3190c18ec02fSPetter Reinholdtsen /* Error */ 3191c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "> Error generating RAKP 3 authcode"); 3192c18ec02fSPetter Reinholdtsen free(msg); 3193c18ec02fSPetter Reinholdtsen msg = NULL; 3194c18ec02fSPetter Reinholdtsen return 1; 3195c18ec02fSPetter Reinholdtsen } 3196c18ec02fSPetter Reinholdtsen else 3197c18ec02fSPetter Reinholdtsen { 3198c18ec02fSPetter Reinholdtsen /* Success */ 3199c18ec02fSPetter Reinholdtsen v2_payload.payload_length += auth_length; 3200c18ec02fSPetter Reinholdtsen } 3201c18ec02fSPetter Reinholdtsen 3202c18ec02fSPetter Reinholdtsen /* Generate our Session Integrity Key, K1, and K2 */ 3203c18ec02fSPetter Reinholdtsen if (lanplus_generate_sik(session, intf)) 3204c18ec02fSPetter Reinholdtsen { 3205c18ec02fSPetter Reinholdtsen /* Error */ 3206c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "> Error generating session integrity key"); 3207c18ec02fSPetter Reinholdtsen free(msg); 3208c18ec02fSPetter Reinholdtsen msg = NULL; 3209c18ec02fSPetter Reinholdtsen return 1; 3210c18ec02fSPetter Reinholdtsen } 3211c18ec02fSPetter Reinholdtsen else if (lanplus_generate_k1(session)) 3212c18ec02fSPetter Reinholdtsen { 3213c18ec02fSPetter Reinholdtsen /* Error */ 3214c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "> Error generating K1 key"); 3215c18ec02fSPetter Reinholdtsen free(msg); 3216c18ec02fSPetter Reinholdtsen msg = NULL; 3217c18ec02fSPetter Reinholdtsen return 1; 3218c18ec02fSPetter Reinholdtsen } 3219c18ec02fSPetter Reinholdtsen else if (lanplus_generate_k2(session)) 3220c18ec02fSPetter Reinholdtsen { 3221c18ec02fSPetter Reinholdtsen /* Error */ 3222c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "> Error generating K1 key"); 3223c18ec02fSPetter Reinholdtsen free(msg); 3224c18ec02fSPetter Reinholdtsen msg = NULL; 3225c18ec02fSPetter Reinholdtsen return 1; 3226c18ec02fSPetter Reinholdtsen } 3227c18ec02fSPetter Reinholdtsen } 3228c18ec02fSPetter Reinholdtsen 3229c18ec02fSPetter Reinholdtsen 3230c18ec02fSPetter Reinholdtsen rsp = ipmi_lanplus_send_payload(intf, &v2_payload); 3231c18ec02fSPetter Reinholdtsen 3232c18ec02fSPetter Reinholdtsen free(msg); 3233c18ec02fSPetter Reinholdtsen msg = NULL; 3234c18ec02fSPetter Reinholdtsen 3235c18ec02fSPetter Reinholdtsen if (session->v2_data.rakp2_return_code != IPMI_RAKP_STATUS_NO_ERRORS) 3236c18ec02fSPetter Reinholdtsen { 3237c18ec02fSPetter Reinholdtsen /* 3238c18ec02fSPetter Reinholdtsen * If the previous RAKP 2 message received was deemed erroneous, 3239c18ec02fSPetter Reinholdtsen * we have nothing else to do here. We only sent the RAKP 3 message 3240c18ec02fSPetter Reinholdtsen * to indicate to the BMC that the RAKP 2 message failed. 3241c18ec02fSPetter Reinholdtsen */ 3242c18ec02fSPetter Reinholdtsen return 1; 3243c18ec02fSPetter Reinholdtsen } 3244c18ec02fSPetter Reinholdtsen else if (rsp == NULL) 3245c18ec02fSPetter Reinholdtsen { 3246176774cfSZdenek Styblik lprintf(LOG_WARNING, "> Error: no response from RAKP 3 message"); 3247176774cfSZdenek Styblik return 2; 3248c18ec02fSPetter Reinholdtsen } 3249c18ec02fSPetter Reinholdtsen 3250c18ec02fSPetter Reinholdtsen 3251c18ec02fSPetter Reinholdtsen /* 3252c18ec02fSPetter Reinholdtsen * We have a RAKP 4 message to chew on. 3253c18ec02fSPetter Reinholdtsen */ 3254c18ec02fSPetter Reinholdtsen if (verbose) 3255c18ec02fSPetter Reinholdtsen lanplus_dump_rakp4_message(rsp, session->v2_data.auth_alg); 3256c18ec02fSPetter Reinholdtsen 3257c18ec02fSPetter Reinholdtsen 3258c18ec02fSPetter Reinholdtsen if (rsp->payload.open_session_response.rakp_return_code != IPMI_RAKP_STATUS_NO_ERRORS) 3259c18ec02fSPetter Reinholdtsen { 3260c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "RAKP 4 message indicates an error : %s", 3261c18ec02fSPetter Reinholdtsen val2str(rsp->payload.rakp4_message.rakp_return_code, 3262c18ec02fSPetter Reinholdtsen ipmi_rakp_return_codes)); 3263c18ec02fSPetter Reinholdtsen return 1; 3264c18ec02fSPetter Reinholdtsen } 3265c18ec02fSPetter Reinholdtsen 3266c18ec02fSPetter Reinholdtsen else 3267c18ec02fSPetter Reinholdtsen { 3268c18ec02fSPetter Reinholdtsen /* Validate the authcode */ 3269c18ec02fSPetter Reinholdtsen if (lanplus_rakp4_hmac_matches(session, 3270c18ec02fSPetter Reinholdtsen rsp->payload.rakp4_message.integrity_check_value, 3271c18ec02fSPetter Reinholdtsen intf)) 3272c18ec02fSPetter Reinholdtsen { 3273c18ec02fSPetter Reinholdtsen /* Success */ 3274c18ec02fSPetter Reinholdtsen session->v2_data.session_state = LANPLUS_STATE_ACTIVE; 3275c18ec02fSPetter Reinholdtsen } 3276c18ec02fSPetter Reinholdtsen else 3277c18ec02fSPetter Reinholdtsen { 3278c18ec02fSPetter Reinholdtsen /* Error */ 3279c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "> RAKP 4 message has invalid integrity check value"); 3280c18ec02fSPetter Reinholdtsen return 1; 3281c18ec02fSPetter Reinholdtsen } 3282c18ec02fSPetter Reinholdtsen } 3283c18ec02fSPetter Reinholdtsen 3284c18ec02fSPetter Reinholdtsen intf->abort = 0; 3285c18ec02fSPetter Reinholdtsen return 0; 3286c18ec02fSPetter Reinholdtsen } 3287c18ec02fSPetter Reinholdtsen 3288c18ec02fSPetter Reinholdtsen 3289c18ec02fSPetter Reinholdtsen 3290c18ec02fSPetter Reinholdtsen /** 3291c18ec02fSPetter Reinholdtsen * ipmi_lan_close 3292c18ec02fSPetter Reinholdtsen */ 3293c18ec02fSPetter Reinholdtsen void 3294c18ec02fSPetter Reinholdtsen ipmi_lanplus_close(struct ipmi_intf * intf) 3295c18ec02fSPetter Reinholdtsen { 3296c18ec02fSPetter Reinholdtsen if (!intf->abort) 3297c18ec02fSPetter Reinholdtsen ipmi_close_session_cmd(intf); 3298c18ec02fSPetter Reinholdtsen 3299c18ec02fSPetter Reinholdtsen if (intf->fd >= 0) 3300c18ec02fSPetter Reinholdtsen close(intf->fd); 3301c18ec02fSPetter Reinholdtsen 3302c18ec02fSPetter Reinholdtsen ipmi_req_clear_entries(); 3303deb9a4edSZdenek Styblik ipmi_intf_session_cleanup(intf); 3304c18ec02fSPetter Reinholdtsen intf->session = NULL; 3305c18ec02fSPetter Reinholdtsen intf->opened = 0; 3306c18ec02fSPetter Reinholdtsen intf->manufacturer_id = IPMI_OEM_UNKNOWN; 3307c18ec02fSPetter Reinholdtsen intf = NULL; 3308c18ec02fSPetter Reinholdtsen } 3309c18ec02fSPetter Reinholdtsen 3310c18ec02fSPetter Reinholdtsen 3311c18ec02fSPetter Reinholdtsen 3312c18ec02fSPetter Reinholdtsen static int 3313c18ec02fSPetter Reinholdtsen ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf) 3314c18ec02fSPetter Reinholdtsen { 3315c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp; 3316c18ec02fSPetter Reinholdtsen struct ipmi_rq req; 3317c18ec02fSPetter Reinholdtsen uint8_t backupBridgePossible; 3318c18ec02fSPetter Reinholdtsen uint8_t privlvl = intf->session->privlvl; 3319c18ec02fSPetter Reinholdtsen 3320c18ec02fSPetter Reinholdtsen if (privlvl <= IPMI_SESSION_PRIV_USER) 3321c18ec02fSPetter Reinholdtsen return 0; /* no need to set higher */ 3322c18ec02fSPetter Reinholdtsen 3323c18ec02fSPetter Reinholdtsen backupBridgePossible = bridgePossible; 3324c18ec02fSPetter Reinholdtsen 3325c18ec02fSPetter Reinholdtsen bridgePossible = 0; 3326c18ec02fSPetter Reinholdtsen 3327c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req)); 3328c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_APP; 3329c18ec02fSPetter Reinholdtsen req.msg.cmd = 0x3b; 3330c18ec02fSPetter Reinholdtsen req.msg.data = &privlvl; 3331c18ec02fSPetter Reinholdtsen req.msg.data_len = 1; 3332c18ec02fSPetter Reinholdtsen 3333c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req); 3334c18ec02fSPetter Reinholdtsen if (rsp == NULL) { 3335c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Set Session Privilege Level to %s failed", 3336c18ec02fSPetter Reinholdtsen val2str(privlvl, ipmi_privlvl_vals)); 3337c18ec02fSPetter Reinholdtsen bridgePossible = backupBridgePossible; 3338c18ec02fSPetter Reinholdtsen return -1; 3339c18ec02fSPetter Reinholdtsen } 3340c18ec02fSPetter Reinholdtsen if (verbose > 2) 3341c18ec02fSPetter Reinholdtsen printbuf(rsp->data, rsp->data_len, "set_session_privlvl"); 3342c18ec02fSPetter Reinholdtsen 3343c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) { 3344c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Set Session Privilege Level to %s failed: %s", 3345c18ec02fSPetter Reinholdtsen val2str(privlvl, ipmi_privlvl_vals), 3346c18ec02fSPetter Reinholdtsen val2str(rsp->ccode, completion_code_vals)); 3347c18ec02fSPetter Reinholdtsen bridgePossible = backupBridgePossible; 3348c18ec02fSPetter Reinholdtsen return -1; 3349c18ec02fSPetter Reinholdtsen } 3350c18ec02fSPetter Reinholdtsen 3351c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "Set Session Privilege Level to %s\n", 3352c18ec02fSPetter Reinholdtsen val2str(rsp->data[0], ipmi_privlvl_vals)); 3353c18ec02fSPetter Reinholdtsen 3354c18ec02fSPetter Reinholdtsen bridgePossible = backupBridgePossible; 3355c18ec02fSPetter Reinholdtsen 3356c18ec02fSPetter Reinholdtsen return 0; 3357c18ec02fSPetter Reinholdtsen } 3358c18ec02fSPetter Reinholdtsen 3359c18ec02fSPetter Reinholdtsen /** 3360c18ec02fSPetter Reinholdtsen * ipmi_lanplus_open 3361c18ec02fSPetter Reinholdtsen */ 3362c18ec02fSPetter Reinholdtsen int 3363c18ec02fSPetter Reinholdtsen ipmi_lanplus_open(struct ipmi_intf * intf) 3364c18ec02fSPetter Reinholdtsen { 3365c18ec02fSPetter Reinholdtsen int rc; 3366176774cfSZdenek Styblik int retry; 3367c18ec02fSPetter Reinholdtsen struct get_channel_auth_cap_rsp auth_cap; 3368c18ec02fSPetter Reinholdtsen struct ipmi_session *session; 3369c18ec02fSPetter Reinholdtsen 3370c18ec02fSPetter Reinholdtsen if (!intf || !intf->session) 3371c18ec02fSPetter Reinholdtsen return -1; 3372c18ec02fSPetter Reinholdtsen session = intf->session; 3373c18ec02fSPetter Reinholdtsen 3374c18ec02fSPetter Reinholdtsen if (!session->port) 3375c18ec02fSPetter Reinholdtsen session->port = IPMI_LANPLUS_PORT; 3376c18ec02fSPetter Reinholdtsen if (!session->privlvl) 3377c18ec02fSPetter Reinholdtsen session->privlvl = IPMI_SESSION_PRIV_ADMIN; 3378c18ec02fSPetter Reinholdtsen if (!session->timeout) 3379c18ec02fSPetter Reinholdtsen session->timeout = IPMI_LAN_TIMEOUT; 3380c18ec02fSPetter Reinholdtsen if (!session->retry) 3381c18ec02fSPetter Reinholdtsen session->retry = IPMI_LAN_RETRY; 3382c18ec02fSPetter Reinholdtsen 3383c18ec02fSPetter Reinholdtsen if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) { 3384c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "No hostname specified!"); 3385c18ec02fSPetter Reinholdtsen return -1; 3386c18ec02fSPetter Reinholdtsen } 3387c18ec02fSPetter Reinholdtsen 3388c18ec02fSPetter Reinholdtsen intf->abort = 1; 3389c18ec02fSPetter Reinholdtsen 3390c18ec02fSPetter Reinholdtsen 3391c18ec02fSPetter Reinholdtsen /* Setup our lanplus session state */ 3392c18ec02fSPetter Reinholdtsen session->v2_data.auth_alg = IPMI_AUTH_RAKP_NONE; 3393c18ec02fSPetter Reinholdtsen session->v2_data.crypt_alg = IPMI_CRYPT_NONE; 3394c18ec02fSPetter Reinholdtsen session->v2_data.console_id = 0x00; 3395c18ec02fSPetter Reinholdtsen session->v2_data.bmc_id = 0x00; 3396c18ec02fSPetter Reinholdtsen session->sol_data.sequence_number = 1; 3397c18ec02fSPetter Reinholdtsen //session->sol_data.last_received_sequence_number = 0; 3398c18ec02fSPetter Reinholdtsen //session->sol_data.last_received_byte_count = 0; 3399c18ec02fSPetter Reinholdtsen memset(session->v2_data.sik, 0, IPMI_SIK_BUFFER_SIZE); 3400c18ec02fSPetter Reinholdtsen 3401c18ec02fSPetter Reinholdtsen /* Kg is set in ipmi_intf */ 3402c18ec02fSPetter Reinholdtsen //memset(session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE); 3403c18ec02fSPetter Reinholdtsen 3404c18ec02fSPetter Reinholdtsen if (ipmi_intf_socket_connect (intf) == -1) { 3405c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Could not open socket!"); 3406c18ec02fSPetter Reinholdtsen return -1; 3407c18ec02fSPetter Reinholdtsen } 3408c18ec02fSPetter Reinholdtsen 3409c18ec02fSPetter Reinholdtsen if (intf->fd < 0) { 3410c18ec02fSPetter Reinholdtsen lperror(LOG_ERR, "Connect to %s failed", 3411c18ec02fSPetter Reinholdtsen session->hostname); 3412c18ec02fSPetter Reinholdtsen intf->close(intf); 3413c18ec02fSPetter Reinholdtsen return -1; 3414c18ec02fSPetter Reinholdtsen } 3415c18ec02fSPetter Reinholdtsen 3416c18ec02fSPetter Reinholdtsen intf->opened = 1; 3417c18ec02fSPetter Reinholdtsen 3418c18ec02fSPetter Reinholdtsen /* 3419c18ec02fSPetter Reinholdtsen * 3420c18ec02fSPetter Reinholdtsen * Make sure the BMC supports IPMI v2 / RMCP+ 3421c18ec02fSPetter Reinholdtsen */ 3422c18ec02fSPetter Reinholdtsen if (!ipmi_oem_active(intf, "i82571spt") && 3423c18ec02fSPetter Reinholdtsen ipmi_get_auth_capabilities_cmd(intf, &auth_cap)) { 3424c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "Error issuing Get Channel " 3425c18ec02fSPetter Reinholdtsen "Authentication Capabilies request"); 3426c18ec02fSPetter Reinholdtsen goto fail; 3427c18ec02fSPetter Reinholdtsen } 3428c18ec02fSPetter Reinholdtsen 3429f56d740dSZdenek Styblik if (!ipmi_oem_active(intf, "i82571spt") && ! auth_cap.v20_data_available) { 3430c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+"); 3431c18ec02fSPetter Reinholdtsen goto fail; 3432c18ec02fSPetter Reinholdtsen } 3433c18ec02fSPetter Reinholdtsen 3434176774cfSZdenek Styblik /* 3435176774cfSZdenek Styblik * If the open/rakp1/rakp3 sequence encounters a timeout, the whole sequence 3436176774cfSZdenek Styblik * needs to restart. The individual messages are not individually retryable, 3437176774cfSZdenek Styblik * as the session state is advancing. 3438176774cfSZdenek Styblik */ 3439176774cfSZdenek Styblik for (retry = 0; retry < IPMI_LAN_RETRY; retry++) { 3440176774cfSZdenek Styblik session->v2_data.session_state = LANPLUS_STATE_PRESESSION; 3441c18ec02fSPetter Reinholdtsen /* 3442c18ec02fSPetter Reinholdtsen * Open session 3443c18ec02fSPetter Reinholdtsen */ 3444176774cfSZdenek Styblik if ((rc = ipmi_lanplus_open_session(intf)) == 1) { 3445c18ec02fSPetter Reinholdtsen intf->close(intf); 3446c18ec02fSPetter Reinholdtsen goto fail; 3447c18ec02fSPetter Reinholdtsen } 3448176774cfSZdenek Styblik if (rc == 2) { 3449176774cfSZdenek Styblik lprintf(LOG_DEBUG, "Retry lanplus open session, %d", retry); 3450176774cfSZdenek Styblik continue; 3451176774cfSZdenek Styblik } 3452c18ec02fSPetter Reinholdtsen /* 3453c18ec02fSPetter Reinholdtsen * RAKP 1 3454c18ec02fSPetter Reinholdtsen */ 3455176774cfSZdenek Styblik if ((rc = ipmi_lanplus_rakp1(intf)) == 1) { 3456c18ec02fSPetter Reinholdtsen intf->close(intf); 3457c18ec02fSPetter Reinholdtsen goto fail; 3458c18ec02fSPetter Reinholdtsen } 3459176774cfSZdenek Styblik if (rc == 2) { 3460176774cfSZdenek Styblik lprintf(LOG_DEBUG, "Retry lanplus rakp1, %d", retry); 3461176774cfSZdenek Styblik continue; 3462176774cfSZdenek Styblik } 3463c18ec02fSPetter Reinholdtsen /* 3464c18ec02fSPetter Reinholdtsen * RAKP 3 3465c18ec02fSPetter Reinholdtsen */ 3466176774cfSZdenek Styblik if ((rc = ipmi_lanplus_rakp3(intf)) == 1) { 3467c18ec02fSPetter Reinholdtsen intf->close(intf); 3468c18ec02fSPetter Reinholdtsen goto fail; 3469c18ec02fSPetter Reinholdtsen } 3470176774cfSZdenek Styblik if (rc == 0) break; 3471176774cfSZdenek Styblik lprintf(LOG_DEBUG,"Retry lanplus rakp3, %d", retry); 3472176774cfSZdenek Styblik } 3473c18ec02fSPetter Reinholdtsen 3474c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n"); 3475c18ec02fSPetter Reinholdtsen 3476c18ec02fSPetter Reinholdtsen if (!ipmi_oem_active(intf, "i82571spt")) { 3477c18ec02fSPetter Reinholdtsen rc = ipmi_set_session_privlvl_cmd(intf); 3478176774cfSZdenek Styblik if (rc < 0) { 3479176774cfSZdenek Styblik intf->close(intf); 3480c18ec02fSPetter Reinholdtsen goto fail; 3481c18ec02fSPetter Reinholdtsen } 3482176774cfSZdenek Styblik } 3483c18ec02fSPetter Reinholdtsen intf->manufacturer_id = ipmi_get_oem(intf); 3484c18ec02fSPetter Reinholdtsen bridgePossible = 1; 3485c18ec02fSPetter Reinholdtsen 348623e9340bSZdenek Styblik /* automatically detect interface request and response sizes */ 348723e9340bSZdenek Styblik hpm2_detect_max_payload_size(intf); 348823e9340bSZdenek Styblik 3489c18ec02fSPetter Reinholdtsen return intf->fd; 3490c18ec02fSPetter Reinholdtsen 3491c18ec02fSPetter Reinholdtsen fail: 3492c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error: Unable to establish IPMI v2 / RMCP+ session"); 3493c18ec02fSPetter Reinholdtsen intf->opened = 0; 3494c18ec02fSPetter Reinholdtsen return -1; 3495c18ec02fSPetter Reinholdtsen } 3496c18ec02fSPetter Reinholdtsen 3497c18ec02fSPetter Reinholdtsen 3498c18ec02fSPetter Reinholdtsen 3499c18ec02fSPetter Reinholdtsen void test_crypt1(void) 3500c18ec02fSPetter Reinholdtsen { 3501c18ec02fSPetter Reinholdtsen uint8_t key[] = 3502c18ec02fSPetter Reinholdtsen {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 3503c18ec02fSPetter Reinholdtsen 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14}; 3504c18ec02fSPetter Reinholdtsen 3505c18ec02fSPetter Reinholdtsen uint16_t bytes_encrypted; 3506c18ec02fSPetter Reinholdtsen uint16_t bytes_decrypted; 3507c18ec02fSPetter Reinholdtsen uint8_t decrypt_buffer[1000]; 3508c18ec02fSPetter Reinholdtsen uint8_t encrypt_buffer[1000]; 3509c18ec02fSPetter Reinholdtsen 3510c18ec02fSPetter Reinholdtsen uint8_t data[] = 3511c18ec02fSPetter Reinholdtsen {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 3512c18ec02fSPetter Reinholdtsen 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 3513c18ec02fSPetter Reinholdtsen 0x11, 0x12}; 3514c18ec02fSPetter Reinholdtsen 3515c18ec02fSPetter Reinholdtsen printbuf(data, sizeof(data), "original data"); 3516c18ec02fSPetter Reinholdtsen 3517c18ec02fSPetter Reinholdtsen if (lanplus_encrypt_payload(IPMI_CRYPT_AES_CBC_128, 3518c18ec02fSPetter Reinholdtsen key, 3519c18ec02fSPetter Reinholdtsen data, 3520c18ec02fSPetter Reinholdtsen sizeof(data), 3521c18ec02fSPetter Reinholdtsen encrypt_buffer, 3522c18ec02fSPetter Reinholdtsen &bytes_encrypted)) 3523c18ec02fSPetter Reinholdtsen { 3524c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Encrypt test failed"); 3525c18ec02fSPetter Reinholdtsen assert(0); 3526c18ec02fSPetter Reinholdtsen } 3527c18ec02fSPetter Reinholdtsen printbuf(encrypt_buffer, bytes_encrypted, "encrypted payload"); 3528c18ec02fSPetter Reinholdtsen 3529c18ec02fSPetter Reinholdtsen 3530c18ec02fSPetter Reinholdtsen if (lanplus_decrypt_payload(IPMI_CRYPT_AES_CBC_128, 3531c18ec02fSPetter Reinholdtsen key, 3532c18ec02fSPetter Reinholdtsen encrypt_buffer, 3533c18ec02fSPetter Reinholdtsen bytes_encrypted, 3534c18ec02fSPetter Reinholdtsen decrypt_buffer, 3535c18ec02fSPetter Reinholdtsen &bytes_decrypted)) 3536c18ec02fSPetter Reinholdtsen { 3537c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Decrypt test failed\n"); 3538c18ec02fSPetter Reinholdtsen assert(0); 3539c18ec02fSPetter Reinholdtsen } 3540c18ec02fSPetter Reinholdtsen printbuf(decrypt_buffer, bytes_decrypted, "decrypted payload"); 3541c18ec02fSPetter Reinholdtsen 3542c18ec02fSPetter Reinholdtsen lprintf(LOG_DEBUG, "\nDone testing the encrypt/decyrpt methods!\n"); 3543c18ec02fSPetter Reinholdtsen exit(0); 3544c18ec02fSPetter Reinholdtsen } 3545c18ec02fSPetter Reinholdtsen 3546c18ec02fSPetter Reinholdtsen 3547c18ec02fSPetter Reinholdtsen 3548c18ec02fSPetter Reinholdtsen void test_crypt2(void) 3549c18ec02fSPetter Reinholdtsen { 3550c18ec02fSPetter Reinholdtsen uint8_t key[] = 3551c18ec02fSPetter Reinholdtsen {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 3552c18ec02fSPetter Reinholdtsen 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14}; 3553c18ec02fSPetter Reinholdtsen uint8_t iv[] = 3554c18ec02fSPetter Reinholdtsen {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 3555c18ec02fSPetter Reinholdtsen 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14}; 3556c18ec02fSPetter Reinholdtsen uint8_t data[8] = "12345678"; 3557c18ec02fSPetter Reinholdtsen 3558c18ec02fSPetter Reinholdtsen uint8_t encrypt_buffer[1000]; 3559c18ec02fSPetter Reinholdtsen uint8_t decrypt_buffer[1000]; 3560c18ec02fSPetter Reinholdtsen uint32_t bytes_encrypted; 3561c18ec02fSPetter Reinholdtsen uint32_t bytes_decrypted; 3562c18ec02fSPetter Reinholdtsen 3563c18ec02fSPetter Reinholdtsen printbuf((const uint8_t *)data, strlen((const char *)data), "input data"); 3564c18ec02fSPetter Reinholdtsen 3565c18ec02fSPetter Reinholdtsen lanplus_encrypt_aes_cbc_128(iv, 3566c18ec02fSPetter Reinholdtsen key, 3567c18ec02fSPetter Reinholdtsen data, 3568c18ec02fSPetter Reinholdtsen strlen((const char *)data), 3569c18ec02fSPetter Reinholdtsen encrypt_buffer, 3570c18ec02fSPetter Reinholdtsen &bytes_encrypted); 3571c18ec02fSPetter Reinholdtsen printbuf((const uint8_t *)encrypt_buffer, bytes_encrypted, "encrypt_buffer"); 3572c18ec02fSPetter Reinholdtsen 3573c18ec02fSPetter Reinholdtsen lanplus_decrypt_aes_cbc_128(iv, 3574c18ec02fSPetter Reinholdtsen key, 3575c18ec02fSPetter Reinholdtsen encrypt_buffer, 3576c18ec02fSPetter Reinholdtsen bytes_encrypted, 3577c18ec02fSPetter Reinholdtsen decrypt_buffer, 3578c18ec02fSPetter Reinholdtsen &bytes_decrypted); 3579c18ec02fSPetter Reinholdtsen printbuf((const uint8_t *)decrypt_buffer, bytes_decrypted, "decrypt_buffer"); 3580c18ec02fSPetter Reinholdtsen 3581c18ec02fSPetter Reinholdtsen lprintf(LOG_INFO, "\nDone testing the encrypt/decyrpt methods!\n"); 3582c18ec02fSPetter Reinholdtsen exit(0); 3583c18ec02fSPetter Reinholdtsen } 3584c18ec02fSPetter Reinholdtsen 3585c18ec02fSPetter Reinholdtsen 3586c18ec02fSPetter Reinholdtsen /** 3587c18ec02fSPetter Reinholdtsen * send a get device id command to keep session active 3588c18ec02fSPetter Reinholdtsen */ 3589c18ec02fSPetter Reinholdtsen static int 3590c18ec02fSPetter Reinholdtsen ipmi_lanplus_keepalive(struct ipmi_intf * intf) 3591c18ec02fSPetter Reinholdtsen { 3592c18ec02fSPetter Reinholdtsen struct ipmi_rs * rsp; 3593c18ec02fSPetter Reinholdtsen struct ipmi_rq req = { msg: { 3594c18ec02fSPetter Reinholdtsen netfn: IPMI_NETFN_APP, 3595c18ec02fSPetter Reinholdtsen cmd: 1, 3596c18ec02fSPetter Reinholdtsen }}; 3597c18ec02fSPetter Reinholdtsen 3598c18ec02fSPetter Reinholdtsen if (!intf->opened) 3599c18ec02fSPetter Reinholdtsen return 0; 3600c18ec02fSPetter Reinholdtsen 3601c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req); 3602c18ec02fSPetter Reinholdtsen while (rsp != NULL && is_sol_packet(rsp)) { 3603c18ec02fSPetter Reinholdtsen /* rsp was SOL data instead of our answer */ 3604c18ec02fSPetter Reinholdtsen /* since it didn't go through the sol recv, do sol recv stuff here */ 3605c18ec02fSPetter Reinholdtsen ack_sol_packet(intf, rsp); 3606c18ec02fSPetter Reinholdtsen check_sol_packet_for_new_data(intf, rsp); 3607c18ec02fSPetter Reinholdtsen if (rsp->data_len) 3608c18ec02fSPetter Reinholdtsen intf->session->sol_data.sol_input_handler(rsp); 3609c18ec02fSPetter Reinholdtsen rsp = ipmi_lan_poll_recv(intf); 3610c18ec02fSPetter Reinholdtsen if (rsp == NULL) /* the get device id answer never got back, but retry mechanism was bypassed by SOL data */ 3611c18ec02fSPetter Reinholdtsen return 0; /* so get device id command never returned, the connection is still alive */ 3612c18ec02fSPetter Reinholdtsen } 3613c18ec02fSPetter Reinholdtsen 3614c18ec02fSPetter Reinholdtsen if (rsp == NULL) 3615c18ec02fSPetter Reinholdtsen return -1; 3616c18ec02fSPetter Reinholdtsen if (rsp->ccode > 0) 3617c18ec02fSPetter Reinholdtsen return -1; 3618c18ec02fSPetter Reinholdtsen 3619c18ec02fSPetter Reinholdtsen return 0; 3620c18ec02fSPetter Reinholdtsen } 3621c18ec02fSPetter Reinholdtsen 3622c18ec02fSPetter Reinholdtsen 3623c18ec02fSPetter Reinholdtsen /** 3624c18ec02fSPetter Reinholdtsen * ipmi_lanplus_setup 3625c18ec02fSPetter Reinholdtsen */ 3626c18ec02fSPetter Reinholdtsen static int ipmi_lanplus_setup(struct ipmi_intf * intf) 3627c18ec02fSPetter Reinholdtsen { 3628c18ec02fSPetter Reinholdtsen //test_crypt1(); 3629c18ec02fSPetter Reinholdtsen assert("ipmi_lanplus_setup"); 3630c18ec02fSPetter Reinholdtsen 3631c18ec02fSPetter Reinholdtsen if (lanplus_seed_prng(16)) 3632c18ec02fSPetter Reinholdtsen return -1; 3633c18ec02fSPetter Reinholdtsen 3634c18ec02fSPetter Reinholdtsen intf->session = malloc(sizeof(struct ipmi_session)); 3635c18ec02fSPetter Reinholdtsen if (intf->session == NULL) { 3636c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "ipmitool: malloc failure"); 3637c18ec02fSPetter Reinholdtsen return -1; 3638c18ec02fSPetter Reinholdtsen } 3639c18ec02fSPetter Reinholdtsen memset(intf->session, 0, sizeof(struct ipmi_session)); 364023e9340bSZdenek Styblik 364123e9340bSZdenek Styblik /* setup default LAN maximum request and response sizes */ 364223e9340bSZdenek Styblik intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE; 364323e9340bSZdenek Styblik intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE; 364423e9340bSZdenek Styblik 3645c18ec02fSPetter Reinholdtsen return 0; 3646c18ec02fSPetter Reinholdtsen } 364723e9340bSZdenek Styblik 364823e9340bSZdenek Styblik static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size) 364923e9340bSZdenek Styblik { 365023e9340bSZdenek Styblik if (intf->session->cipher_suite_id == 3) { 365123e9340bSZdenek Styblik /* 365223e9340bSZdenek Styblik * encrypted payload can only be multiple of 16 bytes 365323e9340bSZdenek Styblik */ 365423e9340bSZdenek Styblik size &= ~15; 365523e9340bSZdenek Styblik 365623e9340bSZdenek Styblik /* 365723e9340bSZdenek Styblik * decrement payload size on confidentiality header size 365823e9340bSZdenek Styblik * plus minimal confidentiality trailer size 365923e9340bSZdenek Styblik */ 366023e9340bSZdenek Styblik size -= (16 + 1); 366123e9340bSZdenek Styblik } 366223e9340bSZdenek Styblik 366323e9340bSZdenek Styblik intf->max_request_data_size = size; 366423e9340bSZdenek Styblik } 366523e9340bSZdenek Styblik 366623e9340bSZdenek Styblik static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size) 366723e9340bSZdenek Styblik { 366823e9340bSZdenek Styblik if (intf->session->cipher_suite_id == 3) { 366923e9340bSZdenek Styblik /* 367023e9340bSZdenek Styblik * encrypted payload can only be multiple of 16 bytes 367123e9340bSZdenek Styblik */ 367223e9340bSZdenek Styblik size &= ~15; 367323e9340bSZdenek Styblik 367423e9340bSZdenek Styblik /* 367523e9340bSZdenek Styblik * decrement payload size on confidentiality header size 367623e9340bSZdenek Styblik * plus minimal confidentiality trailer size 367723e9340bSZdenek Styblik */ 367823e9340bSZdenek Styblik size -= (16 + 1); 367923e9340bSZdenek Styblik } 368023e9340bSZdenek Styblik 368123e9340bSZdenek Styblik intf->max_response_data_size = size; 368223e9340bSZdenek Styblik } 3683