SD_ID128_GET_MACHINE(3)

🌸 SD_ID128_GET_MACHINE(3) β€” the sd_id128_get_machine page, bestie edition 🌸

okay so this is the manual page for the sd_id128_get_machine family of calls, straight out of systemd. it's all about grabbing those cute little 128-bit IDs β€” machine IDs, boot IDs, invocation IDs, and the app-specific versions of all of them πŸ’…


✨ NAME ✨

sd_id128_get_machine, sd_id128_get_app_specific, sd_id128_get_machine_app_specific, sd_id128_get_boot, sd_id128_get_boot_app_specific, sd_id128_get_invocation β€” retrieve 128-bit IDs πŸŽ€

(and yeah, sd_id128_get_invocation_app_specific is in this squad too, she just didn't make the NAME list, iykyk)

πŸ¦‹ SYNOPSIS πŸ¦‹

#include <systemd/sd-id128.h>

int sd_id128_get_machine(sd_id128_t *ret);

int sd_id128_get_app_specific(sd_id128_t base, sd_id128_t app_id,
                              sd_id128_t *ret);

int sd_id128_get_machine_app_specific(sd_id128_t app_id,
                                      sd_id128_t *ret);

int sd_id128_get_boot(sd_id128_t *ret);

int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret);

int sd_id128_get_invocation(sd_id128_t *ret);

int sd_id128_get_invocation_app_specific(sd_id128_t app_id,
                                         sd_id128_t *ret);

πŸ’– DESCRIPTION πŸ’–

sd_id128_get_machine() hands you back the machine ID of the host you're running on. it reads and parses the machine-id(5) file, and β€” slay β€” it caches that machine ID internally so getting it again is basically free. this ID is your go-to whenever you need a unique identifier for the local system. but (and this is the important part, bestie, listen up 🫢) it's only recommended to use this ID as-is in trusted environments. in untrusted environments you should derive an application-specific ID from this machine ID, in an irreversible (cryptographically secure) way. and because doing that by hand is a whole vibe-killer, sd_id128_get_machine_app_specific() exists for exactly this. see below πŸ‘‡

sd_id128_get_app_specific() returns a machine ID that's a combo of the base and app_id parameters. internally it computes HMAC-SHA256 of the app_id parameter keyed by the base parameter, truncates that result so it fits in sd_id128_t, and turns it into a valid Variant 1 Version 4 UUID, in accordance with RFC 4122[1]. and nope β€” neither of the two input parameters can be calculated back from the output parameter ret. no reverse-engineering, no cap πŸ”₯

sd_id128_get_machine_app_specific() is similar to sd_id128_get_machine(), but it retrieves a machine ID specific to the application identified by the indicated application ID. when you're passing an ID into untrusted environments, use this one instead of sd_id128_get_machine() β€” that way the original machine ID can't be determined externally. this way the ID your app uses stays stable on a given machine, but it can't easily be correlated with IDs used by other applications on that same machine. the application-specific ID should be generated with a tool like systemd-id128 new, and it can just be compiled into the application. this function returns the same application-specific ID for every combination of machine ID and application ID. internally it calls sd_id128_get_app_specific() with the result from sd_id128_get_machine() and the app_id parameter. iconic behavior, honestly ✨

sd_id128_get_boot() returns the boot ID of the executing kernel. it reads and parses the /proc/sys/kernel/random/boot_id file exposed by the kernel. this thing is randomly generated early at boot and is unique for every running kernel instance. more info lives in random(4). this function also caches the returned ID internally so this call stays cheap πŸ’Έ and again, only use this ID as-is in trusted environments. in untrusted ones, derive an application-specific ID with sd_id128_get_boot_app_specific(), see below.

sd_id128_get_boot_app_specific() is analogous to sd_id128_get_machine_app_specific(), but returns an ID that changes between boots. some machines stay up for a long time without rebooting, so the boot ID can stay constant for ages and has properties similar to the machine ID during that time. periodt.

sd_id128_get_invocation() returns the invocation ID of the currently executed service. in its current implementation, it tries to read and parse:

  • The $INVOCATION_ID environment variable that the service manager sets when activating a service.
  • An entry in the kernel keyring that the system service manager sets when activating a service.

see systemd.exec(5) for the deets. the ID is cached internally. and heads up β€” in the future, a different mechanism to determine the invocation ID may be added πŸ‘€

sd_id128_get_invocation_app_specific() derives an application-specific ID from the invocation ID.

