int debug_hdr_cmd (uint8_t packet_type, uint8_t packet_direction, uint8_t net_fn, uint8_t cmd, uint8_t group_extension, char *hdrbuf, unsigned int hdrbuf_len) { const char *str_cmd; unsigned int packet_flags = 0; if (IPMI_NET_FN_GROUP_EXTENSION (net_fn)) { if (group_extension == IPMI_NET_FN_GROUP_EXTENSION_IDENTIFICATION_DCMI) str_cmd = ipmi_cmd_dcmi_str (cmd); else str_cmd = "Unknown"; packet_flags = DEBUG_UTIL_FLAGS_GROUP_EXTENSION; } else if (IPMI_NET_FN_OEM_GROUP (net_fn)) { str_cmd = "Unknown"; packet_flags = DEBUG_UTIL_FLAGS_OEM_GROUP; } else if (IPMI_NET_FN_CONTROLLER_SPECIFIC_OEM_GROUP (net_fn)) { str_cmd = "Unknown"; packet_flags = DEBUG_UTIL_FLAGS_OEM; } else str_cmd = ipmi_cmd_str (net_fn, cmd); return (debug_hdr_str (packet_type, packet_direction, packet_flags, str_cmd, hdrbuf, hdrbuf_len)); }
int ipmi_sdr_cache_create (ipmi_sdr_ctx_t ctx, ipmi_ctx_t ipmi_ctx, const char *filename, int cache_create_flags, Ipmi_Sdr_Cache_Create_Callback create_callback, void *create_callback_data) { int open_flags; uint8_t sdr_version; uint16_t record_count, reservation_id, record_id, next_record_id; uint32_t most_recent_addition_timestamp, most_recent_erase_timestamp; unsigned int record_count_written = 0; unsigned int total_bytes_written = 0; uint16_t *record_ids = NULL; unsigned int record_ids_count = 0; unsigned int cache_create_flags_mask = (IPMI_SDR_CACHE_CREATE_FLAGS_OVERWRITE | IPMI_SDR_CACHE_CREATE_FLAGS_DUPLICATE_RECORD_ID | IPMI_SDR_CACHE_CREATE_FLAGS_ASSUME_MAX_SDR_RECORD_COUNT); uint8_t trailer_checksum = 0; int fd = -1; int rv = -1; if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC) { ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx)); return (-1); } /* Version cannot be 0h according to the IPMI spec */ if (!ipmi_ctx || !filename || (strlen (filename) > MAXPATHLEN) || (cache_create_flags & ~cache_create_flags_mask)) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS); return (-1); } if (ctx->operation != IPMI_SDR_OPERATION_UNINITIALIZED) { if (ctx->operation == IPMI_SDR_OPERATION_READ_CACHE) SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CONTEXT_PERFORMING_OTHER_OPERATION); else SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_INTERNAL_ERROR); return (-1); } ctx->operation = IPMI_SDR_OPERATION_CREATE_CACHE; if (cache_create_flags & IPMI_SDR_CACHE_CREATE_FLAGS_OVERWRITE) open_flags = O_CREAT | O_TRUNC | O_WRONLY; else open_flags = O_CREAT | O_EXCL | O_WRONLY; if ((fd = open (filename, open_flags, 0644)) < 0) { if (!(cache_create_flags & IPMI_SDR_CACHE_CREATE_FLAGS_OVERWRITE) && errno == EEXIST) SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_CREATE_CACHE_EXISTS); else if (errno == EPERM || errno == EACCES || errno == EISDIR || errno == EROFS) SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PERMISSION); else if (errno == ENAMETOOLONG || errno == ENOENT || errno == ELOOP) SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_FILENAME_INVALID); else if (errno == ENOSPC || errno == EMFILE || errno == ENFILE) SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_FILESYSTEM); else SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR); goto cleanup; } if (sdr_info (ctx, ipmi_ctx, &sdr_version, &record_count, &most_recent_addition_timestamp, &most_recent_erase_timestamp) < 0) goto cleanup; if (!record_count) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_CREATE_INVALID_RECORD_COUNT); goto cleanup; } if (_sdr_cache_header_write (ctx, ipmi_ctx, fd, &total_bytes_written, sdr_version, record_count, most_recent_addition_timestamp, most_recent_erase_timestamp) < 0) goto cleanup; /* Version cannot be 0h according to the IPMI spec, but we accept it regardless */ ctx->sdr_version = sdr_version; ctx->record_count = record_count; ctx->most_recent_addition_timestamp = most_recent_addition_timestamp; ctx->most_recent_erase_timestamp = most_recent_erase_timestamp; if (cache_create_flags & IPMI_SDR_CACHE_CREATE_FLAGS_DUPLICATE_RECORD_ID) { if (!(record_ids = (uint16_t *)malloc (ctx->record_count * sizeof (uint16_t)))) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_OUT_OF_MEMORY); goto cleanup; } record_ids_count = 0; } if (_sdr_cache_reservation_id (ctx, ipmi_ctx, &reservation_id) < 0) goto cleanup; next_record_id = IPMI_SDR_RECORD_ID_FIRST; while (next_record_id != IPMI_SDR_RECORD_ID_LAST) { uint8_t record_buf[IPMI_SDR_MAX_RECORD_LENGTH]; int record_len; if (record_count_written >= ctx->record_count) { /* IPMI Workaround * * Discovered on unspecified Inspur motherboard * * SDR record reading is broken, the IPMI_SDR_RECORD_ID_LAST * record id never occurs. So this workaround allows the * user to not error out and avoids this loop from looping * infinitely. * */ if (cache_create_flags & IPMI_SDR_CACHE_CREATE_FLAGS_ASSUME_MAX_SDR_RECORD_COUNT) break; SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_CREATE_INVALID_RECORD_COUNT); goto cleanup; } record_id = next_record_id; if ((record_len = _sdr_cache_get_record (ctx, ipmi_ctx, record_id, record_buf, IPMI_SDR_MAX_RECORD_LENGTH, &reservation_id, &next_record_id)) < 0) goto cleanup; if (record_len) { if (ctx->flags & IPMI_SDR_FLAGS_DEBUG_DUMP) { const char *record_str; if ((record_str = sdr_record_type_str (ctx, record_buf, record_len))) { char hdrbuf[IPMI_SDR_CACHE_DEBUG_BUFLEN]; debug_hdr_str (DEBUG_UTIL_TYPE_NONE, DEBUG_UTIL_DIRECTION_NONE, DEBUG_UTIL_FLAGS_DEFAULT, record_str, hdrbuf, IPMI_SDR_CACHE_DEBUG_BUFLEN); ipmi_dump_sdr_record (STDERR_FILENO, ctx->debug_prefix, hdrbuf, NULL, record_buf, record_len); } } if (_sdr_cache_record_write (ctx, fd, &total_bytes_written, record_ids, &record_ids_count, record_buf, record_len, &trailer_checksum) < 0) goto cleanup; record_count_written++; if (create_callback) (*create_callback)(ctx->sdr_version, ctx->record_count, ctx->most_recent_addition_timestamp, ctx->most_recent_erase_timestamp, record_id, create_callback_data); } } if (record_count_written != ctx->record_count) { /* * IPMI Workaround (achu) * * Discovered on Fujitsu RX 100 * Discovered on Fujitsu RX300/200-S8 * * The record_count listed from the Get SDR Repository Info command * is not consistent with the length of SDR records stored. * * We will assume that if we reached the end of the SDR record * list (i.e. next_record_id == 0xFFFF), a non-zero number of * records were written, it's ok and we can continue on. */ if (next_record_id == IPMI_SDR_RECORD_ID_LAST && record_count_written) { unsigned int total_bytes_written_temp = 0; ctx->record_count = record_count_written; /* need to seek back to the beginning of the file and * re-write the header info with the correct number of * records */ if (lseek (fd, 0, SEEK_SET) < 0) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR); goto cleanup; } if (_sdr_cache_header_write (ctx, ipmi_ctx, fd, &total_bytes_written_temp, ctx->sdr_version, ctx->record_count, ctx->most_recent_addition_timestamp, ctx->most_recent_erase_timestamp) < 0) goto cleanup; /* need to seek back to the end of the file to write the * trailer below */ if (lseek (fd, 0, SEEK_END) < 0) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_SYSTEM_ERROR); goto cleanup; } } else { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_CREATE_INVALID_RECORD_COUNT); goto cleanup; } } if (_sdr_cache_trailer_write (ctx, ipmi_ctx, fd, total_bytes_written, trailer_checksum) < 0) goto cleanup; if (fsync (fd) < 0) { SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno); goto cleanup; } if (close (fd) < 0) { SDR_ERRNO_TO_SDR_ERRNUM (ctx, errno); goto cleanup; } fd = -1; rv = 0; ctx->errnum = IPMI_SDR_ERR_SUCCESS; cleanup: ctx->operation = IPMI_SDR_OPERATION_UNINITIALIZED; if (fd >= 0) { /* If the cache create never completed, try to remove the file */ /* ignore potential error, cleanup path */ unlink (filename); /* ignore potential error, cleanup path */ close (fd); } free (record_ids); sdr_init_ctx (ctx); return (rv); }
void ipmipower_ping_process_pings (int *timeout) { int i, send_pings_flag = 0; struct timeval cur_time, result; unsigned int ms_time; assert (timeout); if (!cmd_args.common_args.hostname) return; if (!cmd_args.ping_interval) return; if (gettimeofday (&cur_time, NULL) < 0) { IPMIPOWER_ERROR (("gettimeofday: %s", strerror (errno))); exit (EXIT_FAILURE); } if (timeval_gt (&cur_time, &next_ping_sends_time) || force_discovery_sweep) { force_discovery_sweep = 0; timeval_add_ms (&cur_time, cmd_args.ping_interval, &next_ping_sends_time); send_pings_flag++; } for (i = 0; i < ics_len; i++) { uint8_t buf[IPMIPOWER_PACKET_BUFLEN]; int ret, len; if (send_pings_flag) { int dropped = 0; memset (buf, '\0', IPMIPOWER_PACKET_BUFLEN); /* deal with packet heuristics */ if (cmd_args.ping_packet_count && cmd_args.ping_percent) { if (ics[i].ping_packet_count_send == cmd_args.ping_packet_count) { if ((((double)(ics[i].ping_packet_count_send - ics[i].ping_packet_count_recv))/ics[i].ping_packet_count_send) > ((double)cmd_args.ping_percent/100)) ics[i].link_state = IPMIPOWER_LINK_STATE_BAD; else ics[i].link_state = IPMIPOWER_LINK_STATE_GOOD; ics[i].ping_packet_count_send = 0; ics[i].ping_packet_count_recv = 0; } } if (cmd_args.ping_consec_count) { if (!ics[i].ping_last_packet_recv_flag) ics[i].ping_consec_count = 0; ics[i].ping_last_packet_recv_flag = 0; } /* must increment count before setting message tag, so we * can check sequence number correctly later on */ ics[i].ping_sequence_number_counter++; /* Workaround * * Some motherboards don't support RMCP ping/pong :-( * * Discovered on Intel Windmill, Quanta Winterfell, and Wiwynn Windmill */ if (cmd_args.common_args.section_specific_workaround_flags & IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING) { 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; if (!(obj_rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } if (!(obj_lan_session_hdr = fiid_obj_create (tmpl_lan_session_hdr))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } if (!(obj_lan_msg_hdr = fiid_obj_create (tmpl_lan_msg_hdr_rq))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } if (!(obj_cmd = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rq))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } if (fill_rmcp_hdr_ipmi (obj_rmcp_hdr) < 0) { IPMIPOWER_ERROR (("fill_rmcp_hdr_ipmi: %s", strerror (errno))); exit (EXIT_FAILURE); } if (fill_lan_session_hdr (IPMI_AUTHENTICATION_TYPE_NONE, 0, 0, obj_lan_session_hdr) < 0) { IPMIPOWER_ERROR (("fill_lan_session_hdr: %s", strerror (errno))); exit (EXIT_FAILURE); } if (fill_lan_msg_hdr (IPMI_SLAVE_ADDRESS_BMC, IPMI_NET_FN_APP_RQ, IPMI_BMC_IPMB_LUN_BMC, (ics[i].ping_sequence_number_counter % (IPMI_RQ_SEQ_MAX + 1)), obj_lan_msg_hdr) < 0) { IPMIPOWER_ERROR (("fill_lan_msg_hdr: %s", strerror (errno))); exit (EXIT_FAILURE); } if (fill_cmd_get_channel_authentication_capabilities (IPMI_CHANNEL_NUMBER_CURRENT_CHANNEL, IPMI_PRIVILEGE_LEVEL_USER, IPMI_GET_IPMI_V15_DATA, obj_cmd) < 0) { IPMIPOWER_ERROR (("fill_cmd_get_channel_authentication_capabilities: %s", strerror (errno))); exit (EXIT_FAILURE); } if ((len = assemble_ipmi_lan_pkt (obj_rmcp_hdr, obj_lan_session_hdr, obj_lan_msg_hdr, obj_cmd, NULL, 0, buf, IPMIPOWER_PACKET_BUFLEN, IPMI_INTERFACE_FLAGS_DEFAULT)) < 0) { IPMIPOWER_ERROR (("assemble_ipmi_lan_pkt: %s", strerror (errno))); exit (EXIT_FAILURE); } #ifndef NDEBUG if (cmd_args.rmcpdump) { char hdrbuf[DEBUG_UTIL_HDR_BUFLEN]; const char *str_cmd = NULL; str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES); debug_hdr_str (DEBUG_UTIL_TYPE_IPMI_1_5, DEBUG_UTIL_DIRECTION_REQUEST, DEBUG_UTIL_FLAGS_DEFAULT, str_cmd, hdrbuf, DEBUG_UTIL_HDR_BUFLEN); if (ipmi_dump_lan_packet (STDERR_FILENO, ics[i].hostname, hdrbuf, NULL, buf, len, tmpl_lan_msg_hdr_rq, tmpl_cmd_get_channel_authentication_capabilities_rq) < 0) IPMIPOWER_DEBUG (("ipmi_dump_lan_packet: %s", strerror (errno))); } #endif /* NDEBUG */ 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); } else /* !IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING */ { fiid_obj_t rmcp_hdr = NULL; fiid_obj_t rmcp_ping = NULL; if (!(rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } if (!(rmcp_ping = fiid_obj_create (tmpl_cmd_asf_presence_ping))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } if (fill_rmcp_hdr_asf (rmcp_hdr) < 0) { IPMIPOWER_ERROR (("fill_rmcp_hdr_asf: %s", strerror (errno))); exit (EXIT_FAILURE); } if (fill_cmd_asf_presence_ping ((ics[i].ping_sequence_number_counter % (RMCP_ASF_MESSAGE_TAG_MAX + 1)), rmcp_ping) < 0) { IPMIPOWER_ERROR (("fill_cmd_asf_presence_ping: %s", strerror (errno))); exit (EXIT_FAILURE); } if ((len = assemble_rmcp_pkt (rmcp_hdr, rmcp_ping, buf, IPMIPOWER_PACKET_BUFLEN, IPMI_INTERFACE_FLAGS_DEFAULT)) < 0) { IPMIPOWER_ERROR (("assemble_rmcp_pkt: %s", strerror (errno))); exit (EXIT_FAILURE); } #ifndef NDEBUG if (cmd_args.rmcpdump) { char hdrbuf[DEBUG_UTIL_HDR_BUFLEN]; debug_hdr_str (DEBUG_UTIL_TYPE_NONE, DEBUG_UTIL_DIRECTION_NONE, DEBUG_UTIL_FLAGS_DEFAULT, DEBUG_UTIL_RMCPPING_STR, hdrbuf, DEBUG_UTIL_HDR_BUFLEN); if (ipmi_dump_rmcp_packet (STDERR_FILENO, ics[i].hostname, hdrbuf, NULL, buf, len, tmpl_cmd_asf_presence_ping) < 0) IPMIPOWER_DEBUG (("ipmi_dump_rmcp_packet: %s", strerror (errno))); } #endif /* NDEBUG */ fiid_obj_destroy (rmcp_hdr); fiid_obj_destroy (rmcp_ping); } /* !IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING */ if ((ret = cbuf_write (ics[i].ping_out, buf, len, &dropped)) < 0) { IPMIPOWER_ERROR (("cbuf_write: %s", strerror (errno))); exit (EXIT_FAILURE); } if (ret != len) { IPMIPOWER_ERROR (("cbuf_write: incorrect bytes written %d", ret)); exit (EXIT_FAILURE); } if (dropped) IPMIPOWER_DEBUG (("cbuf_write: dropped %d bytes", dropped)); ics[i].last_ping_send.tv_sec = cur_time.tv_sec; ics[i].last_ping_send.tv_usec = cur_time.tv_usec; if (cmd_args.ping_packet_count && cmd_args.ping_percent) ics[i].ping_packet_count_send++; } /* Did we receive something? */ memset (buf, '\0', IPMIPOWER_PACKET_BUFLEN); len = ipmipower_cbuf_peek_and_drop (ics[i].ping_in, buf, IPMIPOWER_PACKET_BUFLEN); if (len > 0) { uint8_t message_type = 0, ipmi_supported = 0; uint64_t val; /* Workaround * * Some motherboards don't support RMCP ping/pong :-( * * Discovered on Intel Windmill, Quanta Winterfell, and Wiwynn Windmill */ if (cmd_args.common_args.section_specific_workaround_flags & IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING) { 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; int checksum_ret = 0; int unassemble_ret = 0; int cmd_ret = 0; if (!(obj_rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } if (!(obj_lan_session_hdr = fiid_obj_create (tmpl_lan_session_hdr))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } if (!(obj_lan_msg_hdr = fiid_obj_create (tmpl_lan_msg_hdr_rs))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } if (!(obj_cmd = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rs))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } if (!(obj_lan_msg_trlr = fiid_obj_create (tmpl_lan_msg_trlr))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } #ifndef NDEBUG if (cmd_args.rmcpdump) { char hdrbuf[DEBUG_UTIL_HDR_BUFLEN]; const char *str_cmd = NULL; str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES); debug_hdr_str (DEBUG_UTIL_TYPE_IPMI_1_5, DEBUG_UTIL_DIRECTION_RESPONSE, DEBUG_UTIL_FLAGS_DEFAULT, str_cmd, hdrbuf, DEBUG_UTIL_HDR_BUFLEN); if (ipmi_dump_lan_packet (STDERR_FILENO, ics[i].hostname, hdrbuf, NULL, buf, len, tmpl_lan_msg_hdr_rs, tmpl_cmd_get_channel_authentication_capabilities_rs) < 0) IPMIPOWER_DEBUG (("ipmi_dump_lan_packet: %s", strerror (errno))); } #endif /* NDEBUG */ if ((checksum_ret = ipmi_lan_check_packet_checksum (buf, len)) < 0) { IPMIPOWER_ERROR (("ipmi_lan_check_packet_checksum: %s", strerror (errno))); exit (EXIT_FAILURE); } if (checksum_ret && ((unassemble_ret = unassemble_ipmi_lan_pkt (buf, len, obj_rmcp_hdr, obj_lan_session_hdr, obj_lan_msg_hdr, obj_cmd, obj_lan_msg_trlr, IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)) { IPMIPOWER_ERROR (("unassemble_ipmi_lan_pkt: %s", strerror (errno))); exit (EXIT_FAILURE); } /* achu: check for cmd type, but don't bother checking * sequence numbers or completion code. The fact it * returns is sufficient. We just need to make sure we * get something back from the BMC to ensure the machine * is still there. */ if (checksum_ret && unassemble_ret && ((cmd_ret = ipmi_check_cmd (obj_cmd, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES)) < 0)) { IPMIPOWER_ERROR (("ipmi_check_cmd: %s", strerror (errno))); exit (EXIT_FAILURE); } if (checksum_ret && unassemble_ret && cmd_ret) { /* We'll say this is equivalent to what pong response from RMCP */ message_type = RMCP_ASF_MESSAGE_TYPE_PRESENCE_PONG; ipmi_supported = 1; } 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); } else /* !IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING */ { fiid_obj_t rmcp_hdr = NULL; fiid_obj_t rmcp_pong = NULL; if (!(rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } if (!(rmcp_pong = fiid_obj_create (tmpl_cmd_asf_presence_pong))) { IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno))); exit (EXIT_FAILURE); } #ifndef NDEBUG if (cmd_args.rmcpdump) { char hdrbuf[DEBUG_UTIL_HDR_BUFLEN]; debug_hdr_str (DEBUG_UTIL_TYPE_NONE, DEBUG_UTIL_DIRECTION_NONE, DEBUG_UTIL_FLAGS_DEFAULT, DEBUG_UTIL_RMCPPING_STR, hdrbuf, DEBUG_UTIL_HDR_BUFLEN); if (ipmi_dump_rmcp_packet (STDERR_FILENO, ics[i].hostname, hdrbuf, NULL, buf, len, tmpl_cmd_asf_presence_pong) < 0) IPMIPOWER_DEBUG (("ipmi_dump_rmcp_packet: %s", strerror (errno))); } #endif /* NDEBUG */ if ((ret = unassemble_rmcp_pkt (buf, len, rmcp_hdr, rmcp_pong, IPMI_INTERFACE_FLAGS_DEFAULT)) < 0) { IPMIPOWER_ERROR (("unassemble_rmcp_pkt: %s", strerror (errno))); exit (EXIT_FAILURE); } if (ret) { /* achu: check for ipmi_support and pong type, but don't * check for message tag. On occassion, I have witnessed * BMCs send message tags "out of sync". For example, you * send 8, BMC returns 7. You send 9, BMC returns 8. We * really don't care if the BMC is out of sync. We just * need to make sure we get something back from the BMC to * ensure the machine is still there. */ if (FIID_OBJ_GET (rmcp_pong, "message_type", &val) < 0) { IPMIPOWER_ERROR (("FIID_OBJ_GET: 'message_type': %s", fiid_obj_errormsg (rmcp_pong))); exit (EXIT_FAILURE); } message_type = val; if (FIID_OBJ_GET (rmcp_pong, "supported_entities.ipmi_supported", &val) < 0) { IPMIPOWER_ERROR (("FIID_OBJ_GET: 'supported_entities.ipmi_supported': %s", fiid_obj_errormsg (rmcp_pong))); exit (EXIT_FAILURE); } ipmi_supported = val; } fiid_obj_destroy (rmcp_hdr); fiid_obj_destroy (rmcp_pong); } if (message_type == RMCP_ASF_MESSAGE_TYPE_PRESENCE_PONG && ipmi_supported) { if (cmd_args.ping_packet_count && cmd_args.ping_percent) ics[i].ping_packet_count_recv++; if (cmd_args.ping_consec_count) { /* Don't increment twice, its possible a previous pong * response was late, and we quickly receive two * pong responses */ if (!ics[i].ping_last_packet_recv_flag) ics[i].ping_consec_count++; ics[i].ping_last_packet_recv_flag++; } if (cmd_args.ping_packet_count && cmd_args.ping_percent) { if (ics[i].link_state == IPMIPOWER_LINK_STATE_GOOD) ics[i].discover_state = IPMIPOWER_DISCOVER_STATE_DISCOVERED; else { if (cmd_args.ping_consec_count && ics[i].ping_consec_count >= cmd_args.ping_consec_count) ics[i].discover_state = IPMIPOWER_DISCOVER_STATE_DISCOVERED; else ics[i].discover_state = IPMIPOWER_DISCOVER_STATE_BADCONNECTION; } } else { ics[i].discover_state = IPMIPOWER_DISCOVER_STATE_DISCOVERED; } ics[i].last_ping_recv.tv_sec = cur_time.tv_sec; ics[i].last_ping_recv.tv_usec = cur_time.tv_usec; } } /* !IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING */ /* Is the node gone?? */ timeval_sub (&cur_time, &ics[i].last_ping_recv, &result); timeval_millisecond_calc (&result, &ms_time); if (ms_time >= cmd_args.ping_timeout) ics[i].discover_state = IPMIPOWER_DISCOVER_STATE_UNDISCOVERED; } timeval_sub (&next_ping_sends_time, &cur_time, &result); timeval_millisecond_calc (&result, &ms_time); *timeout = ms_time; }