Пример #1
0
static void 
_main_loop(Ipmi_Ping_CreatePacket _create, 
           Ipmi_Ping_ParsePacket _parse, 
           Ipmi_Ping_LatePacket _late) 
{
  unsigned int sequence_number = 0;
  time_t last_send = 0;
  int ret;

  assert(_create != NULL 
         && _parse != NULL 
         && _late != NULL
         && _progname != NULL 
         && _end_result != NULL);

  if (_initial_sequence_number < 0)
    {
      int len;

      if ((len = ipmi_get_random((uint8_t *)&_initial_sequence_number,
                                 sizeof(_initial_sequence_number))) < 0)
        ipmi_ping_err_exit("ipmi_get_random: %s", strerror(errno));
      if (len != sizeof(_initial_sequence_number))
        ipmi_ping_err_exit("ipmi_get_random: invalid len returned");
    }

  sequence_number = _initial_sequence_number;

  printf("%s %s (%s)\n", _progname, _dest, _dest_ip);

  while (_count == -1 || (_pkt_sent < _count)) 
    {
      int rv, len, received = 0;
      uint8_t buffer[IPMI_PING_MAX_PKT_LEN];
      time_t now;

      /* wait if necessary */
      now = time(NULL);
      if ((now - last_send) < _interval) 
        {
          if (_sleep((last_send + _interval - now)) < 0)
            continue;
        }
      
      if ((len = _create(_dest, (char *)buffer, IPMI_PING_MAX_PKT_LEN, 
                         sequence_number, _version, _debug)) < 0)
        ipmi_ping_err_exit("_create failed: %s", strerror(errno));
        
      rv = ipmi_lan_sendto(_sockfd, buffer, len, 0, 
                           (struct sockaddr *)&_destaddr, sizeof(_destaddr));
      if (rv < 0)
        ipmi_ping_err_exit("ipmi_sendto: %s", strerror(errno));
      
      if (rv != len)
        ipmi_ping_err_exit("ipmi_sendto: wrong bytes written"); 
      
      last_send = time(NULL);
      
      _pkt_sent++;

      while (((now = time(NULL)) - last_send) < _timeout) 
        {
          fd_set rset;
          struct timeval tv;
          
          FD_ZERO(&rset);
          FD_SET(_sockfd, &rset);

          tv.tv_sec = (last_send + _timeout - now);
          tv.tv_usec = 0;
        
          if ((rv = select(_sockfd+1, &rset, NULL, NULL, &tv)) < 0)
            ipmi_ping_err_exit("select: %s", strerror(errno));
        
          if (rv == 1) 
            {
              struct sockaddr_in from;
              socklen_t fromlen;
              
              fromlen = sizeof(from);
              len = ipmi_lan_recvfrom(_sockfd, buffer, IPMI_PING_MAX_PKT_LEN, 0,
                                      (struct sockaddr *)&from, &fromlen);
              if (len < 0)
                ipmi_ping_err_exit("ipmi_recvfrom: %s", strerror(errno));
              
              if ((rv = _parse(_dest, (char *)buffer, len, inet_ntoa(from.sin_addr), 
                               sequence_number, _verbose, _version, _debug)) < 0)
                ipmi_ping_err_exit("_parse failed: %s", strerror(errno));

              /* If rv == 0, the sequence numbers don't match, so
               * we'll wait some more for the latest packet we sent
               * out.
               */
              if (rv == 0)
                continue;

              received++;
              _pkt_recv++;
              break;
            }
        }
      
      if (received == 0)
        _late(sequence_number);
      
      sequence_number++;
    }
  
  ret = _end_result(_progname, _dest, _pkt_sent, _pkt_recv);
  _cleanup();
  exit(ret);
}
Пример #2
0
static void
_main_loop (Ipmi_Ping_CreatePacket create,
            Ipmi_Ping_ParsePacket parse,
            Ipmi_Ping_LatePacket late)
{
  unsigned int sequence_number = 0;
  time_t last_send = 0;
  int ret;

  assert (create);
  assert (parse);
  assert (late);
  assert (pingtool_progname);
  assert (pingtool_end_result);

  if (pingtool_initial_sequence_number < 0)
    {
      int len;

      if ((len = ipmi_get_random (&pingtool_initial_sequence_number,
                                  sizeof (pingtool_initial_sequence_number))) < 0)
        ipmi_ping_err_exit ("ipmi_get_random: %s", strerror (errno));
      if (len != sizeof (pingtool_initial_sequence_number))
        ipmi_ping_err_exit ("ipmi_get_random: invalid len returned");
    }

  sequence_number = pingtool_initial_sequence_number;

  printf ("%s %s (%s)\n", pingtool_progname, pingtool_dest, pingtool_dest_ip);

  while (pingtool_count == -1 || (pingtool_pkt_sent < pingtool_count))
    {
      int rv, len, received = 0;
      uint8_t buf[IPMI_PING_MAX_PKT_LEN];
      time_t now;

      /* wait if necessary */
      now = time (NULL);
      if ((now - last_send) < pingtool_interval)
        {
          if (_sleep ((last_send + pingtool_interval - now)) < 0)
            continue;
        }

      if ((len = create (pingtool_dest,
                         buf,
                         IPMI_PING_MAX_PKT_LEN,
                         sequence_number,
                         pingtool_version,
                         pingtool_debug)) < 0)
        ipmi_ping_err_exit ("_create failed: %s", strerror (errno));

      rv = ipmi_lan_sendto (pingtool_sockfd,
                            buf,
                            len,
                            0,
                            (struct sockaddr *)&pingtool_destaddr,
                            sizeof (pingtool_destaddr));
      if (rv < 0)
        ipmi_ping_err_exit ("ipmi_sendto: %s", strerror (errno));

      if (rv != len)
        ipmi_ping_err_exit ("ipmi_sendto: wrong bytes written");

      last_send = time (NULL);

      pingtool_pkt_sent++;

      while (((now = time (NULL)) - last_send) < pingtool_timeout)
        {
          fd_set rset;
          struct timeval tv;

          FD_ZERO (&rset);
          FD_SET (pingtool_sockfd, &rset);

          tv.tv_sec = (last_send + pingtool_timeout - now);
          tv.tv_usec = 0;

          if ((rv = select (pingtool_sockfd+1, &rset, NULL, NULL, &tv)) < 0)
            ipmi_ping_err_exit ("select: %s", strerror (errno));

          if (rv == 1)
            {
              struct sockaddr_in from;
              socklen_t fromlen;

              fromlen = sizeof (from);
              len = ipmi_lan_recvfrom (pingtool_sockfd,
                                       buf,
                                       IPMI_PING_MAX_PKT_LEN,
                                       0,
                                       (struct sockaddr *)&from,
                                       &fromlen);
              
              /* achu & hliebig:
               *
               * Premise from ipmitool (http://ipmitool.sourceforge.net/)
               *
               * On some OSes (it seems Unixes), the behavior is to not return
               * port denied errors up to the client for UDP responses (i.e. you
               * need to timeout).  But on some OSes (it seems Windows), the
               * behavior is to return port denied errors up to the user for UDP
               * responses via ECONNRESET or ECONNREFUSED.
               *
               * If this were just the case, we could return or handle errors
               * properly and move on.  However, it's not the case.
               *
               * According to Ipmitool, on some motherboards, both the OS and the
               * BMC are capable of responding to an IPMI request.  That means you
               * can get an ECONNRESET or ECONNREFUSED, then later on, get your
               * real IPMI response.
               *
               * Our solution is copied from Ipmitool, we'll ignore some specific
               * errors and try to read again.
               *
               * If the ECONNREFUSED or ECONNRESET is from the OS, but we will get
               * an IPMI response later, the recvfrom later on gets the packet we
               * want.
               *
               * If the ECONNREFUSED or ECONNRESET is from the OS but there is no
               * BMC (or IPMI disabled, etc.), just do the recvfrom again to
               * eventually get a timeout, which is the behavior we'd like.
               */

              if (len < 0
                  && (errno == ECONNRESET
                      || errno == ECONNREFUSED))
                continue;

              if (len < 0)
                ipmi_ping_err_exit ("ipmi_recvfrom: %s", strerror (errno));

              if ((rv = parse (pingtool_dest,
                               buf,
                               len,
                               inet_ntoa (from.sin_addr),
                               sequence_number,
                               pingtool_verbose,
                               pingtool_version,
                               pingtool_debug)) < 0)
                ipmi_ping_err_exit ("_parse failed: %s", strerror (errno));

              /* If rv == 0, the sequence numbers don't match, so
               * we'll wait some more for the latest packet we sent
               * out.
               */
              if (!rv)
                continue;

              received++;
              pingtool_pkt_recv++;
              break;
            }
        }

      if (!received)
        late (sequence_number);

      sequence_number++;
    }

  ret = pingtool_end_result (pingtool_progname,
                             pingtool_dest,
                             pingtool_pkt_sent,
                             pingtool_pkt_recv);
  _cleanup ();
  exit (ret);
}
Пример #3
0
/*
 * Return 0 on success
 * Return -1 on fatal error
 */
