]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/hostname/hostnamed.c
Merge pull request #21871 from keszybz/meson-sbat-report
[thirdparty/systemd.git] / src / hostname / hostnamed.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <sys/utsname.h>
5 #include <sys/stat.h>
6 #include <sys/types.h>
7 #include <unistd.h>
8
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 "def.h"
15 #include "env-file-label.h"
16 #include "env-file.h"
17 #include "env-util.h"
18 #include "fileio-label.h"
19 #include "fileio.h"
20 #include "hostname-setup.h"
21 #include "hostname-util.h"
22 #include "id128-util.h"
23 #include "json.h"
24 #include "main-func.h"
25 #include "missing_capability.h"
26 #include "nscd-flush.h"
27 #include "nulstr-util.h"
28 #include "os-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"
37 #include "strv.h"
38 #include "user-util.h"
39 #include "util.h"
40 #include "virt.h"
41
42 #define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:")
43
44 /* Properties we cache are indexed by an enum, to make invalidation easy and systematic (as we can iterate
45 * through them all, and they are uniformly strings). */
46 enum {
47 /* Read from /etc/hostname */
48 PROP_STATIC_HOSTNAME,
49
50 /* Read from /etc/machine-info */
51 PROP_PRETTY_HOSTNAME,
52 PROP_ICON_NAME,
53 PROP_CHASSIS,
54 PROP_DEPLOYMENT,
55 PROP_LOCATION,
56
57 /* Read from /etc/os-release (or /usr/lib/os-release) */
58 PROP_OS_PRETTY_NAME,
59 PROP_OS_CPE_NAME,
60 PROP_OS_HOME_URL,
61 _PROP_MAX,
62 _PROP_INVALID = -EINVAL,
63 };
64
65 typedef struct Context {
66 char *data[_PROP_MAX];
67
68 HostnameSource hostname_source;
69
70 struct stat etc_hostname_stat;
71 struct stat etc_os_release_stat;
72 struct stat etc_machine_info_stat;
73
74 Hashmap *polkit_registry;
75 } Context;
76
77 static void context_reset(Context *c, uint64_t mask) {
78 assert(c);
79
80 for (int p = 0; p < _PROP_MAX; p++) {
81 if (!FLAGS_SET(mask, UINT64_C(1) << p))
82 continue;
83
84 c->data[p] = mfree(c->data[p]);
85 }
86 }
87
88 static void context_destroy(Context *c) {
89 assert(c);
90
91 context_reset(c, UINT64_MAX);
92 bus_verify_polkit_async_registry_free(c->polkit_registry);
93 }
94
95 static void context_read_etc_hostname(Context *c) {
96 struct stat current_stat = {};
97 int r;
98
99 assert(c);
100
101 if (stat("/etc/hostname", &current_stat) >= 0 &&
102 stat_inode_unmodified(&c->etc_hostname_stat, &current_stat))
103 return;
104
105 context_reset(c, UINT64_C(1) << PROP_STATIC_HOSTNAME);
106
107 r = read_etc_hostname(NULL, &c->data[PROP_STATIC_HOSTNAME]);
108 if (r < 0 && r != -ENOENT)
109 log_warning_errno(r, "Failed to read /etc/hostname, ignoring: %m");
110
111 c->etc_hostname_stat = current_stat;
112 }
113
114 static void context_read_machine_info(Context *c) {
115 struct stat current_stat = {};
116 int r;
117
118 assert(c);
119
120 if (stat("/etc/machine-info", &current_stat) >= 0 &&
121 stat_inode_unmodified(&c->etc_machine_info_stat, &current_stat))
122 return;
123
124 context_reset(c,
125 (UINT64_C(1) << PROP_PRETTY_HOSTNAME) |
126 (UINT64_C(1) << PROP_ICON_NAME) |
127 (UINT64_C(1) << PROP_CHASSIS) |
128 (UINT64_C(1) << PROP_DEPLOYMENT) |
129 (UINT64_C(1) << PROP_LOCATION));
130
131 r = parse_env_file(NULL, "/etc/machine-info",
132 "PRETTY_HOSTNAME", &c->data[PROP_PRETTY_HOSTNAME],
133 "ICON_NAME", &c->data[PROP_ICON_NAME],
134 "CHASSIS", &c->data[PROP_CHASSIS],
135 "DEPLOYMENT", &c->data[PROP_DEPLOYMENT],
136 "LOCATION", &c->data[PROP_LOCATION]);
137 if (r < 0 && r != -ENOENT)
138 log_warning_errno(r, "Failed to read /etc/machine-info, ignoring: %m");
139
140 c->etc_machine_info_stat = current_stat;
141 }
142
143 static void context_read_os_release(Context *c) {
144 struct stat current_stat = {};
145 int r;
146
147 assert(c);
148
149 if ((stat("/etc/os-release", &current_stat) >= 0 ||
150 stat("/usr/lib/os-release", &current_stat) >= 0) &&
151 stat_inode_unmodified(&c->etc_os_release_stat, &current_stat))
152 return;
153
154 context_reset(c,
155 (UINT64_C(1) << PROP_OS_PRETTY_NAME) |
156 (UINT64_C(1) << PROP_OS_CPE_NAME) |
157 (UINT64_C(1) << PROP_OS_HOME_URL));
158
159 r = parse_os_release(NULL,
160 "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
161 "CPE_NAME", &c->data[PROP_OS_CPE_NAME],
162 "HOME_URL", &c->data[PROP_OS_HOME_URL]);
163 if (r < 0 && r != -ENOENT)
164 log_warning_errno(r, "Failed to read os-release file, ignoring: %m");
165
166 c->etc_os_release_stat = current_stat;
167 }
168
169 static const char* valid_chassis(const char *chassis) {
170 assert(chassis);
171
172 return nulstr_get(
173 "vm\0"
174 "container\0"
175 "desktop\0"
176 "laptop\0"
177 "convertible\0"
178 "server\0"
179 "tablet\0"
180 "handset\0"
181 "watch\0"
182 "embedded\0",
183 chassis);
184 }
185
186 static bool valid_deployment(const char *deployment) {
187 assert(deployment);
188
189 return in_charset(deployment, VALID_DEPLOYMENT_CHARS);
190 }
191
192 static const char* fallback_chassis(void) {
193 const char *chassis;
194 _cleanup_free_ char *type = NULL;
195 unsigned t;
196 int v, r;
197
198 v = detect_virtualization();
199 if (v < 0)
200 log_debug_errno(v, "Failed to detect virtualization, ignoring: %m");
201 else if (VIRTUALIZATION_IS_VM(v))
202 return "vm";
203 else if (VIRTUALIZATION_IS_CONTAINER(v))
204 return "container";
205
206 r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type);
207 if (r < 0) {
208 log_debug_errno(r, "Failed to read DMI chassis type, ignoring: %m");
209 goto try_acpi;
210 }
211
212 r = safe_atou(type, &t);
213 if (r < 0) {
214 log_debug_errno(r, "Failed to parse DMI chassis type \"%s\", ignoring: %m", type);
215 goto try_acpi;
216 }
217
218 /* We only list the really obvious cases here. The DMI data is unreliable enough, so let's not do any
219 * additional guesswork on top of that.
220 *
221 * See the SMBIOS Specification 3.0 section 7.4.1 for details about the values listed here:
222 *
223 * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
224 */
225
226 switch (t) {
227
228 case 0x3: /* Desktop */
229 case 0x4: /* Low Profile Desktop */
230 case 0x6: /* Mini Tower */
231 case 0x7: /* Tower */
232 case 0xD: /* All in one (i.e. PC built into monitor) */
233 return "desktop";
234
235 case 0x8: /* Portable */
236 case 0x9: /* Laptop */
237 case 0xA: /* Notebook */
238 case 0xE: /* Sub Notebook */
239 return "laptop";
240
241 case 0xB: /* Hand Held */
242 return "handset";
243
244 case 0x11: /* Main Server Chassis */
245 case 0x1C: /* Blade */
246 case 0x1D: /* Blade Enclosure */
247 return "server";
248
249 case 0x1E: /* Tablet */
250 return "tablet";
251
252 case 0x1F: /* Convertible */
253 case 0x20: /* Detachable */
254 return "convertible";
255
256 default:
257 log_debug("Unhandled DMI chassis type 0x%02x, ignoring.", t);
258 }
259
260 try_acpi:
261 type = mfree(type);
262 r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type);
263 if (r < 0) {
264 log_debug_errno(r, "Failed read ACPI PM profile, ignoring: %m");
265 goto try_devicetree;
266 }
267
268 r = safe_atou(type, &t);
269 if (r < 0) {
270 log_debug_errno(r, "Failed parse ACPI PM profile \"%s\", ignoring: %m", type);
271 goto try_devicetree;
272 }
273
274 /* We only list the really obvious cases here as the ACPI data is not really super reliable.
275 *
276 * See the ACPI 5.0 Spec Section 5.2.9.1 for details:
277 *
278 * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf
279 */
280
281 switch(t) {
282
283 case 1: /* Desktop */
284 case 3: /* Workstation */
285 case 6: /* Appliance PC */
286 return "desktop";
287
288 case 2: /* Mobile */
289 return "laptop";
290
291 case 4: /* Enterprise Server */
292 case 5: /* SOHO Server */
293 case 7: /* Performance Server */
294 return "server";
295
296 case 8: /* Tablet */
297 return "tablet";
298
299 default:
300 log_debug("Unhandled ACPI PM profile 0x%02x, ignoring.", t);
301 }
302
303 try_devicetree:
304 type = mfree(type);
305 r = read_one_line_file("/proc/device-tree/chassis-type", &type);
306 if (r < 0) {
307 log_debug_errno(r, "Failed to read device-tree chassis type, ignoring: %m");
308 return NULL;
309 }
310
311 /* Note that the Devicetree specification uses the very same vocabulary
312 * of chassis types as we do, hence we do not need to translate these types:
313 *
314 * https://github.com/devicetree-org/devicetree-specification/blob/master/source/chapter3-devicenodes.rst */
315 chassis = valid_chassis(type);
316 if (!chassis)
317 log_debug("Invalid device-tree chassis type \"%s\", ignoring.", type);
318 return chassis;
319 }
320
321 static char* context_fallback_icon_name(Context *c) {
322 const char *chassis;
323
324 assert(c);
325
326 if (!isempty(c->data[PROP_CHASSIS]))
327 return strjoin("computer-", c->data[PROP_CHASSIS]);
328
329 chassis = fallback_chassis();
330 if (chassis)
331 return strjoin("computer-", chassis);
332
333 return strdup("computer");
334 }
335
336 static int context_update_kernel_hostname(
337 Context *c,
338 const char *transient_hn) {
339
340 _cleanup_free_ char *_hn_free = NULL;
341 const char *hn;
342 HostnameSource hns;
343 int r;
344
345 assert(c);
346
347 /* /etc/hostname has the highest preference ... */
348 if (c->data[PROP_STATIC_HOSTNAME]) {
349 hn = c->data[PROP_STATIC_HOSTNAME];
350 hns = HOSTNAME_STATIC;
351
352 /* ... the transient hostname, (ie: DHCP) comes next ... */
353 } else if (transient_hn) {
354 hn = transient_hn;
355 hns = HOSTNAME_TRANSIENT;
356
357 /* ... and the ultimate fallback */
358 } else {
359 hn = _hn_free = get_default_hostname();
360 if (!hn)
361 return log_oom();
362
363 hns = HOSTNAME_DEFAULT;
364 }
365
366 r = sethostname_idempotent(hn);
367 if (r < 0)
368 return log_error_errno(r, "Failed to set hostname: %m");
369
370 if (c->hostname_source != hns) {
371 c->hostname_source = hns;
372 r = 1;
373 }
374
375 (void) nscd_flush_cache(STRV_MAKE("hosts"));
376
377 if (r == 0)
378 log_debug("Hostname was already set to <%s>.", hn);
379 else {
380 log_info("Hostname set to <%s> (%s)", hn, hostname_source_to_string(hns));
381
382 hostname_update_source_hint(hn, hns);
383 }
384
385 return r; /* 0 if no change, 1 if something was done */
386 }
387
388 static void unset_statp(struct stat **p) {
389 if (!*p)
390 return;
391
392 **p = (struct stat) {};
393 }
394
395 static int context_write_data_static_hostname(Context *c) {
396 _cleanup_(unset_statp) struct stat *s = NULL;
397 int r;
398
399 assert(c);
400
401 /* Make sure that if we fail here, we invalidate the cached information, since it was updated
402 * already, even if we can't make it hit the disk. */
403 s = &c->etc_hostname_stat;
404
405 if (isempty(c->data[PROP_STATIC_HOSTNAME])) {
406 if (unlink("/etc/hostname") < 0 && errno != ENOENT)
407 return -errno;
408
409 TAKE_PTR(s);
410 return 0;
411 }
412
413 r = write_string_file_atomic_label("/etc/hostname", c->data[PROP_STATIC_HOSTNAME]);
414 if (r < 0)
415 return r;
416
417 TAKE_PTR(s);
418 return 0;
419 }
420
421 static int context_write_data_machine_info(Context *c) {
422 _cleanup_(unset_statp) struct stat *s = NULL;
423 static const char * const name[_PROP_MAX] = {
424 [PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME",
425 [PROP_ICON_NAME] = "ICON_NAME",
426 [PROP_CHASSIS] = "CHASSIS",
427 [PROP_DEPLOYMENT] = "DEPLOYMENT",
428 [PROP_LOCATION] = "LOCATION",
429 };
430 _cleanup_strv_free_ char **l = NULL;
431 int r;
432
433 assert(c);
434
435 /* Make sure that if we fail here, we invalidate the cached information, since it was updated
436 * already, even if we can't make it hit the disk. */
437 s = &c->etc_machine_info_stat;
438
439 r = load_env_file(NULL, "/etc/machine-info", &l);
440 if (r < 0 && r != -ENOENT)
441 return r;
442
443 for (int p = PROP_PRETTY_HOSTNAME; p <= PROP_LOCATION; p++) {
444 assert(name[p]);
445
446 r = strv_env_assign(&l, name[p], empty_to_null(c->data[p]));
447 if (r < 0)
448 return r;
449 }
450
451 if (strv_isempty(l)) {
452 if (unlink("/etc/machine-info") < 0 && errno != ENOENT)
453 return -errno;
454
455 TAKE_PTR(s);
456 return 0;
457 }
458
459 r = write_env_file_label("/etc/machine-info", l);
460 if (r < 0)
461 return r;
462
463 TAKE_PTR(s);
464 return 0;
465 }
466
467 static int get_dmi_data(const char *database_key, const char *regular_key, char **ret) {
468 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
469 _cleanup_free_ char *b = NULL;
470 const char *s = NULL;
471 int r;
472
473 r = sd_device_new_from_syspath(&device, "/sys/class/dmi/id");
474 if (r < 0)
475 return log_debug_errno(r, "Failed to open /sys/class/dmi/id device, ignoring: %m");
476
477 if (database_key)
478 (void) sd_device_get_property_value(device, database_key, &s);
479 if (!s && regular_key)
480 (void) sd_device_get_property_value(device, regular_key, &s);
481
482 if (s) {
483 b = strdup(s);
484 if (!b)
485 return -ENOMEM;
486 }
487
488 if (ret)
489 *ret = TAKE_PTR(b);
490
491 return !!s;
492 }
493
494 static int get_hardware_vendor(char **ret) {
495 return get_dmi_data("ID_VENDOR_FROM_DATABASE", "ID_VENDOR", ret);
496 }
497
498 static int get_hardware_model(char **ret) {
499 return get_dmi_data("ID_MODEL_FROM_DATABASE", "ID_MODEL", ret);
500 }
501
502 static int property_get_hardware_vendor(
503 sd_bus *bus,
504 const char *path,
505 const char *interface,
506 const char *property,
507 sd_bus_message *reply,
508 void *userdata,
509 sd_bus_error *error) {
510
511 _cleanup_free_ char *vendor = NULL;
512
513 (void) get_hardware_vendor(&vendor);
514 return sd_bus_message_append(reply, "s", vendor);
515 }
516
517 static int property_get_hardware_model(
518 sd_bus *bus,
519 const char *path,
520 const char *interface,
521 const char *property,
522 sd_bus_message *reply,
523 void *userdata,
524 sd_bus_error *error) {
525
526 _cleanup_free_ char *model = NULL;
527
528 (void) get_hardware_model(&model);
529 return sd_bus_message_append(reply, "s", model);
530 }
531
532 static int property_get_hostname(
533 sd_bus *bus,
534 const char *path,
535 const char *interface,
536 const char *property,
537 sd_bus_message *reply,
538 void *userdata,
539 sd_bus_error *error) {
540
541 _cleanup_free_ char *hn = NULL;
542 int r;
543
544 r = gethostname_strict(&hn);
545 if (r < 0) {
546 if (r != -ENXIO)
547 return r;
548
549 hn = get_default_hostname();
550 if (!hn)
551 return -ENOMEM;
552 }
553
554 return sd_bus_message_append(reply, "s", hn);
555 }
556
557 static int property_get_static_hostname(
558 sd_bus *bus,
559 const char *path,
560 const char *interface,
561 const char *property,
562 sd_bus_message *reply,
563 void *userdata,
564 sd_bus_error *error) {
565
566 Context *c = userdata;
567 assert(c);
568
569 context_read_etc_hostname(c);
570
571 return sd_bus_message_append(reply, "s", c->data[PROP_STATIC_HOSTNAME]);
572 }
573
574 static int property_get_default_hostname(
575 sd_bus *bus,
576 const char *path,
577 const char *interface,
578 const char *property,
579 sd_bus_message *reply,
580 void *userdata,
581 sd_bus_error *error) {
582
583 _cleanup_free_ char *hn = NULL;
584
585 hn = get_default_hostname();
586 if (!hn)
587 return log_oom();
588
589 return sd_bus_message_append(reply, "s", hn);
590 }
591
592 static void context_determine_hostname_source(Context *c) {
593 _cleanup_free_ char *hostname = NULL;
594 int r;
595
596 assert(c);
597
598 if (c->hostname_source >= 0)
599 return;
600
601 (void) gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST, &hostname);
602
603 if (streq_ptr(hostname, c->data[PROP_STATIC_HOSTNAME]))
604 c->hostname_source = HOSTNAME_STATIC;
605 else {
606 _cleanup_free_ char *fallback = NULL;
607
608 /* If the hostname was not set by us, try to figure out where it came from. If we set it to
609 * the default hostname, the file will tell us. We compare the string because it is possible
610 * that the hostname was set by an older version that had a different fallback, in the
611 * initramfs or before we reexecuted. */
612
613 r = read_one_line_file("/run/systemd/default-hostname", &fallback);
614 if (r < 0 && r != -ENOENT)
615 log_warning_errno(r, "Failed to read /run/systemd/default-hostname, ignoring: %m");
616
617 if (streq_ptr(fallback, hostname))
618 c->hostname_source = HOSTNAME_DEFAULT;
619 else
620 c->hostname_source = HOSTNAME_TRANSIENT;
621 }
622 }
623
624 static int property_get_hostname_source(
625 sd_bus *bus,
626 const char *path,
627 const char *interface,
628 const char *property,
629 sd_bus_message *reply,
630 void *userdata,
631 sd_bus_error *error) {
632
633 Context *c = userdata;
634 assert(c);
635
636 context_read_etc_hostname(c);
637 context_determine_hostname_source(c);
638
639 return sd_bus_message_append(reply, "s", hostname_source_to_string(c->hostname_source));
640 }
641
642 static int property_get_machine_info_field(
643 sd_bus *bus,
644 const char *path,
645 const char *interface,
646 const char *property,
647 sd_bus_message *reply,
648 void *userdata,
649 sd_bus_error *error) {
650
651 sd_bus_slot *slot;
652 Context *c;
653
654 /* Acquire the context object without this property's userdata offset added. Explanation: we want
655 * access to two pointers here: a) the main context object we cache all properties in, and b) the
656 * pointer to the property field inside the context object that we are supposed to update and
657 * use. The latter (b) we get in the 'userdata' function parameter, and sd-bus calculates that for us
658 * from the 'userdata' pointer we supplied when the vtable was registered, with the offset we
659 * specified in the vtable added on top. To get the former (a) we need the 'userdata' pointer from
660 * the vtable registration directly, without the offset added. Hence we ask sd-bus what the slot
661 * object is (which encapsulates the vtable registration), and then query the 'userdata' field
662 * directly off it. */
663 assert_se(slot = sd_bus_get_current_slot(bus));
664 assert_se(c = sd_bus_slot_get_userdata(slot));
665
666 context_read_machine_info(c);
667
668 return sd_bus_message_append(reply, "s", *(char**) userdata);
669 }
670
671 static int property_get_os_release_field(
672 sd_bus *bus,
673 const char *path,
674 const char *interface,
675 const char *property,
676 sd_bus_message *reply,
677 void *userdata,
678 sd_bus_error *error) {
679
680 sd_bus_slot *slot;
681 Context *c;
682
683 /* As above, acquire the current context without this property's userdata offset added. */
684 assert_se(slot = sd_bus_get_current_slot(bus));
685 assert_se(c = sd_bus_slot_get_userdata(slot));
686
687 context_read_os_release(c);
688
689 return sd_bus_message_append(reply, "s", *(char**) userdata);
690 }
691
692 static int property_get_icon_name(
693 sd_bus *bus,
694 const char *path,
695 const char *interface,
696 const char *property,
697 sd_bus_message *reply,
698 void *userdata,
699 sd_bus_error *error) {
700
701 _cleanup_free_ char *n = NULL;
702 Context *c = userdata;
703 const char *name;
704
705 context_read_machine_info(c);
706
707 if (isempty(c->data[PROP_ICON_NAME]))
708 name = n = context_fallback_icon_name(c);
709 else
710 name = c->data[PROP_ICON_NAME];
711
712 if (!name)
713 return -ENOMEM;
714
715 return sd_bus_message_append(reply, "s", name);
716 }
717
718 static int property_get_chassis(
719 sd_bus *bus,
720 const char *path,
721 const char *interface,
722 const char *property,
723 sd_bus_message *reply,
724 void *userdata,
725 sd_bus_error *error) {
726
727 Context *c = userdata;
728 const char *name;
729
730 context_read_machine_info(c);
731
732 if (isempty(c->data[PROP_CHASSIS]))
733 name = fallback_chassis();
734 else
735 name = c->data[PROP_CHASSIS];
736
737 return sd_bus_message_append(reply, "s", name);
738 }
739
740 static int property_get_uname_field(
741 sd_bus *bus,
742 const char *path,
743 const char *interface,
744 const char *property,
745 sd_bus_message *reply,
746 void *userdata,
747 sd_bus_error *error) {
748
749 struct utsname u;
750
751 assert_se(uname(&u) >= 0);
752
753 return sd_bus_message_append(reply, "s", (char*) &u + PTR_TO_SIZE(userdata));
754 }
755
756 static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) {
757 Context *c = userdata;
758 const char *name;
759 int interactive, r;
760
761 assert(m);
762 assert(c);
763
764 r = sd_bus_message_read(m, "sb", &name, &interactive);
765 if (r < 0)
766 return r;
767
768 name = empty_to_null(name);
769
770 /* We always go through with the procedure below without comparing to the current hostname, because
771 * we might want to adjust hostname source information even if the actual hostname is unchanged. */
772
773 if (name && !hostname_is_valid(name, 0))
774 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
775
776 context_read_etc_hostname(c);
777
778 r = bus_verify_polkit_async(
779 m,
780 CAP_SYS_ADMIN,
781 "org.freedesktop.hostname1.set-hostname",
782 NULL,
783 interactive,
784 UID_INVALID,
785 &c->polkit_registry,
786 error);
787 if (r < 0)
788 return r;
789 if (r == 0)
790 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
791
792 r = context_update_kernel_hostname(c, name);
793 if (r < 0)
794 return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
795 else if (r > 0)
796 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
797 "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
798 "Hostname", "HostnameSource", NULL);
799
800 return sd_bus_reply_method_return(m, NULL);
801 }
802
803 static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) {
804 Context *c = userdata;
805 const char *name;
806 int interactive;
807 int r;
808
809 assert(m);
810 assert(c);
811
812 r = sd_bus_message_read(m, "sb", &name, &interactive);
813 if (r < 0)
814 return r;
815
816 name = empty_to_null(name);
817
818 context_read_etc_hostname(c);
819
820 if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
821 return sd_bus_reply_method_return(m, NULL);
822
823 if (name && !hostname_is_valid(name, 0))
824 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
825
826 r = bus_verify_polkit_async(
827 m,
828 CAP_SYS_ADMIN,
829 "org.freedesktop.hostname1.set-static-hostname",
830 NULL,
831 interactive,
832 UID_INVALID,
833 &c->polkit_registry,
834 error);
835 if (r < 0)
836 return r;
837 if (r == 0)
838 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
839
840 r = free_and_strdup_warn(&c->data[PROP_STATIC_HOSTNAME], name);
841 if (r < 0)
842 return r;
843
844 r = context_write_data_static_hostname(c);
845 if (r < 0) {
846 log_error_errno(r, "Failed to write static hostname: %m");
847 if (ERRNO_IS_PRIVILEGE(r))
848 return sd_bus_error_set(error, BUS_ERROR_FILE_IS_PROTECTED, "Not allowed to update /etc/hostname.");
849 if (r == -EROFS)
850 return sd_bus_error_set(error, BUS_ERROR_READ_ONLY_FILESYSTEM, "/etc/hostname is in a read-only filesystem.");
851 return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %m");
852 }
853
854 r = context_update_kernel_hostname(c, NULL);
855 if (r < 0) {
856 log_error_errno(r, "Failed to set hostname: %m");
857 return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
858 }
859
860 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
861 "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
862 "StaticHostname", "Hostname", "HostnameSource", NULL);
863
864 return sd_bus_reply_method_return(m, NULL);
865 }
866
867 static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_message_handler_t cb, sd_bus_error *error) {
868 int interactive;
869 const char *name;
870 int r;
871
872 assert(c);
873 assert(m);
874
875 r = sd_bus_message_read(m, "sb", &name, &interactive);
876 if (r < 0)
877 return r;
878
879 name = empty_to_null(name);
880
881 context_read_machine_info(c);
882
883 if (streq_ptr(name, c->data[prop]))
884 return sd_bus_reply_method_return(m, NULL);
885
886 if (!isempty(name)) {
887 /* The icon name might ultimately be used as file
888 * name, so better be safe than sorry */
889
890 if (prop == PROP_ICON_NAME && !filename_is_valid(name))
891 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name);
892 if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL))
893 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty hostname '%s'", name);
894 if (prop == PROP_CHASSIS && !valid_chassis(name))
895 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name);
896 if (prop == PROP_DEPLOYMENT && !valid_deployment(name))
897 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid deployment '%s'", name);
898 if (prop == PROP_LOCATION && string_has_cc(name, NULL))
899 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name);
900 }
901
902 /* Since the pretty hostname should always be changed at the
903 * same time as the static one, use the same policy action for
904 * both... */
905
906 r = bus_verify_polkit_async(
907 m,
908 CAP_SYS_ADMIN,
909 prop == PROP_PRETTY_HOSTNAME ? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info",
910 NULL,
911 interactive,
912 UID_INVALID,
913 &c->polkit_registry,
914 error);
915 if (r < 0)
916 return r;
917 if (r == 0)
918 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
919
920 r = free_and_strdup_warn(&c->data[prop], name);
921 if (r < 0)
922 return r;
923
924 r = context_write_data_machine_info(c);
925 if (r < 0) {
926 log_error_errno(r, "Failed to write machine info: %m");
927 if (ERRNO_IS_PRIVILEGE(r))
928 return sd_bus_error_set(error, BUS_ERROR_FILE_IS_PROTECTED, "Not allowed to update /etc/machine-info.");
929 if (r == -EROFS)
930 return sd_bus_error_set(error, BUS_ERROR_READ_ONLY_FILESYSTEM, "/etc/machine-info is in a read-only filesystem.");
931 return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %m");
932 }
933
934 log_info("Changed %s to '%s'",
935 prop == PROP_PRETTY_HOSTNAME ? "pretty hostname" :
936 prop == PROP_DEPLOYMENT ? "deployment" :
937 prop == PROP_LOCATION ? "location" :
938 prop == PROP_CHASSIS ? "chassis" : "icon name", strna(c->data[prop]));
939
940 (void) sd_bus_emit_properties_changed(
941 sd_bus_message_get_bus(m),
942 "/org/freedesktop/hostname1",
943 "org.freedesktop.hostname1",
944 prop == PROP_PRETTY_HOSTNAME ? "PrettyHostname" :
945 prop == PROP_DEPLOYMENT ? "Deployment" :
946 prop == PROP_LOCATION ? "Location" :
947 prop == PROP_CHASSIS ? "Chassis" : "IconName" , NULL);
948
949 return sd_bus_reply_method_return(m, NULL);
950 }
951
952 static int method_set_pretty_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) {
953 return set_machine_info(userdata, m, PROP_PRETTY_HOSTNAME, method_set_pretty_hostname, error);
954 }
955
956 static int method_set_icon_name(sd_bus_message *m, void *userdata, sd_bus_error *error) {
957 return set_machine_info(userdata, m, PROP_ICON_NAME, method_set_icon_name, error);
958 }
959
960 static int method_set_chassis(sd_bus_message *m, void *userdata, sd_bus_error *error) {
961 return set_machine_info(userdata, m, PROP_CHASSIS, method_set_chassis, error);
962 }
963
964 static int method_set_deployment(sd_bus_message *m, void *userdata, sd_bus_error *error) {
965 return set_machine_info(userdata, m, PROP_DEPLOYMENT, method_set_deployment, error);
966 }
967
968 static int method_set_location(sd_bus_message *m, void *userdata, sd_bus_error *error) {
969 return set_machine_info(userdata, m, PROP_LOCATION, method_set_location, error);
970 }
971
972 static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_error *error) {
973 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
974 Context *c = userdata;
975 int interactive, r;
976 sd_id128_t uuid;
977
978 assert(m);
979 assert(c);
980
981 r = sd_bus_message_read(m, "b", &interactive);
982 if (r < 0)
983 return r;
984
985 r = bus_verify_polkit_async(
986 m,
987 CAP_SYS_ADMIN,
988 "org.freedesktop.hostname1.get-product-uuid",
989 NULL,
990 interactive,
991 UID_INVALID,
992 &c->polkit_registry,
993 error);
994 if (r < 0)
995 return r;
996 if (r == 0)
997 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
998
999 r = id128_get_product(&uuid);
1000 if (r < 0) {
1001 if (r == -EADDRNOTAVAIL)
1002 log_debug_errno(r, "DMI product UUID is all 0x00 or all 0xFF, ignoring.");
1003 else
1004 log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
1005 "Failed to read product UUID, ignoring: %m");
1006
1007 return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID,
1008 "Failed to read product UUID from firmware.");
1009 }
1010
1011 r = sd_bus_message_new_method_return(m, &reply);
1012 if (r < 0)
1013 return r;
1014
1015 r = sd_bus_message_append_array(reply, 'y', uuid.bytes, sizeof(uuid.bytes));
1016 if (r < 0)
1017 return r;
1018
1019 return sd_bus_send(NULL, reply, NULL);
1020 }
1021
1022 static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1023 _cleanup_free_ char *hn = NULL, *dhn = NULL, *in = NULL, *text = NULL, *vendor = NULL, *model = NULL;
1024 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1025 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
1026 sd_id128_t product_uuid = SD_ID128_NULL;
1027 const char *chassis = NULL;
1028 Context *c = userdata;
1029 bool privileged;
1030 struct utsname u;
1031 int r;
1032
1033 assert(m);
1034 assert(c);
1035
1036 r = bus_verify_polkit_async(
1037 m,
1038 CAP_SYS_ADMIN,
1039 "org.freedesktop.hostname1.get-product-uuid",
1040 NULL,
1041 false,
1042 UID_INVALID,
1043 &c->polkit_registry,
1044 NULL);
1045 if (r == 0)
1046 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1047
1048 /* We ignore all authentication errors here, since most data is unprivileged, the one exception being
1049 * the product ID which we'll check explicitly. */
1050 privileged = r > 0;
1051
1052 context_read_etc_hostname(c);
1053 context_read_machine_info(c);
1054 context_read_os_release(c);
1055 context_determine_hostname_source(c);
1056
1057 r = gethostname_strict(&hn);
1058 if (r < 0) {
1059 if (r != -ENXIO)
1060 return log_error_errno(r, "Failed to read local host name: %m");
1061
1062 hn = get_default_hostname();
1063 if (!hn)
1064 return log_oom();
1065 }
1066
1067 dhn = get_default_hostname();
1068 if (!dhn)
1069 return log_oom();
1070
1071 if (isempty(c->data[PROP_ICON_NAME]))
1072 in = context_fallback_icon_name(c);
1073
1074 if (isempty(c->data[PROP_CHASSIS]))
1075 chassis = fallback_chassis();
1076
1077 assert_se(uname(&u) >= 0);
1078
1079 (void) get_hardware_vendor(&vendor);
1080 (void) get_hardware_model(&model);
1081
1082 if (privileged) /* The product UUID is only available to privileged clients */
1083 id128_get_product(&product_uuid);
1084
1085 r = json_build(&v, JSON_BUILD_OBJECT(
1086 JSON_BUILD_PAIR("Hostname", JSON_BUILD_STRING(hn)),
1087 JSON_BUILD_PAIR("StaticHostname", JSON_BUILD_STRING(c->data[PROP_STATIC_HOSTNAME])),
1088 JSON_BUILD_PAIR("PrettyHostname", JSON_BUILD_STRING(c->data[PROP_PRETTY_HOSTNAME])),
1089 JSON_BUILD_PAIR("DefaultHostname", JSON_BUILD_STRING(dhn)),
1090 JSON_BUILD_PAIR("HostnameSource", JSON_BUILD_STRING(hostname_source_to_string(c->hostname_source))),
1091 JSON_BUILD_PAIR("IconName", JSON_BUILD_STRING(in ?: c->data[PROP_ICON_NAME])),
1092 JSON_BUILD_PAIR("Chassis", JSON_BUILD_STRING(chassis ?: c->data[PROP_CHASSIS])),
1093 JSON_BUILD_PAIR("Deployment", JSON_BUILD_STRING(c->data[PROP_DEPLOYMENT])),
1094 JSON_BUILD_PAIR("Location", JSON_BUILD_STRING(c->data[PROP_LOCATION])),
1095 JSON_BUILD_PAIR("KernelName", JSON_BUILD_STRING(u.sysname)),
1096 JSON_BUILD_PAIR("KernelRelease", JSON_BUILD_STRING(u.release)),
1097 JSON_BUILD_PAIR("KernelVersion", JSON_BUILD_STRING(u.version)),
1098 JSON_BUILD_PAIR("OperatingSystemPrettyName", JSON_BUILD_STRING(c->data[PROP_OS_PRETTY_NAME])),
1099 JSON_BUILD_PAIR("OperatingSystemCPEName", JSON_BUILD_STRING(c->data[PROP_OS_CPE_NAME])),
1100 JSON_BUILD_PAIR("OperatingSystemHomeURL", JSON_BUILD_STRING(c->data[PROP_OS_HOME_URL])),
1101 JSON_BUILD_PAIR("HardwareVendor", JSON_BUILD_STRING(vendor)),
1102 JSON_BUILD_PAIR("HardwareModel", JSON_BUILD_STRING(model)),
1103 JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(product_uuid), "ProductUUID", JSON_BUILD_ID128(product_uuid)),
1104 JSON_BUILD_PAIR_CONDITION(sd_id128_is_null(product_uuid), "ProductUUID", JSON_BUILD_NULL)));
1105
1106 if (r < 0)
1107 return log_error_errno(r, "Failed to build JSON data: %m");
1108
1109 r = json_variant_format(v, 0, &text);
1110 if (r < 0)
1111 return log_error_errno(r, "Failed to format JSON data: %m");
1112
1113 r = sd_bus_message_new_method_return(m, &reply);
1114 if (r < 0)
1115 return r;
1116
1117 r = sd_bus_message_append(reply, "s", text);
1118 if (r < 0)
1119 return r;
1120
1121 return sd_bus_send(NULL, reply, NULL);
1122 }
1123
1124 static const sd_bus_vtable hostname_vtable[] = {
1125 SD_BUS_VTABLE_START(0),
1126 SD_BUS_PROPERTY("Hostname", "s", property_get_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1127 SD_BUS_PROPERTY("StaticHostname", "s", property_get_static_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1128 SD_BUS_PROPERTY("PrettyHostname", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_PRETTY_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1129 SD_BUS_PROPERTY("DefaultHostname", "s", property_get_default_hostname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1130 SD_BUS_PROPERTY("HostnameSource", "s", property_get_hostname_source, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1131 SD_BUS_PROPERTY("IconName", "s", property_get_icon_name, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1132 SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1133 SD_BUS_PROPERTY("Deployment", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_DEPLOYMENT, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1134 SD_BUS_PROPERTY("Location", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_LOCATION, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1135 SD_BUS_PROPERTY("KernelName", "s", property_get_uname_field, offsetof(struct utsname, sysname), SD_BUS_VTABLE_ABSOLUTE_OFFSET|SD_BUS_VTABLE_PROPERTY_CONST),
1136 SD_BUS_PROPERTY("KernelRelease", "s", property_get_uname_field, offsetof(struct utsname, release), SD_BUS_VTABLE_ABSOLUTE_OFFSET|SD_BUS_VTABLE_PROPERTY_CONST),
1137 SD_BUS_PROPERTY("KernelVersion", "s", property_get_uname_field, offsetof(struct utsname, version), SD_BUS_VTABLE_ABSOLUTE_OFFSET|SD_BUS_VTABLE_PROPERTY_CONST),
1138 SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", property_get_os_release_field, offsetof(Context, data) + sizeof(char*) * PROP_OS_PRETTY_NAME, SD_BUS_VTABLE_PROPERTY_CONST),
1139 SD_BUS_PROPERTY("OperatingSystemCPEName", "s", property_get_os_release_field, offsetof(Context, data) + sizeof(char*) * PROP_OS_CPE_NAME, SD_BUS_VTABLE_PROPERTY_CONST),
1140 SD_BUS_PROPERTY("HomeURL", "s", property_get_os_release_field, offsetof(Context, data) + sizeof(char*) * PROP_OS_HOME_URL, SD_BUS_VTABLE_PROPERTY_CONST),
1141 SD_BUS_PROPERTY("HardwareVendor", "s", property_get_hardware_vendor, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1142 SD_BUS_PROPERTY("HardwareModel", "s", property_get_hardware_model, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1143
1144 SD_BUS_METHOD_WITH_NAMES("SetHostname",
1145 "sb",
1146 SD_BUS_PARAM(hostname)
1147 SD_BUS_PARAM(interactive),
1148 NULL,,
1149 method_set_hostname,
1150 SD_BUS_VTABLE_UNPRIVILEGED),
1151 SD_BUS_METHOD_WITH_NAMES("SetStaticHostname",
1152 "sb",
1153 SD_BUS_PARAM(hostname)
1154 SD_BUS_PARAM(interactive),
1155 NULL,,
1156 method_set_static_hostname,
1157 SD_BUS_VTABLE_UNPRIVILEGED),
1158 SD_BUS_METHOD_WITH_NAMES("SetPrettyHostname",
1159 "sb",
1160 SD_BUS_PARAM(hostname)
1161 SD_BUS_PARAM(interactive),
1162 NULL,,
1163 method_set_pretty_hostname,
1164 SD_BUS_VTABLE_UNPRIVILEGED),
1165 SD_BUS_METHOD_WITH_NAMES("SetIconName",
1166 "sb",
1167 SD_BUS_PARAM(icon)
1168 SD_BUS_PARAM(interactive),
1169 NULL,,
1170 method_set_icon_name,
1171 SD_BUS_VTABLE_UNPRIVILEGED),
1172 SD_BUS_METHOD_WITH_NAMES("SetChassis",
1173 "sb",
1174 SD_BUS_PARAM(chassis)
1175 SD_BUS_PARAM(interactive),
1176 NULL,,
1177 method_set_chassis,
1178 SD_BUS_VTABLE_UNPRIVILEGED),
1179 SD_BUS_METHOD_WITH_NAMES("SetDeployment",
1180 "sb",
1181 SD_BUS_PARAM(deployment)
1182 SD_BUS_PARAM(interactive),
1183 NULL,,
1184 method_set_deployment,
1185 SD_BUS_VTABLE_UNPRIVILEGED),
1186 SD_BUS_METHOD_WITH_NAMES("SetLocation",
1187 "sb",
1188 SD_BUS_PARAM(location)
1189 SD_BUS_PARAM(interactive),
1190 NULL,,
1191 method_set_location,
1192 SD_BUS_VTABLE_UNPRIVILEGED),
1193 SD_BUS_METHOD_WITH_NAMES("GetProductUUID",
1194 "b",
1195 SD_BUS_PARAM(interactive),
1196 "ay",
1197 SD_BUS_PARAM(uuid),
1198 method_get_product_uuid,
1199 SD_BUS_VTABLE_UNPRIVILEGED),
1200 SD_BUS_METHOD_WITH_ARGS("Describe",
1201 SD_BUS_NO_ARGS,
1202 SD_BUS_RESULT("s", json),
1203 method_describe,
1204 SD_BUS_VTABLE_UNPRIVILEGED),
1205
1206 SD_BUS_VTABLE_END,
1207 };
1208
1209 static const BusObjectImplementation manager_object = {
1210 "/org/freedesktop/hostname1",
1211 "org.freedesktop.hostname1",
1212 .vtables = BUS_VTABLES(hostname_vtable),
1213 };
1214
1215 static int connect_bus(Context *c, sd_event *event, sd_bus **ret) {
1216 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
1217 int r;
1218
1219 assert(c);
1220 assert(event);
1221 assert(ret);
1222
1223 r = sd_bus_default_system(&bus);
1224 if (r < 0)
1225 return log_error_errno(r, "Failed to get system bus connection: %m");
1226
1227 r = bus_add_implementation(bus, &manager_object, c);
1228 if (r < 0)
1229 return r;
1230
1231 r = bus_log_control_api_register(bus);
1232 if (r < 0)
1233 return r;
1234
1235 r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.hostname1", 0, NULL, NULL);
1236 if (r < 0)
1237 return log_error_errno(r, "Failed to request name: %m");
1238
1239 r = sd_bus_attach_event(bus, event, 0);
1240 if (r < 0)
1241 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1242
1243 *ret = TAKE_PTR(bus);
1244 return 0;
1245 }
1246
1247 static int run(int argc, char *argv[]) {
1248 _cleanup_(context_destroy) Context context = {
1249 .hostname_source = _HOSTNAME_INVALID, /* appropriate value will be set later */
1250 };
1251 _cleanup_(sd_event_unrefp) sd_event *event = NULL;
1252 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
1253 int r;
1254
1255 log_setup();
1256
1257 r = service_parse_argv("systemd-hostnamed.service",
1258 "Manage the system hostname and related metadata.",
1259 BUS_IMPLEMENTATIONS(&manager_object,
1260 &log_control_object),
1261 argc, argv);
1262 if (r <= 0)
1263 return r;
1264
1265 umask(0022);
1266
1267 r = mac_selinux_init();
1268 if (r < 0)
1269 return r;
1270
1271 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
1272
1273 r = sd_event_default(&event);
1274 if (r < 0)
1275 return log_error_errno(r, "Failed to allocate event loop: %m");
1276
1277 (void) sd_event_set_watchdog(event, true);
1278
1279 r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
1280 if (r < 0)
1281 return log_error_errno(r, "Failed to install SIGINT handler: %m");
1282
1283 r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
1284 if (r < 0)
1285 return log_error_errno(r, "Failed to install SIGTERM handler: %m");
1286
1287 r = connect_bus(&context, event, &bus);
1288 if (r < 0)
1289 return r;
1290
1291 r = bus_event_loop_with_idle(event, bus, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC, NULL, NULL);
1292 if (r < 0)
1293 return log_error_errno(r, "Failed to run event loop: %m");
1294
1295 return 0;
1296 }
1297
1298 DEFINE_MAIN_FUNCTION(run);