/* callback function invoked from OpenIPMI */ static void got_discrete_states(ipmi_sensor_t *sensor, int err, ipmi_states_t *states, void *cb_data) { const char *__function_name = "got_discrete_states"; char id_str[2 * IPMI_SENSOR_ID_SZ + 1]; int id, i, val, ret, is_state_set; ipmi_entity_t *ent; zbx_ipmi_host_t *h = cb_data; zbx_ipmi_sensor_t *s; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); s = get_ipmi_sensor(h, sensor); if (NULL == s) { THIS_SHOULD_NEVER_HAPPEN; h->err = zbx_strdup(h->err, "fatal error"); h->ret = NOTSUPPORTED; goto out; } if (0 != err) { h->err = zbx_dsprintf(h->err, "error 0x%x while reading a discrete sensor %s@[%s]:%d", err, sensor_id_to_str(id_str, sizeof(id_str), s->id, s->id_type, s->id_sz), h->ip, h->port); h->ret = NOTSUPPORTED; goto out; } ent = ipmi_sensor_get_entity(sensor); id = ipmi_entity_get_entity_id(ent); /* Discrete values are 16-bit. We're storing them into a 64-bit uint. */ #define MAX_DISCRETE_STATES 15 s->value.discrete = 0; for (i = 0; i < MAX_DISCRETE_STATES; i++) { ret = ipmi_sensor_discrete_event_readable(sensor, i, &val); if (0 != ret || 0 == val) continue; is_state_set = ipmi_is_state_set(states, i); zabbix_log(LOG_LEVEL_DEBUG, "State [%s | %s | %s | %s | state %d value is %d]", sensor_id_to_str(id_str, sizeof(id_str), s->id, s->id_type, s->id_sz), ipmi_get_entity_id_string(id), ipmi_sensor_get_sensor_type_string(sensor), ipmi_sensor_get_event_reading_type_string(sensor), i, is_state_set); if (0 != is_state_set) s->value.discrete |= 1 << i; } #undef MAX_DISCRETE_STATES out: h->done = 1; zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(h->ret)); }
int ipmi_sdr_parse_entity_sensor_name (ipmi_sdr_ctx_t ctx, const void *sdr_record, unsigned int sdr_record_len, uint8_t sensor_number, unsigned int flags, char *buf, unsigned int buflen) { char id_string[IPMI_SDR_MAX_ID_STRING_LENGTH + 1]; char device_id_string[IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH + 1]; char entity_name_buf[IPMI_SDR_ENTITY_NAME_BUFLEN + 1]; char *id_string_ptr = NULL; uint8_t entity_id, entity_instance, entity_instance_type; const char *entity_id_str; uint8_t record_type; unsigned int flags_mask = (IPMI_SDR_SENSOR_NAME_FLAGS_IGNORE_SHARED_SENSORS | IPMI_SDR_SENSOR_NAME_FLAGS_ALWAYS_OUTPUT_INSTANCE_NUMBER); if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC) { ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx)); return (-1); } if (ctx->operation != IPMI_SDR_OPERATION_READ_CACHE) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CACHE_READ_INITIALIZATION); return (-1); } if (((sdr_record_len && !sdr_record_len) || (!sdr_record && sdr_record_len)) || (flags & ~flags_mask) || !buf || !buflen) { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS); return (-1); } memset (buf, '\0', buflen); memset (entity_name_buf, '\0', IPMI_SDR_ENTITY_NAME_BUFLEN + 1); if (ipmi_sdr_parse_record_id_and_type (ctx, sdr_record, sdr_record_len, NULL, &record_type) < 0) return (-1); if (record_type == IPMI_SDR_FORMAT_FULL_SENSOR_RECORD || record_type == IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD || record_type == IPMI_SDR_FORMAT_EVENT_ONLY_RECORD) { memset (id_string, '\0', IPMI_SDR_MAX_ID_STRING_LENGTH + 1); if (ipmi_sdr_parse_id_string (ctx, sdr_record, sdr_record_len, id_string, IPMI_SDR_MAX_ID_STRING_LENGTH) < 0) return (-1); id_string_ptr = id_string; } else if (record_type == IPMI_SDR_FORMAT_GENERIC_DEVICE_LOCATOR_RECORD || record_type == IPMI_SDR_FORMAT_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD) { memset (device_id_string, '\0', IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH + 1); if (ipmi_sdr_parse_device_id_string (ctx, sdr_record, sdr_record_len, device_id_string, IPMI_SDR_MAX_DEVICE_ID_STRING_LENGTH) < 0) return (-1); id_string_ptr = device_id_string; } else { SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARSE_INVALID_SDR_RECORD); return (-1); } if (ipmi_sdr_parse_entity_id_instance_type (ctx, sdr_record, sdr_record_len, &entity_id, &entity_instance, &entity_instance_type) < 0) return (-1); /* Table 39-1 * * "It is recommended that console software subtract 60h when * presenting device-relative Entity Instance values, and present * the Entity Instance number along with an ID for the device * providing the interface to the entity." * * achu: For the time being we do not output the device providing * the interface, only the right instance number. Adjust later if * necessary. */ if (IPMI_ENTITY_INSTANCE_DEVICE_RELATIVE (entity_instance)) entity_instance -= IPMI_ENTITY_INSTANCE_DEVICE_RELATIVE_MIN; entity_id_str = ipmi_get_entity_id_string (entity_id); /* a few special cases, for entity_ids are special, the vendor has * specifically stated there is no "entity" associated with this sdr * record */ if (entity_id == IPMI_ENTITY_ID_UNSPECIFIED || entity_id == IPMI_ENTITY_ID_OTHER || entity_id == IPMI_ENTITY_ID_UNKNOWN) snprintf (buf, buflen, "%s", id_string_ptr); else { if (ipmi_sdr_stats_compile (ctx) < 0) return (-1); if (ipmi_sdr_stats_entity_instance_unique (ctx, entity_id) > 1) { /* special case if sensor sharing is involved */ if ((record_type == IPMI_SDR_FORMAT_COMPACT_SENSOR_RECORD || record_type == IPMI_SDR_FORMAT_EVENT_ONLY_RECORD) && !(flags & IPMI_SDR_SENSOR_NAME_FLAGS_IGNORE_SHARED_SENSORS)) { uint8_t share_count; uint8_t entity_instance_sharing; char sensor_name_buf[IPMI_SDR_MAX_SENSOR_NAME_LENGTH + 1]; if (ipmi_sdr_parse_sensor_record_sharing (ctx, sdr_record, sdr_record_len, &share_count, NULL, NULL, &entity_instance_sharing) < 0) return (-1); if (share_count > 1 && entity_instance_sharing == IPMI_SDR_ENTITY_INSTANCE_INCREMENTS_FOR_EACH_SHARED_RECORD) { uint8_t sensor_number_base; if (ipmi_sdr_parse_sensor_number (ctx, sdr_record, sdr_record_len, &sensor_number_base) < 0) return (-1); /* I guess it's a bug if the sensor number passed in is bad */ if (sensor_number >= sensor_number_base) entity_instance += (sensor_number - sensor_number_base); else goto fallthrough; } memset (sensor_name_buf, '\0', IPMI_SDR_MAX_SENSOR_NAME_LENGTH + 1); if (_get_shared_sensor_name (ctx, sdr_record, sdr_record_len, sensor_number, id_string_ptr, sensor_name_buf, IPMI_SDR_MAX_SENSOR_NAME_LENGTH) < 0) return (-1); snprintf (entity_name_buf, IPMI_SDR_ENTITY_NAME_BUFLEN, "%s %u", entity_id_str, entity_instance); /* In odd chance the strings end up identical */ if (!strcasecmp (entity_name_buf, sensor_name_buf)) snprintf (buf, buflen, "%s", sensor_name_buf); else snprintf (buf, buflen, "%s %s", entity_name_buf, sensor_name_buf); } else { fallthrough: snprintf (entity_name_buf, IPMI_SDR_ENTITY_NAME_BUFLEN, "%s %u", entity_id_str, entity_instance); /* In odd chance the strings end up identical */ if (!strcasecmp (entity_name_buf, id_string_ptr)) snprintf (buf, buflen, "%s", id_string_ptr); else snprintf (buf, buflen, "%s %s", entity_name_buf, id_string_ptr); } } else { if (flags & IPMI_SDR_SENSOR_NAME_FLAGS_ALWAYS_OUTPUT_INSTANCE_NUMBER) { snprintf (entity_name_buf, IPMI_SDR_ENTITY_NAME_BUFLEN, "%s %u", entity_id_str, entity_instance); /* In odd chance the strings end up identical */ if (!strcasecmp (entity_name_buf, id_string_ptr)) snprintf (buf, buflen, "%s", id_string_ptr); else snprintf (buf, buflen, "%s %s", entity_name_buf, id_string_ptr); } else { /* In odd chance the strings end up identical */ if (!strcasecmp (entity_id_str, id_string_ptr)) snprintf (buf, buflen, "%s", id_string_ptr); else snprintf (buf, buflen, "%s %s", entity_id_str, id_string_ptr); } } } return (0); }