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