1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <sys/utsname.h>
9 #include "alloc-util.h"
10 #include "bus-common-errors.h"
11 #include "bus-get-properties.h"
12 #include "bus-log-control-api.h"
13 #include "bus-polkit.h"
14 #include "constants.h"
15 #include "env-file-label.h"
18 #include "fileio-label.h"
20 #include "hostname-setup.h"
21 #include "hostname-util.h"
22 #include "id128-util.h"
24 #include "main-func.h"
25 #include "missing_capability.h"
26 #include "nscd-flush.h"
27 #include "nulstr-util.h"
29 #include "parse-util.h"
30 #include "path-util.h"
31 #include "sd-device.h"
32 #include "selinux-util.h"
33 #include "service-util.h"
34 #include "signal-util.h"
35 #include "stat-util.h"
36 #include "string-table.h"
38 #include "user-util.h"
41 #define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:")
43 /* Properties we cache are indexed by an enum, to make invalidation easy and systematic (as we can iterate
44 * through them all, and they are uniformly strings). */
46 /* Read from /etc/hostname */
49 /* Read from /etc/machine-info */
58 /* Read from /etc/os-release (or /usr/lib/os-release) */
64 _PROP_INVALID
= -EINVAL
,
67 typedef struct Context
{
68 char *data
[_PROP_MAX
];
70 HostnameSource hostname_source
;
72 struct stat etc_hostname_stat
;
73 struct stat etc_os_release_stat
;
74 struct stat etc_machine_info_stat
;
76 Hashmap
*polkit_registry
;
79 static void context_reset(Context
*c
, uint64_t mask
) {
82 for (int p
= 0; p
< _PROP_MAX
; p
++) {
83 if (!FLAGS_SET(mask
, UINT64_C(1) << p
))
86 c
->data
[p
] = mfree(c
->data
[p
]);
90 static void context_destroy(Context
*c
) {
93 context_reset(c
, UINT64_MAX
);
94 bus_verify_polkit_async_registry_free(c
->polkit_registry
);
97 static void context_read_etc_hostname(Context
*c
) {
98 struct stat current_stat
= {};
103 if (stat("/etc/hostname", ¤t_stat
) >= 0 &&
104 stat_inode_unmodified(&c
->etc_hostname_stat
, ¤t_stat
))
107 context_reset(c
, UINT64_C(1) << PROP_STATIC_HOSTNAME
);
109 r
= read_etc_hostname(NULL
, &c
->data
[PROP_STATIC_HOSTNAME
]);
110 if (r
< 0 && r
!= -ENOENT
)
111 log_warning_errno(r
, "Failed to read /etc/hostname, ignoring: %m");
113 c
->etc_hostname_stat
= current_stat
;
116 static void context_read_machine_info(Context
*c
) {
117 struct stat current_stat
= {};
122 if (stat("/etc/machine-info", ¤t_stat
) >= 0 &&
123 stat_inode_unmodified(&c
->etc_machine_info_stat
, ¤t_stat
))
127 (UINT64_C(1) << PROP_PRETTY_HOSTNAME
) |
128 (UINT64_C(1) << PROP_ICON_NAME
) |
129 (UINT64_C(1) << PROP_CHASSIS
) |
130 (UINT64_C(1) << PROP_DEPLOYMENT
) |
131 (UINT64_C(1) << PROP_LOCATION
) |
132 (UINT64_C(1) << PROP_HARDWARE_VENDOR
) |
133 (UINT64_C(1) << PROP_HARDWARE_MODEL
));
135 r
= parse_env_file(NULL
, "/etc/machine-info",
136 "PRETTY_HOSTNAME", &c
->data
[PROP_PRETTY_HOSTNAME
],
137 "ICON_NAME", &c
->data
[PROP_ICON_NAME
],
138 "CHASSIS", &c
->data
[PROP_CHASSIS
],
139 "DEPLOYMENT", &c
->data
[PROP_DEPLOYMENT
],
140 "LOCATION", &c
->data
[PROP_LOCATION
],
141 "HARDWARE_VENDOR", &c
->data
[PROP_HARDWARE_VENDOR
],
142 "HARDWARE_MODEL", &c
->data
[PROP_HARDWARE_MODEL
]);
143 if (r
< 0 && r
!= -ENOENT
)
144 log_warning_errno(r
, "Failed to read /etc/machine-info, ignoring: %m");
146 c
->etc_machine_info_stat
= current_stat
;
149 static void context_read_os_release(Context
*c
) {
150 _cleanup_free_
char *os_name
= NULL
, *os_pretty_name
= NULL
;
151 struct stat current_stat
= {};
156 if ((stat("/etc/os-release", ¤t_stat
) >= 0 ||
157 stat("/usr/lib/os-release", ¤t_stat
) >= 0) &&
158 stat_inode_unmodified(&c
->etc_os_release_stat
, ¤t_stat
))
162 (UINT64_C(1) << PROP_OS_PRETTY_NAME
) |
163 (UINT64_C(1) << PROP_OS_CPE_NAME
) |
164 (UINT64_C(1) << PROP_OS_HOME_URL
) |
165 (UINT64_C(1) << PROP_OS_SUPPORT_END
));
167 r
= parse_os_release(NULL
,
168 "PRETTY_NAME", &os_pretty_name
,
170 "CPE_NAME", &c
->data
[PROP_OS_CPE_NAME
],
171 "HOME_URL", &c
->data
[PROP_OS_HOME_URL
],
172 "SUPPORT_END", &c
->data
[PROP_OS_SUPPORT_END
]);
173 if (r
< 0 && r
!= -ENOENT
)
174 log_warning_errno(r
, "Failed to read os-release file, ignoring: %m");
176 if (free_and_strdup(&c
->data
[PROP_OS_PRETTY_NAME
], os_release_pretty_name(os_pretty_name
, os_name
)) < 0)
179 c
->etc_os_release_stat
= current_stat
;
182 static bool use_dmi_data(void) {
185 r
= getenv_bool("SYSTEMD_HOSTNAME_FORCE_DMI");
187 log_debug("Honouring $SYSTEMD_HOSTNAME_FORCE_DMI override: %s", yes_no(r
));
191 log_debug_errno(r
, "Failed to parse $SYSTEMD_HOSTNAME_FORCE_DMI, ignoring: %m");
193 if (detect_container() > 0) {
194 log_debug("Running in a container, not using DMI hardware data.");
201 static int get_dmi_data(const char *database_key
, const char *regular_key
, char **ret
) {
202 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
203 _cleanup_free_
char *b
= NULL
;
204 const char *s
= NULL
;
210 r
= sd_device_new_from_syspath(&device
, "/sys/class/dmi/id");
212 return log_debug_errno(r
, "Failed to open /sys/class/dmi/id device, ignoring: %m");
215 (void) sd_device_get_property_value(device
, database_key
, &s
);
216 if (!s
&& regular_key
)
217 (void) sd_device_get_property_value(device
, regular_key
, &s
);
232 static int get_hardware_vendor(char **ret
) {
233 return get_dmi_data("ID_VENDOR_FROM_DATABASE", "ID_VENDOR", ret
);
236 static int get_hardware_model(char **ret
) {
237 return get_dmi_data("ID_MODEL_FROM_DATABASE", "ID_MODEL", ret
);
240 static int get_hardware_firmware_data(const char *sysattr
, char **ret
) {
241 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
242 _cleanup_free_
char *b
= NULL
;
243 const char *s
= NULL
;
251 r
= sd_device_new_from_syspath(&device
, "/sys/class/dmi/id");
253 return log_debug_errno(r
, "Failed to open /sys/class/dmi/id device, ignoring: %m");
255 (void) sd_device_get_sysattr_value(device
, sysattr
, &s
);
268 static int get_hardware_serial(char **ret
) {
271 r
= get_hardware_firmware_data("product_serial", ret
);
273 return get_hardware_firmware_data("board_serial", ret
);
278 static int get_firmware_version(char **ret
) {
279 return get_hardware_firmware_data("bios_version", ret
);
282 static int get_firmware_vendor(char **ret
) {
283 return get_hardware_firmware_data("bios_vendor", ret
);
286 static int get_firmware_date(usec_t
*ret
) {
287 _cleanup_free_
char *bios_date
= NULL
, *month
= NULL
, *day
= NULL
, *year
= NULL
;
292 r
= get_hardware_firmware_data("bios_date", &bios_date
);
296 *ret
= USEC_INFINITY
;
300 const char *p
= bios_date
;
301 r
= extract_many_words(&p
, "/", EXTRACT_DONT_COALESCE_SEPARATORS
, &month
, &day
, &year
, NULL
);
304 if (r
!= 3) /* less than three args read? */
306 if (!isempty(p
)) /* more left in the string? */
310 r
= safe_atou_full(month
, 10 | SAFE_ATO_REFUSE_PLUS_MINUS
| SAFE_ATO_REFUSE_LEADING_WHITESPACE
, &m
);
317 r
= safe_atou_full(day
, 10 | SAFE_ATO_REFUSE_PLUS_MINUS
| SAFE_ATO_REFUSE_LEADING_WHITESPACE
, &d
);
323 r
= safe_atou_full(year
, 10 | SAFE_ATO_REFUSE_PLUS_MINUS
| SAFE_ATO_REFUSE_LEADING_WHITESPACE
, &y
);
326 if (y
< 1970 || y
> (unsigned) INT_MAX
)
335 time_t v
= timegm(&tm
);
336 if (v
== (time_t) -1)
338 if (tm
.tm_mday
!= (int) d
|| tm
.tm_mon
!= (int) m
|| tm
.tm_year
!= (int) y
)
339 return -EINVAL
; /* date was not normalized? (e.g. "30th of feb") */
341 *ret
= (usec_t
) v
* USEC_PER_SEC
;
346 static const char* valid_chassis(const char *chassis
) {
363 static bool valid_deployment(const char *deployment
) {
366 return in_charset(deployment
, VALID_DEPLOYMENT_CHARS
);
369 static const char* fallback_chassis(void) {
371 _cleanup_free_
char *type
= NULL
;
376 v
= detect_virtualization();
378 log_debug_errno(v
, "Failed to detect virtualization, ignoring: %m");
379 else if (VIRTUALIZATION_IS_VM(v
))
381 else if (VIRTUALIZATION_IS_CONTAINER(v
))
384 r
= read_one_line_file("/sys/class/dmi/id/chassis_type", &type
);
386 log_debug_errno(r
, "Failed to read DMI chassis type, ignoring: %m");
390 r
= safe_atou(type
, &t
);
392 log_debug_errno(r
, "Failed to parse DMI chassis type \"%s\", ignoring: %m", type
);
396 /* We only list the really obvious cases here. The DMI data is unreliable enough, so let's not do any
397 * additional guesswork on top of that.
399 * See the SMBIOS Specification 3.5.0 section 7.4.1 for details about the values listed here:
401 * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.5.0.pdf
406 case 0x03: /* Desktop */
407 case 0x04: /* Low Profile Desktop */
408 case 0x06: /* Mini Tower */
409 case 0x07: /* Tower */
410 case 0x0D: /* All in one (i.e. PC built into monitor) */
411 case 0x23: /* Mini PC */
412 case 0x24: /* Stick PC */
415 case 0x8: /* Portable */
416 case 0x9: /* Laptop */
417 case 0xA: /* Notebook */
418 case 0xE: /* Sub Notebook */
421 case 0xB: /* Hand Held */
424 case 0x11: /* Main Server Chassis */
425 case 0x1C: /* Blade */
426 case 0x1D: /* Blade Enclosure */
429 case 0x1E: /* Tablet */
432 case 0x1F: /* Convertible */
433 case 0x20: /* Detachable */
434 return "convertible";
436 case 0x21: /* IoT Gateway */
437 case 0x22: /* Embedded PC */
441 log_debug("Unhandled DMI chassis type 0x%02x, ignoring.", t
);
446 r
= read_one_line_file("/sys/firmware/acpi/pm_profile", &type
);
448 log_debug_errno(r
, "Failed read ACPI PM profile, ignoring: %m");
452 r
= safe_atou(type
, &t
);
454 log_debug_errno(r
, "Failed parse ACPI PM profile \"%s\", ignoring: %m", type
);
458 /* We only list the really obvious cases here as the ACPI data is not really super reliable.
460 * See the ACPI 5.0 Spec Section 5.2.9.1 for details:
462 * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf
467 case 1: /* Desktop */
468 case 3: /* Workstation */
469 case 6: /* Appliance PC */
475 case 4: /* Enterprise Server */
476 case 5: /* SOHO Server */
477 case 7: /* Performance Server */
484 log_debug("Unhandled ACPI PM profile 0x%02x, ignoring.", t
);
489 r
= read_one_line_file("/proc/device-tree/chassis-type", &type
);
491 log_debug_errno(r
, "Failed to read device-tree chassis type, ignoring: %m");
495 /* Note that the Devicetree specification uses the very same vocabulary
496 * of chassis types as we do, hence we do not need to translate these types:
498 * https://github.com/devicetree-org/devicetree-specification/blob/master/source/chapter3-devicenodes.rst */
499 chassis
= valid_chassis(type
);
501 log_debug("Invalid device-tree chassis type \"%s\", ignoring.", type
);
505 static char* context_get_chassis(Context
*c
) {
506 const char *fallback
;
511 if (!isempty(c
->data
[PROP_CHASSIS
]))
512 return strdup(c
->data
[PROP_CHASSIS
]);
514 if (get_dmi_data("ID_CHASSIS", NULL
, &dmi
) > 0)
517 fallback
= fallback_chassis();
519 return strdup(fallback
);
524 static char* context_fallback_icon_name(Context
*c
) {
525 _cleanup_free_
char *chassis
= NULL
;
529 chassis
= context_get_chassis(c
);
531 return strjoin("computer-", chassis
);
533 return strdup("computer");
536 static int context_update_kernel_hostname(
538 const char *transient_hn
) {
540 _cleanup_free_
char *_hn_free
= NULL
;
547 /* /etc/hostname has the highest preference ... */
548 if (c
->data
[PROP_STATIC_HOSTNAME
]) {
549 hn
= c
->data
[PROP_STATIC_HOSTNAME
];
550 hns
= HOSTNAME_STATIC
;
552 /* ... the transient hostname, (ie: DHCP) comes next ... */
553 } else if (transient_hn
) {
555 hns
= HOSTNAME_TRANSIENT
;
557 /* ... and the ultimate fallback */
559 hn
= _hn_free
= get_default_hostname();
563 hns
= HOSTNAME_DEFAULT
;
566 r
= sethostname_idempotent(hn
);
568 return log_error_errno(r
, "Failed to set hostname: %m");
570 if (c
->hostname_source
!= hns
) {
571 c
->hostname_source
= hns
;
575 (void) nscd_flush_cache(STRV_MAKE("hosts"));
578 log_debug("Hostname was already set to <%s>.", hn
);
580 log_info("Hostname set to <%s> (%s)", hn
, hostname_source_to_string(hns
));
582 hostname_update_source_hint(hn
, hns
);
585 return r
; /* 0 if no change, 1 if something was done */
588 static void unset_statp(struct stat
**p
) {
592 **p
= (struct stat
) {};
595 static int context_write_data_static_hostname(Context
*c
) {
596 _cleanup_(unset_statp
) struct stat
*s
= NULL
;
601 /* Make sure that if we fail here, we invalidate the cached information, since it was updated
602 * already, even if we can't make it hit the disk. */
603 s
= &c
->etc_hostname_stat
;
605 if (isempty(c
->data
[PROP_STATIC_HOSTNAME
])) {
606 if (unlink("/etc/hostname") < 0 && errno
!= ENOENT
)
613 r
= write_string_file_atomic_label("/etc/hostname", c
->data
[PROP_STATIC_HOSTNAME
]);
621 static int context_write_data_machine_info(Context
*c
) {
622 _cleanup_(unset_statp
) struct stat
*s
= NULL
;
623 static const char * const name
[_PROP_MAX
] = {
624 [PROP_PRETTY_HOSTNAME
] = "PRETTY_HOSTNAME",
625 [PROP_ICON_NAME
] = "ICON_NAME",
626 [PROP_CHASSIS
] = "CHASSIS",
627 [PROP_DEPLOYMENT
] = "DEPLOYMENT",
628 [PROP_LOCATION
] = "LOCATION",
630 _cleanup_strv_free_
char **l
= NULL
;
635 /* Make sure that if we fail here, we invalidate the cached information, since it was updated
636 * already, even if we can't make it hit the disk. */
637 s
= &c
->etc_machine_info_stat
;
639 r
= load_env_file(NULL
, "/etc/machine-info", &l
);
640 if (r
< 0 && r
!= -ENOENT
)
643 for (int p
= PROP_PRETTY_HOSTNAME
; p
<= PROP_LOCATION
; p
++) {
646 r
= strv_env_assign(&l
, name
[p
], empty_to_null(c
->data
[p
]));
651 if (strv_isempty(l
)) {
652 if (unlink("/etc/machine-info") < 0 && errno
!= ENOENT
)
659 r
= write_env_file_label(AT_FDCWD
, "/etc/machine-info", NULL
, l
);
667 static int property_get_hardware_property(
668 sd_bus_message
*reply
,
671 int (*getter
)(char **)) {
673 _cleanup_free_
char *from_dmi
= NULL
;
677 assert(IN_SET(prop
, PROP_HARDWARE_VENDOR
, PROP_HARDWARE_MODEL
));
680 context_read_machine_info(c
);
682 if (isempty(c
->data
[prop
]))
683 (void) getter(&from_dmi
);
685 return sd_bus_message_append(reply
, "s", from_dmi
?: c
->data
[prop
]);
688 static int property_get_hardware_vendor(
691 const char *interface
,
692 const char *property
,
693 sd_bus_message
*reply
,
695 sd_bus_error
*error
) {
697 return property_get_hardware_property(reply
, userdata
, PROP_HARDWARE_VENDOR
, get_hardware_vendor
);
700 static int property_get_hardware_model(
703 const char *interface
,
704 const char *property
,
705 sd_bus_message
*reply
,
707 sd_bus_error
*error
) {
709 return property_get_hardware_property(reply
, userdata
, PROP_HARDWARE_MODEL
, get_hardware_model
);
712 static int property_get_firmware_version(
715 const char *interface
,
716 const char *property
,
717 sd_bus_message
*reply
,
719 sd_bus_error
*error
) {
721 _cleanup_free_
char *firmware_version
= NULL
;
723 (void) get_firmware_version(&firmware_version
);
725 return sd_bus_message_append(reply
, "s", firmware_version
);
728 static int property_get_firmware_vendor(
731 const char *interface
,
732 const char *property
,
733 sd_bus_message
*reply
,
735 sd_bus_error
*error
) {
737 _cleanup_free_
char *firmware_vendor
= NULL
;
739 (void) get_firmware_vendor(&firmware_vendor
);
741 return sd_bus_message_append(reply
, "s", firmware_vendor
);
744 static int property_get_firmware_date(
747 const char *interface
,
748 const char *property
,
749 sd_bus_message
*reply
,
751 sd_bus_error
*error
) {
753 usec_t firmware_date
= USEC_INFINITY
;
755 (void) get_firmware_date(&firmware_date
);
757 return sd_bus_message_append(reply
, "t", firmware_date
);
759 static int property_get_hostname(
762 const char *interface
,
763 const char *property
,
764 sd_bus_message
*reply
,
766 sd_bus_error
*error
) {
768 _cleanup_free_
char *hn
= NULL
;
771 r
= gethostname_strict(&hn
);
776 hn
= get_default_hostname();
781 return sd_bus_message_append(reply
, "s", hn
);
784 static int property_get_static_hostname(
787 const char *interface
,
788 const char *property
,
789 sd_bus_message
*reply
,
791 sd_bus_error
*error
) {
793 Context
*c
= ASSERT_PTR(userdata
);
795 context_read_etc_hostname(c
);
797 return sd_bus_message_append(reply
, "s", c
->data
[PROP_STATIC_HOSTNAME
]);
800 static int property_get_default_hostname(
803 const char *interface
,
804 const char *property
,
805 sd_bus_message
*reply
,
807 sd_bus_error
*error
) {
809 _cleanup_free_
char *hn
= NULL
;
811 hn
= get_default_hostname();
815 return sd_bus_message_append(reply
, "s", hn
);
818 static void context_determine_hostname_source(Context
*c
) {
819 _cleanup_free_
char *hostname
= NULL
;
824 if (c
->hostname_source
>= 0)
827 (void) gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST
, &hostname
);
829 if (streq_ptr(hostname
, c
->data
[PROP_STATIC_HOSTNAME
]))
830 c
->hostname_source
= HOSTNAME_STATIC
;
832 _cleanup_free_
char *fallback
= NULL
;
834 /* If the hostname was not set by us, try to figure out where it came from. If we set it to
835 * the default hostname, the file will tell us. We compare the string because it is possible
836 * that the hostname was set by an older version that had a different fallback, in the initrd
837 * or before we reexecuted. */
839 r
= read_one_line_file("/run/systemd/default-hostname", &fallback
);
840 if (r
< 0 && r
!= -ENOENT
)
841 log_warning_errno(r
, "Failed to read /run/systemd/default-hostname, ignoring: %m");
843 if (streq_ptr(fallback
, hostname
))
844 c
->hostname_source
= HOSTNAME_DEFAULT
;
846 c
->hostname_source
= HOSTNAME_TRANSIENT
;
850 static int property_get_hostname_source(
853 const char *interface
,
854 const char *property
,
855 sd_bus_message
*reply
,
857 sd_bus_error
*error
) {
859 Context
*c
= ASSERT_PTR(userdata
);
861 context_read_etc_hostname(c
);
862 context_determine_hostname_source(c
);
864 return sd_bus_message_append(reply
, "s", hostname_source_to_string(c
->hostname_source
));
867 static int property_get_machine_info_field(
870 const char *interface
,
871 const char *property
,
872 sd_bus_message
*reply
,
874 sd_bus_error
*error
) {
879 /* Acquire the context object without this property's userdata offset added. Explanation: we want
880 * access to two pointers here: a) the main context object we cache all properties in, and b) the
881 * pointer to the property field inside the context object that we are supposed to update and
882 * use. The latter (b) we get in the 'userdata' function parameter, and sd-bus calculates that for us
883 * from the 'userdata' pointer we supplied when the vtable was registered, with the offset we
884 * specified in the vtable added on top. To get the former (a) we need the 'userdata' pointer from
885 * the vtable registration directly, without the offset added. Hence we ask sd-bus what the slot
886 * object is (which encapsulates the vtable registration), and then query the 'userdata' field
887 * directly off it. */
888 assert_se(slot
= sd_bus_get_current_slot(bus
));
889 assert_se(c
= sd_bus_slot_get_userdata(slot
));
891 context_read_machine_info(c
);
893 return sd_bus_message_append(reply
, "s", *(char**) userdata
);
896 static int property_get_os_release_field(
899 const char *interface
,
900 const char *property
,
901 sd_bus_message
*reply
,
903 sd_bus_error
*error
) {
908 /* As above, acquire the current context without this property's userdata offset added. */
909 assert_se(slot
= sd_bus_get_current_slot(bus
));
910 assert_se(c
= sd_bus_slot_get_userdata(slot
));
912 context_read_os_release(c
);
914 return sd_bus_message_append(reply
, "s", *(char**) userdata
);
917 static int property_get_os_support_end(
920 const char *interface
,
921 const char *property
,
922 sd_bus_message
*reply
,
924 sd_bus_error
*error
) {
926 Context
*c
= userdata
;
927 usec_t eol
= USEC_INFINITY
;
929 context_read_os_release(c
);
931 if (c
->data
[PROP_OS_SUPPORT_END
])
932 (void) os_release_support_ended(c
->data
[PROP_OS_SUPPORT_END
], /* quiet= */ false, &eol
);
934 return sd_bus_message_append(reply
, "t", eol
);
937 static int property_get_icon_name(
940 const char *interface
,
941 const char *property
,
942 sd_bus_message
*reply
,
944 sd_bus_error
*error
) {
946 _cleanup_free_
char *n
= NULL
;
947 Context
*c
= userdata
;
950 context_read_machine_info(c
);
952 if (isempty(c
->data
[PROP_ICON_NAME
]))
953 name
= n
= context_fallback_icon_name(c
);
955 name
= c
->data
[PROP_ICON_NAME
];
960 return sd_bus_message_append(reply
, "s", name
);
963 static int property_get_chassis(
966 const char *interface
,
967 const char *property
,
968 sd_bus_message
*reply
,
970 sd_bus_error
*error
) {
972 _cleanup_free_
char *chassis
= NULL
;
973 Context
*c
= userdata
;
975 context_read_machine_info(c
);
977 chassis
= context_get_chassis(c
);
979 return sd_bus_message_append(reply
, "s", chassis
);
982 static int property_get_uname_field(
985 const char *interface
,
986 const char *property
,
987 sd_bus_message
*reply
,
989 sd_bus_error
*error
) {
993 assert_se(uname(&u
) >= 0);
995 return sd_bus_message_append(reply
, "s", (char*) &u
+ PTR_TO_SIZE(userdata
));
998 static int property_get_machine_id(
1001 const char *interface
,
1002 const char *property
,
1003 sd_bus_message
*reply
,
1005 sd_bus_error
*error
) {
1010 r
= sd_id128_get_machine(&id
);
1014 return bus_property_get_id128(bus
, path
, interface
, property
, reply
, &id
, error
);
1017 static int property_get_boot_id(
1020 const char *interface
,
1021 const char *property
,
1022 sd_bus_message
*reply
,
1024 sd_bus_error
*error
) {
1029 r
= sd_id128_get_boot(&id
);
1033 return bus_property_get_id128(bus
, path
, interface
, property
, reply
, &id
, error
);
1036 static int method_set_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1037 Context
*c
= ASSERT_PTR(userdata
);
1043 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
1047 name
= empty_to_null(name
);
1049 /* We always go through with the procedure below without comparing to the current hostname, because
1050 * we might want to adjust hostname source information even if the actual hostname is unchanged. */
1052 if (name
&& !hostname_is_valid(name
, 0))
1053 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", name
);
1055 context_read_etc_hostname(c
);
1057 r
= bus_verify_polkit_async(
1060 "org.freedesktop.hostname1.set-hostname",
1064 &c
->polkit_registry
,
1069 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1071 r
= context_update_kernel_hostname(c
, name
);
1073 return sd_bus_error_set_errnof(error
, r
, "Failed to set hostname: %m");
1075 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m
),
1076 "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
1077 "Hostname", "HostnameSource", NULL
);
1079 return sd_bus_reply_method_return(m
, NULL
);
1082 static int method_set_static_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1083 Context
*c
= ASSERT_PTR(userdata
);
1090 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
1094 name
= empty_to_null(name
);
1096 context_read_etc_hostname(c
);
1098 if (streq_ptr(name
, c
->data
[PROP_STATIC_HOSTNAME
]))
1099 return sd_bus_reply_method_return(m
, NULL
);
1101 if (name
&& !hostname_is_valid(name
, 0))
1102 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid static hostname '%s'", name
);
1104 r
= bus_verify_polkit_async(
1107 "org.freedesktop.hostname1.set-static-hostname",
1111 &c
->polkit_registry
,
1116 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1118 r
= free_and_strdup_warn(&c
->data
[PROP_STATIC_HOSTNAME
], name
);
1122 r
= context_write_data_static_hostname(c
);
1124 log_error_errno(r
, "Failed to write static hostname: %m");
1125 if (ERRNO_IS_PRIVILEGE(r
))
1126 return sd_bus_error_set(error
, BUS_ERROR_FILE_IS_PROTECTED
, "Not allowed to update /etc/hostname.");
1128 return sd_bus_error_set(error
, BUS_ERROR_READ_ONLY_FILESYSTEM
, "/etc/hostname is in a read-only filesystem.");
1129 return sd_bus_error_set_errnof(error
, r
, "Failed to set static hostname: %m");
1132 r
= context_update_kernel_hostname(c
, NULL
);
1134 log_error_errno(r
, "Failed to set hostname: %m");
1135 return sd_bus_error_set_errnof(error
, r
, "Failed to set hostname: %m");
1138 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m
),
1139 "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
1140 "StaticHostname", "Hostname", "HostnameSource", NULL
);
1142 return sd_bus_reply_method_return(m
, NULL
);
1145 static int set_machine_info(Context
*c
, sd_bus_message
*m
, int prop
, sd_bus_message_handler_t cb
, sd_bus_error
*error
) {
1153 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
1157 name
= empty_to_null(name
);
1159 context_read_machine_info(c
);
1161 if (streq_ptr(name
, c
->data
[prop
]))
1162 return sd_bus_reply_method_return(m
, NULL
);
1164 if (!isempty(name
)) {
1165 /* The icon name might ultimately be used as file
1166 * name, so better be safe than sorry */
1168 if (prop
== PROP_ICON_NAME
&& !filename_is_valid(name
))
1169 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid icon name '%s'", name
);
1170 if (prop
== PROP_PRETTY_HOSTNAME
&& string_has_cc(name
, NULL
))
1171 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid pretty hostname '%s'", name
);
1172 if (prop
== PROP_CHASSIS
&& !valid_chassis(name
))
1173 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid chassis '%s'", name
);
1174 if (prop
== PROP_DEPLOYMENT
&& !valid_deployment(name
))
1175 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid deployment '%s'", name
);
1176 if (prop
== PROP_LOCATION
&& string_has_cc(name
, NULL
))
1177 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid location '%s'", name
);
1180 /* Since the pretty hostname should always be changed at the
1181 * same time as the static one, use the same policy action for
1184 r
= bus_verify_polkit_async(
1187 prop
== PROP_PRETTY_HOSTNAME
? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info",
1191 &c
->polkit_registry
,
1196 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1198 r
= free_and_strdup_warn(&c
->data
[prop
], name
);
1202 r
= context_write_data_machine_info(c
);
1204 log_error_errno(r
, "Failed to write machine info: %m");
1205 if (ERRNO_IS_PRIVILEGE(r
))
1206 return sd_bus_error_set(error
, BUS_ERROR_FILE_IS_PROTECTED
, "Not allowed to update /etc/machine-info.");
1208 return sd_bus_error_set(error
, BUS_ERROR_READ_ONLY_FILESYSTEM
, "/etc/machine-info is in a read-only filesystem.");
1209 return sd_bus_error_set_errnof(error
, r
, "Failed to write machine info: %m");
1212 log_info("Changed %s to '%s'",
1213 prop
== PROP_PRETTY_HOSTNAME
? "pretty hostname" :
1214 prop
== PROP_DEPLOYMENT
? "deployment" :
1215 prop
== PROP_LOCATION
? "location" :
1216 prop
== PROP_CHASSIS
? "chassis" : "icon name", strna(c
->data
[prop
]));
1218 (void) sd_bus_emit_properties_changed(
1219 sd_bus_message_get_bus(m
),
1220 "/org/freedesktop/hostname1",
1221 "org.freedesktop.hostname1",
1222 prop
== PROP_PRETTY_HOSTNAME
? "PrettyHostname" :
1223 prop
== PROP_DEPLOYMENT
? "Deployment" :
1224 prop
== PROP_LOCATION
? "Location" :
1225 prop
== PROP_CHASSIS
? "Chassis" : "IconName" , NULL
);
1227 return sd_bus_reply_method_return(m
, NULL
);
1230 static int method_set_pretty_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1231 return set_machine_info(userdata
, m
, PROP_PRETTY_HOSTNAME
, method_set_pretty_hostname
, error
);
1234 static int method_set_icon_name(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1235 return set_machine_info(userdata
, m
, PROP_ICON_NAME
, method_set_icon_name
, error
);
1238 static int method_set_chassis(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1239 return set_machine_info(userdata
, m
, PROP_CHASSIS
, method_set_chassis
, error
);
1242 static int method_set_deployment(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1243 return set_machine_info(userdata
, m
, PROP_DEPLOYMENT
, method_set_deployment
, error
);
1246 static int method_set_location(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1247 return set_machine_info(userdata
, m
, PROP_LOCATION
, method_set_location
, error
);
1250 static int method_get_product_uuid(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1251 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1252 Context
*c
= ASSERT_PTR(userdata
);
1258 r
= sd_bus_message_read(m
, "b", &interactive
);
1262 r
= bus_verify_polkit_async(
1265 "org.freedesktop.hostname1.get-product-uuid",
1269 &c
->polkit_registry
,
1274 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1276 r
= id128_get_product(&uuid
);
1278 if (r
== -EADDRNOTAVAIL
)
1279 log_debug_errno(r
, "DMI product UUID is all 0x00 or all 0xFF, ignoring.");
1281 log_full_errno(r
== -ENOENT
? LOG_DEBUG
: LOG_WARNING
, r
,
1282 "Failed to read product UUID, ignoring: %m");
1284 return sd_bus_error_set(error
, BUS_ERROR_NO_PRODUCT_UUID
,
1285 "Failed to read product UUID from firmware.");
1288 r
= sd_bus_message_new_method_return(m
, &reply
);
1292 r
= sd_bus_message_append_array(reply
, 'y', uuid
.bytes
, sizeof(uuid
.bytes
));
1296 return sd_bus_send(NULL
, reply
, NULL
);
1299 static int method_get_hardware_serial(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1300 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1301 _cleanup_free_
char *serial
= NULL
;
1302 Context
*c
= ASSERT_PTR(userdata
);
1307 r
= bus_verify_polkit_async(
1310 "org.freedesktop.hostname1.get-hardware-serial",
1314 &c
->polkit_registry
,
1319 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1321 r
= get_hardware_serial(&serial
);
1325 r
= sd_bus_message_new_method_return(m
, &reply
);
1329 r
= sd_bus_message_append(reply
, "s", serial
);
1333 return sd_bus_send(NULL
, reply
, NULL
);
1336 static int method_describe(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
1337 _cleanup_free_
char *hn
= NULL
, *dhn
= NULL
, *in
= NULL
, *text
= NULL
,
1338 *chassis
= NULL
, *vendor
= NULL
, *model
= NULL
, *serial
= NULL
, *firmware_version
= NULL
,
1339 *firmware_vendor
= NULL
;
1340 usec_t firmware_date
= USEC_INFINITY
, eol
= USEC_INFINITY
;
1341 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1342 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
1343 sd_id128_t machine_id
, boot_id
, product_uuid
= SD_ID128_NULL
;
1344 Context
*c
= ASSERT_PTR(userdata
);
1351 r
= bus_verify_polkit_async(
1354 "org.freedesktop.hostname1.get-description",
1358 &c
->polkit_registry
,
1361 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1363 /* We ignore all authentication errors here, since most data is unprivileged, the one exception being
1364 * the product ID which we'll check explicitly. */
1367 context_read_etc_hostname(c
);
1368 context_read_machine_info(c
);
1369 context_read_os_release(c
);
1370 context_determine_hostname_source(c
);
1372 r
= gethostname_strict(&hn
);
1375 return log_error_errno(r
, "Failed to read local host name: %m");
1377 hn
= get_default_hostname();
1382 dhn
= get_default_hostname();
1386 if (isempty(c
->data
[PROP_ICON_NAME
]))
1387 in
= context_fallback_icon_name(c
);
1389 chassis
= context_get_chassis(c
);
1391 assert_se(uname(&u
) >= 0);
1393 if (isempty(c
->data
[PROP_HARDWARE_VENDOR
]))
1394 (void) get_hardware_vendor(&vendor
);
1395 if (isempty(c
->data
[PROP_HARDWARE_MODEL
]))
1396 (void) get_hardware_model(&model
);
1399 /* The product UUID and hardware serial is only available to privileged clients */
1400 (void) id128_get_product(&product_uuid
);
1401 (void) get_hardware_serial(&serial
);
1403 (void) get_firmware_version(&firmware_version
);
1404 (void) get_firmware_vendor(&firmware_vendor
);
1405 (void) get_firmware_date(&firmware_date
);
1407 if (c
->data
[PROP_OS_SUPPORT_END
])
1408 (void) os_release_support_ended(c
->data
[PROP_OS_SUPPORT_END
], /* quiet= */ false, &eol
);
1410 r
= sd_id128_get_machine(&machine_id
);
1412 return log_error_errno(r
, "Failed to get machine ID: %m");
1414 r
= sd_id128_get_boot(&boot_id
);
1416 return log_error_errno(r
, "Failed to get boot ID: %m");
1418 r
= json_build(&v
, JSON_BUILD_OBJECT(
1419 JSON_BUILD_PAIR("Hostname", JSON_BUILD_STRING(hn
)),
1420 JSON_BUILD_PAIR("StaticHostname", JSON_BUILD_STRING(c
->data
[PROP_STATIC_HOSTNAME
])),
1421 JSON_BUILD_PAIR("PrettyHostname", JSON_BUILD_STRING(c
->data
[PROP_PRETTY_HOSTNAME
])),
1422 JSON_BUILD_PAIR("DefaultHostname", JSON_BUILD_STRING(dhn
)),
1423 JSON_BUILD_PAIR("HostnameSource", JSON_BUILD_STRING(hostname_source_to_string(c
->hostname_source
))),
1424 JSON_BUILD_PAIR("IconName", JSON_BUILD_STRING(in
?: c
->data
[PROP_ICON_NAME
])),
1425 JSON_BUILD_PAIR("Chassis", JSON_BUILD_STRING(chassis
)),
1426 JSON_BUILD_PAIR("Deployment", JSON_BUILD_STRING(c
->data
[PROP_DEPLOYMENT
])),
1427 JSON_BUILD_PAIR("Location", JSON_BUILD_STRING(c
->data
[PROP_LOCATION
])),
1428 JSON_BUILD_PAIR("KernelName", JSON_BUILD_STRING(u
.sysname
)),
1429 JSON_BUILD_PAIR("KernelRelease", JSON_BUILD_STRING(u
.release
)),
1430 JSON_BUILD_PAIR("KernelVersion", JSON_BUILD_STRING(u
.version
)),
1431 JSON_BUILD_PAIR("OperatingSystemPrettyName", JSON_BUILD_STRING(c
->data
[PROP_OS_PRETTY_NAME
])),
1432 JSON_BUILD_PAIR("OperatingSystemCPEName", JSON_BUILD_STRING(c
->data
[PROP_OS_CPE_NAME
])),
1433 JSON_BUILD_PAIR("OperatingSystemHomeURL", JSON_BUILD_STRING(c
->data
[PROP_OS_HOME_URL
])),
1434 JSON_BUILD_PAIR_FINITE_USEC("OperatingSystemSupportEnd", eol
),
1435 JSON_BUILD_PAIR("HardwareVendor", JSON_BUILD_STRING(vendor
?: c
->data
[PROP_HARDWARE_VENDOR
])),
1436 JSON_BUILD_PAIR("HardwareModel", JSON_BUILD_STRING(model
?: c
->data
[PROP_HARDWARE_MODEL
])),
1437 JSON_BUILD_PAIR("HardwareSerial", JSON_BUILD_STRING(serial
)),
1438 JSON_BUILD_PAIR("FirmwareVersion", JSON_BUILD_STRING(firmware_version
)),
1439 JSON_BUILD_PAIR("FirmwareVendor", JSON_BUILD_STRING(firmware_vendor
)),
1440 JSON_BUILD_PAIR_FINITE_USEC("FirmwareDate", firmware_date
),
1441 JSON_BUILD_PAIR_ID128("MachineID", machine_id
),
1442 JSON_BUILD_PAIR_ID128("BootID", boot_id
),
1443 JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(product_uuid
), "ProductUUID", JSON_BUILD_ID128(product_uuid
)),
1444 JSON_BUILD_PAIR_CONDITION(sd_id128_is_null(product_uuid
), "ProductUUID", JSON_BUILD_NULL
)));
1447 return log_error_errno(r
, "Failed to build JSON data: %m");
1449 r
= json_variant_format(v
, 0, &text
);
1451 return log_error_errno(r
, "Failed to format JSON data: %m");
1453 r
= sd_bus_message_new_method_return(m
, &reply
);
1457 r
= sd_bus_message_append(reply
, "s", text
);
1461 return sd_bus_send(NULL
, reply
, NULL
);
1464 static const sd_bus_vtable hostname_vtable
[] = {
1465 SD_BUS_VTABLE_START(0),
1466 SD_BUS_PROPERTY("Hostname", "s", property_get_hostname
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1467 SD_BUS_PROPERTY("StaticHostname", "s", property_get_static_hostname
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1468 SD_BUS_PROPERTY("PrettyHostname", "s", property_get_machine_info_field
, offsetof(Context
, data
) + sizeof(char*) * PROP_PRETTY_HOSTNAME
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1469 SD_BUS_PROPERTY("DefaultHostname", "s", property_get_default_hostname
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1470 SD_BUS_PROPERTY("HostnameSource", "s", property_get_hostname_source
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1471 SD_BUS_PROPERTY("IconName", "s", property_get_icon_name
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1472 SD_BUS_PROPERTY("Chassis", "s", property_get_chassis
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1473 SD_BUS_PROPERTY("Deployment", "s", property_get_machine_info_field
, offsetof(Context
, data
) + sizeof(char*) * PROP_DEPLOYMENT
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1474 SD_BUS_PROPERTY("Location", "s", property_get_machine_info_field
, offsetof(Context
, data
) + sizeof(char*) * PROP_LOCATION
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
1475 SD_BUS_PROPERTY("KernelName", "s", property_get_uname_field
, offsetof(struct utsname
, sysname
), SD_BUS_VTABLE_ABSOLUTE_OFFSET
|SD_BUS_VTABLE_PROPERTY_CONST
),
1476 SD_BUS_PROPERTY("KernelRelease", "s", property_get_uname_field
, offsetof(struct utsname
, release
), SD_BUS_VTABLE_ABSOLUTE_OFFSET
|SD_BUS_VTABLE_PROPERTY_CONST
),
1477 SD_BUS_PROPERTY("KernelVersion", "s", property_get_uname_field
, offsetof(struct utsname
, version
), SD_BUS_VTABLE_ABSOLUTE_OFFSET
|SD_BUS_VTABLE_PROPERTY_CONST
),
1478 SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", property_get_os_release_field
, offsetof(Context
, data
) + sizeof(char*) * PROP_OS_PRETTY_NAME
, SD_BUS_VTABLE_PROPERTY_CONST
),
1479 SD_BUS_PROPERTY("OperatingSystemCPEName", "s", property_get_os_release_field
, offsetof(Context
, data
) + sizeof(char*) * PROP_OS_CPE_NAME
, SD_BUS_VTABLE_PROPERTY_CONST
),
1480 SD_BUS_PROPERTY("OperatingSystemSupportEnd", "t", property_get_os_support_end
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1481 SD_BUS_PROPERTY("HomeURL", "s", property_get_os_release_field
, offsetof(Context
, data
) + sizeof(char*) * PROP_OS_HOME_URL
, SD_BUS_VTABLE_PROPERTY_CONST
),
1482 SD_BUS_PROPERTY("HardwareVendor", "s", property_get_hardware_vendor
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1483 SD_BUS_PROPERTY("HardwareModel", "s", property_get_hardware_model
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1484 SD_BUS_PROPERTY("FirmwareVersion", "s", property_get_firmware_version
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1485 SD_BUS_PROPERTY("FirmwareVendor", "s", property_get_firmware_vendor
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1486 SD_BUS_PROPERTY("FirmwareDate", "t", property_get_firmware_date
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1487 SD_BUS_PROPERTY("MachineID", "ay", property_get_machine_id
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1488 SD_BUS_PROPERTY("BootID", "ay", property_get_boot_id
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
1490 SD_BUS_METHOD_WITH_ARGS("SetHostname",
1491 SD_BUS_ARGS("s", hostname
, "b", interactive
),
1493 method_set_hostname
,
1494 SD_BUS_VTABLE_UNPRIVILEGED
),
1495 SD_BUS_METHOD_WITH_ARGS("SetStaticHostname",
1496 SD_BUS_ARGS("s", hostname
, "b", interactive
),
1498 method_set_static_hostname
,
1499 SD_BUS_VTABLE_UNPRIVILEGED
),
1500 SD_BUS_METHOD_WITH_ARGS("SetPrettyHostname",
1501 SD_BUS_ARGS("s", hostname
, "b", interactive
),
1503 method_set_pretty_hostname
,
1504 SD_BUS_VTABLE_UNPRIVILEGED
),
1505 SD_BUS_METHOD_WITH_ARGS("SetIconName",
1506 SD_BUS_ARGS("s", icon
, "b", interactive
),
1508 method_set_icon_name
,
1509 SD_BUS_VTABLE_UNPRIVILEGED
),
1510 SD_BUS_METHOD_WITH_ARGS("SetChassis",
1511 SD_BUS_ARGS("s", chassis
, "b", interactive
),
1514 SD_BUS_VTABLE_UNPRIVILEGED
),
1515 SD_BUS_METHOD_WITH_ARGS("SetDeployment",
1516 SD_BUS_ARGS("s", deployment
, "b", interactive
),
1518 method_set_deployment
,
1519 SD_BUS_VTABLE_UNPRIVILEGED
),
1520 SD_BUS_METHOD_WITH_ARGS("SetLocation",
1521 SD_BUS_ARGS("s", location
, "b", interactive
),
1523 method_set_location
,
1524 SD_BUS_VTABLE_UNPRIVILEGED
),
1525 SD_BUS_METHOD_WITH_ARGS("GetProductUUID",
1526 SD_BUS_ARGS("b", interactive
),
1527 SD_BUS_RESULT("ay", uuid
),
1528 method_get_product_uuid
,
1529 SD_BUS_VTABLE_UNPRIVILEGED
),
1530 SD_BUS_METHOD_WITH_ARGS("GetHardwareSerial",
1532 SD_BUS_RESULT("s", serial
),
1533 method_get_hardware_serial
,
1534 SD_BUS_VTABLE_UNPRIVILEGED
),
1535 SD_BUS_METHOD_WITH_ARGS("Describe",
1537 SD_BUS_RESULT("s", json
),
1539 SD_BUS_VTABLE_UNPRIVILEGED
),
1544 static const BusObjectImplementation manager_object
= {
1545 "/org/freedesktop/hostname1",
1546 "org.freedesktop.hostname1",
1547 .vtables
= BUS_VTABLES(hostname_vtable
),
1550 static int connect_bus(Context
*c
, sd_event
*event
, sd_bus
**ret
) {
1551 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1558 r
= sd_bus_default_system(&bus
);
1560 return log_error_errno(r
, "Failed to get system bus connection: %m");
1562 r
= bus_add_implementation(bus
, &manager_object
, c
);
1566 r
= bus_log_control_api_register(bus
);
1570 r
= sd_bus_request_name_async(bus
, NULL
, "org.freedesktop.hostname1", 0, NULL
, NULL
);
1572 return log_error_errno(r
, "Failed to request name: %m");
1574 r
= sd_bus_attach_event(bus
, event
, 0);
1576 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
1578 *ret
= TAKE_PTR(bus
);
1582 static int run(int argc
, char *argv
[]) {
1583 _cleanup_(context_destroy
) Context context
= {
1584 .hostname_source
= _HOSTNAME_INVALID
, /* appropriate value will be set later */
1586 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
1587 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
1592 r
= service_parse_argv("systemd-hostnamed.service",
1593 "Manage the system hostname and related metadata.",
1594 BUS_IMPLEMENTATIONS(&manager_object
,
1595 &log_control_object
),
1606 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGTERM
, SIGINT
, -1) >= 0);
1608 r
= sd_event_default(&event
);
1610 return log_error_errno(r
, "Failed to allocate event loop: %m");
1612 (void) sd_event_set_watchdog(event
, true);
1614 r
= sd_event_add_signal(event
, NULL
, SIGINT
, NULL
, NULL
);
1616 return log_error_errno(r
, "Failed to install SIGINT handler: %m");
1618 r
= sd_event_add_signal(event
, NULL
, SIGTERM
, NULL
, NULL
);
1620 return log_error_errno(r
, "Failed to install SIGTERM handler: %m");
1622 r
= connect_bus(&context
, event
, &bus
);
1626 r
= bus_event_loop_with_idle(event
, bus
, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC
, NULL
, NULL
);
1628 return log_error_errno(r
, "Failed to run event loop: %m");
1633 DEFINE_MAIN_FUNCTION(run
);