1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <sys/utsname.h>
12 #include "alloc-util.h"
14 #include "bus-common-errors.h"
15 #include "bus-get-properties.h"
16 #include "bus-log-control-api.h"
17 #include "bus-object.h"
18 #include "bus-polkit.h"
20 #include "constants.h"
21 #include "daemon-util.h"
22 #include "device-private.h"
25 #include "extract-word.h"
28 #include "hostname-setup.h"
29 #include "hostname-util.h"
30 #include "id128-util.h"
31 #include "json-util.h"
32 #include "label-util.h"
34 #include "main-func.h"
35 #include "nulstr-util.h"
37 #include "parse-util.h"
38 #include "path-util.h"
39 #include "service-util.h"
40 #include "socket-util.h"
41 #include "stat-util.h"
42 #include "string-util.h"
44 #include "time-util.h"
46 #include "varlink-io.systemd.Hostname.h"
47 #include "varlink-io.systemd.service.h"
48 #include "varlink-util.h"
51 #define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:")
53 /* Properties we cache are indexed by an enum, to make invalidation easy and systematic (as we can iterate
54 * through them all, and they are uniformly strings). */
56 /* Read from /etc/hostname */
58 PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS
,
60 /* Read from /etc/machine-info */
69 PROP_HARDWARE_VERSION
,
71 /* Read from /etc/os-release (or /usr/lib/os-release) */
77 PROP_OS_IMAGE_VERSION
,
79 _PROP_INVALID
= -EINVAL
,
82 typedef struct Context
{
83 char *data
[_PROP_MAX
];
85 HostnameSource hostname_source
;
87 struct stat etc_hostname_stat
;
88 struct stat etc_os_release_stat
;
89 struct stat etc_machine_info_stat
;
93 sd_varlink_server
*varlink_server
;
94 Hashmap
*polkit_registry
;
95 sd_device
*device_dmi
;
96 sd_device
*device_acpi
;
97 sd_device
*device_tree
;
100 static void context_reset(Context
*c
, uint64_t mask
) {
103 for (HostProperty p
= 0; p
< _PROP_MAX
; p
++) {
104 if (!BIT_SET(mask
, p
))
107 c
->data
[p
] = mfree(c
->data
[p
]);
111 static void context_destroy(Context
*c
) {
114 context_reset(c
, UINT64_MAX
);
115 hashmap_free(c
->polkit_registry
);
116 sd_event_unref(c
->event
);
117 sd_bus_flush_close_unref(c
->bus
);
118 sd_varlink_server_unref(c
->varlink_server
);
119 sd_device_unref(c
->device_dmi
);
120 sd_device_unref(c
->device_acpi
);
121 sd_device_unref(c
->device_tree
);
124 static void context_read_etc_hostname(Context
*c
) {
125 struct stat current_stat
= {};
130 if (stat(etc_hostname(), ¤t_stat
) >= 0 &&
131 stat_inode_unmodified(&c
->etc_hostname_stat
, ¤t_stat
))
135 (UINT64_C(1) << PROP_STATIC_HOSTNAME
) |
136 (UINT64_C(1) << PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS
));
138 r
= read_etc_hostname(/* path= */ NULL
, /* substitute_wildcards= */ false, &c
->data
[PROP_STATIC_HOSTNAME
]);
141 log_warning_errno(r
, "Failed to read /etc/hostname, ignoring: %m");
143 _cleanup_free_
char *substituted
= strdup(c
->data
[PROP_STATIC_HOSTNAME
]);
145 return (void) log_oom();
147 r
= hostname_substitute_wildcards(substituted
);
149 log_warning_errno(r
, "Failed to substitute wildcards in /etc/hostname, ignoring: %m");
151 c
->data
[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS
] = TAKE_PTR(substituted
);
154 c
->etc_hostname_stat
= current_stat
;
157 static void context_read_machine_info(Context
*c
) {
158 struct stat current_stat
= {};
163 if (stat(etc_machine_info(), ¤t_stat
) >= 0 &&
164 stat_inode_unmodified(&c
->etc_machine_info_stat
, ¤t_stat
))
168 (UINT64_C(1) << PROP_PRETTY_HOSTNAME
) |
169 (UINT64_C(1) << PROP_ICON_NAME
) |
170 (UINT64_C(1) << PROP_CHASSIS
) |
171 (UINT64_C(1) << PROP_DEPLOYMENT
) |
172 (UINT64_C(1) << PROP_LOCATION
) |
173 (UINT64_C(1) << PROP_HARDWARE_VENDOR
) |
174 (UINT64_C(1) << PROP_HARDWARE_MODEL
) |
175 (UINT64_C(1) << PROP_HARDWARE_SKU
) |
176 (UINT64_C(1) << PROP_HARDWARE_VERSION
));
178 r
= parse_env_file(NULL
, etc_machine_info(),
179 "PRETTY_HOSTNAME", &c
->data
[PROP_PRETTY_HOSTNAME
],
180 "ICON_NAME", &c
->data
[PROP_ICON_NAME
],
181 "CHASSIS", &c
->data
[PROP_CHASSIS
],
182 "DEPLOYMENT", &c
->data
[PROP_DEPLOYMENT
],
183 "LOCATION", &c
->data
[PROP_LOCATION
],
184 "HARDWARE_VENDOR", &c
->data
[PROP_HARDWARE_VENDOR
],
185 "HARDWARE_MODEL", &c
->data
[PROP_HARDWARE_MODEL
],
186 "HARDWARE_SKU", &c
->data
[PROP_HARDWARE_SKU
],
187 "HARDWARE_VERSION", &c
->data
[PROP_HARDWARE_VERSION
]);
188 if (r
< 0 && r
!= -ENOENT
)
189 log_warning_errno(r
, "Failed to read /etc/machine-info, ignoring: %m");
191 c
->etc_machine_info_stat
= current_stat
;
194 static void context_read_os_release(Context
*c
) {
195 _cleanup_free_
char *os_name
= NULL
, *os_pretty_name
= NULL
;
196 struct stat current_stat
= {};
201 if ((stat("/etc/os-release", ¤t_stat
) >= 0 ||
202 stat("/usr/lib/os-release", ¤t_stat
) >= 0) &&
203 stat_inode_unmodified(&c
->etc_os_release_stat
, ¤t_stat
))
207 (UINT64_C(1) << PROP_OS_PRETTY_NAME
) |
208 (UINT64_C(1) << PROP_OS_CPE_NAME
) |
209 (UINT64_C(1) << PROP_OS_HOME_URL
) |
210 (UINT64_C(1) << PROP_OS_SUPPORT_END
) |
211 (UINT64_C(1) << PROP_OS_IMAGE_ID
) |
212 (UINT64_C(1) << PROP_OS_IMAGE_VERSION
));
214 r
= parse_os_release(NULL
,
215 "PRETTY_NAME", &os_pretty_name
,
217 "CPE_NAME", &c
->data
[PROP_OS_CPE_NAME
],
218 "HOME_URL", &c
->data
[PROP_OS_HOME_URL
],
219 "SUPPORT_END", &c
->data
[PROP_OS_SUPPORT_END
],
220 "IMAGE_ID", &c
->data
[PROP_OS_IMAGE_ID
],
221 "IMAGE_VERSION", &c
->data
[PROP_OS_IMAGE_VERSION
]);
222 if (r
< 0 && r
!= -ENOENT
)
223 log_warning_errno(r
, "Failed to read os-release file, ignoring: %m");
225 if (free_and_strdup(&c
->data
[PROP_OS_PRETTY_NAME
], os_release_pretty_name(os_pretty_name
, os_name
)) < 0)
228 c
->etc_os_release_stat
= current_stat
;
231 static bool use_dmi_data(void) {
234 r
= getenv_bool("SYSTEMD_HOSTNAME_FORCE_DMI");
236 log_debug("Honouring $SYSTEMD_HOSTNAME_FORCE_DMI override: %s", yes_no(r
));
240 log_debug_errno(r
, "Failed to parse $SYSTEMD_HOSTNAME_FORCE_DMI, ignoring: %m");
242 if (detect_container() > 0) {
243 log_debug("Running in a container, not using DMI hardware data.");
250 static int context_acquire_dmi_device(Context
*c
) {
254 assert(!c
->device_dmi
);
259 r
= sd_device_new_from_syspath(&c
->device_dmi
, "/sys/class/dmi/id/");
260 if (ERRNO_IS_NEG_DEVICE_ABSENT(r
)) {
261 log_debug_errno(r
, "Failed to open /sys/class/dmi/id/ device, ignoring: %m");
265 return log_error_errno(r
, "Failed to open /sys/class/dmi/id/ device: %m");
270 static int context_acquire_acpi_device(Context
*c
) {
274 assert(!c
->device_acpi
);
276 r
= sd_device_new_from_syspath(&c
->device_acpi
, "/sys/firmware/acpi/");
277 if (ERRNO_IS_NEG_DEVICE_ABSENT(r
)) {
278 log_debug_errno(r
, "Failed to open /sys/firmware/acpi/ device, ignoring: %m");
282 return log_error_errno(r
, "Failed to open /sys/firmware/acpi/ device: %m");
287 static int context_acquire_device_tree(Context
*c
) {
291 assert(!c
->device_tree
);
293 r
= sd_device_new_from_path(&c
->device_tree
, "/proc/device-tree/");
294 if (ERRNO_IS_NEG_DEVICE_ABSENT(r
)) {
295 log_debug_errno(r
, "Failed to open /proc/device-tree/ device, ignoring: %m");
299 return log_error_errno(r
, "Failed to open /proc/device-tree/ device: %m");
304 static bool string_is_safe_for_dbus(const char *s
) {
307 /* Do some superficial validation: do not allow CCs and make sure D-Bus won't kick us off the bus
308 * because we send invalid UTF-8 data */
310 if (string_has_cc(s
, /* ok= */ NULL
))
313 return utf8_is_valid(s
);
316 static int get_dmi_property(Context
*c
, const char *key
, char **ret
) {
327 r
= sd_device_get_property_value(c
->device_dmi
, key
, &s
);
331 if (!string_is_safe_for_dbus(s
))
334 return strdup_to(ret
, s
);
337 static int get_dmi_properties(Context
*c
, const char * const * keys
, char **ret
) {
343 STRV_FOREACH(k
, keys
) {
344 r
= get_dmi_property(c
, *k
, ret
);
345 if (r
>= 0 || !ERRNO_IS_NEG_DEVICE_ABSENT(r
))
352 static int get_chassis_asset_tag(Context
*c
, char **ret
) {
353 return get_dmi_property(c
, "ID_CHASSIS_ASSET_TAG", ret
);
356 static int get_hardware_vendor(Context
*c
, char **ret
) {
357 return get_dmi_properties(c
, STRV_MAKE_CONST("ID_VENDOR_FROM_DATABASE", "ID_VENDOR"), ret
);
360 static int get_hardware_model(Context
*c
, char **ret
) {
361 return get_dmi_properties(c
, STRV_MAKE_CONST("ID_MODEL_FROM_DATABASE", "ID_MODEL"), ret
);
364 static int get_hardware_sku(Context
*c
, char **ret
) {
365 _cleanup_free_
char *model
= NULL
, *sku
= NULL
;
368 r
= get_dmi_property(c
, "ID_SKU", &sku
);
372 /* Suppress reporting the SKU field, if it's the same string as the
373 * model field, which it appears to be on various systems */
374 r
= get_hardware_model(c
, &model
);
378 } else if (streq_ptr(sku
, model
))
381 *ret
= TAKE_PTR(sku
);
385 static int get_hardware_version(Context
*c
, char **ret
) {
386 _cleanup_free_
char *version
= NULL
;
389 r
= get_dmi_property(c
, "ID_HARDWARE_VERSION", &version
);
393 /* Suppress reporting the version field, if it's the same string as the
394 * model or sku field, which it appears to be on various systems */
395 int (*getter
)(Context
*c
, char **ret
);
396 FOREACH_ARGUMENT(getter
, get_hardware_model
, get_hardware_sku
) {
397 _cleanup_free_
char *value
= NULL
;
399 r
= getter(c
, &value
);
404 if (streq_ptr(version
, value
))
408 *ret
= TAKE_PTR(version
);
412 static int get_sysattr(sd_device
*device
, const char *key
, char **ret
) {
422 r
= sd_device_get_sysattr_value(device
, key
, &s
);
426 if (!string_is_safe_for_dbus(s
))
429 return strdup_to(ret
, empty_to_null(s
));
432 static int get_dmi_sysattr(Context
*c
, const char *key
, char **ret
) {
433 return get_sysattr(ASSERT_PTR(c
)->device_dmi
, key
, ret
);
436 static int get_device_tree_sysattr(Context
*c
, const char *key
, char **ret
) {
437 return get_sysattr(ASSERT_PTR(c
)->device_tree
, key
, ret
);
440 static int get_hardware_serial(Context
*c
, char **ret
) {
446 FOREACH_STRING(attr
, "product_serial", "board_serial") {
447 r
= get_dmi_sysattr(c
, attr
, ret
);
448 if (r
>= 0 || !ERRNO_IS_NEG_DEVICE_ABSENT(r
))
452 return get_device_tree_sysattr(c
, "serial-number", ret
);
455 static int get_firmware_version(Context
*c
, char **ret
) {
456 return get_dmi_sysattr(c
, "bios_version", ret
);
459 static int get_firmware_vendor(Context
*c
, char **ret
) {
460 return get_dmi_sysattr(c
, "bios_vendor", ret
);
463 static int get_firmware_date(Context
*c
, usec_t
*ret
) {
464 _cleanup_free_
char *bios_date
= NULL
, *month
= NULL
, *day
= NULL
, *year
= NULL
;
470 r
= get_dmi_sysattr(c
, "bios_date", &bios_date
);
471 if (ERRNO_IS_NEG_DEVICE_ABSENT(r
)) {
472 *ret
= USEC_INFINITY
;
478 const char *p
= bios_date
;
479 r
= extract_many_words(&p
, "/", EXTRACT_DONT_COALESCE_SEPARATORS
, &month
, &day
, &year
);
482 if (r
!= 3) /* less than three args read? */
484 if (!isempty(p
)) /* more left in the string? */
488 r
= safe_atou_full(month
, 10 | SAFE_ATO_REFUSE_PLUS_MINUS
| SAFE_ATO_REFUSE_LEADING_WHITESPACE
, &m
);
495 r
= safe_atou_full(day
, 10 | SAFE_ATO_REFUSE_PLUS_MINUS
| SAFE_ATO_REFUSE_LEADING_WHITESPACE
, &d
);
501 r
= safe_atou_full(year
, 10 | SAFE_ATO_REFUSE_PLUS_MINUS
| SAFE_ATO_REFUSE_LEADING_WHITESPACE
, &y
);
504 if (y
< 1970 || y
> (unsigned) INT_MAX
)
515 r
= mktime_or_timegm_usec(&tm
, /* utc= */ true, &v
);
518 if (tm
.tm_mday
!= (int) d
|| tm
.tm_mon
!= (int) m
|| tm
.tm_year
!= (int) y
)
519 return -EINVAL
; /* date was not normalized? (e.g. "30th of feb") */
525 static const char* valid_chassis(const char *chassis
) {
542 static bool valid_deployment(const char *deployment
) {
545 return in_charset(deployment
, VALID_DEPLOYMENT_CHARS
);
548 static const char* fallback_chassis_by_virtualization(void) {
549 Virtualization v
= detect_virtualization();
551 log_debug_errno(v
, "Failed to detect virtualization, ignoring: %m");
555 if (VIRTUALIZATION_IS_VM(v
))
557 if (VIRTUALIZATION_IS_CONTAINER(v
))
563 static const char* fallback_chassis_by_dmi(Context
*c
) {
572 r
= device_get_sysattr_unsigned(c
->device_dmi
, "chassis_type", &t
);
574 log_debug_errno(r
, "Failed to read/parse DMI chassis type, ignoring: %m");
578 /* We only list the really obvious cases here. The DMI data is unreliable enough, so let's not do any
579 * additional guesswork on top of that.
581 * See the SMBIOS Specification 3.5.0 section 7.4.1 for details about the values listed here:
583 * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.5.0.pdf
588 case 0x03: /* Desktop */
589 case 0x04: /* Low Profile Desktop */
590 case 0x06: /* Mini Tower */
591 case 0x07: /* Tower */
592 case 0x0D: /* All in one (i.e. PC built into monitor) */
593 case 0x23: /* Mini PC */
594 case 0x24: /* Stick PC */
597 case 0x8: /* Portable */
598 case 0x9: /* Laptop */
599 case 0xA: /* Notebook */
600 case 0xE: /* Sub Notebook */
603 case 0xB: /* Hand Held */
606 case 0x11: /* Main Server Chassis */
607 case 0x1C: /* Blade */
608 case 0x1D: /* Blade Enclosure */
611 case 0x1E: /* Tablet */
614 case 0x1F: /* Convertible */
615 case 0x20: /* Detachable */
616 return "convertible";
618 case 0x21: /* IoT Gateway */
619 case 0x22: /* Embedded PC */
623 log_debug("Unhandled DMI chassis type 0x%02x, ignoring.", t
);
628 static const char* fallback_chassis_by_acpi(Context
*c
) {
637 r
= device_get_sysattr_unsigned(c
->device_acpi
, "pm_profile", &t
);
639 log_debug_errno(r
, "Failed read/parse ACPI PM profile, ignoring: %m");
643 /* We only list the really obvious cases here as the ACPI data is not really super reliable.
645 * See the ACPI 5.0 Spec Section 5.2.9.1 for details:
647 * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf
652 case 1: /* Desktop */
653 case 3: /* Workstation */
654 case 6: /* Appliance PC */
660 case 4: /* Enterprise Server */
661 case 5: /* SOHO Server */
662 case 7: /* Performance Server */
669 log_debug("Unhandled ACPI PM profile 0x%02x, ignoring.", t
);
674 static const char* fallback_chassis_by_device_tree(Context
*c
) {
675 const char *type
, *chassis
;
683 r
= sd_device_get_sysattr_value(c
->device_tree
, "chassis-type", &type
);
685 log_debug_errno(r
, "Failed to read device-tree chassis type, ignoring: %m");
689 /* Note that the DeviceTree specification uses the very same vocabulary
690 * of chassis types as we do, hence we do not need to translate these types:
692 * https://github.com/devicetree-org/devicetree-specification/blob/master/source/chapter3-devicenodes.rst */
694 chassis
= valid_chassis(type
);
696 log_debug("Invalid device-tree chassis type \"%s\", ignoring.", type
);
700 static const char* fallback_chassis(Context
*c
) {
704 fallback_chassis_by_virtualization() ?:
705 fallback_chassis_by_dmi(c
) ?:
706 fallback_chassis_by_acpi(c
) ?:
707 fallback_chassis_by_device_tree(c
);
710 static char* context_get_chassis(Context
*c
) {
711 const char *fallback
;
716 if (!isempty(c
->data
[PROP_CHASSIS
]))
717 return strdup(c
->data
[PROP_CHASSIS
]);
719 if (get_dmi_property(c
, "ID_CHASSIS", &dmi
) >= 0)
722 fallback
= fallback_chassis(c
);
724 return strdup(fallback
);
729 static char* context_fallback_icon_name(Context
*c
) {
730 _cleanup_free_
char *chassis
= NULL
;
734 chassis
= context_get_chassis(c
);
736 return strjoin("computer-", chassis
);
738 return strdup("computer");
741 static int context_update_kernel_hostname(
743 const char *transient_hostname
) {
745 _cleanup_free_
char *_hn_free
= NULL
;
752 /* /etc/hostname has the highest preference ... */
753 if (c
->data
[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS
]) {
754 hn
= c
->data
[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS
];
755 hns
= HOSTNAME_STATIC
;
757 /* ... the transient hostname, (ie: DHCP) comes next ... */
758 } else if (transient_hostname
) {
759 hn
= transient_hostname
;
760 hns
= HOSTNAME_TRANSIENT
;
762 /* ... and the ultimate fallback */
764 hn
= _hn_free
= get_default_hostname();
768 hns
= HOSTNAME_DEFAULT
;
771 r
= sethostname_idempotent(hn
);
773 return log_error_errno(r
, "Failed to set hostname: %m");
775 if (c
->hostname_source
!= hns
) {
776 c
->hostname_source
= hns
;
781 log_debug("Hostname was already set to <%s>.", hn
);
783 log_info("Hostname set to <%s> (%s)", hn
, hostname_source_to_string(hns
));
785 hostname_update_source_hint(hn
, hns
);
788 return r
; /* 0 if no change, 1 if something was done */
791 static void unset_statp(struct stat
**p
) {
795 **p
= (struct stat
) {};
798 static int context_write_data_static_hostname(Context
*c
) {
799 _cleanup_(unset_statp
) struct stat
*s
= NULL
;
804 /* Make sure that if we fail here, we invalidate the cached information, since it was updated
805 * already, even if we can't make it hit the disk. */
806 s
= &c
->etc_hostname_stat
;
808 if (isempty(c
->data
[PROP_STATIC_HOSTNAME
])) {
809 if (unlink(etc_hostname()) < 0 && errno
!= ENOENT
)
816 r
= write_string_file(etc_hostname(), c
->data
[PROP_STATIC_HOSTNAME
], WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
|WRITE_STRING_FILE_LABEL
);
824 static int context_write_data_machine_info(Context
*c
) {
825 _cleanup_(unset_statp
) struct stat
*s
= NULL
;
826 static const char * const name
[_PROP_MAX
] = {
827 [PROP_PRETTY_HOSTNAME
] = "PRETTY_HOSTNAME",
828 [PROP_ICON_NAME
] = "ICON_NAME",
829 [PROP_CHASSIS
] = "CHASSIS",
830 [PROP_DEPLOYMENT
] = "DEPLOYMENT",
831 [PROP_LOCATION
] = "LOCATION",
833 _cleanup_strv_free_
char **l
= NULL
;
838 /* Make sure that if we fail here, we invalidate the cached information, since it was updated
839 * already, even if we can't make it hit the disk. */
840 s
= &c
->etc_machine_info_stat
;
842 r
= load_env_file(NULL
, etc_machine_info(), &l
);
843 if (r
< 0 && r
!= -ENOENT
)
846 for (HostProperty p
= PROP_PRETTY_HOSTNAME
; p
<= PROP_LOCATION
; p
++) {
849 r
= strv_env_assign(&l
, name
[p
], empty_to_null(c
->data
[p
]));
854 if (strv_isempty(l
)) {
855 if (unlink(etc_machine_info()) < 0 && errno
!= ENOENT
)
867 WRITE_ENV_FILE_LABEL
);
875 static int property_get_hardware_property(
876 sd_bus_message
*reply
,
879 int (*getter
)(Context
*c
, char **ret
)) {
881 _cleanup_free_
char *from_dmi
= NULL
;
885 assert(IN_SET(prop
, PROP_HARDWARE_VENDOR
, PROP_HARDWARE_MODEL
,
886 PROP_HARDWARE_SKU
, PROP_HARDWARE_VERSION
));
889 context_read_machine_info(c
);
891 if (isempty(c
->data
[prop
]))
892 (void) getter(c
, &from_dmi
);
894 return sd_bus_message_append(reply
, "s", from_dmi
?: c
->data
[prop
]);
897 static int property_get_hardware_vendor(
900 const char *interface
,
901 const char *property
,
902 sd_bus_message
*reply
,
904 sd_bus_error
*error
) {
906 return property_get_hardware_property(reply
, userdata
, PROP_HARDWARE_VENDOR
, get_hardware_vendor
);
909 static int property_get_hardware_model(
912 const char *interface
,
913 const char *property
,
914 sd_bus_message
*reply
,
916 sd_bus_error
*error
) {
918 return property_get_hardware_property(reply
, userdata
, PROP_HARDWARE_MODEL
, get_hardware_model
);
921 static int property_get_hardware_sku(
924 const char *interface
,
925 const char *property
,
926 sd_bus_message
*reply
,
928 sd_bus_error
*error
) {
930 return property_get_hardware_property(reply
, userdata
, PROP_HARDWARE_SKU
, get_hardware_sku
);
933 static int property_get_hardware_version(
936 const char *interface
,
937 const char *property
,
938 sd_bus_message
*reply
,
940 sd_bus_error
*error
) {
942 return property_get_hardware_property(reply
, userdata
, PROP_HARDWARE_VERSION
, get_hardware_version
);
945 static int property_get_firmware_version(
948 const char *interface
,
949 const char *property
,
950 sd_bus_message
*reply
,
952 sd_bus_error
*error
) {
954 _cleanup_free_
char *firmware_version
= NULL
;
955 Context
*c
= ASSERT_PTR(userdata
);
957 (void) get_firmware_version(c
, &firmware_version
);
959 return sd_bus_message_append(reply
, "s", firmware_version
);
962 static int property_get_firmware_vendor(
965 const char *interface
,
966 const char *property
,
967 sd_bus_message
*reply
,
969 sd_bus_error
*error
) {
971 _cleanup_free_
char *firmware_vendor
= NULL
;
972 Context
*c
= ASSERT_PTR(userdata
);
974 (void) get_firmware_vendor(c
, &firmware_vendor
);
976 return sd_bus_message_append(reply
, "s", firmware_vendor
);
979 static int property_get_firmware_date(
982 const char *interface
,
983 const char *property
,
984 sd_bus_message
*reply
,
986 sd_bus_error
*error
) {
988 usec_t firmware_date
= USEC_INFINITY
;
989 Context
*c
= ASSERT_PTR(userdata
);
991 (void) get_firmware_date(c
, &firmware_date
);
993 return sd_bus_message_append(reply
, "t", firmware_date
);
996 static int property_get_chassis_asset_tag(
999 const char *interface
,
1000 const char *property
,
1001 sd_bus_message
*reply
,
1003 sd_bus_error
*error
) {
1005 _cleanup_free_
char *chassis_asset_tag
= NULL
;
1006 Context
*c
= ASSERT_PTR(userdata
);
1008 (void) get_chassis_asset_tag(c
, &chassis_asset_tag
);
1010 return sd_bus_message_append(reply
, "s", chassis_asset_tag
);
1013 static int property_get_hostname(
1016 const char *interface
,
1017 const char *property
,
1018 sd_bus_message
*reply
,
1020 sd_bus_error
*error
) {
1022 _cleanup_free_
char *hn
= NULL
;
1025 r
= gethostname_strict(&hn
);
1030 hn
= get_default_hostname();
1035 return sd_bus_message_append(reply
, "s", hn
);
1038 static int property_get_static_hostname(
1041 const char *interface
,
1042 const char *property
,
1043 sd_bus_message
*reply
,
1045 sd_bus_error
*error
) {
1047 Context
*c
= ASSERT_PTR(userdata
);
1049 context_read_etc_hostname(c
);
1051 return sd_bus_message_append(reply
, "s", c
->data
[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS
]);
1054 static int property_get_default_hostname(
1057 const char *interface
,
1058 const char *property
,
1059 sd_bus_message
*reply
,
1061 sd_bus_error
*error
) {
1063 _cleanup_free_
char *hn
= NULL
;
1065 hn
= get_default_hostname();
1069 return sd_bus_message_append(reply
, "s", hn
);
1072 static void context_determine_hostname_source(Context
*c
) {
1073 _cleanup_free_
char *hostname
= NULL
;
1078 if (c
->hostname_source
>= 0)
1081 (void) gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST
, &hostname
);
1083 if (streq_ptr(hostname
, c
->data
[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS
]))
1084 c
->hostname_source
= HOSTNAME_STATIC
;
1086 _cleanup_free_
char *fallback
= NULL
;
1088 /* If the hostname was not set by us, try to figure out where it came from. If we set it to
1089 * the default hostname, the file will tell us. We compare the string because it is possible
1090 * that the hostname was set by an older version that had a different fallback, in the initrd
1091 * or before we reexecuted. */
1093 r
= read_one_line_file("/run/systemd/default-hostname", &fallback
);
1094 if (r
< 0 && r
!= -ENOENT
)
1095 log_warning_errno(r
, "Failed to read /run/systemd/default-hostname, ignoring: %m");
1097 if (streq_ptr(fallback
, hostname
))
1098 c
->hostname_source
= HOSTNAME_DEFAULT
;
1100 c
->hostname_source
= HOSTNAME_TRANSIENT
;
1104 static int property_get_hostname_source(
1107 const char *interface
,
1108 const char *property
,
1109 sd_bus_message
*reply
,
1111 sd_bus_error
*error
) {
1113 Context
*c
= ASSERT_PTR(userdata
);
1115 context_read_etc_hostname(c
);
1116 context_determine_hostname_source(c
);
1118 return sd_bus_message_append(reply
, "s", hostname_source_to_string(c
->hostname_source
));
1121 static int property_get_machine_info_field(
1124 const char *interface
,
1125 const char *property
,
1126 sd_bus_message
*reply
,
1128 sd_bus_error
*error
) {
1133 /* Acquire the context object without this property's userdata offset added. Explanation: we want
1134 * access to two pointers here: a) the main context object we cache all properties in, and b) the
1135 * pointer to the property field inside the context object that we are supposed to update and
1136 * use. The latter (b) we get in the 'userdata' function parameter, and sd-bus calculates that for us
1137 * from the 'userdata' pointer we supplied when the vtable was registered, with the offset we
1138 * specified in the vtable added on top. To get the former (a) we need the 'userdata' pointer from
1139 * the vtable registration directly, without the offset added. Hence we ask sd-bus what the slot
1140 * object is (which encapsulates the vtable registration), and then query the 'userdata' field
1141 * directly off it. */
1142 assert_se(slot
= sd_bus_get_current_slot(bus
));
1143 assert_se(c
= sd_bus_slot_get_userdata(slot
));
1145 context_read_machine_info(c
);
1147 return sd_bus_message_append(reply
, "s", *(char**) userdata
);
1150 static int property_get_os_release_field(
1153 const char *interface
,
1154 const char *property
,
1155 sd_bus_message
*reply
,
1157 sd_bus_error
*error
) {
1162 /* As above, acquire the current context without this property's userdata offset added. */
1163 assert_se(slot
= sd_bus_get_current_slot(bus
));
1164 assert_se(c
= sd_bus_slot_get_userdata(slot
));
1166 context_read_os_release(c
);
1168 return sd_bus_message_append(reply
, "s", *(char**) userdata
);
1171 static int property_get_os_support_end(
1174 const char *interface
,
1175 const char *property
,
1176 sd_bus_message
*reply
,
1178 sd_bus_error
*error
) {
1180 Context
*c
= userdata
;
1181 usec_t eol
= USEC_INFINITY
;
1183 context_read_os_release(c
);
1185 if (c
->data
[PROP_OS_SUPPORT_END
])
1186 (void) os_release_support_ended(c
->data
[PROP_OS_SUPPORT_END
], /* quiet= */ false, &eol
);
1188 return sd_bus_message_append(reply
, "t", eol
);
1191 static int property_get_icon_name(
1194 const char *interface
,
1195 const char *property
,
1196 sd_bus_message
*reply
,
1198 sd_bus_error
*error
) {
1200 _cleanup_free_
char *n
= NULL
;
1201 Context
*c
= userdata
;
1204 context_read_machine_info(c
);
1206 if (isempty(c
->data
[PROP_ICON_NAME
]))
1207 name
= n
= context_fallback_icon_name(c
);
1209 name
= c
->data
[PROP_ICON_NAME
];
1214 return sd_bus_message_append(reply
, "s", name
);
1217 static int property_get_chassis(
1220 const char *interface
,
1221 const char *property
,
1222 sd_bus_message
*reply
,
1224 sd_bus_error
*error
) {
1226 _cleanup_free_
char *chassis
= NULL
;
1227 Context
*c
= userdata
;
1229 context_read_machine_info(c
);
1231 chassis
= context_get_chassis(c
);
1233 return sd_bus_message_append(reply
, "s", chassis
);
1236 static int property_get_uname_field(
1239 const char *interface
,
1240 const char *property
,
1241 sd_bus_message
*reply
,
1243 sd_bus_error
*error
) {
1247 assert_se(uname(&u
) >= 0);
1249 return sd_bus_message_append(reply
, "s", (char*) &u
+ PTR_TO_SIZE(userdata
));
1252 static int property_get_machine_id(
1255 const char *interface
,
1256 const char *property
,
1257 sd_bus_message
*reply
,
1259 sd_bus_error
*error
) {
1264 r
= sd_id128_get_machine(&id
);
1268 return bus_property_get_id128(bus
, path
, interface
, property
, reply
, &id
, error
);
1271 static int property_get_boot_id(
1274 const char *interface
,
1275 const char *property
,
1276 sd_bus_message
*reply
,
1278 sd_bus_error
*error
) {
1283 r
= sd_id128_get_boot(&id
);
1287 return bus_property_get_id128(bus
, path
, interface
, property
, reply
, &id
, error
);
1290 static int property_get_vsock_cid(
1293 const char *interface
,
1294 const char *property
,
1295 sd_bus_message
*reply
,
1297 sd_bus_error
*error
) {
1299 unsigned local_cid
= VMADDR_CID_ANY
;
1301 (void) vsock_get_local_cid(&local_cid
);
1303 return sd_bus_message_append(reply
, "u", (uint32_t) local_cid
);
1306 static int validate_and_substitute_hostname(const char *name
, char **ret_substituted
, sd_bus_error
*error
) {
1309 assert(ret_substituted
);
1312 *ret_substituted
= NULL
;
1316 _cleanup_free_
char *substituted
= strdup(name
);
1320 r
= hostname_substitute_wildcards(substituted
);
1322 return log_error_errno(r
, "Failed to substitute wildcards in hostname: %m");
1324 if (!hostname_is_valid(substituted
, 0))
1325 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", name
);
1327 *ret_substituted
= TAKE_PTR(substituted
);
1331 static int method_set_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1332 Context
*c
= ASSERT_PTR(userdata
);
1338 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
1342 name
= empty_to_null(name
);
1344 /* We always go through with the procedure below without comparing to the current hostname, because
1345 * we might want to adjust hostname source information even if the actual hostname is unchanged. */
1347 _cleanup_free_
char *substituted
= NULL
;
1348 r
= validate_and_substitute_hostname(name
, &substituted
, error
);
1354 r
= bus_verify_polkit_async_full(
1356 "org.freedesktop.hostname1.set-hostname",
1357 /* details= */ NULL
,
1358 /* good_user= */ UID_INVALID
,
1359 interactive
? POLKIT_ALLOW_INTERACTIVE
: 0,
1360 &c
->polkit_registry
,
1365 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1367 context_read_etc_hostname(c
);
1369 r
= context_update_kernel_hostname(c
, name
);
1371 return sd_bus_error_set_errnof(error
, r
, "Failed to set hostname: %m");
1373 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m
),
1374 "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
1375 "Hostname", "HostnameSource", NULL
);
1377 return sd_bus_reply_method_return(m
, NULL
);
1380 static int method_set_static_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1381 Context
*c
= ASSERT_PTR(userdata
);
1387 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
1391 name
= empty_to_null(name
);
1393 context_read_etc_hostname(c
);
1395 if (streq_ptr(name
, c
->data
[PROP_STATIC_HOSTNAME
]))
1396 return sd_bus_reply_method_return(m
, NULL
);
1398 _cleanup_free_
char *substituted
= NULL
;
1399 r
= validate_and_substitute_hostname(name
, &substituted
, error
);
1403 r
= bus_verify_polkit_async_full(
1405 "org.freedesktop.hostname1.set-static-hostname",
1406 /* details= */ NULL
,
1407 /* good_user= */ UID_INVALID
,
1408 interactive
? POLKIT_ALLOW_INTERACTIVE
: 0,
1409 &c
->polkit_registry
,
1414 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1416 r
= free_and_strdup_warn(&c
->data
[PROP_STATIC_HOSTNAME
], name
);
1420 free_and_replace(c
->data
[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS
], substituted
);
1422 r
= context_write_data_static_hostname(c
);
1424 log_error_errno(r
, "Failed to write static hostname: %m");
1425 if (ERRNO_IS_PRIVILEGE(r
))
1426 return sd_bus_error_set(error
, BUS_ERROR_FILE_IS_PROTECTED
, "Not allowed to update /etc/hostname.");
1428 return sd_bus_error_set(error
, BUS_ERROR_READ_ONLY_FILESYSTEM
, "/etc/hostname is in a read-only filesystem.");
1429 return sd_bus_error_set_errnof(error
, r
, "Failed to set static hostname: %m");
1432 r
= context_update_kernel_hostname(c
, /* transient_hostname= */ NULL
);
1434 log_error_errno(r
, "Failed to set hostname: %m");
1435 return sd_bus_error_set_errnof(error
, r
, "Failed to set hostname: %m");
1438 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m
),
1439 "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
1440 "StaticHostname", "Hostname", "HostnameSource", NULL
);
1442 return sd_bus_reply_method_return(m
, NULL
);
1445 static int set_machine_info(Context
*c
, sd_bus_message
*m
, int prop
, sd_bus_message_handler_t cb
, sd_bus_error
*error
) {
1453 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
1457 name
= empty_to_null(name
);
1459 context_read_machine_info(c
);
1461 if (streq_ptr(name
, c
->data
[prop
]))
1462 return sd_bus_reply_method_return(m
, NULL
);
1464 if (!isempty(name
)) {
1465 /* The icon name might ultimately be used as file
1466 * name, so better be safe than sorry */
1468 if (prop
== PROP_ICON_NAME
&& !filename_is_valid(name
))
1469 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid icon name '%s'", name
);
1470 if (prop
== PROP_PRETTY_HOSTNAME
&& string_has_cc(name
, NULL
))
1471 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid pretty hostname '%s'", name
);
1472 if (prop
== PROP_CHASSIS
&& !valid_chassis(name
))
1473 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid chassis '%s'", name
);
1474 if (prop
== PROP_DEPLOYMENT
&& !valid_deployment(name
))
1475 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid deployment '%s'", name
);
1476 if (prop
== PROP_LOCATION
&& string_has_cc(name
, NULL
))
1477 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid location '%s'", name
);
1480 /* Since the pretty hostname should always be changed at the same time as the static one, use the
1481 * same policy action for both... */
1483 r
= bus_verify_polkit_async_full(
1485 prop
== PROP_PRETTY_HOSTNAME
? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info",
1486 /* details= */ NULL
,
1487 /* good_user= */ UID_INVALID
,
1488 interactive
? POLKIT_ALLOW_INTERACTIVE
: 0,
1489 &c
->polkit_registry
,
1494 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1496 r
= free_and_strdup_warn(&c
->data
[prop
], name
);
1500 r
= context_write_data_machine_info(c
);
1502 log_error_errno(r
, "Failed to write machine info: %m");
1503 if (ERRNO_IS_PRIVILEGE(r
))
1504 return sd_bus_error_set(error
, BUS_ERROR_FILE_IS_PROTECTED
, "Not allowed to update /etc/machine-info.");
1506 return sd_bus_error_set(error
, BUS_ERROR_READ_ONLY_FILESYSTEM
, "/etc/machine-info is in a read-only filesystem.");
1507 return sd_bus_error_set_errnof(error
, r
, "Failed to write machine info: %m");
1510 log_info("Changed %s to '%s'",
1511 prop
== PROP_PRETTY_HOSTNAME
? "pretty hostname" :
1512 prop
== PROP_DEPLOYMENT
? "deployment" :
1513 prop
== PROP_LOCATION
? "location" :
1514 prop
== PROP_CHASSIS
? "chassis" : "icon name", strna(c
->data
[prop
]));
1516 (void) sd_bus_emit_properties_changed(
1517 sd_bus_message_get_bus(m
),
1518 "/org/freedesktop/hostname1",
1519 "org.freedesktop.hostname1",
1520 prop
== PROP_PRETTY_HOSTNAME
? "PrettyHostname" :
1521 prop
== PROP_DEPLOYMENT
? "Deployment" :
1522 prop
== PROP_LOCATION
? "Location" :
1523 prop
== PROP_CHASSIS
? "Chassis" : "IconName" , NULL
);
1525 return sd_bus_reply_method_return(m
, NULL
);
1528 static int method_set_pretty_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1529 return set_machine_info(userdata
, m
, PROP_PRETTY_HOSTNAME
, method_set_pretty_hostname
, error
);
1532 static int method_set_icon_name(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1533 return set_machine_info(userdata
, m
, PROP_ICON_NAME
, method_set_icon_name
, error
);
1536 static int method_set_chassis(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1537 return set_machine_info(userdata
, m
, PROP_CHASSIS
, method_set_chassis
, error
);
1540 static int method_set_deployment(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1541 return set_machine_info(userdata
, m
, PROP_DEPLOYMENT
, method_set_deployment
, error
);
1544 static int method_set_location(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1545 return set_machine_info(userdata
, m
, PROP_LOCATION
, method_set_location
, error
);
1548 static int method_get_product_uuid(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1549 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1550 Context
*c
= ASSERT_PTR(userdata
);
1556 r
= sd_bus_message_read(m
, "b", &interactive
);
1560 r
= bus_verify_polkit_async_full(
1562 "org.freedesktop.hostname1.get-product-uuid",
1563 /* details= */ NULL
,
1564 /* good_user= */ UID_INVALID
,
1565 interactive
? POLKIT_ALLOW_INTERACTIVE
: 0,
1566 &c
->polkit_registry
,
1571 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1573 r
= id128_get_product(&uuid
);
1575 if (r
== -EADDRNOTAVAIL
)
1576 log_debug_errno(r
, "DMI product UUID is all 0x00 or all 0xFF, ignoring.");
1578 log_full_errno(r
== -ENOENT
? LOG_DEBUG
: LOG_WARNING
, r
,
1579 "Failed to read product UUID, ignoring: %m");
1581 return sd_bus_error_set(error
, BUS_ERROR_NO_PRODUCT_UUID
,
1582 "Failed to read product UUID from firmware.");
1585 r
= sd_bus_message_new_method_return(m
, &reply
);
1589 r
= sd_bus_message_append_array(reply
, 'y', uuid
.bytes
, sizeof(uuid
.bytes
));
1593 return sd_bus_message_send(reply
);
1596 static int method_get_hardware_serial(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1597 _cleanup_free_
char *serial
= NULL
;
1598 Context
*c
= ASSERT_PTR(userdata
);
1603 r
= bus_verify_polkit_async(
1605 "org.freedesktop.hostname1.get-hardware-serial",
1606 /* details= */ NULL
,
1607 &c
->polkit_registry
,
1612 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1614 r
= get_hardware_serial(c
, &serial
);
1616 return sd_bus_error_set(error
, BUS_ERROR_NO_HARDWARE_SERIAL
,
1617 "Failed to read hardware serial from firmware.");
1619 return sd_bus_reply_method_return(m
, "s", serial
);
1622 static int build_describe_response(Context
*c
, bool privileged
, sd_json_variant
**ret
) {
1623 _cleanup_free_
char *hn
= NULL
, *dhn
= NULL
, *in
= NULL
,
1624 *chassis
= NULL
, *vendor
= NULL
, *model
= NULL
, *serial
= NULL
, *firmware_version
= NULL
,
1625 *firmware_vendor
= NULL
, *chassis_asset_tag
= NULL
, *sku
= NULL
, *hardware_version
= NULL
;
1626 _cleanup_strv_free_
char **os_release_pairs
= NULL
, **machine_info_pairs
= NULL
;
1627 usec_t firmware_date
= USEC_INFINITY
, eol
= USEC_INFINITY
;
1628 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
1629 sd_id128_t machine_id
, boot_id
, product_uuid
= SD_ID128_NULL
;
1630 unsigned local_cid
= VMADDR_CID_ANY
;
1637 context_read_etc_hostname(c
);
1638 context_read_machine_info(c
);
1639 context_read_os_release(c
);
1640 context_determine_hostname_source(c
);
1642 dhn
= get_default_hostname();
1646 r
= gethostname_strict(&hn
);
1647 if (r
< 0 && r
!= -ENXIO
)
1648 return log_error_errno(r
, "Failed to read local host name: %m");
1650 if (isempty(c
->data
[PROP_ICON_NAME
]))
1651 in
= context_fallback_icon_name(c
);
1653 chassis
= context_get_chassis(c
);
1655 assert_se(uname(&u
) >= 0);
1657 if (isempty(c
->data
[PROP_HARDWARE_VENDOR
]))
1658 (void) get_hardware_vendor(c
, &vendor
);
1659 if (isempty(c
->data
[PROP_HARDWARE_MODEL
]))
1660 (void) get_hardware_model(c
, &model
);
1661 if (isempty(c
->data
[PROP_HARDWARE_SKU
]))
1662 (void) get_hardware_sku(c
, &sku
);
1663 if (isempty(c
->data
[PROP_HARDWARE_VERSION
]))
1664 (void) get_hardware_version(c
, &hardware_version
);
1667 /* The product UUID and hardware serial is only available to privileged clients */
1668 (void) id128_get_product(&product_uuid
);
1669 (void) get_hardware_serial(c
, &serial
);
1671 (void) get_firmware_version(c
, &firmware_version
);
1672 (void) get_firmware_vendor(c
, &firmware_vendor
);
1673 (void) get_firmware_date(c
, &firmware_date
);
1674 (void) get_chassis_asset_tag(c
, &chassis_asset_tag
);
1676 if (c
->data
[PROP_OS_SUPPORT_END
])
1677 (void) os_release_support_ended(c
->data
[PROP_OS_SUPPORT_END
], /* quiet= */ false, &eol
);
1679 r
= sd_id128_get_machine(&machine_id
);
1681 return log_error_errno(r
, "Failed to get machine ID: %m");
1683 r
= sd_id128_get_boot(&boot_id
);
1685 return log_error_errno(r
, "Failed to get boot ID: %m");
1687 (void) vsock_get_local_cid(&local_cid
);
1689 (void) load_os_release_pairs(/* root= */ NULL
, &os_release_pairs
);
1690 (void) load_env_file_pairs(/* f=*/ NULL
, etc_machine_info(), &machine_info_pairs
);
1694 SD_JSON_BUILD_PAIR_STRING("Hostname", hn
?: dhn
),
1695 SD_JSON_BUILD_PAIR_STRING("StaticHostname", c
->data
[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS
]),
1696 SD_JSON_BUILD_PAIR_STRING("PrettyHostname", c
->data
[PROP_PRETTY_HOSTNAME
]),
1697 SD_JSON_BUILD_PAIR_STRING("DefaultHostname", dhn
),
1698 SD_JSON_BUILD_PAIR_STRING("HostnameSource", hostname_source_to_string(c
->hostname_source
)),
1699 SD_JSON_BUILD_PAIR_STRING("IconName", in
?: c
->data
[PROP_ICON_NAME
]),
1700 SD_JSON_BUILD_PAIR_STRING("Chassis", chassis
),
1701 SD_JSON_BUILD_PAIR_STRING("ChassisAssetTag", chassis_asset_tag
),
1702 SD_JSON_BUILD_PAIR_STRING("Deployment", c
->data
[PROP_DEPLOYMENT
]),
1703 SD_JSON_BUILD_PAIR_STRING("Location", c
->data
[PROP_LOCATION
]),
1704 SD_JSON_BUILD_PAIR_STRING("KernelName", u
.sysname
),
1705 SD_JSON_BUILD_PAIR_STRING("KernelRelease", u
.release
),
1706 SD_JSON_BUILD_PAIR_STRING("KernelVersion", u
.version
),
1707 SD_JSON_BUILD_PAIR_STRING("OperatingSystemPrettyName", c
->data
[PROP_OS_PRETTY_NAME
]),
1708 SD_JSON_BUILD_PAIR_STRING("OperatingSystemCPEName", c
->data
[PROP_OS_CPE_NAME
]),
1709 SD_JSON_BUILD_PAIR_STRING("OperatingSystemHomeURL", c
->data
[PROP_OS_HOME_URL
]),
1710 JSON_BUILD_PAIR_FINITE_USEC("OperatingSystemSupportEnd", eol
),
1711 SD_JSON_BUILD_PAIR("OperatingSystemReleaseData", JSON_BUILD_STRV_ENV_PAIR(os_release_pairs
)),
1712 SD_JSON_BUILD_PAIR_STRING("OperatingSystemImageID", c
->data
[PROP_OS_IMAGE_ID
]),
1713 SD_JSON_BUILD_PAIR_STRING("OperatingSystemImageVersion", c
->data
[PROP_OS_IMAGE_VERSION
]),
1714 SD_JSON_BUILD_PAIR("MachineInformationData", JSON_BUILD_STRV_ENV_PAIR(machine_info_pairs
)),
1715 SD_JSON_BUILD_PAIR_STRING("HardwareVendor", vendor
?: c
->data
[PROP_HARDWARE_VENDOR
]),
1716 SD_JSON_BUILD_PAIR_STRING("HardwareModel", model
?: c
->data
[PROP_HARDWARE_MODEL
]),
1717 SD_JSON_BUILD_PAIR_STRING("HardwareSerial", serial
),
1718 SD_JSON_BUILD_PAIR_STRING("HardwareSKU", sku
?: c
->data
[PROP_HARDWARE_SKU
]),
1719 SD_JSON_BUILD_PAIR_STRING("HardwareVersion", hardware_version
?: c
->data
[PROP_HARDWARE_VERSION
]),
1720 SD_JSON_BUILD_PAIR_STRING("FirmwareVersion", firmware_version
),
1721 SD_JSON_BUILD_PAIR_STRING("FirmwareVendor", firmware_vendor
),
1722 JSON_BUILD_PAIR_FINITE_USEC("FirmwareDate", firmware_date
),
1723 SD_JSON_BUILD_PAIR_ID128("MachineID", machine_id
),
1724 SD_JSON_BUILD_PAIR_ID128("BootID", boot_id
),
1725 SD_JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(product_uuid
), "ProductUUID", SD_JSON_BUILD_ID128(product_uuid
)),
1726 SD_JSON_BUILD_PAIR_CONDITION(sd_id128_is_null(product_uuid
), "ProductUUID", SD_JSON_BUILD_NULL
),
1727 SD_JSON_BUILD_PAIR_CONDITION(local_cid
!= VMADDR_CID_ANY
, "VSockCID", SD_JSON_BUILD_UNSIGNED(local_cid
)),
1728 SD_JSON_BUILD_PAIR_CONDITION(local_cid
== VMADDR_CID_ANY
, "VSockCID", SD_JSON_BUILD_NULL
));
1730 return log_error_errno(r
, "Failed to build JSON data: %m");
1736 static int method_describe(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1737 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
1738 Context
*c
= ASSERT_PTR(userdata
);
1739 _cleanup_free_
char *text
= NULL
;
1745 r
= bus_verify_polkit_async(
1747 "org.freedesktop.hostname1.get-description",
1748 /* details= */ NULL
,
1749 &c
->polkit_registry
,
1752 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1754 /* We ignore all authentication errors here, since most data is unprivileged, the one exception being
1755 * the product ID which we'll check explicitly. */
1758 r
= build_describe_response(c
, privileged
, &v
);
1762 r
= sd_json_variant_format(v
, 0, &text
);
1764 return log_error_errno(r
, "Failed to format JSON data: %m");
1766 return sd_bus_reply_method_return(m
, "s", text
);
1769 static const sd_bus_vtable hostname_vtable
[] = {
1770 SD_BUS_VTABLE_START(0),
1771 SD_BUS_PROPERTY("Hostname", "s", property_get_hostname
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1772 SD_BUS_PROPERTY("StaticHostname", "s", property_get_static_hostname
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1773 SD_BUS_PROPERTY("PrettyHostname", "s", property_get_machine_info_field
, offsetof(Context
, data
[PROP_PRETTY_HOSTNAME
]), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1774 SD_BUS_PROPERTY("DefaultHostname", "s", property_get_default_hostname
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1775 SD_BUS_PROPERTY("HostnameSource", "s", property_get_hostname_source
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1776 SD_BUS_PROPERTY("IconName", "s", property_get_icon_name
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1777 SD_BUS_PROPERTY("Chassis", "s", property_get_chassis
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1778 SD_BUS_PROPERTY("Deployment", "s", property_get_machine_info_field
, offsetof(Context
, data
[PROP_DEPLOYMENT
]), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1779 SD_BUS_PROPERTY("Location", "s", property_get_machine_info_field
, offsetof(Context
, data
[PROP_LOCATION
]), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1780 SD_BUS_PROPERTY("KernelName", "s", property_get_uname_field
, offsetof(struct utsname
, sysname
), SD_BUS_VTABLE_ABSOLUTE_OFFSET
|SD_BUS_VTABLE_PROPERTY_CONST
),
1781 SD_BUS_PROPERTY("KernelRelease", "s", property_get_uname_field
, offsetof(struct utsname
, release
), SD_BUS_VTABLE_ABSOLUTE_OFFSET
|SD_BUS_VTABLE_PROPERTY_CONST
),
1782 SD_BUS_PROPERTY("KernelVersion", "s", property_get_uname_field
, offsetof(struct utsname
, version
), SD_BUS_VTABLE_ABSOLUTE_OFFSET
|SD_BUS_VTABLE_PROPERTY_CONST
),
1783 SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", property_get_os_release_field
, offsetof(Context
, data
[PROP_OS_PRETTY_NAME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1784 SD_BUS_PROPERTY("OperatingSystemCPEName", "s", property_get_os_release_field
, offsetof(Context
, data
[PROP_OS_CPE_NAME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1785 SD_BUS_PROPERTY("OperatingSystemSupportEnd", "t", property_get_os_support_end
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1786 SD_BUS_PROPERTY("HomeURL", "s", property_get_os_release_field
, offsetof(Context
, data
[PROP_OS_HOME_URL
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1787 SD_BUS_PROPERTY("OperatingSystemImageID", "s", property_get_os_release_field
, offsetof(Context
, data
[PROP_OS_IMAGE_ID
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1788 SD_BUS_PROPERTY("OperatingSystemImageVersion", "s", property_get_os_release_field
, offsetof(Context
, data
[PROP_OS_IMAGE_VERSION
]), SD_BUS_VTABLE_PROPERTY_CONST
),
1789 SD_BUS_PROPERTY("HardwareVendor", "s", property_get_hardware_vendor
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1790 SD_BUS_PROPERTY("HardwareModel", "s", property_get_hardware_model
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1791 SD_BUS_PROPERTY("HardwareSKU", "s", property_get_hardware_sku
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1792 SD_BUS_PROPERTY("HardwareVersion", "s", property_get_hardware_version
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1793 SD_BUS_PROPERTY("FirmwareVersion", "s", property_get_firmware_version
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1794 SD_BUS_PROPERTY("FirmwareVendor", "s", property_get_firmware_vendor
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1795 SD_BUS_PROPERTY("FirmwareDate", "t", property_get_firmware_date
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1796 SD_BUS_PROPERTY("MachineID", "ay", property_get_machine_id
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1797 SD_BUS_PROPERTY("BootID", "ay", property_get_boot_id
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1798 SD_BUS_PROPERTY("VSockCID", "u", property_get_vsock_cid
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1799 SD_BUS_PROPERTY("ChassisAssetTag", "s", property_get_chassis_asset_tag
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1801 SD_BUS_METHOD_WITH_ARGS("SetHostname",
1802 SD_BUS_ARGS("s", hostname
, "b", interactive
),
1804 method_set_hostname
,
1805 SD_BUS_VTABLE_UNPRIVILEGED
),
1806 SD_BUS_METHOD_WITH_ARGS("SetStaticHostname",
1807 SD_BUS_ARGS("s", hostname
, "b", interactive
),
1809 method_set_static_hostname
,
1810 SD_BUS_VTABLE_UNPRIVILEGED
),
1811 SD_BUS_METHOD_WITH_ARGS("SetPrettyHostname",
1812 SD_BUS_ARGS("s", hostname
, "b", interactive
),
1814 method_set_pretty_hostname
,
1815 SD_BUS_VTABLE_UNPRIVILEGED
),
1816 SD_BUS_METHOD_WITH_ARGS("SetIconName",
1817 SD_BUS_ARGS("s", icon
, "b", interactive
),
1819 method_set_icon_name
,
1820 SD_BUS_VTABLE_UNPRIVILEGED
),
1821 SD_BUS_METHOD_WITH_ARGS("SetChassis",
1822 SD_BUS_ARGS("s", chassis
, "b", interactive
),
1825 SD_BUS_VTABLE_UNPRIVILEGED
),
1826 SD_BUS_METHOD_WITH_ARGS("SetDeployment",
1827 SD_BUS_ARGS("s", deployment
, "b", interactive
),
1829 method_set_deployment
,
1830 SD_BUS_VTABLE_UNPRIVILEGED
),
1831 SD_BUS_METHOD_WITH_ARGS("SetLocation",
1832 SD_BUS_ARGS("s", location
, "b", interactive
),
1834 method_set_location
,
1835 SD_BUS_VTABLE_UNPRIVILEGED
),
1836 SD_BUS_METHOD_WITH_ARGS("GetProductUUID",
1837 SD_BUS_ARGS("b", interactive
),
1838 SD_BUS_RESULT("ay", uuid
),
1839 method_get_product_uuid
,
1840 SD_BUS_VTABLE_UNPRIVILEGED
),
1841 SD_BUS_METHOD_WITH_ARGS("GetHardwareSerial",
1843 SD_BUS_RESULT("s", serial
),
1844 method_get_hardware_serial
,
1845 SD_BUS_VTABLE_UNPRIVILEGED
),
1846 SD_BUS_METHOD_WITH_ARGS("Describe",
1848 SD_BUS_RESULT("s", json
),
1850 SD_BUS_VTABLE_UNPRIVILEGED
),
1855 static const BusObjectImplementation manager_object
= {
1856 "/org/freedesktop/hostname1",
1857 "org.freedesktop.hostname1",
1858 .vtables
= BUS_VTABLES(hostname_vtable
),
1861 static int connect_bus(Context
*c
) {
1868 r
= sd_bus_default_system(&c
->bus
);
1870 return log_error_errno(r
, "Failed to get system bus connection: %m");
1872 r
= bus_add_implementation(c
->bus
, &manager_object
, c
);
1876 r
= bus_log_control_api_register(c
->bus
);
1880 r
= sd_bus_request_name_async(c
->bus
, NULL
, "org.freedesktop.hostname1", 0, NULL
, NULL
);
1882 return log_error_errno(r
, "Failed to request name: %m");
1884 r
= sd_bus_attach_event(c
->bus
, c
->event
, 0);
1886 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
1891 static int vl_method_describe(sd_varlink
*link
, sd_json_variant
*parameters
, sd_varlink_method_flags_t flags
, void *userdata
) {
1892 Context
*c
= ASSERT_PTR(userdata
);
1899 r
= sd_varlink_dispatch(link
, parameters
, dispatch_table_polkit_only
, /* userdata= */ NULL
);
1903 r
= varlink_verify_polkit_async_full(
1906 "org.freedesktop.hostname1.get-hardware-serial",
1907 /* details= */ NULL
,
1910 &c
->polkit_registry
);
1912 return 0; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1914 /* We ignore all authentication errors here, since most data is unprivileged, the one exception being
1915 * the product ID which we'll check explicitly. */
1918 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
1919 r
= build_describe_response(c
, privileged
, &v
);
1923 return sd_varlink_reply(link
, v
);
1926 static int connect_varlink(Context
*c
) {
1931 assert(!c
->varlink_server
);
1933 r
= varlink_server_new(
1935 SD_VARLINK_SERVER_ACCOUNT_UID
|SD_VARLINK_SERVER_INHERIT_USERDATA
,
1938 return log_error_errno(r
, "Failed to allocate Varlink server: %m");
1940 r
= sd_varlink_server_add_interface_many(
1942 &vl_interface_io_systemd_Hostname
,
1943 &vl_interface_io_systemd_service
);
1945 return log_error_errno(r
, "Failed to add Hostname interface to Varlink server: %m");
1947 r
= sd_varlink_server_bind_method_many(
1949 "io.systemd.Hostname.Describe", vl_method_describe
,
1950 "io.systemd.service.Ping", varlink_method_ping
,
1951 "io.systemd.service.SetLogLevel", varlink_method_set_log_level
,
1952 "io.systemd.service.GetEnvironment", varlink_method_get_environment
);
1954 return log_error_errno(r
, "Failed to bind Varlink method calls: %m");
1956 r
= sd_varlink_server_attach_event(c
->varlink_server
, c
->event
, SD_EVENT_PRIORITY_NORMAL
);
1958 return log_error_errno(r
, "Failed to attach Varlink server to event loop: %m");
1960 r
= sd_varlink_server_listen_auto(c
->varlink_server
);
1962 return log_error_errno(r
, "Failed to bind to passed Varlink sockets: %m");
1964 r
= sd_varlink_server_listen_address(c
->varlink_server
, "/run/systemd/io.systemd.Hostname", 0666);
1966 return log_error_errno(r
, "Failed to bind to Varlink socket: %m");
1972 static bool context_check_idle(void *userdata
) {
1973 Context
*c
= ASSERT_PTR(userdata
);
1975 return sd_varlink_server_current_connections(c
->varlink_server
) == 0 &&
1976 hashmap_isempty(c
->polkit_registry
);
1979 static int run(int argc
, char *argv
[]) {
1980 _cleanup_(context_destroy
) Context context
= {
1981 .hostname_source
= _HOSTNAME_INVALID
, /* appropriate value will be set later */
1987 r
= service_parse_argv("systemd-hostnamed.service",
1988 "Manage the system hostname and related metadata.",
1989 BUS_IMPLEMENTATIONS(&manager_object
,
1990 &log_control_object
),
2001 r
= context_acquire_dmi_device(&context
);
2005 r
= context_acquire_acpi_device(&context
);
2009 r
= context_acquire_device_tree(&context
);
2013 r
= sd_event_default(&context
.event
);
2015 return log_error_errno(r
, "Failed to allocate event loop: %m");
2017 (void) sd_event_set_watchdog(context
.event
, true);
2019 r
= sd_event_set_signal_exit(context
.event
, true);
2021 return log_error_errno(r
, "Failed to install SIGINT/SIGTERM handlers: %m");
2023 r
= connect_bus(&context
);
2027 r
= connect_varlink(&context
);
2031 r
= sd_notify(false, NOTIFY_READY_MESSAGE
);
2033 log_warning_errno(r
, "Failed to send readiness notification, ignoring: %m");
2035 r
= bus_event_loop_with_idle(
2038 "org.freedesktop.hostname1",
2043 return log_error_errno(r
, "Failed to run event loop: %m");
2048 DEFINE_MAIN_FUNCTION(run
);