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