]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/hostname/hostnamed.c
326883bbe3635dd1794e4618d0030ea17904d0a6
[thirdparty/systemd.git] / src / hostname / hostnamed.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <sys/stat.h>
4 #include <sys/utsname.h>
5 #include <unistd.h>
6
7 #include "sd-bus.h"
8 #include "sd-device.h"
9 #include "sd-event.h"
10 #include "sd-json.h"
11
12 #include "alloc-util.h"
13 #include "bitfield.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"
19 #include "bus-util.h"
20 #include "constants.h"
21 #include "daemon-util.h"
22 #include "device-private.h"
23 #include "env-file.h"
24 #include "env-util.h"
25 #include "extract-word.h"
26 #include "fileio.h"
27 #include "hashmap.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"
33 #include "log.h"
34 #include "main-func.h"
35 #include "nulstr-util.h"
36 #include "os-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"
43 #include "strv.h"
44 #include "time-util.h"
45 #include "utf8.h"
46 #include "varlink-io.systemd.Hostname.h"
47 #include "varlink-io.systemd.service.h"
48 #include "varlink-util.h"
49 #include "virt.h"
50
51 #define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:")
52
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). */
55 typedef enum {
56 /* Read from /etc/hostname */
57 PROP_STATIC_HOSTNAME,
58 PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS,
59
60 /* Read from /etc/machine-info */
61 PROP_PRETTY_HOSTNAME,
62 PROP_ICON_NAME,
63 PROP_CHASSIS,
64 PROP_DEPLOYMENT,
65 PROP_LOCATION,
66 PROP_HARDWARE_VENDOR,
67 PROP_HARDWARE_MODEL,
68 PROP_HARDWARE_SKU,
69 PROP_HARDWARE_VERSION,
70
71 /* Read from /etc/os-release (or /usr/lib/os-release) */
72 PROP_OS_PRETTY_NAME,
73 PROP_OS_CPE_NAME,
74 PROP_OS_HOME_URL,
75 PROP_OS_SUPPORT_END,
76 PROP_OS_IMAGE_ID,
77 PROP_OS_IMAGE_VERSION,
78 _PROP_MAX,
79 _PROP_INVALID = -EINVAL,
80 } HostProperty;
81
82 typedef struct Context {
83 char *data[_PROP_MAX];
84
85 HostnameSource hostname_source;
86
87 struct stat etc_hostname_stat;
88 struct stat etc_os_release_stat;
89 struct stat etc_machine_info_stat;
90
91 sd_event *event;
92 sd_bus *bus;
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;
98 } Context;
99
100 static void context_reset(Context *c, uint64_t mask) {
101 assert(c);
102
103 for (HostProperty p = 0; p < _PROP_MAX; p++) {
104 if (!BIT_SET(mask, p))
105 continue;
106
107 c->data[p] = mfree(c->data[p]);
108 }
109 }
110
111 static void context_destroy(Context *c) {
112 assert(c);
113
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);
122 }
123
124 static void context_read_etc_hostname(Context *c) {
125 struct stat current_stat = {};
126 int r;
127
128 assert(c);
129
130 if (stat(etc_hostname(), &current_stat) >= 0 &&
131 stat_inode_unmodified(&c->etc_hostname_stat, &current_stat))
132 return;
133
134 context_reset(c,
135 (UINT64_C(1) << PROP_STATIC_HOSTNAME) |
136 (UINT64_C(1) << PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS));
137
138 r = read_etc_hostname(/* path= */ NULL, /* substitute_wildcards= */ false, &c->data[PROP_STATIC_HOSTNAME]);
139 if (r < 0) {
140 if (r != -ENOENT)
141 log_warning_errno(r, "Failed to read /etc/hostname, ignoring: %m");
142 } else {
143 _cleanup_free_ char *substituted = strdup(c->data[PROP_STATIC_HOSTNAME]);
144 if (!substituted)
145 return (void) log_oom();
146
147 r = hostname_substitute_wildcards(substituted);
148 if (r < 0)
149 log_warning_errno(r, "Failed to substitute wildcards in /etc/hostname, ignoring: %m");
150 else
151 c->data[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS] = TAKE_PTR(substituted);
152 }
153
154 c->etc_hostname_stat = current_stat;
155 }
156
157 static void context_read_machine_info(Context *c) {
158 struct stat current_stat = {};
159 int r;
160
161 assert(c);
162
163 if (stat(etc_machine_info(), &current_stat) >= 0 &&
164 stat_inode_unmodified(&c->etc_machine_info_stat, &current_stat))
165 return;
166
167 context_reset(c,
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));
177
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");
190
191 c->etc_machine_info_stat = current_stat;
192 }
193
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 = {};
197 int r;
198
199 assert(c);
200
201 if ((stat("/etc/os-release", &current_stat) >= 0 ||
202 stat("/usr/lib/os-release", &current_stat) >= 0) &&
203 stat_inode_unmodified(&c->etc_os_release_stat, &current_stat))
204 return;
205
206 context_reset(c,
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));
213
214 r = parse_os_release(NULL,
215 "PRETTY_NAME", &os_pretty_name,
216 "NAME", &os_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");
224
225 if (free_and_strdup(&c->data[PROP_OS_PRETTY_NAME], os_release_pretty_name(os_pretty_name, os_name)) < 0)
226 log_oom();
227
228 c->etc_os_release_stat = current_stat;
229 }
230
231 static bool use_dmi_data(void) {
232 int r;
233
234 r = getenv_bool("SYSTEMD_HOSTNAME_FORCE_DMI");
235 if (r >= 0) {
236 log_debug("Honouring $SYSTEMD_HOSTNAME_FORCE_DMI override: %s", yes_no(r));
237 return r;
238 }
239 if (r != -ENXIO)
240 log_debug_errno(r, "Failed to parse $SYSTEMD_HOSTNAME_FORCE_DMI, ignoring: %m");
241
242 if (detect_container() > 0) {
243 log_debug("Running in a container, not using DMI hardware data.");
244 return false;
245 }
246
247 return true;
248 }
249
250 static int context_acquire_dmi_device(Context *c) {
251 int r;
252
253 assert(c);
254 assert(!c->device_dmi);
255
256 if (!use_dmi_data())
257 return 0;
258
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");
262 return 0;
263 }
264 if (r < 0)
265 return log_error_errno(r, "Failed to open /sys/class/dmi/id/ device: %m");
266
267 return 1;
268 }
269
270 static int context_acquire_acpi_device(Context *c) {
271 int r;
272
273 assert(c);
274 assert(!c->device_acpi);
275
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");
279 return 0;
280 }
281 if (r < 0)
282 return log_error_errno(r, "Failed to open /sys/firmware/acpi/ device: %m");
283
284 return 1;
285 }
286
287 static int context_acquire_device_tree(Context *c) {
288 int r;
289
290 assert(c);
291 assert(!c->device_tree);
292
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");
296 return 0;
297 }
298 if (r < 0)
299 return log_error_errno(r, "Failed to open /proc/device-tree/ device: %m");
300
301 return 1;
302 }
303
304 static bool string_is_safe_for_dbus(const char *s) {
305 assert(s);
306
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 */
309
310 if (string_has_cc(s, /* ok= */ NULL))
311 return false;
312
313 return utf8_is_valid(s);
314 }
315
316 static int get_dmi_property(Context *c, const char *key, char **ret) {
317 const char *s;
318 int r;
319
320 assert(c);
321 assert(key);
322 assert(ret);
323
324 if (!c->device_dmi)
325 return -ENODEV;
326
327 r = sd_device_get_property_value(c->device_dmi, key, &s);
328 if (r < 0)
329 return r;
330
331 if (!string_is_safe_for_dbus(s))
332 return -ENXIO;
333
334 return strdup_to(ret, s);
335 }
336
337 static int get_dmi_properties(Context *c, const char * const * keys, char **ret) {
338 int r = -ENOENT;
339
340 assert(c);
341 assert(ret);
342
343 STRV_FOREACH(k, keys) {
344 r = get_dmi_property(c, *k, ret);
345 if (r >= 0 || !ERRNO_IS_NEG_DEVICE_ABSENT(r))
346 return r;
347 }
348
349 return r;
350 }
351
352 static int get_chassis_asset_tag(Context *c, char **ret) {
353 return get_dmi_property(c, "ID_CHASSIS_ASSET_TAG", ret);
354 }
355
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);
358 }
359
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);
362 }
363
364 static int get_hardware_sku(Context *c, char **ret) {
365 _cleanup_free_ char *model = NULL, *sku = NULL;
366 int r;
367
368 r = get_dmi_property(c, "ID_SKU", &sku);
369 if (r < 0)
370 return r;
371
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);
375 if (r < 0) {
376 if (r != -ENOENT)
377 return r;
378 } else if (streq_ptr(sku, model))
379 return -ENOENT;
380
381 *ret = TAKE_PTR(sku);
382 return 0;
383 }
384
385 static int get_hardware_version(Context *c, char **ret) {
386 _cleanup_free_ char *version = NULL;
387 int r;
388
389 r = get_dmi_property(c, "ID_HARDWARE_VERSION", &version);
390 if (r < 0)
391 return r;
392
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;
398
399 r = getter(c, &value);
400 if (r == -ENOENT)
401 continue;
402 if (r < 0)
403 return r;
404 if (streq_ptr(version, value))
405 return -ENOENT;
406 }
407
408 *ret = TAKE_PTR(version);
409 return 0;
410 }
411
412 static int get_sysattr(sd_device *device, const char *key, char **ret) {
413 const char *s;
414 int r;
415
416 assert(key);
417 assert(ret);
418
419 if (!device)
420 return -ENODEV;
421
422 r = sd_device_get_sysattr_value(device, key, &s);
423 if (r < 0)
424 return r;
425
426 if (!string_is_safe_for_dbus(s))
427 return -ENXIO;
428
429 return strdup_to(ret, empty_to_null(s));
430 }
431
432 static int get_dmi_sysattr(Context *c, const char *key, char **ret) {
433 return get_sysattr(ASSERT_PTR(c)->device_dmi, key, ret);
434 }
435
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);
438 }
439
440 static int get_hardware_serial(Context *c, char **ret) {
441 int r;
442
443 assert(c);
444 assert(ret);
445
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))
449 return r;
450 }
451
452 return get_device_tree_sysattr(c, "serial-number", ret);
453 }
454
455 static int get_firmware_version(Context *c, char **ret) {
456 return get_dmi_sysattr(c, "bios_version", ret);
457 }
458
459 static int get_firmware_vendor(Context *c, char **ret) {
460 return get_dmi_sysattr(c, "bios_vendor", ret);
461 }
462
463 static int get_firmware_date(Context *c, usec_t *ret) {
464 _cleanup_free_ char *bios_date = NULL, *month = NULL, *day = NULL, *year = NULL;
465 int r;
466
467 assert(c);
468 assert(ret);
469
470 r = get_dmi_sysattr(c, "bios_date", &bios_date);
471 if (ERRNO_IS_NEG_DEVICE_ABSENT(r)) {
472 *ret = USEC_INFINITY;
473 return 0;
474 }
475 if (r < 0)
476 return r;
477
478 const char *p = bios_date;
479 r = extract_many_words(&p, "/", EXTRACT_DONT_COALESCE_SEPARATORS, &month, &day, &year);
480 if (r < 0)
481 return r;
482 if (r != 3) /* less than three args read? */
483 return -EINVAL;
484 if (!isempty(p)) /* more left in the string? */
485 return -EINVAL;
486
487 unsigned m, d, y;
488 r = safe_atou_full(month, 10 | SAFE_ATO_REFUSE_PLUS_MINUS | SAFE_ATO_REFUSE_LEADING_WHITESPACE, &m);
489 if (r < 0)
490 return r;
491 if (m < 1 || m > 12)
492 return -EINVAL;
493 m -= 1;
494
495 r = safe_atou_full(day, 10 | SAFE_ATO_REFUSE_PLUS_MINUS | SAFE_ATO_REFUSE_LEADING_WHITESPACE, &d);
496 if (r < 0)
497 return r;
498 if (d < 1 || d > 31)
499 return -EINVAL;
500
501 r = safe_atou_full(year, 10 | SAFE_ATO_REFUSE_PLUS_MINUS | SAFE_ATO_REFUSE_LEADING_WHITESPACE, &y);
502 if (r < 0)
503 return r;
504 if (y < 1970 || y > (unsigned) INT_MAX)
505 return -EINVAL;
506 y -= 1900;
507
508 struct tm tm = {
509 .tm_mday = d,
510 .tm_mon = m,
511 .tm_year = y,
512 };
513
514 usec_t v;
515 r = mktime_or_timegm_usec(&tm, /* utc= */ true, &v);
516 if (r < 0)
517 return r;
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") */
520
521 *ret = v;
522 return 0;
523 }
524
525 static const char* valid_chassis(const char *chassis) {
526 assert(chassis);
527
528 return nulstr_get(
529 "vm\0"
530 "container\0"
531 "desktop\0"
532 "laptop\0"
533 "convertible\0"
534 "server\0"
535 "tablet\0"
536 "handset\0"
537 "watch\0"
538 "embedded\0",
539 chassis);
540 }
541
542 static bool valid_deployment(const char *deployment) {
543 assert(deployment);
544
545 return in_charset(deployment, VALID_DEPLOYMENT_CHARS);
546 }
547
548 static const char* fallback_chassis_by_virtualization(void) {
549 Virtualization v = detect_virtualization();
550 if (v < 0) {
551 log_debug_errno(v, "Failed to detect virtualization, ignoring: %m");
552 return NULL;
553 }
554
555 if (VIRTUALIZATION_IS_VM(v))
556 return "vm";
557 if (VIRTUALIZATION_IS_CONTAINER(v))
558 return "container";
559
560 return NULL;
561 }
562
563 static const char* fallback_chassis_by_dmi(Context *c) {
564 unsigned t;
565 int r;
566
567 assert(c);
568
569 if (!c->device_dmi)
570 return NULL;
571
572 r = device_get_sysattr_unsigned(c->device_dmi, "chassis_type", &t);
573 if (r < 0) {
574 log_debug_errno(r, "Failed to read/parse DMI chassis type, ignoring: %m");
575 return NULL;
576 }
577
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.
580 *
581 * See the SMBIOS Specification 3.5.0 section 7.4.1 for details about the values listed here:
582 *
583 * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.5.0.pdf
584 */
585
586 switch (t) {
587
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 */
595 return "desktop";
596
597 case 0x8: /* Portable */
598 case 0x9: /* Laptop */
599 case 0xA: /* Notebook */
600 case 0xE: /* Sub Notebook */
601 return "laptop";
602
603 case 0xB: /* Hand Held */
604 return "handset";
605
606 case 0x11: /* Main Server Chassis */
607 case 0x1C: /* Blade */
608 case 0x1D: /* Blade Enclosure */
609 return "server";
610
611 case 0x1E: /* Tablet */
612 return "tablet";
613
614 case 0x1F: /* Convertible */
615 case 0x20: /* Detachable */
616 return "convertible";
617
618 case 0x21: /* IoT Gateway */
619 case 0x22: /* Embedded PC */
620 return "embedded";
621
622 default:
623 log_debug("Unhandled DMI chassis type 0x%02x, ignoring.", t);
624 return NULL;
625 }
626 }
627
628 static const char* fallback_chassis_by_acpi(Context *c) {
629 unsigned t;
630 int r;
631
632 assert(c);
633
634 if (!c->device_acpi)
635 return NULL;
636
637 r = device_get_sysattr_unsigned(c->device_acpi, "pm_profile", &t);
638 if (r < 0) {
639 log_debug_errno(r, "Failed read/parse ACPI PM profile, ignoring: %m");
640 return NULL;
641 }
642
643 /* We only list the really obvious cases here as the ACPI data is not really super reliable.
644 *
645 * See the ACPI 5.0 Spec Section 5.2.9.1 for details:
646 *
647 * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf
648 */
649
650 switch (t) {
651
652 case 1: /* Desktop */
653 case 3: /* Workstation */
654 case 6: /* Appliance PC */
655 return "desktop";
656
657 case 2: /* Mobile */
658 return "laptop";
659
660 case 4: /* Enterprise Server */
661 case 5: /* SOHO Server */
662 case 7: /* Performance Server */
663 return "server";
664
665 case 8: /* Tablet */
666 return "tablet";
667
668 default:
669 log_debug("Unhandled ACPI PM profile 0x%02x, ignoring.", t);
670 return NULL;
671 }
672 }
673
674 static const char* fallback_chassis_by_device_tree(Context *c) {
675 const char *type, *chassis;
676 int r;
677
678 assert(c);
679
680 if (!c->device_tree)
681 return NULL;
682
683 r = sd_device_get_sysattr_value(c->device_tree, "chassis-type", &type);
684 if (r < 0) {
685 log_debug_errno(r, "Failed to read device-tree chassis type, ignoring: %m");
686 return NULL;
687 }
688
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:
691 *
692 * https://github.com/devicetree-org/devicetree-specification/blob/master/source/chapter3-devicenodes.rst */
693
694 chassis = valid_chassis(type);
695 if (!chassis)
696 log_debug("Invalid device-tree chassis type \"%s\", ignoring.", type);
697 return chassis;
698 }
699
700 static const char* fallback_chassis(Context *c) {
701 assert(c);
702
703 return
704 fallback_chassis_by_virtualization() ?:
705 fallback_chassis_by_dmi(c) ?:
706 fallback_chassis_by_acpi(c) ?:
707 fallback_chassis_by_device_tree(c);
708 }
709
710 static char* context_get_chassis(Context *c) {
711 const char *fallback;
712 char *dmi;
713
714 assert(c);
715
716 if (!isempty(c->data[PROP_CHASSIS]))
717 return strdup(c->data[PROP_CHASSIS]);
718
719 if (get_dmi_property(c, "ID_CHASSIS", &dmi) >= 0)
720 return dmi;
721
722 fallback = fallback_chassis(c);
723 if (fallback)
724 return strdup(fallback);
725
726 return NULL;
727 }
728
729 static char* context_fallback_icon_name(Context *c) {
730 _cleanup_free_ char *chassis = NULL;
731
732 assert(c);
733
734 chassis = context_get_chassis(c);
735 if (chassis)
736 return strjoin("computer-", chassis);
737
738 return strdup("computer");
739 }
740
741 static int context_update_kernel_hostname(
742 Context *c,
743 const char *transient_hostname) {
744
745 _cleanup_free_ char *_hn_free = NULL;
746 const char *hn;
747 HostnameSource hns;
748 int r;
749
750 assert(c);
751
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;
756
757 /* ... the transient hostname, (ie: DHCP) comes next ... */
758 } else if (transient_hostname) {
759 hn = transient_hostname;
760 hns = HOSTNAME_TRANSIENT;
761
762 /* ... and the ultimate fallback */
763 } else {
764 hn = _hn_free = get_default_hostname();
765 if (!hn)
766 return log_oom();
767
768 hns = HOSTNAME_DEFAULT;
769 }
770
771 r = sethostname_idempotent(hn);
772 if (r < 0)
773 return log_error_errno(r, "Failed to set hostname: %m");
774
775 if (c->hostname_source != hns) {
776 c->hostname_source = hns;
777 r = 1;
778 }
779
780 if (r == 0)
781 log_debug("Hostname was already set to <%s>.", hn);
782 else {
783 log_info("Hostname set to <%s> (%s)", hn, hostname_source_to_string(hns));
784
785 hostname_update_source_hint(hn, hns);
786 }
787
788 return r; /* 0 if no change, 1 if something was done */
789 }
790
791 static void unset_statp(struct stat **p) {
792 if (!*p)
793 return;
794
795 **p = (struct stat) {};
796 }
797
798 static int context_write_data_static_hostname(Context *c) {
799 _cleanup_(unset_statp) struct stat *s = NULL;
800 int r;
801
802 assert(c);
803
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;
807
808 if (isempty(c->data[PROP_STATIC_HOSTNAME])) {
809 if (unlink(etc_hostname()) < 0 && errno != ENOENT)
810 return -errno;
811
812 TAKE_PTR(s);
813 return 0;
814 }
815
816 r = write_string_file(etc_hostname(), c->data[PROP_STATIC_HOSTNAME], WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL);
817 if (r < 0)
818 return r;
819
820 TAKE_PTR(s);
821 return 0;
822 }
823
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",
832 };
833 _cleanup_strv_free_ char **l = NULL;
834 int r;
835
836 assert(c);
837
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;
841
842 r = load_env_file(NULL, etc_machine_info(), &l);
843 if (r < 0 && r != -ENOENT)
844 return r;
845
846 for (HostProperty p = PROP_PRETTY_HOSTNAME; p <= PROP_LOCATION; p++) {
847 assert(name[p]);
848
849 r = strv_env_assign(&l, name[p], empty_to_null(c->data[p]));
850 if (r < 0)
851 return r;
852 }
853
854 if (strv_isempty(l)) {
855 if (unlink(etc_machine_info()) < 0 && errno != ENOENT)
856 return -errno;
857
858 TAKE_PTR(s);
859 return 0;
860 }
861
862 r = write_env_file(
863 AT_FDCWD,
864 etc_machine_info(),
865 /* headers= */NULL,
866 l,
867 WRITE_ENV_FILE_LABEL);
868 if (r < 0)
869 return r;
870
871 TAKE_PTR(s);
872 return 0;
873 }
874
875 static int property_get_hardware_property(
876 sd_bus_message *reply,
877 Context *c,
878 HostProperty prop,
879 int (*getter)(Context *c, char **ret)) {
880
881 _cleanup_free_ char *from_dmi = NULL;
882
883 assert(reply);
884 assert(c);
885 assert(IN_SET(prop, PROP_HARDWARE_VENDOR, PROP_HARDWARE_MODEL,
886 PROP_HARDWARE_SKU, PROP_HARDWARE_VERSION));
887 assert(getter);
888
889 context_read_machine_info(c);
890
891 if (isempty(c->data[prop]))
892 (void) getter(c, &from_dmi);
893
894 return sd_bus_message_append(reply, "s", from_dmi ?: c->data[prop]);
895 }
896
897 static int property_get_hardware_vendor(
898 sd_bus *bus,
899 const char *path,
900 const char *interface,
901 const char *property,
902 sd_bus_message *reply,
903 void *userdata,
904 sd_bus_error *error) {
905
906 return property_get_hardware_property(reply, userdata, PROP_HARDWARE_VENDOR, get_hardware_vendor);
907 }
908
909 static int property_get_hardware_model(
910 sd_bus *bus,
911 const char *path,
912 const char *interface,
913 const char *property,
914 sd_bus_message *reply,
915 void *userdata,
916 sd_bus_error *error) {
917
918 return property_get_hardware_property(reply, userdata, PROP_HARDWARE_MODEL, get_hardware_model);
919 }
920
921 static int property_get_hardware_sku(
922 sd_bus *bus,
923 const char *path,
924 const char *interface,
925 const char *property,
926 sd_bus_message *reply,
927 void *userdata,
928 sd_bus_error *error) {
929
930 return property_get_hardware_property(reply, userdata, PROP_HARDWARE_SKU, get_hardware_sku);
931 }
932
933 static int property_get_hardware_version(
934 sd_bus *bus,
935 const char *path,
936 const char *interface,
937 const char *property,
938 sd_bus_message *reply,
939 void *userdata,
940 sd_bus_error *error) {
941
942 return property_get_hardware_property(reply, userdata, PROP_HARDWARE_VERSION, get_hardware_version);
943 }
944
945 static int property_get_firmware_version(
946 sd_bus *bus,
947 const char *path,
948 const char *interface,
949 const char *property,
950 sd_bus_message *reply,
951 void *userdata,
952 sd_bus_error *error) {
953
954 _cleanup_free_ char *firmware_version = NULL;
955 Context *c = ASSERT_PTR(userdata);
956
957 (void) get_firmware_version(c, &firmware_version);
958
959 return sd_bus_message_append(reply, "s", firmware_version);
960 }
961
962 static int property_get_firmware_vendor(
963 sd_bus *bus,
964 const char *path,
965 const char *interface,
966 const char *property,
967 sd_bus_message *reply,
968 void *userdata,
969 sd_bus_error *error) {
970
971 _cleanup_free_ char *firmware_vendor = NULL;
972 Context *c = ASSERT_PTR(userdata);
973
974 (void) get_firmware_vendor(c, &firmware_vendor);
975
976 return sd_bus_message_append(reply, "s", firmware_vendor);
977 }
978
979 static int property_get_firmware_date(
980 sd_bus *bus,
981 const char *path,
982 const char *interface,
983 const char *property,
984 sd_bus_message *reply,
985 void *userdata,
986 sd_bus_error *error) {
987
988 usec_t firmware_date = USEC_INFINITY;
989 Context *c = ASSERT_PTR(userdata);
990
991 (void) get_firmware_date(c, &firmware_date);
992
993 return sd_bus_message_append(reply, "t", firmware_date);
994 }
995
996 static int property_get_chassis_asset_tag(
997 sd_bus *bus,
998 const char *path,
999 const char *interface,
1000 const char *property,
1001 sd_bus_message *reply,
1002 void *userdata,
1003 sd_bus_error *error) {
1004
1005 _cleanup_free_ char *chassis_asset_tag = NULL;
1006 Context *c = ASSERT_PTR(userdata);
1007
1008 (void) get_chassis_asset_tag(c, &chassis_asset_tag);
1009
1010 return sd_bus_message_append(reply, "s", chassis_asset_tag);
1011 }
1012
1013 static int property_get_hostname(
1014 sd_bus *bus,
1015 const char *path,
1016 const char *interface,
1017 const char *property,
1018 sd_bus_message *reply,
1019 void *userdata,
1020 sd_bus_error *error) {
1021
1022 _cleanup_free_ char *hn = NULL;
1023 int r;
1024
1025 r = gethostname_strict(&hn);
1026 if (r < 0) {
1027 if (r != -ENXIO)
1028 return r;
1029
1030 hn = get_default_hostname();
1031 if (!hn)
1032 return -ENOMEM;
1033 }
1034
1035 return sd_bus_message_append(reply, "s", hn);
1036 }
1037
1038 static int property_get_static_hostname(
1039 sd_bus *bus,
1040 const char *path,
1041 const char *interface,
1042 const char *property,
1043 sd_bus_message *reply,
1044 void *userdata,
1045 sd_bus_error *error) {
1046
1047 Context *c = ASSERT_PTR(userdata);
1048
1049 context_read_etc_hostname(c);
1050
1051 return sd_bus_message_append(reply, "s", c->data[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS]);
1052 }
1053
1054 static int property_get_default_hostname(
1055 sd_bus *bus,
1056 const char *path,
1057 const char *interface,
1058 const char *property,
1059 sd_bus_message *reply,
1060 void *userdata,
1061 sd_bus_error *error) {
1062
1063 _cleanup_free_ char *hn = NULL;
1064
1065 hn = get_default_hostname();
1066 if (!hn)
1067 return log_oom();
1068
1069 return sd_bus_message_append(reply, "s", hn);
1070 }
1071
1072 static void context_determine_hostname_source(Context *c) {
1073 _cleanup_free_ char *hostname = NULL;
1074 int r;
1075
1076 assert(c);
1077
1078 if (c->hostname_source >= 0)
1079 return;
1080
1081 (void) gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST, &hostname);
1082
1083 if (streq_ptr(hostname, c->data[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS]))
1084 c->hostname_source = HOSTNAME_STATIC;
1085 else {
1086 _cleanup_free_ char *fallback = NULL;
1087
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. */
1092
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");
1096
1097 if (streq_ptr(fallback, hostname))
1098 c->hostname_source = HOSTNAME_DEFAULT;
1099 else
1100 c->hostname_source = HOSTNAME_TRANSIENT;
1101 }
1102 }
1103
1104 static int property_get_hostname_source(
1105 sd_bus *bus,
1106 const char *path,
1107 const char *interface,
1108 const char *property,
1109 sd_bus_message *reply,
1110 void *userdata,
1111 sd_bus_error *error) {
1112
1113 Context *c = ASSERT_PTR(userdata);
1114
1115 context_read_etc_hostname(c);
1116 context_determine_hostname_source(c);
1117
1118 return sd_bus_message_append(reply, "s", hostname_source_to_string(c->hostname_source));
1119 }
1120
1121 static int property_get_machine_info_field(
1122 sd_bus *bus,
1123 const char *path,
1124 const char *interface,
1125 const char *property,
1126 sd_bus_message *reply,
1127 void *userdata,
1128 sd_bus_error *error) {
1129
1130 sd_bus_slot *slot;
1131 Context *c;
1132
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));
1144
1145 context_read_machine_info(c);
1146
1147 return sd_bus_message_append(reply, "s", *(char**) userdata);
1148 }
1149
1150 static int property_get_os_release_field(
1151 sd_bus *bus,
1152 const char *path,
1153 const char *interface,
1154 const char *property,
1155 sd_bus_message *reply,
1156 void *userdata,
1157 sd_bus_error *error) {
1158
1159 sd_bus_slot *slot;
1160 Context *c;
1161
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));
1165
1166 context_read_os_release(c);
1167
1168 return sd_bus_message_append(reply, "s", *(char**) userdata);
1169 }
1170
1171 static int property_get_os_support_end(
1172 sd_bus *bus,
1173 const char *path,
1174 const char *interface,
1175 const char *property,
1176 sd_bus_message *reply,
1177 void *userdata,
1178 sd_bus_error *error) {
1179
1180 Context *c = userdata;
1181 usec_t eol = USEC_INFINITY;
1182
1183 context_read_os_release(c);
1184
1185 if (c->data[PROP_OS_SUPPORT_END])
1186 (void) os_release_support_ended(c->data[PROP_OS_SUPPORT_END], /* quiet= */ false, &eol);
1187
1188 return sd_bus_message_append(reply, "t", eol);
1189 }
1190
1191 static int property_get_icon_name(
1192 sd_bus *bus,
1193 const char *path,
1194 const char *interface,
1195 const char *property,
1196 sd_bus_message *reply,
1197 void *userdata,
1198 sd_bus_error *error) {
1199
1200 _cleanup_free_ char *n = NULL;
1201 Context *c = userdata;
1202 const char *name;
1203
1204 context_read_machine_info(c);
1205
1206 if (isempty(c->data[PROP_ICON_NAME]))
1207 name = n = context_fallback_icon_name(c);
1208 else
1209 name = c->data[PROP_ICON_NAME];
1210
1211 if (!name)
1212 return -ENOMEM;
1213
1214 return sd_bus_message_append(reply, "s", name);
1215 }
1216
1217 static int property_get_chassis(
1218 sd_bus *bus,
1219 const char *path,
1220 const char *interface,
1221 const char *property,
1222 sd_bus_message *reply,
1223 void *userdata,
1224 sd_bus_error *error) {
1225
1226 _cleanup_free_ char *chassis = NULL;
1227 Context *c = userdata;
1228
1229 context_read_machine_info(c);
1230
1231 chassis = context_get_chassis(c);
1232
1233 return sd_bus_message_append(reply, "s", chassis);
1234 }
1235
1236 static int property_get_uname_field(
1237 sd_bus *bus,
1238 const char *path,
1239 const char *interface,
1240 const char *property,
1241 sd_bus_message *reply,
1242 void *userdata,
1243 sd_bus_error *error) {
1244
1245 struct utsname u;
1246
1247 assert_se(uname(&u) >= 0);
1248
1249 return sd_bus_message_append(reply, "s", (char*) &u + PTR_TO_SIZE(userdata));
1250 }
1251
1252 static int property_get_machine_id(
1253 sd_bus *bus,
1254 const char *path,
1255 const char *interface,
1256 const char *property,
1257 sd_bus_message *reply,
1258 void *userdata,
1259 sd_bus_error *error) {
1260
1261 sd_id128_t id;
1262 int r;
1263
1264 r = sd_id128_get_machine(&id);
1265 if (r < 0)
1266 return r;
1267
1268 return bus_property_get_id128(bus, path, interface, property, reply, &id, error);
1269 }
1270
1271 static int property_get_boot_id(
1272 sd_bus *bus,
1273 const char *path,
1274 const char *interface,
1275 const char *property,
1276 sd_bus_message *reply,
1277 void *userdata,
1278 sd_bus_error *error) {
1279
1280 sd_id128_t id;
1281 int r;
1282
1283 r = sd_id128_get_boot(&id);
1284 if (r < 0)
1285 return r;
1286
1287 return bus_property_get_id128(bus, path, interface, property, reply, &id, error);
1288 }
1289
1290 static int property_get_vsock_cid(
1291 sd_bus *bus,
1292 const char *path,
1293 const char *interface,
1294 const char *property,
1295 sd_bus_message *reply,
1296 void *userdata,
1297 sd_bus_error *error) {
1298
1299 unsigned local_cid = VMADDR_CID_ANY;
1300
1301 (void) vsock_get_local_cid(&local_cid);
1302
1303 return sd_bus_message_append(reply, "u", (uint32_t) local_cid);
1304 }
1305
1306 static int validate_and_substitute_hostname(const char *name, char **ret_substituted, sd_bus_error *error) {
1307 int r;
1308
1309 assert(ret_substituted);
1310
1311 if (!name) {
1312 *ret_substituted = NULL;
1313 return 0;
1314 }
1315
1316 _cleanup_free_ char *substituted = strdup(name);
1317 if (!substituted)
1318 return log_oom();
1319
1320 r = hostname_substitute_wildcards(substituted);
1321 if (r < 0)
1322 return log_error_errno(r, "Failed to substitute wildcards in hostname: %m");
1323
1324 if (!hostname_is_valid(substituted, 0))
1325 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
1326
1327 *ret_substituted = TAKE_PTR(substituted);
1328 return 1;
1329 }
1330
1331 static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1332 Context *c = ASSERT_PTR(userdata);
1333 const char *name;
1334 int interactive, r;
1335
1336 assert(m);
1337
1338 r = sd_bus_message_read(m, "sb", &name, &interactive);
1339 if (r < 0)
1340 return r;
1341
1342 name = empty_to_null(name);
1343
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. */
1346
1347 _cleanup_free_ char *substituted = NULL;
1348 r = validate_and_substitute_hostname(name, &substituted, error);
1349 if (r < 0)
1350 return r;
1351
1352 name = substituted;
1353
1354 r = bus_verify_polkit_async_full(
1355 m,
1356 "org.freedesktop.hostname1.set-hostname",
1357 /* details= */ NULL,
1358 /* good_user= */ UID_INVALID,
1359 interactive ? POLKIT_ALLOW_INTERACTIVE : 0,
1360 &c->polkit_registry,
1361 error);
1362 if (r < 0)
1363 return r;
1364 if (r == 0)
1365 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1366
1367 context_read_etc_hostname(c);
1368
1369 r = context_update_kernel_hostname(c, name);
1370 if (r < 0)
1371 return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
1372 else if (r > 0)
1373 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
1374 "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
1375 "Hostname", "HostnameSource", NULL);
1376
1377 return sd_bus_reply_method_return(m, NULL);
1378 }
1379
1380 static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1381 Context *c = ASSERT_PTR(userdata);
1382 const char *name;
1383 int interactive, r;
1384
1385 assert(m);
1386
1387 r = sd_bus_message_read(m, "sb", &name, &interactive);
1388 if (r < 0)
1389 return r;
1390
1391 name = empty_to_null(name);
1392
1393 context_read_etc_hostname(c);
1394
1395 if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
1396 return sd_bus_reply_method_return(m, NULL);
1397
1398 _cleanup_free_ char *substituted = NULL;
1399 r = validate_and_substitute_hostname(name, &substituted, error);
1400 if (r < 0)
1401 return r;
1402
1403 r = bus_verify_polkit_async_full(
1404 m,
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,
1410 error);
1411 if (r < 0)
1412 return r;
1413 if (r == 0)
1414 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1415
1416 r = free_and_strdup_warn(&c->data[PROP_STATIC_HOSTNAME], name);
1417 if (r < 0)
1418 return r;
1419
1420 free_and_replace(c->data[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS], substituted);
1421
1422 r = context_write_data_static_hostname(c);
1423 if (r < 0) {
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.");
1427 if (r == -EROFS)
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");
1430 }
1431
1432 r = context_update_kernel_hostname(c, /* transient_hostname= */ NULL);
1433 if (r < 0) {
1434 log_error_errno(r, "Failed to set hostname: %m");
1435 return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
1436 }
1437
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);
1441
1442 return sd_bus_reply_method_return(m, NULL);
1443 }
1444
1445 static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_message_handler_t cb, sd_bus_error *error) {
1446 int interactive;
1447 const char *name;
1448 int r;
1449
1450 assert(c);
1451 assert(m);
1452
1453 r = sd_bus_message_read(m, "sb", &name, &interactive);
1454 if (r < 0)
1455 return r;
1456
1457 name = empty_to_null(name);
1458
1459 context_read_machine_info(c);
1460
1461 if (streq_ptr(name, c->data[prop]))
1462 return sd_bus_reply_method_return(m, NULL);
1463
1464 if (!isempty(name)) {
1465 /* The icon name might ultimately be used as file
1466 * name, so better be safe than sorry */
1467
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);
1478 }
1479
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... */
1482
1483 r = bus_verify_polkit_async_full(
1484 m,
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,
1490 error);
1491 if (r < 0)
1492 return r;
1493 if (r == 0)
1494 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1495
1496 r = free_and_strdup_warn(&c->data[prop], name);
1497 if (r < 0)
1498 return r;
1499
1500 r = context_write_data_machine_info(c);
1501 if (r < 0) {
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.");
1505 if (r == -EROFS)
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");
1508 }
1509
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]));
1515
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);
1524
1525 return sd_bus_reply_method_return(m, NULL);
1526 }
1527
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);
1530 }
1531
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);
1534 }
1535
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);
1538 }
1539
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);
1542 }
1543
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);
1546 }
1547
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);
1551 int interactive, r;
1552 sd_id128_t uuid;
1553
1554 assert(m);
1555
1556 r = sd_bus_message_read(m, "b", &interactive);
1557 if (r < 0)
1558 return r;
1559
1560 r = bus_verify_polkit_async_full(
1561 m,
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,
1567 error);
1568 if (r < 0)
1569 return r;
1570 if (r == 0)
1571 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1572
1573 r = id128_get_product(&uuid);
1574 if (r < 0) {
1575 if (r == -EADDRNOTAVAIL)
1576 log_debug_errno(r, "DMI product UUID is all 0x00 or all 0xFF, ignoring.");
1577 else
1578 log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
1579 "Failed to read product UUID, ignoring: %m");
1580
1581 return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID,
1582 "Failed to read product UUID from firmware.");
1583 }
1584
1585 r = sd_bus_message_new_method_return(m, &reply);
1586 if (r < 0)
1587 return r;
1588
1589 r = sd_bus_message_append_array(reply, 'y', uuid.bytes, sizeof(uuid.bytes));
1590 if (r < 0)
1591 return r;
1592
1593 return sd_bus_message_send(reply);
1594 }
1595
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);
1599 int r;
1600
1601 assert(m);
1602
1603 r = bus_verify_polkit_async(
1604 m,
1605 "org.freedesktop.hostname1.get-hardware-serial",
1606 /* details= */ NULL,
1607 &c->polkit_registry,
1608 error);
1609 if (r < 0)
1610 return r;
1611 if (r == 0)
1612 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1613
1614 r = get_hardware_serial(c, &serial);
1615 if (r < 0)
1616 return sd_bus_error_set(error, BUS_ERROR_NO_HARDWARE_SERIAL,
1617 "Failed to read hardware serial from firmware.");
1618
1619 return sd_bus_reply_method_return(m, "s", serial);
1620 }
1621
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;
1631 struct utsname u;
1632 int r;
1633
1634 assert(c);
1635 assert(ret);
1636
1637 context_read_etc_hostname(c);
1638 context_read_machine_info(c);
1639 context_read_os_release(c);
1640 context_determine_hostname_source(c);
1641
1642 dhn = get_default_hostname();
1643 if (!dhn)
1644 return log_oom();
1645
1646 r = gethostname_strict(&hn);
1647 if (r < 0 && r != -ENXIO)
1648 return log_error_errno(r, "Failed to read local host name: %m");
1649
1650 if (isempty(c->data[PROP_ICON_NAME]))
1651 in = context_fallback_icon_name(c);
1652
1653 chassis = context_get_chassis(c);
1654
1655 assert_se(uname(&u) >= 0);
1656
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);
1665
1666 if (privileged) {
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);
1670 }
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);
1675
1676 if (c->data[PROP_OS_SUPPORT_END])
1677 (void) os_release_support_ended(c->data[PROP_OS_SUPPORT_END], /* quiet= */ false, &eol);
1678
1679 r = sd_id128_get_machine(&machine_id);
1680 if (r < 0)
1681 return log_error_errno(r, "Failed to get machine ID: %m");
1682
1683 r = sd_id128_get_boot(&boot_id);
1684 if (r < 0)
1685 return log_error_errno(r, "Failed to get boot ID: %m");
1686
1687 (void) vsock_get_local_cid(&local_cid);
1688
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);
1691
1692 r = sd_json_buildo(
1693 &v,
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));
1729 if (r < 0)
1730 return log_error_errno(r, "Failed to build JSON data: %m");
1731
1732 *ret = TAKE_PTR(v);
1733 return 0;
1734 }
1735
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;
1740 bool privileged;
1741 int r;
1742
1743 assert(m);
1744
1745 r = bus_verify_polkit_async(
1746 m,
1747 "org.freedesktop.hostname1.get-description",
1748 /* details= */ NULL,
1749 &c->polkit_registry,
1750 error);
1751 if (r == 0)
1752 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1753
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. */
1756 privileged = r > 0;
1757
1758 r = build_describe_response(c, privileged, &v);
1759 if (r < 0)
1760 return r;
1761
1762 r = sd_json_variant_format(v, 0, &text);
1763 if (r < 0)
1764 return log_error_errno(r, "Failed to format JSON data: %m");
1765
1766 return sd_bus_reply_method_return(m, "s", text);
1767 }
1768
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),
1800
1801 SD_BUS_METHOD_WITH_ARGS("SetHostname",
1802 SD_BUS_ARGS("s", hostname, "b", interactive),
1803 SD_BUS_NO_RESULT,
1804 method_set_hostname,
1805 SD_BUS_VTABLE_UNPRIVILEGED),
1806 SD_BUS_METHOD_WITH_ARGS("SetStaticHostname",
1807 SD_BUS_ARGS("s", hostname, "b", interactive),
1808 SD_BUS_NO_RESULT,
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),
1813 SD_BUS_NO_RESULT,
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),
1818 SD_BUS_NO_RESULT,
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),
1823 SD_BUS_NO_RESULT,
1824 method_set_chassis,
1825 SD_BUS_VTABLE_UNPRIVILEGED),
1826 SD_BUS_METHOD_WITH_ARGS("SetDeployment",
1827 SD_BUS_ARGS("s", deployment, "b", interactive),
1828 SD_BUS_NO_RESULT,
1829 method_set_deployment,
1830 SD_BUS_VTABLE_UNPRIVILEGED),
1831 SD_BUS_METHOD_WITH_ARGS("SetLocation",
1832 SD_BUS_ARGS("s", location, "b", interactive),
1833 SD_BUS_NO_RESULT,
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",
1842 SD_BUS_NO_ARGS,
1843 SD_BUS_RESULT("s", serial),
1844 method_get_hardware_serial,
1845 SD_BUS_VTABLE_UNPRIVILEGED),
1846 SD_BUS_METHOD_WITH_ARGS("Describe",
1847 SD_BUS_NO_ARGS,
1848 SD_BUS_RESULT("s", json),
1849 method_describe,
1850 SD_BUS_VTABLE_UNPRIVILEGED),
1851
1852 SD_BUS_VTABLE_END,
1853 };
1854
1855 static const BusObjectImplementation manager_object = {
1856 "/org/freedesktop/hostname1",
1857 "org.freedesktop.hostname1",
1858 .vtables = BUS_VTABLES(hostname_vtable),
1859 };
1860
1861 static int connect_bus(Context *c) {
1862 int r;
1863
1864 assert(c);
1865 assert(c->event);
1866 assert(!c->bus);
1867
1868 r = sd_bus_default_system(&c->bus);
1869 if (r < 0)
1870 return log_error_errno(r, "Failed to get system bus connection: %m");
1871
1872 r = bus_add_implementation(c->bus, &manager_object, c);
1873 if (r < 0)
1874 return r;
1875
1876 r = bus_log_control_api_register(c->bus);
1877 if (r < 0)
1878 return r;
1879
1880 r = sd_bus_request_name_async(c->bus, NULL, "org.freedesktop.hostname1", 0, NULL, NULL);
1881 if (r < 0)
1882 return log_error_errno(r, "Failed to request name: %m");
1883
1884 r = sd_bus_attach_event(c->bus, c->event, 0);
1885 if (r < 0)
1886 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1887
1888 return 0;
1889 }
1890
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);
1893 bool privileged;
1894 int r;
1895
1896 assert(link);
1897 assert(parameters);
1898
1899 r = sd_varlink_dispatch(link, parameters, dispatch_table_polkit_only, /* userdata= */ NULL);
1900 if (r != 0)
1901 return r;
1902
1903 r = varlink_verify_polkit_async_full(
1904 link,
1905 c->bus,
1906 "org.freedesktop.hostname1.get-hardware-serial",
1907 /* details= */ NULL,
1908 UID_INVALID,
1909 POLKIT_DONT_REPLY,
1910 &c->polkit_registry);
1911 if (r == 0)
1912 return 0; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1913
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. */
1916 privileged = r > 0;
1917
1918 _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
1919 r = build_describe_response(c, privileged, &v);
1920 if (r < 0)
1921 return r;
1922
1923 return sd_varlink_reply(link, v);
1924 }
1925
1926 static int connect_varlink(Context *c) {
1927 int r;
1928
1929 assert(c);
1930 assert(c->event);
1931 assert(!c->varlink_server);
1932
1933 r = varlink_server_new(
1934 &c->varlink_server,
1935 SD_VARLINK_SERVER_ACCOUNT_UID|SD_VARLINK_SERVER_INHERIT_USERDATA,
1936 c);
1937 if (r < 0)
1938 return log_error_errno(r, "Failed to allocate Varlink server: %m");
1939
1940 r = sd_varlink_server_add_interface_many(
1941 c->varlink_server,
1942 &vl_interface_io_systemd_Hostname,
1943 &vl_interface_io_systemd_service);
1944 if (r < 0)
1945 return log_error_errno(r, "Failed to add Hostname interface to Varlink server: %m");
1946
1947 r = sd_varlink_server_bind_method_many(
1948 c->varlink_server,
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);
1953 if (r < 0)
1954 return log_error_errno(r, "Failed to bind Varlink method calls: %m");
1955
1956 r = sd_varlink_server_attach_event(c->varlink_server, c->event, SD_EVENT_PRIORITY_NORMAL);
1957 if (r < 0)
1958 return log_error_errno(r, "Failed to attach Varlink server to event loop: %m");
1959
1960 r = sd_varlink_server_listen_auto(c->varlink_server);
1961 if (r < 0)
1962 return log_error_errno(r, "Failed to bind to passed Varlink sockets: %m");
1963 if (r == 0) {
1964 r = sd_varlink_server_listen_address(c->varlink_server, "/run/systemd/io.systemd.Hostname", 0666);
1965 if (r < 0)
1966 return log_error_errno(r, "Failed to bind to Varlink socket: %m");
1967 }
1968
1969 return 0;
1970 }
1971
1972 static bool context_check_idle(void *userdata) {
1973 Context *c = ASSERT_PTR(userdata);
1974
1975 return sd_varlink_server_current_connections(c->varlink_server) == 0 &&
1976 hashmap_isempty(c->polkit_registry);
1977 }
1978
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 */
1982 };
1983 int r;
1984
1985 log_setup();
1986
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),
1991 argc, argv);
1992 if (r <= 0)
1993 return r;
1994
1995 umask(0022);
1996
1997 r = mac_init();
1998 if (r < 0)
1999 return r;
2000
2001 r = context_acquire_dmi_device(&context);
2002 if (r < 0)
2003 return r;
2004
2005 r = context_acquire_acpi_device(&context);
2006 if (r < 0)
2007 return r;
2008
2009 r = context_acquire_device_tree(&context);
2010 if (r < 0)
2011 return r;
2012
2013 r = sd_event_default(&context.event);
2014 if (r < 0)
2015 return log_error_errno(r, "Failed to allocate event loop: %m");
2016
2017 (void) sd_event_set_watchdog(context.event, true);
2018
2019 r = sd_event_set_signal_exit(context.event, true);
2020 if (r < 0)
2021 return log_error_errno(r, "Failed to install SIGINT/SIGTERM handlers: %m");
2022
2023 r = connect_bus(&context);
2024 if (r < 0)
2025 return r;
2026
2027 r = connect_varlink(&context);
2028 if (r < 0)
2029 return r;
2030
2031 r = sd_notify(false, NOTIFY_READY_MESSAGE);
2032 if (r < 0)
2033 log_warning_errno(r, "Failed to send readiness notification, ignoring: %m");
2034
2035 r = bus_event_loop_with_idle(
2036 context.event,
2037 context.bus,
2038 "org.freedesktop.hostname1",
2039 DEFAULT_EXIT_USEC,
2040 context_check_idle,
2041 &context);
2042 if (r < 0)
2043 return log_error_errno(r, "Failed to run event loop: %m");
2044
2045 return 0;
2046 }
2047
2048 DEFINE_MAIN_FUNCTION(run);