/* signal handlers + sleep(3) is a bad idea, so use select(3) */ static int _sleep (unsigned int len) { struct timeval tv; tv.tv_sec = len; tv.tv_usec = 0; if (select (1, NULL, NULL, NULL, &tv) < 0) ipmi_ping_err_exit ("select: %s", strerror (errno)); return (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); }
static void _setup (void) { struct hostent *hptr; char *temp; if (signal (SIGINT, _signal_handler) == SIG_ERR) ipmi_ping_err_exit ("signal setup failed"); if ((pingtool_sockfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) ipmi_ping_err_exit ("socket: %s", strerror (errno)); memset (&pingtool_srcaddr, '\0', sizeof (pingtool_srcaddr)); pingtool_srcaddr.sin_family = AF_INET; pingtool_srcaddr.sin_port = htons (0); if (!pingtool_interface) pingtool_srcaddr.sin_addr.s_addr = htonl (INADDR_ANY); else { /* If there is a period, assume user input an IP address. No * period, assume user input an interface name */ if (strchr (pingtool_interface, '.')) { int rv; if ((rv = inet_pton (AF_INET, pingtool_interface, &pingtool_srcaddr.sin_addr)) < 0) ipmi_ping_err_exit ("inet_pton: %s", strerror (errno)); if (!rv) ipmi_ping_err_exit ("invalid interface address"); } else { struct ifreq ifr; struct sockaddr_in temp_sockaddr; _strncpy (ifr.ifr_name, pingtool_interface, IFNAMSIZ); ifr.ifr_addr.sa_family = AF_INET; if (ioctl (pingtool_sockfd, SIOCGIFADDR, &ifr) < 0) ipmi_ping_err_exit ("ioctl: %s", strerror (errno)); temp_sockaddr = *((struct sockaddr_in *)&ifr.ifr_addr); memcpy (&pingtool_srcaddr.sin_addr.s_addr, &temp_sockaddr.sin_addr.s_addr, sizeof (pingtool_srcaddr.sin_addr.s_addr)); } } if (bind (pingtool_sockfd, (struct sockaddr *)&pingtool_srcaddr, sizeof (pingtool_srcaddr)) < 0) ipmi_ping_err_exit ("bind: %s", strerror (errno)); memset (&pingtool_destaddr, '\0', sizeof (pingtool_destaddr)); pingtool_destaddr.sin_family = AF_INET; pingtool_destaddr.sin_port = htons (RMCP_PRIMARY_RMCP_PORT); if (!(hptr = gethostbyname (pingtool_dest))) { #if HAVE_HSTRERROR ipmi_ping_err_exit ("gethostbyname: %s", hstrerror (h_errno)); #else /* !HAVE_HSTRERROR */ ipmi_ping_err_exit ("gethostbyname: h_errno = %d", h_errno); #endif /* !HAVE_HSTRERROR */ } pingtool_destaddr.sin_addr = *((struct in_addr *)hptr->h_addr); temp = inet_ntoa (pingtool_destaddr.sin_addr); _strncpy (pingtool_dest_ip, temp, INET_ADDRSTRLEN); srand (time (NULL)); }
static void _cmdline_parse (int argc, char **argv, unsigned int min_sequence_number, unsigned int max_sequence_number, const char *options) { char *endptr; int c; assert (argc >= 0); assert (argv); /* Turn off error messages */ opterr = 0; while ((c = getopt (argc, argv, options)) != -1) { switch (c) { case 'h': _output_usage (options); case 'V': _output_version (); case 'r': if (!strcmp (optarg, IPMI_PING_VERSION_1_5_STR)) pingtool_version = IPMI_PING_VERSION_1_5; else if (!strcmp (optarg, IPMI_PING_VERSION_2_0_STR)) pingtool_version = IPMI_PING_VERSION_2_0; else ipmi_ping_err_exit ("invalid version"); break; case 'c': errno = 0; pingtool_count = strtol (optarg, &endptr, 10); if (errno || endptr[0] != '\0') ipmi_ping_err_exit ("count argument invalid"); if (!pingtool_count) ipmi_ping_err_exit ("count must be > 0"); break; case 'i': errno = 0; pingtool_interval = strtol (optarg, &endptr, 10); if (errno || endptr[0] != '\0') ipmi_ping_err_exit ("interval argument invalid"); if (!pingtool_interval) ipmi_ping_err_exit ("interval must be > 0"); break; case 'I': pingtool_interface = optarg; break; case 't': errno = 0; pingtool_timeout = strtol (optarg, &endptr, 10); if (errno || endptr[0] != '\0') ipmi_ping_err_exit ("timeout argument invalid"); if (!pingtool_timeout) ipmi_ping_err_exit ("timeout must be > 0"); break; case 'v': pingtool_verbose++; break; case 's': errno = 0; pingtool_initial_sequence_number = strtol (optarg, &endptr, 10); if (errno || endptr[0] != '\0') ipmi_ping_err_exit ("initial sequence number invalid"); if (pingtool_initial_sequence_number < min_sequence_number || pingtool_initial_sequence_number > max_sequence_number) ipmi_ping_err_exit ("initial sequence number out of range"); break; case 'd': pingtool_debug++; break; default: ipmi_ping_err_exit ("Command line option error"); break; } } /* last argument is destination */ if (optind >= argc) ipmi_ping_err_exit ("destination must be specified"); _strncpy (pingtool_dest, argv[optind], MAXHOSTNAMELEN); }
int createpacket (const char *destination, void *buf, unsigned int buflen, unsigned int sequence_number, int version, int debug) { fiid_obj_t obj_rmcp_hdr = NULL; fiid_obj_t obj_lan_session_hdr = NULL; fiid_obj_t obj_lan_msg_hdr = NULL; fiid_obj_t obj_cmd = NULL; int len; assert (destination); assert (buf); assert (version == IPMI_PING_VERSION_1_5 || version == IPMI_PING_VERSION_2_0); if (!buflen) return (0); if (!(obj_rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr))) ipmi_ping_err_exit ("fiid_obj_create: %s", strerror (errno)); if (!(obj_lan_session_hdr = fiid_obj_create (tmpl_lan_session_hdr))) ipmi_ping_err_exit ("fiid_obj_create: %s", strerror (errno)); if (!(obj_lan_msg_hdr = fiid_obj_create (tmpl_lan_msg_hdr_rq))) ipmi_ping_err_exit ("fiid_obj_create: %s", strerror (errno)); if (!(obj_cmd = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rq))) ipmi_ping_err_exit ("fiid_obj_create: %s", strerror (errno)); if (fill_rmcp_hdr_ipmi (obj_rmcp_hdr) < 0) ipmi_ping_err_exit ("fill_rmcp_hdr_ipmi: %s", strerror (errno)); if (fill_lan_session_hdr (IPMI_AUTHENTICATION_TYPE_NONE, 0, 0, obj_lan_session_hdr) < 0) ipmi_ping_err_exit ("fill_lan_session_hdr: %s", strerror (errno)); if (fill_lan_msg_hdr (IPMI_SLAVE_ADDRESS_BMC, IPMI_NET_FN_APP_RQ, IPMI_BMC_IPMB_LUN_BMC, sequence_number % (IPMI_RQ_SEQ_MAX+1), obj_lan_msg_hdr) < 0) ipmi_ping_err_exit ("fill_lan_msg_hdr: %s", strerror (errno)); if (version == IPMI_PING_VERSION_1_5) { if (fill_cmd_get_channel_authentication_capabilities (IPMI_CHANNEL_NUMBER_CURRENT_CHANNEL, IPMI_PRIVILEGE_LEVEL_USER, IPMI_GET_IPMI_V15_DATA, obj_cmd) < 0) ipmi_ping_err_exit ("fill_cmd_get_channel_authentication_capabilities: %s", strerror (errno)); } else { if (fill_cmd_get_channel_authentication_capabilities (IPMI_CHANNEL_NUMBER_CURRENT_CHANNEL, IPMI_PRIVILEGE_LEVEL_USER, IPMI_GET_IPMI_V20_EXTENDED_DATA, obj_cmd) < 0) ipmi_ping_err_exit ("fill_cmd_get_channel_authentication_capabilities: %s", strerror (errno)); } if ((len = assemble_ipmi_lan_pkt (obj_rmcp_hdr, obj_lan_session_hdr, obj_lan_msg_hdr, obj_cmd, NULL, 0, buf, buflen, IPMI_INTERFACE_FLAGS_DEFAULT)) < 0) ipmi_ping_err_exit ("assemble_ipmi_lan_pkt: %s", strerror (errno)); if (debug) { char hdrbuf[DEBUG_UTIL_HDR_BUFLEN]; debug_hdr_cmd ((version == IPMI_PING_VERSION_1_5) ? DEBUG_UTIL_TYPE_IPMI_1_5 : DEBUG_UTIL_TYPE_IPMI_2_0, DEBUG_UTIL_DIRECTION_REQUEST, IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES, 0, hdrbuf, DEBUG_UTIL_HDR_BUFLEN); if (ipmi_dump_lan_packet (STDERR_FILENO, destination, hdrbuf, NULL, buf, len, tmpl_lan_msg_hdr_rq, tmpl_cmd_get_channel_authentication_capabilities_rq) < 0) ipmi_ping_err_exit ("ipmi_dump_lan_packet: %s", strerror (errno)); } fiid_obj_destroy (obj_rmcp_hdr); fiid_obj_destroy (obj_lan_session_hdr); fiid_obj_destroy (obj_lan_msg_hdr); fiid_obj_destroy (obj_cmd); return (len); }
int parsepacket (const char *destination, const void *buf, unsigned int buflen, const char *from, unsigned int sequence_number, int verbose, int version, int debug) { fiid_obj_t obj_rmcp_hdr = NULL; fiid_obj_t obj_lan_session_hdr = NULL; fiid_obj_t obj_lan_msg_hdr = NULL; fiid_obj_t obj_cmd = NULL; fiid_obj_t obj_lan_msg_trlr = NULL; uint8_t req_seq, none, md2, md5, straight_password_key, oem, anonymous_login, null_username, non_null_username, user_level_authentication, per_message_authentication, k_g, ipmi_v20_extended_capabilities_available, ipmi_v15, ipmi_v20; uint64_t val; int ret, rv = -1; assert (destination); assert (buf); assert (from); assert (version == IPMI_PING_VERSION_1_5 || version == IPMI_PING_VERSION_2_0); if (!buflen) return (0); if (!(obj_rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr))) ipmi_ping_err_exit ("fiid_obj_create: %s", strerror (errno)); if (!(obj_lan_session_hdr = fiid_obj_create (tmpl_lan_session_hdr))) ipmi_ping_err_exit ("fiid_obj_create: %s", strerror (errno)); if (!(obj_lan_msg_hdr = fiid_obj_create (tmpl_lan_msg_hdr_rs))) ipmi_ping_err_exit ("fiid_obj_create: %s", strerror (errno)); if (!(obj_cmd = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rs))) ipmi_ping_err_exit ("fiid_obj_create: %s", strerror (errno)); if (!(obj_lan_msg_trlr = fiid_obj_create (tmpl_lan_msg_trlr))) ipmi_ping_err_exit ("fiid_obj_create: %s", strerror (errno)); if (debug) { char hdrbuf[DEBUG_UTIL_HDR_BUFLEN]; debug_hdr_cmd ((version == IPMI_PING_VERSION_1_5) ? DEBUG_UTIL_TYPE_IPMI_1_5 : DEBUG_UTIL_TYPE_IPMI_2_0, DEBUG_UTIL_DIRECTION_RESPONSE, IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES, 0, hdrbuf, DEBUG_UTIL_HDR_BUFLEN); if (ipmi_dump_lan_packet (STDERR_FILENO, destination, hdrbuf, NULL, buf, buflen, tmpl_lan_msg_hdr_rs, tmpl_cmd_get_channel_authentication_capabilities_rs) < 0) ipmi_ping_err_exit ("ipmi_dump_lan_packet: %s", strerror (errno)); } if ((ret = ipmi_lan_check_packet_checksum (buf, buflen)) < 0) ipmi_ping_err_exit ("ipmi_lan_check_checksum: %s", strerror (errno)); if (!ret) { if (debug) fprintf (stderr, "%s(%d): checksum failed\n", __FUNCTION__, __LINE__); rv = 0; goto cleanup; } if ((ret = unassemble_ipmi_lan_pkt (buf, buflen, obj_rmcp_hdr, obj_lan_session_hdr, obj_lan_msg_hdr, obj_cmd, obj_lan_msg_trlr, IPMI_INTERFACE_FLAGS_DEFAULT)) < 0) ipmi_ping_err_exit ("unassemble_ipmi_lan_pkt: %s", strerror (errno)); if (!ret) { if (debug) fprintf (stderr, "%s(%d): Could not unassemble packet\n", __FUNCTION__, __LINE__); rv = 0; goto cleanup; } if ((ret = ipmi_lan_check_net_fn (obj_lan_msg_hdr, IPMI_NET_FN_APP_RS)) < 0) ipmi_ping_err_exit ("ipmi_lan_check_net_fn: %s", strerror (errno)); if (!ret) { if (debug) fprintf (stderr, "%s(%d): net_fn failed\n", __FUNCTION__, __LINE__); rv = 0; goto cleanup; } if ((ret = ipmi_check_cmd (obj_cmd, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES)) < 0) ipmi_ping_err_exit ("ipmi_check_cmd: %s", strerror (errno)); if (!ret) { if (debug) fprintf (stderr, "%s(%d): cmd failed\n", __FUNCTION__, __LINE__); rv = 0; goto cleanup; } if ((ret = ipmi_check_completion_code_success (obj_cmd)) < 0) ipmi_ping_err_exit ("ipmi_check_comp_code: %s", strerror (errno)); if (!ret) { if (debug) fprintf (stderr, "%s(%d): comp_code failed\n", __FUNCTION__, __LINE__); rv = 0; goto cleanup; } if (FIID_OBJ_GET (obj_lan_msg_hdr, "rq_seq", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'rq_seq': %s", fiid_obj_errormsg (obj_lan_msg_hdr)); req_seq = val; if (req_seq != sequence_number % (IPMI_RQ_SEQ_MAX + 1)) { if (debug) fprintf (stderr, "%s(%d): req_seq failed\n", __FUNCTION__, __LINE__); rv = 0; goto cleanup; } printf ("response received from %s: rq_seq=%u", from, req_seq); if (verbose) { if (FIID_OBJ_GET (obj_cmd, "authentication_type.none", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_type.none': %s", fiid_obj_errormsg (obj_cmd)); none = val; if (FIID_OBJ_GET (obj_cmd, "authentication_type.md2", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_type.md2': %s", fiid_obj_errormsg (obj_cmd)); md2 = val; if (FIID_OBJ_GET (obj_cmd, "authentication_type.md5", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_type.md5': %s", fiid_obj_errormsg (obj_cmd)); md5 = val; if (FIID_OBJ_GET (obj_cmd, "authentication_type.straight_password_key", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_type.straight_password_key': %s", fiid_obj_errormsg (obj_cmd)); straight_password_key = val; if (FIID_OBJ_GET (obj_cmd, "authentication_type.oem_prop", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_type.oem_prop': %s", fiid_obj_errormsg (obj_cmd)); oem = val; if (FIID_OBJ_GET (obj_cmd, "authentication_status.anonymous_login", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_status.anonymous_login': %s", fiid_obj_errormsg (obj_cmd)); anonymous_login = val; if (FIID_OBJ_GET (obj_cmd, "authentication_status.null_username", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_status.null_username': %s", fiid_obj_errormsg (obj_cmd)); null_username = val; if (FIID_OBJ_GET (obj_cmd, "authentication_status.non_null_username", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_status.non_null_username': %s", fiid_obj_errormsg (obj_cmd)); non_null_username = val; if (FIID_OBJ_GET (obj_cmd, "authentication_status.user_level_authentication", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_status.user_level_authentication': %s", fiid_obj_errormsg (obj_cmd)); user_level_authentication = val; if (FIID_OBJ_GET (obj_cmd, "authentication_status.per_message_authentication", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_status.per_message_authentication': %s", fiid_obj_errormsg (obj_cmd)); per_message_authentication = val; if (FIID_OBJ_GET (obj_cmd, "authentication_status.per_message_authentication", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_status.per_message_authentication': %s", fiid_obj_errormsg (obj_cmd)); per_message_authentication = val; printf (", auth: none=%s md2=%s md5=%s password=%s oem=%s anon=%s null=%s non-null=%s user=%s permsg=%s ", _setstr (none), _setstr (md2), _setstr (md5), _setstr (straight_password_key),_setstr (oem), _setstr (anonymous_login), _setstr (null_username), _setstr (non_null_username), _setstr (user_level_authentication), _setstr (per_message_authentication)); if (version == IPMI_PING_VERSION_2_0) { if (FIID_OBJ_GET (obj_cmd, "authentication_type.ipmi_v2.0_extended_capabilities_available", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_type.ipmi_v2.0_extended_capabilities_available': %s", fiid_obj_errormsg (obj_cmd)); ipmi_v20_extended_capabilities_available = val; if (FIID_OBJ_GET (obj_cmd, "authentication_status.k_g", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'authentication_status.k_g': %s", fiid_obj_errormsg (obj_cmd)); k_g = val; printf ("k_g=%s ipmi_v2.0_extended_capabilities_available=%s ", _setstr (k_g), _setstr (ipmi_v20_extended_capabilities_available)); if (ipmi_v20_extended_capabilities_available) { if (FIID_OBJ_GET (obj_cmd, "channel_supports_ipmi_v1.5_connections", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'channel_supports_ipmi_v1.5_connections': %s", fiid_obj_errormsg (obj_cmd)); ipmi_v15 = val; if (FIID_OBJ_GET (obj_cmd, "channel_supports_ipmi_v2.0_connections", &val) < 0) ipmi_ping_err_exit ("fiid_obj_get: 'channel_supports_ipmi_v2.0_connections': %s", fiid_obj_errormsg (obj_cmd)); ipmi_v20 = val; printf ("ipmi_v1.5=%s ipmi_v2.0=%s ", _setstr (ipmi_v15), _setstr (ipmi_v20)); } } } printf ("\n"); rv = 1; cleanup: fiid_obj_destroy (obj_rmcp_hdr); fiid_obj_destroy (obj_lan_session_hdr); fiid_obj_destroy (obj_lan_msg_hdr); fiid_obj_destroy (obj_cmd); fiid_obj_destroy (obj_lan_msg_trlr); return (rv); }
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); }