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

📄 ipmi_con_lan.cpp

📁 HIP 硬件设备管理标准接口
💻 CPP
📖 第 1 页 / 共 2 页
字号:
  m_session_id       = 0;  m_working_auth     = eIpmiAuthTypeNone;  m_recv_msg_map     = 0;  m_inbound_seq_num  = 0;  // start seq with 0  m_current_seq = 0;  SaErrorT rv = AuthCap();  if ( rv != SA_OK )       return -1;  rv = Challange();          if ( rv != SA_OK )       return -1;  rv = ActiveSession();  if ( rv != SA_OK )       return -1;  rv = SetSessionPriv();  if ( rv != SA_OK )       return rv;  assert( m_num_outstanding == 0 );  // reset seq  m_current_seq = 0;  stdlog << "RMCP session is up.\n";  return SA_OK;}// Send a final "close session" to shut down the connection.voidcIpmiConLan::SendCloseSession(){  cIpmiAddr si( eIpmiAddrTypeSystemInterface );  cIpmiMsg  msg( eIpmiNetfnApp, eIpmiCmdCloseSession );  IpmiSetUint32( msg.m_data, m_session_id );  msg.m_data_len = 4;  cIpmiRequest r( si, msg );  r.m_seq = 1;  IfSendCmd( &r );}voidcIpmiConLan::IfClose(){  if ( m_fd >= 0 )     {       SendCloseSession();       close( m_fd );       m_fd = -1;       if ( m_auth_method )          {            delete m_auth_method;            m_auth_method = 0;          }     }}voidcIpmiConLan::Reconnect(){  stdlog << "RMCP reconnection in progress.\n";  RequeueOutstanding();  GList *list = m_queue;  m_queue = 0;  while( true )     {       // send a ping       SendPing();       if ( WaitForPong( m_timeout ) == false )            continue;       stdlog << "create new RMCP session.\n";       if ( CreateSession() == SA_OK )            break;     }  m_queue = list;  stdlog << "RMCP reconnection done.\n";}SaErrorTcIpmiConLan::IfSendCmd( cIpmiRequest *r ){  IfAddrToSendAddr( r->m_addr, r->m_send_addr );  unsigned char  data[dIpmiMaxLanLen];  unsigned char *tmsg;  int            pos;  int            msgstart;  switch( r->m_send_addr.m_type )     {       case eIpmiAddrTypeSystemInterface:       case eIpmiAddrTypeIpmb:       case eIpmiAddrTypeIpmbBroadcast:	    break;       default:            assert( 0 );	    return SA_ERR_HPI_INVALID_PARAMS;     }  data[0] = 6; // RMCP version 1.0.  data[1] = 0;  data[2] = 0xff;  data[3] = 0x07;  data[4] = m_working_auth;  IpmiSetUint32( data+5, m_outbound_seq_num );  IpmiSetUint32( data+9, m_session_id );  if ( m_working_auth == 0 )       tmsg = data + 14;  else       tmsg = data + 30;  if ( r->m_send_addr.m_type == eIpmiAddrTypeSystemInterface )     {       // It's a message straight to the BMC.       tmsg[0] = 0x20; // To the BMC.       tmsg[1] = (r->m_msg.m_netfn << 2) | r->m_send_addr.m_lun;       tmsg[2] = Checksum( tmsg, 2 );       tmsg[3] = 0x81; // Remote console IPMI Software ID       tmsg[4] = r->m_seq << 2;       tmsg[5] = r->m_msg.m_cmd;       memcpy( tmsg + 6, r->m_msg.m_data, r->m_msg.m_data_len );       pos = r->m_msg.m_data_len + 6;       tmsg[pos] = Checksum( tmsg + 3, pos - 3 );       pos++;     }  else     {       // It's an IPMB address, route it using a send message       // command.       pos = 0;       tmsg[pos++] = 0x20; // BMC is the bridge.       tmsg[pos++] = (eIpmiNetfnApp << 2) | 0;       tmsg[pos++] = Checksum( tmsg, 2 );       tmsg[pos++] = 0x81; // Remote console IPMI Software ID       tmsg[pos++] = r->m_seq << 2;       tmsg[pos++] = eIpmiCmdSendMsg;       tmsg[pos++] =   r->m_send_addr.m_channel & 0xf                     | (1 << 6); // Turn on tracking       if ( r->m_send_addr.m_type == eIpmiAddrTypeIpmbBroadcast )	    tmsg[pos++] = 0; // Do a broadcast.       msgstart = pos;       tmsg[pos++] = r->m_send_addr.m_slave_addr;       tmsg[pos++] = (r->m_msg.m_netfn << 2) | r->m_send_addr.m_lun;       tmsg[pos++] = Checksum( tmsg + msgstart, 2 );       msgstart = pos;       tmsg[pos++] = 0x20;       tmsg[pos++] = (r->m_seq << 2) | 2; // Add 2 as the SMS Lun       tmsg[pos++] = r->m_msg.m_cmd;       memcpy( tmsg + pos, r->m_msg.m_data, r->m_msg.m_data_len );       pos += r->m_msg.m_data_len;       tmsg[pos] = Checksum( tmsg + msgstart, pos - msgstart );       pos++;       tmsg[pos] = Checksum( tmsg + 3, pos - 3 );       pos++;     }  if ( m_working_auth == 0 )     {       // No authentication, so no authcode.       data[13] = pos;       pos += 14; // Convert to pos in data     }  else     {       data[29] = pos;       int rv = AuthGen( data+13, data+9, data+5, tmsg, pos );       if ( rv )	    return SA_ERR_HPI_INVALID_PARAMS;       pos += 30; // Convert to pos in data     }  // Increment the outbound number, but make sure it's not zero.  If  // it's already zero, ignore it, we are in pre-setup.  if ( m_outbound_seq_num != 0 )     {       m_outbound_seq_num++;       if ( m_outbound_seq_num == 0 )	    m_outbound_seq_num++;     }  int rv = sendto( m_fd, data, pos, 0,                   (struct sockaddr *)&m_ip_addr,                   sizeof(struct sockaddr_in) );  if ( rv == -1 )       return SA_ERR_HPI_NOT_PRESENT;  return SA_OK;}cIpmiConLan::tResponseTypecIpmiConLan::ReadResponse( int &seq, cIpmiAddr &addr, cIpmiMsg &msg ){  unsigned char       data[dIpmiMaxLanLen];  struct sockaddr     ipaddrd;  struct sockaddr_in *ipaddr;  int                 len;  socklen_t           from_len;  uint32_t            sess_id;  unsigned char      *tmsg;  unsigned int        data_len;  from_len = sizeof( ipaddrd );  len = recvfrom( m_fd, data, dIpmiMaxLanLen, 0, &ipaddrd, &from_len );  if ( len < 0 )       return eResponseTypeError;  //stdlog << "rmcp msg: " );  //IpmiLogHex( data, len );  // Make sure the source IP matches what we expect the other end to  // be.  ipaddr = (struct sockaddr_in *)(void *)&ipaddrd;  if (    (ipaddr->sin_port != m_ip_addr.sin_port)       || (ipaddr->sin_addr.s_addr != m_ip_addr.sin_addr.s_addr) )     {       stdlog << "Dropped message due to invalid IP !\n";       return eResponseTypeError;     }  // Validate the length first, so we know that all the data in the  // buffer we will deal with is valid.  if ( len < 21 )     {        // Minimum size of an IPMI msg.       stdlog << "Dropped message because too small(1)\n";       return eResponseTypeError;     }  // Validate the RMCP portion of the message.  if (    data[0] != 6       || data[2] != 0xff )     {       stdlog << "Dropped message not valid IPMI/RMCP !\n";       return eResponseTypeError;     }  if ( data[3] == 0x06 )     {       unsigned int asf_iana = IpmiGetUint32( data+4 );       if ( asf_iana != dAsfIana || data[8] != 0x40 )          {            stdlog.Log( "Dropped message not valid RMCP pong message %04x, %04x, %02x !\n",                        asf_iana, dAsfIana, data[8] );            return eResponseTypeError;          }       m_ping_count--;       stdlog << "reading RMCP pong.\n";       return eResponseTypePong;     }  if ( data[3] != 0x07 )     {       stdlog << "Dropped message not valid IPMI/RMCP\n";       return eResponseTypeError;     }    if ( data[4] == 0 )     {       // No authentication.       if ( len < data[13] + 14 ) 	  {	    // Not enough data was supplied, reject the message.	    stdlog << "Dropped message because too small(2)\n";	    return eResponseTypeError;	  }       data_len = data[13];     }  else     {       if ( len < 37 )	  { 	    // Minimum size of an authenticated IPMI msg.	    stdlog << "Dropped message because too small(3)\n";	    return eResponseTypeError;	  }       // authcode in message, add 16 to the above checks.       if ( len < data[29] + 30 )	  {	    // Not enough data was supplied, reject the message.	    stdlog << "Dropped message because too small(4)\n";	    return eResponseTypeError;	  }       data_len = data[29];     }  // Drop if the authtypes are incompatible.  if ( m_working_auth != data[4] )     {       stdlog << "Dropped message not valid authtype\n";       return eResponseTypeError;     }  // Drop if sessions ID's don't match.  sess_id = IpmiGetUint32( data+9 );  if ( sess_id != m_session_id )     {       stdlog << "Dropped message not valid session id "              << sess_id << " != " << m_session_id << " !\n";       return eResponseTypeError;     }  seq = IpmiGetUint32( data+5 );  if ( data[4] != 0 )     {       // Validate the message's authcode.  Do this before checking       // the session seq num so we know the data is valid.       int rv = AuthCheck( data+9, data+5, data+30, data[29], data+13 );       if ( rv )          {            stdlog << "Dropped message auth fail !\n";            return eResponseTypeError;          }       tmsg = data + 30;     }  else       tmsg = data + 14;  // Check the sequence number.  if ( seq - m_inbound_seq_num <= 8 )     {       // It's after the current sequence number, but within 8.  We       // move the sequence number forward.       m_recv_msg_map <<= seq - m_inbound_seq_num;       m_recv_msg_map |= 1;       m_inbound_seq_num = seq;     }  else if ( m_inbound_seq_num - seq <= 8 )     {       // It's before the current sequence number, but within 8.       uint8_t bit = 1 << (m_inbound_seq_num - seq);       if ( m_recv_msg_map & bit )	  {	    stdlog << "Dropped message duplicate\n";	    return eResponseTypeError;	  }       m_recv_msg_map |= bit;     }  else     {       // It's outside the current sequence number range, discard       // the packet.       stdlog << "Dropped message out of seq range\n";       return eResponseTypeError;     }  // Now we have an authentic in-sequence message.  // We don't check the checksums, because the network layer should  // validate all this for us.  if ( tmsg[5] == eIpmiCmdReadEventMsgBuffer       && (tmsg[1] >> 2) == eIpmiNetfnAppRsp )     {       // event       if ( tmsg[6] != 0 )	  {	    // An error getting the events, just ignore it.	    stdlog << "Dropped message err getting event\n";	    return eResponseTypeError;	  }       addr.m_type       = eIpmiAddrTypeIpmb;       addr.m_slave_addr = tmsg[3];       addr.m_lun        = tmsg[4] & 0x3;       addr.m_channel    = 0;       msg.m_netfn    = (tIpmiNetfn)(tmsg[1] >> 2);       msg.m_cmd      = (tIpmiCmd)tmsg[5];       msg.m_data_len = data_len - 6 - 2; /* Remove completion code and checksum */       memcpy( msg.m_data, tmsg + 6 + 1, msg.m_data_len );       return eResponseTypeEvent;     }  seq = tmsg[4] >> 2;  if ( m_outstanding[seq] == 0 )     {       stdlog << "Dropped message seq not in use: " << (unsigned char)seq << " !\n";       return eResponseTypeError;     }  if ( tmsg[5] == eIpmiCmdSendMsg       && (tmsg[1] >> 2) == eIpmiNetfnAppRsp )     {       // It's a response to a sent message.       // FIXME - this entire thing is a cheap hack.       if ( tmsg[6] != 0 )	  {	    // Got an error from the send message.  We don't have any	    // IPMB information to work with, so just extract it from            // the message.            addr = m_outstanding[seq]->m_send_addr;            // Just in case it's a broadcast.	    addr.m_type = eIpmiAddrTypeIpmb;            msg.m_netfn    = (tIpmiNetfn)(m_outstanding[seq]->m_msg.m_netfn | 1);            msg.m_cmd      = m_outstanding[seq]->m_msg.m_cmd;            msg.m_data[0]  = tmsg[6];            msg.m_data_len = 1;	  }       else	  {            if ( data_len < 15 )                 return eResponseTypeError;            if ( tmsg[10] == m_slave_addr )                 addr.Si();            else               {                 addr.m_type       = eIpmiAddrTypeIpmb;                 addr.m_channel    = m_outstanding[seq]->m_send_addr.m_channel;                 addr.m_slave_addr = tmsg[10];               }            addr.m_lun = tmsg[11] & 0x3;	    msg.m_netfn    = (tIpmiNetfn)(tmsg[8] >> 2);	    msg.m_cmd      = (tIpmiCmd)tmsg[12];	    msg.m_data_len = data_len - 15;	    memcpy( msg.m_data, tmsg + 13, msg.m_data_len );	  }     }  else if ( m_outstanding[seq]->m_send_addr.m_type == eIpmiAddrTypeSystemInterface            && tmsg[3] == m_slave_addr )     {       // In some cases, a message from the IPMB looks like it came       // from the BMC itself, IMHO a misinterpretation of the       // errata.  IPMIv1_5_rev1_1_0926 markup, section 6.12.4,       // didn't clear things up at all.  Some manufacturers have       // interpreted it this way, but IMHO it is incorrect.       addr = m_outstanding[seq]->m_send_addr;       msg.m_netfn    = (tIpmiNetfn)(tmsg[1] >> 2);       msg.m_cmd      = (tIpmiCmd)tmsg[5];       msg.m_data_len = data_len - 7;       memcpy( msg.m_data, tmsg+6, msg.m_data_len );     }  else     {       // It's not encapsulated in a send message response.       if ( tmsg[3] == m_slave_addr )          {            // It's directly from the BMC, so it's a system interface            // message.            addr.Si();            addr.m_lun = tmsg[1] & 3;          }       else          {	    // A message from the IPMB.	    addr.m_type       = eIpmiAddrTypeIpmb;	    // This is a hack, but the channel does not come back in the            // message.  So we use the channel from the original            // instead.	    addr.m_channel    = m_outstanding[seq]->m_send_addr.m_channel;	    addr.m_slave_addr = tmsg[3];	    addr.m_lun        = tmsg[4] & 0x3;	}       msg.m_netfn    = (tIpmiNetfn)(tmsg[1] >> 2);       msg.m_cmd      = (tIpmiCmd)tmsg[5];       msg.m_data_len = data_len - 6 - 1; // Remove the checksum       memcpy( msg.m_data, tmsg+6, msg.m_data_len );     }  if ( (tIpmiNetfn)(m_outstanding[seq]->m_msg.m_netfn | 1) != msg.m_netfn       || m_outstanding[seq]->m_msg.m_cmd != msg.m_cmd )     {       stdlog << "Message mismatch seq " << (unsigned char)seq << ":\n" << "read ";       IpmiLogDataMsg( addr, msg );       stdlog << "\n";       stdlog << "expt ";       IpmiLogDataMsg( m_outstanding[seq]->m_send_addr,                       m_outstanding[seq]->m_msg );       stdlog << "\n";       stdlog.Hex( data, len );       stdlog << "len " << len << ", m_num_outstanding " << m_num_outstanding << ", m_queue "               << (m_queue ? "full" : "empty") << "\n";       assert( 0 );       return eResponseTypeError;     }  if ( m_outstanding[seq]->m_send_addr != m_outstanding[seq]->m_addr )       addr = m_outstanding[seq]->m_addr;  return eResponseTypeMessage;}voidcIpmiConLan::IfReadResponse(){  int       seq;  cIpmiAddr addr;  cIpmiMsg  msg;  tResponseType rt = ReadResponse( seq, addr, msg );  switch( rt )     {       case eResponseTypeError:            break;       case eResponseTypePong:            stdlog << "connection seems to be ok.\n";            HandleCheckConnection( true );            break;       case eResponseTypeTimeout:            break;       case eResponseTypeMessage:            HandleResponse( seq, addr, msg );            break;       case eResponseTypeEvent:            HandleEvent( addr, msg );            break;     }}boolcIpmiConLan::IfCheckConnection( cTime &timeout ){  stdlog << "check connection.\n";  SendPing();  timeout = cTime::Now();  timeout += m_timeout;  return true;}voidcIpmiConLan::IfCheckConnectionTimeout(){  stdlog << "connection timeout !\n";  m_queue_lock.Lock();  Reconnect();  m_queue_lock.Unlock();}

⌨️ 快捷键说明

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