static int
_ipmi_sendto (ipmiconsole_ctx_t c)
{
  char buffer[IPMICONSOLE_PACKET_BUFLEN];
  ssize_t len;
  int n;

  assert (c);
  assert (c->magic == IPMICONSOLE_CTX_MAGIC);

  if ((n = scbuf_read (c->connection.ipmi_to_bmc, buffer, IPMICONSOLE_PACKET_BUFLEN)) < 0)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("scbuf_read: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR);
      return (-1);
    }

  if (ipmi_is_ipmi_1_5_packet (buffer, n))
    {
      do
	{
	  len = ipmi_lan_sendto (c->connection.ipmi_fd,
				 buffer,
				 n,
				 0,
				 (struct sockaddr *)&(c->session.addr),
				 sizeof (struct sockaddr_in));
	} while (len < 0 && errno == EINTR);
    }
  else
    {
      do
	{
	  len = ipmi_rmcpplus_sendto (c->connection.ipmi_fd,
				      buffer,
				      n,
				      0,
				      (struct sockaddr *)&(c->session.addr),
				      sizeof (struct sockaddr_in));
	} while (len < 0 && errno == EINTR);
    }

  if (len < 0)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("ipmi_lan_sendto: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      return (-1);
    }

#if 0
  /* don't check, let bad packet timeout */
  if (len != n)
    {
      IPMICONSOLE_CTX_DEBUG (c, ("ipmi_lan_sendto: invalid bytes written; n=%d; len=%d", n, len));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      return (-1);
    }
#endif

  /* scbuf should be empty now */
  if (!scbuf_is_empty (c->connection.ipmi_to_bmc))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("ipmi_to_bmc not empty"));
      /* Note: Not a fatal error, just return*/
      return (0);
    }

  return (0);
}