static void copy_hw_info(char *buf, size_t len) { int i; buf[0] = '\0'; for (i = 0; i < sizeof(dmidecode_param) / sizeof(dmidecode_param[0]); i++) { strncat(buf, get_dmi_string(dmidecode_param[i]), len); buf[strlen(buf) - 1] = ' '; } buf[strlen(buf) - 1] = '\0'; }
static int get_dmi_info(char *buf, int bufsize, int flags) { int ret = SYSINFO_RET_FAIL, fd, offset = 0; unsigned char membuf[SMBIOS_ENTRY_POINT_SIZE], *smbuf = NULL, *data; size_t len, fp; void *mmp = NULL; static long pagesize = 0; static int smbios_status = SMBIOS_STATUS_UNKNOWN; static size_t smbios_len, smbios; /* length and address of SMBIOS table (if found) */ if (-1 == (fd = open(DEV_MEM, O_RDONLY))) return ret; if (SMBIOS_STATUS_UNKNOWN == smbios_status) /* look for SMBIOS table only once */ { pagesize = sysconf(_SC_PAGESIZE); /* find smbios entry point - located between 0xF0000 and 0xFFFFF (according to the specs) */ for (fp = 0xf0000; 0xfffff > fp; fp += 16) { memset(membuf, 0, sizeof(membuf)); len = fp % pagesize; /* mmp needs to be a multiple of pagesize for munmap */ if (MAP_FAILED == (mmp = mmap(0, len + SMBIOS_ENTRY_POINT_SIZE, PROT_READ, MAP_SHARED, fd, fp - len))) goto close; memcpy(membuf, mmp + len, sizeof(membuf)); munmap(mmp, len + SMBIOS_ENTRY_POINT_SIZE); if (0 == strncmp((char *)membuf, "_DMI_", 5)) /* entry point found */ { smbios_len = membuf[7] << 8 | membuf[6]; smbios = (size_t)membuf[11] << 24 | (size_t)membuf[10] << 16 | (size_t)membuf[9] << 8 | membuf[8]; smbios_status = SMBIOS_STATUS_OK; break; } } } if (SMBIOS_STATUS_OK != smbios_status) { smbios_status = SMBIOS_STATUS_ERROR; goto close; } smbuf = zbx_malloc(smbuf, smbios_len); len = smbios % pagesize; /* mmp needs to be a multiple of pagesize for munmap */ if (MAP_FAILED == (mmp = mmap(0, len + smbios_len, PROT_READ, MAP_SHARED, fd, smbios - len))) goto clean; memcpy(smbuf, mmp + len, smbios_len); munmap(mmp, len + smbios_len); data = smbuf; while (data + DMI_HEADER_SIZE <= smbuf + smbios_len) { if (1 == data[0]) /* system information */ { if (0 != (flags & DMI_GET_VENDOR)) { offset += get_dmi_string(buf + offset, bufsize - offset, data, data[4]); flags &= ~DMI_GET_VENDOR; } if (0 != (flags & DMI_GET_MODEL)) { offset += get_dmi_string(buf + offset, bufsize - offset, data, data[5]); flags &= ~DMI_GET_MODEL; } if (0 != (flags & DMI_GET_SERIAL)) { offset += get_dmi_string(buf + offset, bufsize - offset, data, data[7]); flags &= ~DMI_GET_SERIAL; } } else if (3 == data[0] && 0 != (flags & DMI_GET_TYPE)) /* chassis */ { offset += get_chassis_type(buf + offset, bufsize - offset, data[5]); flags &= ~DMI_GET_TYPE; } if (0 == flags) break; data += data[1]; /* skip the main data */ while (0 != data[0] || 0 != data[1]) /* string data ends with two nulls */ { data++; } data += 2; } if (0 < offset) ret = SYSINFO_RET_OK; clean: zbx_free(smbuf); close: close(fd); return ret; }