now, a lil note πŸ“: sd_id128_get_machine_app_specific(), sd_id128_get_boot(), sd_id128_get_boot_app_specific(), sd_id128_get_invocation() and sd_id128_get_invocation_app_specific() always return UUID Variant 1 Version 4 compatible IDs. sd_id128_get_machine() will also return a UUID Variant 1 Version 4 compatible ID on new installations, but might not on older ones. it is possible to convert the machine ID non-reversibly into a UUID Variant 1 Version 4 compatible one β€” see machine-id(5) for more. so it's guaranteed these functions will never return an ID made of all zero or all one bits (SD_ID128_NULL, SD_ID128_ALLF) β€” with the possible exception of sd_id128_get_machine(), as mentioned πŸ™ˆ

want the whole tea on the sd_id128_t type? that's in sd-id128(3).

⭐ RETURN VALUE ⭐

these calls return 0 on success (and ret gets filled in πŸŽ‰), or a negative errno-style error code when things go sideways.

πŸ’€ Errors πŸ’€

the errors you might get back mean the following:

  • -ENOENT β€” returned by sd_id128_get_machine() and sd_id128_get_machine_app_specific() when /etc/machine-id is missing. Added in version 242.
  • -ENOMEDIUM β€” returned by sd_id128_get_machine() and sd_id128_get_machine_app_specific() when /etc/machine-id is empty or all zeros. also returned by sd_id128_get_invocation() when the invocation ID is all zeros. Added in version 242.
  • -ENOPKG β€” returned by sd_id128_get_machine() and sd_id128_get_machine_app_specific() when the content of /etc/machine-id is "uninitialized". Added in version 253.
  • -ENOSYS β€” returned by sd_id128_get_boot() and sd_id128_get_boot_app_specific() when /proc/ is not mounted. Added in version 253.
  • -ENXIO β€” returned by sd_id128_get_invocation() if no invocation ID is set. also returned by sd_id128_get_app_specific(), sd_id128_get_machine_app_specific(), and sd_id128_get_boot_app_specific() when the app_id parameter is all zeros. Added in version 242.
  • -EUCLEAN β€” returned by any of the functions described here when the configured value has invalid format. Added in version 253.
  • -EPERM β€” requested information could not be retrieved because of insufficient permissions. Added in version 242.

🧚 NOTES 🧚

the functions described here are available as a shared library, which you can compile against and link to with the libsystemd pkg-config(1) file πŸ“š

⚠️ okay this one matters: the code described here uses getenv(3), which is declared to be not multi-thread-safe. that means code calling the functions described here must not call setenv(3) from a parallel thread. it's recommended to only call setenv() from an early phase of the program, when no other threads have been started yet. no cap, respect the thread boundaries 🫑

🌈 EXAMPLES 🌈

Example 1. Application-specific machine ID

first, generate the application ID:

$ systemd-id128 -p new
As string:
c273277323db454ea63bb96e79b53e97

As UUID:
c2732773-23db-454e-a63b-b96e79b53e97

As man:sd-id128(3) macro:
#define MESSAGE_XYZ SD_ID128_MAKE(c2,73,27,73,23,db,45,4e,a6,3b,b9,6e,79,b5,3e,97)
...

then use that new identifier in an example application:

/* SPDX-License-Identifier: MIT-0 */

#include <stdio.h>
#include <systemd/sd-id128.h>

#define OUR_APPLICATION_ID SD_ID128_MAKE(c2,73,27,73,23,db,45,4e,a6,3b,b9,6e,79,b5,3e,97)

int main(int argc, char *argv[]) {
  sd_id128_t id;
  sd_id128_get_machine_app_specific(OUR_APPLICATION_ID, &id);
  printf("Our application ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id));
  return 0;
}

πŸ‘‘ HISTORY πŸ‘‘

  • sd_id128_get_machine() and sd_id128_get_boot() were added in version 187.
  • sd_id128_get_invocation() was added in version 232.
  • sd_id128_get_machine_app_specific() was added in version 233.
  • sd_id128_get_boot_app_specific() was added in version 240.
  • sd_id128_get_app_specific() was added in version 255.
  • sd_id128_get_invocation_app_specific() was added in version 256.

πŸ“ SEE ALSO πŸ“

systemd(1), systemd-id128(1), sd-id128(3), machine-id(5), systemd.exec(5), sd_id128_randomize(3), random(4)

πŸ“Ž NOTES πŸ“Ž

  1. RFC 4122 β€” https://tools.ietf.org/html/rfc4122

and that's the whole page, bestie πŸ’œ it came from systemd 261.3, and this version of SD_ID128_GET_MACHINE(3) is dated right alongside it. go forth and ID responsibly β€” mwah πŸŽ€βœ¨

πŸ“¦ where this page comes from