⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipmi_con_lan.cpp

📁 HIP 硬件设备管理标准接口
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * * Copyright (c) 2003,2004 by FORCE Computers * * Note that this file is based on parts of OpenIPMI * written by Corey Minyard <minyard@mvista.com> * of MontaVista Software. Corey's code was helpful * and many thanks go to him. He gave the permission * to use this code in OpenHPI under BSD license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  This * file and program are licensed under a BSD style license.  See * the Copying file included with the OpenHPI distribution for * full licensing terms. * * Authors: *     Thomas Kanngieser <thomas.kanngieser@fci.com> */#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <errno.h>#include <unistd.h>#include <assert.h>#include <poll.h>#include <sys/time.h>#include "ipmi_con_lan.h"#define dIpmiMaxLanLen (dIpmiMaxMsgLength + 42)cIpmiConLan::cIpmiConLan( unsigned int timeout, int log_level, struct in_addr addr, int port,                          tIpmiAuthType auth, tIpmiPrivilege priv,                          char *user, char *passwd )  : cIpmiCon( timeout, log_level ),    m_port( port ), m_auth( auth ), m_priv( priv ), m_auth_method( 0 ),    m_session_id( 0 ), m_working_auth( eIpmiAuthTypeNone ),    m_ping_count( 0 ),    m_outbound_seq_num( 0 ), m_inbound_seq_num( 0 ),    m_recv_msg_map( 0 ){  assert( strlen( user ) < dIpmiUsernameMax );  assert( strlen( passwd ) < dIpmiPasswordMax );  m_ip_addr.sin_family = AF_INET;  m_ip_addr.sin_port = htons( port );  m_ip_addr.sin_addr = addr;  m_port = port;  memset( m_username, 0, dIpmiUsernameMax );  strcpy( m_username, user );  memset( m_passwd, 0, dIpmiPasswordMax );  strcpy( m_passwd, passwd );}cIpmiConLan::~cIpmiConLan(){  if ( IsOpen() )       Close();  if ( m_auth_method )       delete m_auth_method;}intcIpmiConLan::AuthGen( unsigned char *out,                      uint8_t       *ses_id,                      uint8_t       *seq,                      unsigned char *data,                      unsigned int   data_len ){  assert( m_auth == m_working_auth );  assert( m_auth_method );    int rv;  cIpmiAuthSg l[] =  {    { ses_id, 4 },    { data,   data_len },    { seq,    4 },    { NULL,   0 }  };  rv = m_auth_method->Gen( l, out );  return rv;}intcIpmiConLan::AuthCheck( uint8_t       *ses_id,                        uint8_t       *seq,                        unsigned char *data,                        unsigned int   data_len,                        unsigned char *code ){  assert( m_auth == m_working_auth );  assert( m_auth_method );  int rv;  cIpmiAuthSg l[] =  {    { ses_id, 4  },    { data,   data_len },    { seq,    4 },    { NULL,   0 }  };  rv = m_auth_method->Check( l, code );  return rv;}intcIpmiConLan::OpenLanFd(){  int                fd;  struct sockaddr_in addr;  int                curr_port;  int                rv;  fd = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );  if ( fd == -1 )       return fd;  curr_port = 7000;  do     {       curr_port++;       addr.sin_family = AF_INET;       addr.sin_port = htons( curr_port );       addr.sin_addr.s_addr = INADDR_ANY;       rv = bind( fd, (struct sockaddr *)&addr, sizeof( addr ) );     }  while( curr_port < 7100 && rv == -1 );  if ( rv == -1 )     {       int tmp_errno = errno;       close( fd );       errno = tmp_errno;       return -1;     }  stdlog << "using port " << curr_port << ".\n";  return fd;}unsigned charcIpmiConLan::Checksum( unsigned char *data, int size ){  unsigned char csum = 0;  for( ; size > 0; size--, data++ )       csum += *data;  return -csum;}intcIpmiConLan::SendPing(){  unsigned char data[dIpmiMaxLanLen];  data[0]  = 6; // RMCP version 1.0.  data[1]  = 0;  data[2]  = 0xff; // no RMCP ACK  data[3]  = 0x06; // ASF  IpmiSetUint32( data + 4,  dAsfIana );  data[8]  = 0x80; // presence ping  data[9]  = 0xff; // ????  data[10] = 0x00;  data[11] = 0x00;  stdlog << "sending RMCP ping.\n";  int rv = sendto( m_fd, data, 12, 0,                   (struct sockaddr *)&m_ip_addr,                   sizeof( struct sockaddr_in ) );  if ( rv == -1 )       return errno;  m_ping_count++;  return 0;}boolcIpmiConLan::WaitForPong( unsigned int timeout_ms ){  struct pollfd pfd;  pfd.fd     = m_fd;  pfd.events = POLLIN;  tResponseType ret;  // loop  do     {       int rv = poll( &pfd, 1, timeout_ms );       // timeout       if ( !rv )	    return false;       if ( rv == -1 )	  {	    assert( 0 );	    return false;	  }       assert( rv == 1 );       int seq;       cIpmiAddr addr;       cIpmiMsg msg;       ret = ReadResponse( seq, addr, msg );       if ( ret == eResponseTypeMessage )          {            stdlog << "reading unexpected message while waiting for pong:\n";            IpmiLogDataMsg( addr, msg );          }     }  while( ret != eResponseTypePong );  return true;}cIpmiConLan::tResponseTypecIpmiConLan::WaitForResponse( unsigned int timeout_ms, int &seq,                              cIpmiAddr &addr, cIpmiMsg &msg ){  struct timeval tv;  struct timeval timeout;  struct timeval t0;  // create absolute timeout  gettimeofday( &timeout, 0 );  timeout.tv_sec += timeout_ms / 1000;  timeout.tv_usec += (timeout_ms % 1000) * 1000;  while( timeout.tv_usec > 1000000 )     {       timeout.tv_sec++;       timeout.tv_usec -= 1000000;     }  tResponseType ret;  // loop  do     {       struct pollfd pfd;       pfd.fd = m_fd;       pfd.events = POLLIN;       // relative timeout       gettimeofday( &t0, 0 );       timersub( &timeout, &t0, &tv );       if ( tv.tv_sec < 0 || tv.tv_usec < 0 )	  {	    tv.tv_sec  = 0;	    tv.tv_usec = 0;	  }       timeout_ms =  tv.tv_sec * 1000 + tv.tv_usec / 1000;       int rv = poll( &pfd, 1, timeout_ms );       // timeout       if ( !rv )	    return eResponseTypeTimeout;       if ( rv == -1 )	  {	    assert( 0 );	    return eResponseTypeError;	  }       assert( rv == 1 );       ret = ReadResponse( seq, addr, msg );     }  while( ret != eResponseTypeMessage );  return eResponseTypeMessage;}SaErrorTcIpmiConLan::SendMsgAndWaitForResponse( const cIpmiAddr &addr, const cIpmiMsg &msg,                                        cIpmiAddr &rsp_addr, cIpmiMsg &rsp_msg ){  cIpmiRequest *r = new cIpmiRequest( addr, msg );  r->m_retries_left = dIpmiDefaultRetries;  int seq;  while( r->m_retries_left > 0 )     {       SaErrorT rv = SendCmd( r );       if ( rv != SA_OK )            continue;       tResponseType rt;       do          {            rt = WaitForResponse( m_timeout, seq, rsp_addr,                                  rsp_msg );          }       while( rt == eResponseTypeEvent || rt == eResponseTypePong );       RemOutstanding( r->m_seq );       if ( rt == eResponseTypeMessage )          {            // check seq            if ( seq == r->m_seq )               {                 delete r;                 return SA_OK;               }          }       // resend message       stdlog << "resending RMCP msg.\n";     }  return SA_ERR_HPI_TIMEOUT;}SaErrorTcIpmiConLan::AuthCap(){  SaErrorT rv;  cIpmiAddr addr( eIpmiAddrTypeSystemInterface );  cIpmiMsg  msg( eIpmiNetfnApp, eIpmiCmdGetChannelAuthCapabilities );  cIpmiAddr rsp_addr;  cIpmiMsg  rsp_msg;  msg.m_data[0] = 0xe;  msg.m_data[1] = m_priv;  msg.m_data_len = 2;  // dbg( "RMCP: sending GetChannelAuthCapabilitiesCmd" );  rv = SendMsgAndWaitForResponse( addr, msg,                                  rsp_addr, rsp_msg );  if ( rv != SA_OK )       return rv;  if (    (rsp_msg.m_data[0] != 0 )       || (rsp_msg.m_data_len < 9 ) )     {       stdlog << "auth response = " << rsp_msg.m_data[0] << " !\n";       return SA_ERR_HPI_INVALID_DATA;     }  if ( !( rsp_msg.m_data[2] & (1 << m_auth ) ) )     {       stdlog << "Requested authentication not supported !\n";       char str[256] = "";       if ( rsp_msg.m_data[2] & ( 1 << eIpmiAuthTypeNone ) )            strcat( str, " none" );       if ( rsp_msg.m_data[2] & ( 1 << eIpmiAuthTypeMd2 ) )            strcat( str, " md2" );       if ( rsp_msg.m_data[2] & ( 1 << eIpmiAuthTypeMd5 ) )            strcat( str, " md5" );       if ( rsp_msg.m_data[2] & ( 1 << eIpmiAuthTypeStraight ) )            strcat( str, " straight" );       if ( rsp_msg.m_data[2] & ( 1 << eIpmiAuthTypeOem ) )            strcat( str, " oem" );       stdlog << "supported authentication types: " << str << ".\n";       return SA_ERR_HPI_INVALID_DATA;     }  return SA_OK;}SaErrorTcIpmiConLan::SetSessionPriv(){  SaErrorT  rv;  cIpmiAddr addr( eIpmiAddrTypeSystemInterface );  cIpmiMsg  msg( eIpmiNetfnApp, eIpmiCmdSetSessionPrivilege );  cIpmiAddr rsp_addr;  cIpmiMsg  rsp_msg;  msg.m_data[0]  = m_priv;  msg.m_data_len = 1;  // dbg( "RMCP: sending SetSessionPrivilegeCmd" );  rv = SendMsgAndWaitForResponse( addr, msg,                                  rsp_addr, rsp_msg );  if ( rv != SA_OK )       return rv;  if ( rsp_msg.m_data[0] != 0 )     {       stdlog << "set session priv: " << rsp_msg.m_data[0] << " !\n";       return SA_ERR_HPI_INVALID_DATA;     }  if ( rsp_msg.m_data_len < 2 )     {       stdlog << "set session priv: msg to small: " << rsp_msg.m_data_len << " !\n";       return SA_ERR_HPI_DATA_LEN_INVALID;     }  if ( (unsigned char)m_priv != (rsp_msg.m_data[1] & 0xf))     {       // Requested privilege level did not match.       stdlog << "set session priv: Requested privilege level did not match: "              << m_priv << ", " << (rsp_msg.m_data[1] & 0xf ) << " !\n";       return SA_ERR_HPI_INVALID_DATA;     }  return SA_OK;}SaErrorTcIpmiConLan::ActiveSession(){  SaErrorT  rv;  cIpmiAddr addr( eIpmiAddrTypeSystemInterface );  cIpmiMsg  msg( eIpmiNetfnApp, eIpmiCmdActivateSession );  cIpmiAddr rsp_addr;  cIpmiMsg  rsp_msg;  msg.m_data[0] = m_auth;  msg.m_data[1] = m_priv;  memcpy( msg.m_data + 2, m_challenge_string, 16 );  IpmiSetUint32( msg.m_data + 18, m_inbound_seq_num );  msg.m_data_len = 22;  // dbg( "RMCP: sending ActivateSessionCmd" );  rv = SendMsgAndWaitForResponse( addr, msg,                                  rsp_addr, rsp_msg );  if ( rv != SA_OK )       return rv;  if ( rsp_msg.m_data[0] != 0 )     {       stdlog << "active session: " << rsp_msg.m_data[0] << " !\n";       return SA_ERR_HPI_INVALID_DATA;     }  if ( rsp_msg.m_data_len < 11 )     {       stdlog << "active session: msg to small: " << rsp_msg.m_data_len << " !\n";       return SA_ERR_HPI_DATA_LEN_INVALID;     }  m_working_auth = (tIpmiAuthType)(rsp_msg.m_data[1] & 0xf);  if (    m_working_auth != 0       && m_working_auth != m_auth )     {       // Eh?  It didn't return a valid authtype.       stdlog << "active session: wrong auth: " << m_working_auth << " !\n";       return SA_ERR_HPI_INVALID_DATA;     }  m_session_id = IpmiGetUint32( rsp_msg.m_data + 2 );  m_outbound_seq_num = IpmiGetUint32( rsp_msg.m_data + 6 );  //        dbg( "reading: sid = 0x%x, seq = 0x%x",   //             m_session_id, m_outbound_seq_num );  return SA_OK;}SaErrorTcIpmiConLan::Challange(){  SaErrorT  rv;  cIpmiAddr addr( eIpmiAddrTypeSystemInterface );  cIpmiMsg  msg( eIpmiNetfnApp, eIpmiCmdGetSessionChallenge );  cIpmiAddr rsp_addr;  cIpmiMsg  rsp_msg;  msg.m_data[0]  = m_auth;  msg.m_data_len = 1;  memcpy( msg.m_data + 1, m_username, dIpmiUsernameMax );  msg.m_data_len += dIpmiUsernameMax;  // dbg( "RMCP: sending GetSessionChallengeCmd" );  rv = SendMsgAndWaitForResponse( addr, msg,                                  rsp_addr, rsp_msg );  if ( rv != SA_OK )       return rv;  if ( rsp_msg.m_data[0] != 0 )     {       stdlog << "Challange returns: " << rsp_msg.m_data[0] << " !\n";       return SA_ERR_HPI_INVALID_DATA;     }  if ( rsp_msg.m_data_len < 21 )     {       stdlog << "Challange response to small !\n";       return SA_ERR_HPI_DATA_LEN_INVALID;     }  // Get the temporary session id.  m_session_id = IpmiGetUint32( rsp_msg.m_data + 1 );  m_outbound_seq_num = 0;  m_working_auth     = m_auth;  memcpy( m_challenge_string, rsp_msg.m_data + 5, 16 );  // Get a random number of the other end to start sending me sequence  // numbers at, but don't let it be zero.  while( m_inbound_seq_num == 0 )       m_inbound_seq_num = random();  return SA_OK;}intcIpmiConLan::IfGetMaxSeq(){  return 64;}intcIpmiConLan::IfOpen(){  m_auth_method = IpmiAuthFactory( m_auth );  if ( m_auth_method == 0 )     {       stdlog << "unknown authentication method " << m_auth << " !\n";       return -1;     }  m_auth_method->Init( (unsigned char *)m_passwd );  m_fd = OpenLanFd();  if ( m_fd < 0 )       return -1;  SaErrorT rv = CreateSession();  if ( rv != SA_OK )     {       close( m_fd );       m_fd = -1;     }  return m_fd;}SaErrorTcIpmiConLan::CreateSession(){  m_ping_count       = 0;  m_outbound_seq_num = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -