void knox_print_event_log(int sg_fd) { #define EVENT_LOG_BUFFER_SIZE 8192 unsigned char buf[EVENT_LOG_BUFFER_SIZE]; unsigned char *buf_ptr; int64_t timestamp = 0; int i, j; char id_str[16]; perr("NOTE: Event log in Knox is not complete at this time...\n"); sg_ll_read_buffer(sg_fd, 2, 0xe5, 0, (void *) buf, EVENT_LOG_BUFFER_SIZE, 1, 0); for (i = 0; i < EVENT_LOG_BUFFER_SIZE; i += 64) { buf_ptr = buf + i; timestamp = *((int64_t *)(buf_ptr)); IF_PRINT_NONE_JSON printf("[%11ld][Event %d] %d %x %s\n", timestamp, buf_ptr[13] * 256 + buf_ptr[12], buf_ptr[15] * 256 + buf_ptr[14], *((int *)(buf_ptr + 16)), (char *)(buf_ptr + 24)); PRINT_JSON_GROUP_SEPARATE; snprintf(id_str, 16, "%d", buf_ptr[13] * 256 + buf_ptr[12]); PRINT_JSON_GROUP_HEADER(id_str); PRINT_JSON_ITEM("timestamp", "%ld", timestamp); PRINT_JSON_ITEM("id", "%d", buf_ptr[13] * 256 + buf_ptr[12]); PRINT_JSON_LAST_ITEM("description", "%s", (char *)(buf_ptr + 24)); PRINT_JSON_GROUP_ENDING; } }
/* Buffer ID 0x04: Read Device Slot Status (mandatory) */ static int do_safte_slot_status(int sg_fd, int do_hex, int do_raw, int verbose) { int res, i; unsigned int rb_len; unsigned char *rb_buff, slot_status; rb_len = safte_cfg.slots * 4; rb_buff = (unsigned char *)malloc(rb_len); if (verbose > 1) pr2serr("Use READ BUFFER,mode=vendor_specific,buff_id=4 to read " "device slot status\n"); res = sg_ll_read_buffer(sg_fd, RWB_MODE_VENDOR, 4, 0, rb_buff, rb_len, 0, verbose); if (res && res != SG_LIB_CAT_RECOVERED) { free(rb_buff); return res; } if (do_raw > 1) { dStrRaw((const char *)rb_buff, buf_capacity); return 0; } if (do_hex > 1) { dStrHex((const char *)rb_buff, buf_capacity, 1); return 0; } printf("Slot status:\n"); for (i = 0; i < safte_cfg.slots; i++) { slot_status = rb_buff[i * 4 + 3]; printf("\tSlot %d: ", i); if (slot_status & 0x7) { if (slot_status & 0x1) printf("inserted "); if (slot_status & 0x2) printf("ready "); if (slot_status & 0x4) printf("activated "); printf("\n"); } else { printf("empty\n"); } } free(rb_buff); return 0; }
/* Buffer ID 0x02: Read Usage Statistics (optional) */ static int do_safte_usage_statistics(int sg_fd, int do_hex, int do_raw, int verbose) { int res; unsigned int rb_len; unsigned char *rb_buff; unsigned int minutes; rb_len = 16 + safte_cfg.vendor_specific; rb_buff = (unsigned char *)malloc(rb_len); if (verbose > 1) fprintf(stderr, "Use READ BUFFER,mode=vendor_specific,buff_id=2 " "to read usage statistics\n"); res = sg_ll_read_buffer(sg_fd, RWB_MODE_VENDOR, 2, 0, rb_buff, rb_len, 0, verbose); if (res) { if (res == SG_LIB_CAT_ILLEGAL_REQ) { printf("Usage Statistics:\n\tNot implemented\n"); return 0; } if (res != SG_LIB_CAT_RECOVERED) { free(rb_buff); return res; } } if (do_raw > 1) { dStrRaw((const char *)rb_buff, buf_capacity); return 0; } if (do_hex > 1) { dStrHex((const char *)rb_buff, buf_capacity, 1); return 0; } printf("Usage Statistics:\n"); minutes = (rb_buff[0] << 24) + (rb_buff[1] << 16) + (rb_buff[2] << 8) + rb_buff[3]; printf("\tPower on Minutes: %u\n", minutes); minutes = (rb_buff[4] << 24) + (rb_buff[5] << 16) + (rb_buff[6] << 8) + rb_buff[7]; printf("\tPower on Cycles: %u\n", minutes); free(rb_buff); return 0; }
/* Buffer ID 0x03: Read Device Insertions (optional) */ static int do_safte_slot_insertions(int sg_fd, int do_hex, int do_raw, int verbose) { int res, i; unsigned int rb_len; unsigned char *rb_buff, slot_status; rb_len = safte_cfg.slots * 2; rb_buff = (unsigned char *)malloc(rb_len); if (verbose > 1) pr2serr("Use READ BUFFER,mode=vendor_specific,buff_id=3 to read " "device insertions\n"); res = sg_ll_read_buffer(sg_fd, RWB_MODE_VENDOR, 3, 0, rb_buff, rb_len, 0, verbose); if (res ) { if (res == SG_LIB_CAT_ILLEGAL_REQ) { printf("Slot insertions:\n\tNot implemented\n"); return 0; } if (res != SG_LIB_CAT_RECOVERED) { free(rb_buff); return res; } } if (do_raw > 1) { dStrRaw((const char *)rb_buff, buf_capacity); return 0; } if (do_hex > 1) { dStrHex((const char *)rb_buff, buf_capacity, 1); return 0; } printf("Slot insertions:\n"); for (i = 0; i < safte_cfg.slots; i++) { slot_status = sg_get_unaligned_be16(rb_buff + (i * 2)); printf("\tSlot %d: %d insertions", i, slot_status); } free(rb_buff); return 0; }
/* Buffer ID 0x0: Read Enclosure Configuration (mandatory) */ static int read_safte_configuration(int sg_fd, unsigned char *rb_buff, unsigned int rb_len, int verbose) { int res; if (rb_len < buf_capacity) { pr2serr("SCSI BUFFER size too small (%d/%d bytes)\n", rb_len, buf_capacity); return SG_LIB_CAT_ILLEGAL_REQ; } if (verbose > 1) pr2serr("Use READ BUFFER,mode=vendor_specific,buff_id=0 to fetch " "configuration\n"); res = sg_ll_read_buffer(sg_fd, RWB_MODE_VENDOR, 0, 0, rb_buff, rb_len, 1, verbose); if (res && res != SG_LIB_CAT_RECOVERED) return res; safte_cfg.fans = rb_buff[0]; safte_cfg.psupplies = rb_buff[1]; safte_cfg.slots = rb_buff[2]; safte_cfg.temps = rb_buff[4]; if (rb_buff[3]) safte_cfg.flags |= SAFTE_CFG_FLAG_DOORLOCK; if (rb_buff[5]) safte_cfg.flags |= SAFTE_CFG_FLAG_ALARM; if (rb_buff[6] & 0x80) safte_cfg.flags |= SAFTE_CFG_FLAG_CELSIUS; safte_cfg.thermostats = rb_buff[6] & 0x0f; safte_cfg.vendor_specific = rb_buff[63]; return 0; }
/* Buffer ID 0x05: Read Global Flags (optional) */ static int do_safte_global_flags(int sg_fd, int do_hex, int do_raw, int verbose) { int res; unsigned int rb_len; unsigned char *rb_buff; rb_len = 16; rb_buff = (unsigned char *)malloc(rb_len); if (verbose > 1) pr2serr("Use READ BUFFER,mode=vendor_specific,buff_id=5 to read " "global flags\n"); res = sg_ll_read_buffer(sg_fd, RWB_MODE_VENDOR, 5, 0, rb_buff, rb_len, 0, verbose); if (res ) { if (res == SG_LIB_CAT_ILLEGAL_REQ) { printf("Global Flags:\n\tNot implemented\n"); return 0; } if (res != SG_LIB_CAT_RECOVERED) { free(rb_buff); return res; } } if (do_raw > 1) { dStrRaw((const char *)rb_buff, buf_capacity); return 0; } if (do_hex > 1) { dStrHex((const char *)rb_buff, buf_capacity, 1); return 0; } printf("Global Flags:\n"); printf("\tAudible Alarm Control: %s\n", rb_buff[0] & 0x1?"on":"off"); printf("\tGlobal Failure Indicator: %s\n", rb_buff[0] & 0x2?"on":"off"); printf("\tGlobal Warning Indicator: %s\n", rb_buff[0] & 0x4?"on":"off"); printf("\tEnclosure Power: %s\n", rb_buff[0] & 0x8?"on":"off"); printf("\tCooling Failure: %s\n", rb_buff[0] & 0x10?"yes":"no"); printf("\tPower Failure: %s\n", rb_buff[0] & 0x20?"yes":"no"); printf("\tDrive Failure: %s\n", rb_buff[0] & 0x40?"yes":"no"); printf("\tDrive Warning: %s\n", rb_buff[0] & 0x80?"yes":"no"); printf("\tArray Failure: %s\n", rb_buff[1] & 0x1?"yes":"no"); printf("\tArray Warning: %s\n", rb_buff[0] & 0x2?"yes":"no"); printf("\tEnclosure Lock: %s\n", rb_buff[0] & 0x4?"on":"off"); printf("\tEnclosure Identify: %s\n", rb_buff[0] & 0x8?"on":"off"); free(rb_buff); return 0; }
/* Buffer ID 0x01: Read Enclosure Status (mandatory) */ static int do_safte_encl_status(int sg_fd, int do_hex, int do_raw, int verbose) { int res, i, offset; unsigned int rb_len; unsigned char *rb_buff; rb_len = safte_cfg.fans + safte_cfg.psupplies + safte_cfg.slots + safte_cfg.temps + 5 + safte_cfg.vendor_specific; rb_buff = (unsigned char *)malloc(rb_len); if (verbose > 1) pr2serr("Use READ BUFFER,mode=vendor_specific,buff_id=1 to read " "enclosure status\n"); res = sg_ll_read_buffer(sg_fd, RWB_MODE_VENDOR, 1, 0, rb_buff, rb_len, 0, verbose); if (res && res != SG_LIB_CAT_RECOVERED) return res; if (do_raw > 1) { dStrRaw((const char *)rb_buff, buf_capacity); return 0; } if (do_hex > 1) { dStrHex((const char *)rb_buff, buf_capacity, 1); return 0; } printf("Enclosure Status:\n"); offset = 0; for (i = 0; i < safte_cfg.fans; i++) { printf("\tFan %d status: ", i); switch(rb_buff[i]) { case 0: printf("operational\n"); break; case 1: printf("malfunctioning\n"); break; case 2: printf("not installed\n"); break; case 80: printf("not reportable\n"); break; default: printf("unknown\n"); break; } } offset += safte_cfg.fans; for (i = 0; i < safte_cfg.psupplies; i++) { printf("\tPower supply %d status: ", i); switch(rb_buff[i + offset]) { case 0: printf("operational / on\n"); break; case 1: printf("operational / off\n"); break; case 0x10: printf("malfunctioning / on\n"); break; case 0x11: printf("malfunctioning / off\n"); break; case 0x20: printf("not present\n"); break; case 0x21: printf("present\n"); break; case 0x80: printf("not reportable\n"); break; default: printf("unknown\n"); break; } } offset += safte_cfg.psupplies; for (i = 0; i < safte_cfg.slots; i++) { printf("\tDevice Slot %d: SCSI ID %d\n", i, rb_buff[i + offset]); } offset += safte_cfg.slots; if (safte_cfg.flags & SAFTE_CFG_FLAG_DOORLOCK) { switch(rb_buff[offset]) { case 0x0: printf("\tDoor lock status: locked\n"); break; case 0x01: printf("\tDoor lock status: unlocked\n"); break; case 0x80: printf("\tDoor lock status: not reportable\n"); break; } } else { printf("\tDoor lock status: not installed\n"); } offset++; if (!(safte_cfg.flags & SAFTE_CFG_FLAG_ALARM)) { printf("\tSpeaker status: not installed\n"); } else { switch(rb_buff[offset]) { case 0x0: printf("\tSpeaker status: off\n"); break; case 0x01: printf("\tSpeaker status: on\n"); break; } } offset++; for (i = 0; i < safte_cfg.temps; i++) { int temp = rb_buff[i + offset]; int is_celsius = !!(safte_cfg.flags & SAFTE_CFG_FLAG_CELSIUS); if (! is_celsius) temp -= 10; printf("\tTemperature sensor %d: %d deg %c\n", i, temp, is_celsius ? 'C' : 'F'); } offset += safte_cfg.temps; if (safte_cfg.thermostats) { if (rb_buff[offset] & 0x80) { printf("\tEnclosure Temperature alert status: abnormal\n"); } else { printf("\tEnclosure Temperature alert status: normal\n"); } } return 0; }