/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include "libipmi.h"
#include "ipmi_lan.h"
#include "ipmi_impl.h"
typedef struct ipmi_rs {
int ir_dlen;
} ipmi_rs_t;
typedef struct ipmi_rq_entry {
int ire_msg_len;
/*
* LAN transport-specific data
*/
typedef struct ipmi_lan {
int il_sd;
} ipmi_lan_t;
/*
* Calculate and returns IPMI checksum
*
* Checksum algorithm is described in Section 13.8
*
* d: buffer to check
* s: position in buffer to start checksum from
*/
static uint8_t
{
uint8_t c = 0;
for (; s > 0; s--, d++)
c += *d;
return (-c);
}
static ipmi_rq_entry_t *
{
ipmi_rq_entry_t *e;
return (NULL);
return (e);
}
/*ARGSUSED*/
static ipmi_rq_entry_t *
{
ipmi_rq_entry_t *e;
e = ipmi_list_next(e))
return (e);
return (NULL);
}
static void
{
ipmi_rq_entry_t *e;
if (e) {
}
}
static void
{
ipmi_rq_entry_t *e;
}
}
static int
{
int fd;
return (-1);
return (-1);
}
return (0);
}
static int
{
}
static ipmi_rs_t *
{
int ret;
return (NULL);
/*
* The first read may return ECONNREFUSED because the rmcp ping
* packet--sent to UDP port 623--will be processed by both the
* BMC and the OS.
*
* The problem with this is that the ECONNREFUSED takes
* priority over any other received datagram; that means that
* the Connection Refused shows up _before_ the response packet,
* regardless of the order they were sent out. (unless the
* response is read before the connection refused is returned)
*/
if (ret < 0) {
if (ret < 0) {
return (NULL);
if (ret < 0)
return (NULL);
}
}
if (ret == 0)
return (NULL);
return (&rsp);
}
/*
*
* See section 13.2.4
*/
struct rmcp_pong {
};
/*
* parse response RMCP "pong" packet
*
* return -1 if ping response not received
* returns 0 if IPMI is NOT supported
* returns 1 if IPMI is supported
*/
/*ARGSUSED*/
static int
{
return (-1);
/*LINTED: E_BAD_PTR_CAST_ALIGN*/
}
/*
* Build and send RMCP presence ping message
*/
static int
{
return (-1);
if (rv < 0)
return (0);
}
static ipmi_rs_t *
{
/* parse response headers */
switch (rmcp_rsp.rh_msg_class) {
case RMCP_CLASS_ASF:
/* ping response packet */
case RMCP_CLASS_IPMI:
/* handled by rest of function */
break;
default:
/* Invalid RMCP class */
continue;
}
off = sizeof (rmcp_hdr_t);
off += 26;
else
off += 10;
if (entry) {
} else {
continue;
}
break;
}
/* shift response data to start of array */
}
return (rsp);
}
/*
* IPMI LAN Request Message Format
*
* See section 13.8
*
* +---------------------+
* | rmcp_hdr_t | 4 bytes
* +---------------------+
* | v15_session_hdr_t | 9 bytes
* +---------------------+
* | [authcode] | 16 bytes (if AUTHTYPE != none)
* +---------------------+
* | msg length | 1 byte
* +---------------------+
* | ipmi_msg_hdr_t | 6 bytes
* +---------------------+
* | [msg data] | variable
* +---------------------+
* | msg data checksum | 1 byte
* +---------------------+
*/
static ipmi_rq_entry_t *
{
static int curr_seq = 0;
if (curr_seq >= 64)
curr_seq = 0;
return (NULL);
len += 16;
/* ipmi_errno set */
return (NULL);
/* RMCP header */
/* IPMI session header */
if (! ilp->il_send_authcode)
else
/* hardcode passwd authentication */
sizeof (uint32_t));
off += sizeof (session_hdr);
/* IPMI session authcode */
off += 16;
}
/* message length */
/* IPMI message header */
/* message data */
}
/* message data checksum */
}
return (entry);
}
static int
int *completion)
{
for (;;) {
return (-1);
entry->ire_msg_len) < 0) {
return (-1);
(void) usleep(5000);
continue;
}
(void) usleep(100);
break;
(void) usleep(5000);
return (-1);
}
} else {
*completion = 0;
}
return (0);
}
/*
* IPMI Get Session Challenge Command
*
* Copies the returned session ID and 16-byte challenge string to the supplied
* buffers
*
* See section 22.16
*/
static int
{
int ccode;
switch (ilp->il_authtype) {
msg_data[0] = 0x00;
break;
msg_data[0] = 0x01;
break;
msg_data[0] = 0x02;
break;
msg_data[0] = 0x04;
break;
msg_data[0] = 0x05;
break;
}
return (0);
}
/*
* IPMI Activate Session Command
*
* See section 22.17
*/
static int
{
int ccode;
switch (ilp->il_authtype) {
msg_data[0] = 0x00;
break;
msg_data[0] = 0x01;
break;
msg_data[0] = 0x02;
break;
msg_data[0] = 0x04;
break;
msg_data[0] = 0x05;
break;
}
/* setup initial outbound sequence number */
}
return (0);
}
/*
* See section 22.18
*
* returns privilege level or -1 on error
*/
static int
{
if (privlvl > IPMI_SESSION_PRIV_OEM)
return (ret);
}
/*
* See section 22.19
*/
static int
{
if (! ilp->il_session_active)
return (-1);
ret = -1;
return (ret);
}
/*
* IPMI LAN Session Activation
*
* See section 13.14
*
* 1. send "RMCP Presence Ping" message, response message will
* indicate whether the platform supports IPMI
* 2. send "Get Channel Authentication Capabilities" command
* with AUTHTYPE = none, response packet will contain information
* 3. send "Get Session Challenge" command with AUTHTYPE = none
* and indicate the authentication type in the message, response
* packet will contain challenge string and temporary session ID.
* 4. send "Activate Session" command, authenticated with AUTHTYPE
* sent in previous message. Also sends the initial value for
* the outbound sequence number for BMC.
* 5. BMC returns response confirming session activation and
* session ID for this session and initial inbound sequence.
*/
static int
{
if (ipmi_lan_ping(ihp) != 0)
return (-1);
return (-1);
/*
* For the sake of simplicity, we're just supporting basic password
* authentication. If this authentication type is not supported then
* we'll bail here.
*/
}
ilp->il_challenge) != 0)
return (-1);
if (ipmi_activate_session_cmd(ihp) != 0)
return (-1);
return (-1);
return (0);
}
static void
{
if (ilp->il_session_active)
}
static void *
{
int rc;
/* ipmi errno set */
return (NULL);
}
/*
* Parse the parameters passed in the params nvlist. The following
* parameters are required
* IPMI_LAN_HOST, IPMI_LAN_USER and IPMI_LAN_PASSWD
*
* If any of these were not specified then we abort
*/
return (NULL);
}
/*
* IPMI_LAN_PORT is an optional parameter and defaults to port 623
* IPMI_LAN_PRIVLVL is also optional and defaults to admin
* IPMI_LAN_TIMEOUT is optional and will default to 3 seconds
* IPMI_LAN_NUM_RETIES is optional and will default to 5
*/
&ilp->il_num_retries))
/*
* Open up and connect a UDP socket between us and the service
* processor
*/
if (rc <= 0) {
== NULL) {
return (NULL);
}
}
return (NULL);
}
sizeof (struct sockaddr_in)) < 0) {
return (NULL);
}
== NULL)
return (NULL);
/*
* Finally we start up the IPMI LAN session
*/
return (NULL);
}
return (ilp);
}
};