mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 10:37:22 +00:00
mc: guid: Fix timestamp decoding
Before this commit the 'Timestamp' line was always printed for all versions of GUID, even for non-time-based ones. Plus, only the time_low field was used, and it was used as if it contained seconds since UNIX Epoch, which it didn't. In fact this field along with other time_* fields constitute a single 60-bit value representing the count of 100ns intervals since adoption of Gregorial calendar (00:00:00.00 15 Oct 1582). For non-time-based versions of GUID, the time_* fields do not represent any time at all. So, after this commit, the timestamp will be properly decoded for time-based GUID version 1 only. For other versions the 'Timestamp' line will not be displayed. A line showing the GUID version will be added to the output. Partially resolves ipmitool/ipmitool#25 Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
This commit is contained in:
parent
f43a78bfc3
commit
0b6abe8cd9
@ -110,6 +110,25 @@ typedef enum {
|
||||
|
||||
#define GUID_NODE_SZ 6
|
||||
|
||||
#define GUID_VER_MASK 0x0F
|
||||
#define GUID_VER_SHIFT 12
|
||||
#define GUID_VERSION(t_hi) (((t_hi) >> GUID_VER_SHIFT) & GUID_VER_MASK)
|
||||
#define GUID_TIME_HI(t_hi) ((t_hi) & ~(GUID_VER_MASK << GUID_VER_SHIFT))
|
||||
|
||||
typedef enum {
|
||||
GUID_VERSION_UNKNOWN = 0, /* Not valid according to any specification */
|
||||
|
||||
/* The following are according to IPMI/SMBIOS/RFC4122 */
|
||||
GUID_VERSION_TIME, /* Time-based, recommended for IPMI */
|
||||
GUID_VERSION_DCE, /* DCE Security with POSIX UIDs, not for IPMI */
|
||||
GUID_VERSION_MD5, /* Name-based, using MD5 */
|
||||
GUID_VERSION_RND, /* Randomly generated */
|
||||
GUID_VERSION_SHA1, /* Name-based, using SHA-1 */
|
||||
|
||||
GUID_VERSION_MAX = GUID_VERSION_SHA1, /* The maximum supported version */
|
||||
GUID_VERSION_COUNT /* The number of supported versions */
|
||||
} guid_version_t;
|
||||
|
||||
/* The structure follows IPMI v2.0, rev 1.1
|
||||
* See section 20.8 */
|
||||
#ifdef HAVE_PRAGMA_PACK
|
||||
|
@ -540,9 +540,19 @@ ipmi_mc_print_guid(struct ipmi_intf *intf, ipmi_guid_mode_t guid_mode)
|
||||
uint8_t node[GUID_NODE_SZ]; /* MSB first */
|
||||
/* These are host architecture specific */
|
||||
uint16_t clock_seq_and_rsvd;
|
||||
uint16_t time_hi_and_version;
|
||||
uint16_t time_mid;
|
||||
uint32_t time_low;
|
||||
uint64_t time_hi_and_version;
|
||||
uint64_t time_mid;
|
||||
uint64_t time_low;
|
||||
|
||||
guid_version_t guid_ver;
|
||||
const char *guid_ver_str[GUID_VERSION_COUNT] = {
|
||||
[GUID_VERSION_UNKNOWN] = "Unknown/unsupported",
|
||||
[GUID_VERSION_TIME] = "Time-based",
|
||||
[GUID_VERSION_DCE] = "DCE Security with POSIX UIDs (not for IPMI)",
|
||||
[GUID_VERSION_MD5] = "Name-based using MD5",
|
||||
[GUID_VERSION_RND] = "Random or pseudo-random",
|
||||
[GUID_VERSION_SHA1] = "Name-based using SHA-1"
|
||||
};
|
||||
|
||||
char tbuf[40] = { 0 };
|
||||
struct tm *tm;
|
||||
@ -592,16 +602,47 @@ ipmi_mc_print_guid(struct ipmi_intf *intf, ipmi_guid_mode_t guid_mode)
|
||||
}
|
||||
|
||||
printf("%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n",
|
||||
time_low, time_mid, time_hi_and_version,
|
||||
(int)time_low, (int)time_mid, (int)time_hi_and_version,
|
||||
clock_seq_and_rsvd,
|
||||
node[0], node[1], node[2], node[3], node[4], node[5]);
|
||||
|
||||
if(time_in_utc)
|
||||
tm = gmtime(&time_low);
|
||||
else
|
||||
tm = localtime(&time_low);
|
||||
strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", tm);
|
||||
printf("Timestamp : %s\n", tbuf);
|
||||
guid_ver = GUID_VERSION(time_hi_and_version);
|
||||
|
||||
if (guid_ver > GUID_VERSION_MAX) {
|
||||
/* Reset any unsupported value fto UNKNOWN */
|
||||
guid_ver = GUID_VERSION_UNKNOWN;
|
||||
}
|
||||
|
||||
printf("GUID Version : %s", guid_ver_str[guid_ver]);
|
||||
if (GUID_VERSION_UNKNOWN == guid_ver)
|
||||
printf(" (%d)", GUID_VERSION((int)time_hi_and_version));
|
||||
printf("\n");
|
||||
|
||||
if (GUID_VERSION_TIME == guid_ver) {
|
||||
/* GUID time-stamp is a 60-bit value representing the
|
||||
* count of 100ns intervals since 00:00:00.00, 15 Oct 1582 */
|
||||
|
||||
const uint64_t t100ns_in_sec = 10000000LL;
|
||||
|
||||
/* Seconds from 15 Oct 1582 to 1 Jan 1970 00:00:00 */
|
||||
uint64_t epoch_since_gregorian = 12219292800;
|
||||
|
||||
/* 100ns intervals since 15 Oct 1582 00:00:00 */
|
||||
uint64_t gregorian = (GUID_TIME_HI(time_hi_and_version) << 48)
|
||||
| (time_mid << 32)
|
||||
| time_low;
|
||||
time_t unixtime; /* We need timestamp in seconds since UNIX epoch */
|
||||
|
||||
gregorian /= t100ns_in_sec; /* Convert to seconds */
|
||||
unixtime = gregorian - epoch_since_gregorian;
|
||||
|
||||
if(time_in_utc)
|
||||
tm = gmtime(&unixtime);
|
||||
else
|
||||
tm = localtime(&unixtime);
|
||||
strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", tm);
|
||||
printf("Timestamp : %s\n", tbuf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user